1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_basegfx.hxx" 30 #include <osl/diagnose.h> 31 #include <basegfx/polygon/b3dpolygon.hxx> 32 #include <basegfx/point/b3dpoint.hxx> 33 #include <basegfx/matrix/b3dhommatrix.hxx> 34 #include <rtl/instance.hxx> 35 #include <basegfx/point/b2dpoint.hxx> 36 #include <basegfx/color/bcolor.hxx> 37 #include <basegfx/matrix/b2dhommatrix.hxx> 38 #include <vector> 39 #include <algorithm> 40 41 ////////////////////////////////////////////////////////////////////////////// 42 43 class CoordinateData3D 44 { 45 basegfx::B3DPoint maPoint; 46 47 public: 48 CoordinateData3D() 49 : maPoint() 50 { 51 } 52 53 explicit CoordinateData3D(const basegfx::B3DPoint& rData) 54 : maPoint(rData) 55 { 56 } 57 58 const basegfx::B3DPoint& getCoordinate() const 59 { 60 return maPoint; 61 } 62 63 void setCoordinate(const basegfx::B3DPoint& rValue) 64 { 65 if(rValue != maPoint) 66 maPoint = rValue; 67 } 68 69 bool operator==(const CoordinateData3D& rData) const 70 { 71 return (maPoint == rData.getCoordinate()); 72 } 73 74 void transform(const basegfx::B3DHomMatrix& rMatrix) 75 { 76 maPoint *= rMatrix; 77 } 78 }; 79 80 ////////////////////////////////////////////////////////////////////////////// 81 82 class CoordinateDataArray3D 83 { 84 typedef ::std::vector< CoordinateData3D > CoordinateData3DVector; 85 86 CoordinateData3DVector maVector; 87 88 public: 89 explicit CoordinateDataArray3D(sal_uInt32 nCount) 90 : maVector(nCount) 91 { 92 } 93 94 explicit CoordinateDataArray3D(const CoordinateDataArray3D& rOriginal) 95 : maVector(rOriginal.maVector) 96 { 97 } 98 99 CoordinateDataArray3D(const CoordinateDataArray3D& rOriginal, sal_uInt32 nIndex, sal_uInt32 nCount) 100 : maVector(rOriginal.maVector.begin() + nIndex, rOriginal.maVector.begin() + (nIndex + nCount)) 101 { 102 } 103 104 ~CoordinateDataArray3D() 105 { 106 } 107 108 ::basegfx::B3DVector getNormal() const 109 { 110 ::basegfx::B3DVector aRetval; 111 const sal_uInt32 nPointCount(maVector.size()); 112 113 if(nPointCount > 2) 114 { 115 sal_uInt32 nISmallest(0); 116 sal_uInt32 a(0); 117 const basegfx::B3DPoint* pSmallest(&maVector[0].getCoordinate()); 118 const basegfx::B3DPoint* pNext(0); 119 const basegfx::B3DPoint* pPrev(0); 120 121 // To guarantee a correctly oriented point, choose an outmost one 122 // which then cannot be concave 123 for(a = 1; a < nPointCount; a++) 124 { 125 const basegfx::B3DPoint& rCandidate = maVector[a].getCoordinate(); 126 127 if((rCandidate.getX() < pSmallest->getX()) 128 || (rCandidate.getX() == pSmallest->getX() && rCandidate.getY() < pSmallest->getY()) 129 || (rCandidate.getX() == pSmallest->getX() && rCandidate.getY() == pSmallest->getY() && rCandidate.getZ() < pSmallest->getZ())) 130 { 131 nISmallest = a; 132 pSmallest = &rCandidate; 133 } 134 } 135 136 // look for a next point different from minimal one 137 for(a = (nISmallest + 1) % nPointCount; a != nISmallest; a = (a + 1) % nPointCount) 138 { 139 const basegfx::B3DPoint& rCandidate = maVector[a].getCoordinate(); 140 141 if(!rCandidate.equal(*pSmallest)) 142 { 143 pNext = &rCandidate; 144 break; 145 } 146 } 147 148 // look for a previous point different from minimal one 149 for(a = (nISmallest + nPointCount - 1) % nPointCount; a != nISmallest; a = (a + nPointCount - 1) % nPointCount) 150 { 151 const basegfx::B3DPoint& rCandidate = maVector[a].getCoordinate(); 152 153 if(!rCandidate.equal(*pSmallest)) 154 { 155 pPrev = &rCandidate; 156 break; 157 } 158 } 159 160 // we always have a minimal point. If we also have a different next and previous, 161 // we can calculate the normal 162 if(pNext && pPrev) 163 { 164 const basegfx::B3DVector aPrev(*pPrev - *pSmallest); 165 const basegfx::B3DVector aNext(*pNext - *pSmallest); 166 167 aRetval = cross(aPrev, aNext); 168 aRetval.normalize(); 169 } 170 } 171 172 return aRetval; 173 } 174 175 sal_uInt32 count() const 176 { 177 return maVector.size(); 178 } 179 180 bool operator==(const CoordinateDataArray3D& rCandidate) const 181 { 182 return (maVector == rCandidate.maVector); 183 } 184 185 const basegfx::B3DPoint& getCoordinate(sal_uInt32 nIndex) const 186 { 187 return maVector[nIndex].getCoordinate(); 188 } 189 190 void setCoordinate(sal_uInt32 nIndex, const basegfx::B3DPoint& rValue) 191 { 192 maVector[nIndex].setCoordinate(rValue); 193 } 194 195 void insert(sal_uInt32 nIndex, const CoordinateData3D& rValue, sal_uInt32 nCount) 196 { 197 if(nCount) 198 { 199 // add nCount copies of rValue 200 CoordinateData3DVector::iterator aIndex(maVector.begin()); 201 aIndex += nIndex; 202 maVector.insert(aIndex, nCount, rValue); 203 } 204 } 205 206 void insert(sal_uInt32 nIndex, const CoordinateDataArray3D& rSource) 207 { 208 const sal_uInt32 nCount(rSource.maVector.size()); 209 210 if(nCount) 211 { 212 // insert data 213 CoordinateData3DVector::iterator aIndex(maVector.begin()); 214 aIndex += nIndex; 215 CoordinateData3DVector::const_iterator aStart(rSource.maVector.begin()); 216 CoordinateData3DVector::const_iterator aEnd(rSource.maVector.end()); 217 maVector.insert(aIndex, aStart, aEnd); 218 } 219 } 220 221 void remove(sal_uInt32 nIndex, sal_uInt32 nCount) 222 { 223 if(nCount) 224 { 225 // remove point data 226 CoordinateData3DVector::iterator aStart(maVector.begin()); 227 aStart += nIndex; 228 const CoordinateData3DVector::iterator aEnd(aStart + nCount); 229 maVector.erase(aStart, aEnd); 230 } 231 } 232 233 void flip() 234 { 235 if(maVector.size() > 1) 236 { 237 const sal_uInt32 nHalfSize(maVector.size() >> 1L); 238 CoordinateData3DVector::iterator aStart(maVector.begin()); 239 CoordinateData3DVector::iterator aEnd(maVector.end() - 1L); 240 241 for(sal_uInt32 a(0); a < nHalfSize; a++) 242 { 243 ::std::swap(*aStart, *aEnd); 244 aStart++; 245 aEnd--; 246 } 247 } 248 } 249 250 void transform(const ::basegfx::B3DHomMatrix& rMatrix) 251 { 252 CoordinateData3DVector::iterator aStart(maVector.begin()); 253 CoordinateData3DVector::iterator aEnd(maVector.end()); 254 255 for(; aStart != aEnd; aStart++) 256 { 257 aStart->transform(rMatrix); 258 } 259 } 260 }; 261 262 ////////////////////////////////////////////////////////////////////////////// 263 264 class BColorArray 265 { 266 typedef ::std::vector< ::basegfx::BColor > BColorDataVector; 267 268 BColorDataVector maVector; 269 sal_uInt32 mnUsedEntries; 270 271 public: 272 explicit BColorArray(sal_uInt32 nCount) 273 : maVector(nCount), 274 mnUsedEntries(0L) 275 { 276 } 277 278 explicit BColorArray(const BColorArray& rOriginal) 279 : maVector(rOriginal.maVector), 280 mnUsedEntries(rOriginal.mnUsedEntries) 281 { 282 } 283 284 BColorArray(const BColorArray& rOriginal, sal_uInt32 nIndex, sal_uInt32 nCount) 285 : maVector(), 286 mnUsedEntries(0L) 287 { 288 BColorDataVector::const_iterator aStart(rOriginal.maVector.begin()); 289 aStart += nIndex; 290 BColorDataVector::const_iterator aEnd(aStart); 291 aEnd += nCount; 292 maVector.reserve(nCount); 293 294 for(; aStart != aEnd; aStart++) 295 { 296 if(!aStart->equalZero()) 297 mnUsedEntries++; 298 299 maVector.push_back(*aStart); 300 } 301 } 302 303 ~BColorArray() 304 { 305 } 306 307 sal_uInt32 count() const 308 { 309 return maVector.size(); 310 } 311 312 bool operator==(const BColorArray& rCandidate) const 313 { 314 return (maVector == rCandidate.maVector); 315 } 316 317 bool isUsed() const 318 { 319 return (0L != mnUsedEntries); 320 } 321 322 const ::basegfx::BColor& getBColor(sal_uInt32 nIndex) const 323 { 324 return maVector[nIndex]; 325 } 326 327 void setBColor(sal_uInt32 nIndex, const ::basegfx::BColor& rValue) 328 { 329 bool bWasUsed(mnUsedEntries && !maVector[nIndex].equalZero()); 330 bool bIsUsed(!rValue.equalZero()); 331 332 if(bWasUsed) 333 { 334 if(bIsUsed) 335 { 336 maVector[nIndex] = rValue; 337 } 338 else 339 { 340 maVector[nIndex] = ::basegfx::BColor::getEmptyBColor(); 341 mnUsedEntries--; 342 } 343 } 344 else 345 { 346 if(bIsUsed) 347 { 348 maVector[nIndex] = rValue; 349 mnUsedEntries++; 350 } 351 } 352 } 353 354 void insert(sal_uInt32 nIndex, const ::basegfx::BColor& rValue, sal_uInt32 nCount) 355 { 356 if(nCount) 357 { 358 // add nCount copies of rValue 359 BColorDataVector::iterator aIndex(maVector.begin()); 360 aIndex += nIndex; 361 maVector.insert(aIndex, nCount, rValue); 362 363 if(!rValue.equalZero()) 364 mnUsedEntries += nCount; 365 } 366 } 367 368 void insert(sal_uInt32 nIndex, const BColorArray& rSource) 369 { 370 const sal_uInt32 nCount(rSource.maVector.size()); 371 372 if(nCount) 373 { 374 // insert data 375 BColorDataVector::iterator aIndex(maVector.begin()); 376 aIndex += nIndex; 377 BColorDataVector::const_iterator aStart(rSource.maVector.begin()); 378 BColorDataVector::const_iterator aEnd(rSource.maVector.end()); 379 maVector.insert(aIndex, aStart, aEnd); 380 381 for(; aStart != aEnd; aStart++) 382 { 383 if(!aStart->equalZero()) 384 mnUsedEntries++; 385 } 386 } 387 } 388 389 void remove(sal_uInt32 nIndex, sal_uInt32 nCount) 390 { 391 if(nCount) 392 { 393 const BColorDataVector::iterator aDeleteStart(maVector.begin() + nIndex); 394 const BColorDataVector::iterator aDeleteEnd(aDeleteStart + nCount); 395 BColorDataVector::const_iterator aStart(aDeleteStart); 396 397 for(; mnUsedEntries && aStart != aDeleteEnd; aStart++) 398 { 399 if(!aStart->equalZero()) 400 mnUsedEntries--; 401 } 402 403 // remove point data 404 maVector.erase(aDeleteStart, aDeleteEnd); 405 } 406 } 407 408 void flip() 409 { 410 if(maVector.size() > 1) 411 { 412 const sal_uInt32 nHalfSize(maVector.size() >> 1L); 413 BColorDataVector::iterator aStart(maVector.begin()); 414 BColorDataVector::iterator aEnd(maVector.end() - 1L); 415 416 for(sal_uInt32 a(0); a < nHalfSize; a++) 417 { 418 ::std::swap(*aStart, *aEnd); 419 aStart++; 420 aEnd--; 421 } 422 } 423 } 424 }; 425 426 ////////////////////////////////////////////////////////////////////////////// 427 428 class NormalsArray3D 429 { 430 typedef ::std::vector< ::basegfx::B3DVector > NormalsData3DVector; 431 432 NormalsData3DVector maVector; 433 sal_uInt32 mnUsedEntries; 434 435 public: 436 explicit NormalsArray3D(sal_uInt32 nCount) 437 : maVector(nCount), 438 mnUsedEntries(0L) 439 { 440 } 441 442 explicit NormalsArray3D(const NormalsArray3D& rOriginal) 443 : maVector(rOriginal.maVector), 444 mnUsedEntries(rOriginal.mnUsedEntries) 445 { 446 } 447 448 NormalsArray3D(const NormalsArray3D& rOriginal, sal_uInt32 nIndex, sal_uInt32 nCount) 449 : maVector(), 450 mnUsedEntries(0L) 451 { 452 NormalsData3DVector::const_iterator aStart(rOriginal.maVector.begin()); 453 aStart += nIndex; 454 NormalsData3DVector::const_iterator aEnd(aStart); 455 aEnd += nCount; 456 maVector.reserve(nCount); 457 458 for(; aStart != aEnd; aStart++) 459 { 460 if(!aStart->equalZero()) 461 mnUsedEntries++; 462 463 maVector.push_back(*aStart); 464 } 465 } 466 467 ~NormalsArray3D() 468 { 469 } 470 471 sal_uInt32 count() const 472 { 473 return maVector.size(); 474 } 475 476 bool operator==(const NormalsArray3D& rCandidate) const 477 { 478 return (maVector == rCandidate.maVector); 479 } 480 481 bool isUsed() const 482 { 483 return (0L != mnUsedEntries); 484 } 485 486 const ::basegfx::B3DVector& getNormal(sal_uInt32 nIndex) const 487 { 488 return maVector[nIndex]; 489 } 490 491 void setNormal(sal_uInt32 nIndex, const ::basegfx::B3DVector& rValue) 492 { 493 bool bWasUsed(mnUsedEntries && !maVector[nIndex].equalZero()); 494 bool bIsUsed(!rValue.equalZero()); 495 496 if(bWasUsed) 497 { 498 if(bIsUsed) 499 { 500 maVector[nIndex] = rValue; 501 } 502 else 503 { 504 maVector[nIndex] = ::basegfx::B3DVector::getEmptyVector(); 505 mnUsedEntries--; 506 } 507 } 508 else 509 { 510 if(bIsUsed) 511 { 512 maVector[nIndex] = rValue; 513 mnUsedEntries++; 514 } 515 } 516 } 517 518 void insert(sal_uInt32 nIndex, const ::basegfx::B3DVector& rValue, sal_uInt32 nCount) 519 { 520 if(nCount) 521 { 522 // add nCount copies of rValue 523 NormalsData3DVector::iterator aIndex(maVector.begin()); 524 aIndex += nIndex; 525 maVector.insert(aIndex, nCount, rValue); 526 527 if(!rValue.equalZero()) 528 mnUsedEntries += nCount; 529 } 530 } 531 532 void insert(sal_uInt32 nIndex, const NormalsArray3D& rSource) 533 { 534 const sal_uInt32 nCount(rSource.maVector.size()); 535 536 if(nCount) 537 { 538 // insert data 539 NormalsData3DVector::iterator aIndex(maVector.begin()); 540 aIndex += nIndex; 541 NormalsData3DVector::const_iterator aStart(rSource.maVector.begin()); 542 NormalsData3DVector::const_iterator aEnd(rSource.maVector.end()); 543 maVector.insert(aIndex, aStart, aEnd); 544 545 for(; aStart != aEnd; aStart++) 546 { 547 if(!aStart->equalZero()) 548 mnUsedEntries++; 549 } 550 } 551 } 552 553 void remove(sal_uInt32 nIndex, sal_uInt32 nCount) 554 { 555 if(nCount) 556 { 557 const NormalsData3DVector::iterator aDeleteStart(maVector.begin() + nIndex); 558 const NormalsData3DVector::iterator aDeleteEnd(aDeleteStart + nCount); 559 NormalsData3DVector::const_iterator aStart(aDeleteStart); 560 561 for(; mnUsedEntries && aStart != aDeleteEnd; aStart++) 562 { 563 if(!aStart->equalZero()) 564 mnUsedEntries--; 565 } 566 567 // remove point data 568 maVector.erase(aDeleteStart, aDeleteEnd); 569 } 570 } 571 572 void flip() 573 { 574 if(maVector.size() > 1) 575 { 576 const sal_uInt32 nHalfSize(maVector.size() >> 1L); 577 NormalsData3DVector::iterator aStart(maVector.begin()); 578 NormalsData3DVector::iterator aEnd(maVector.end() - 1L); 579 580 for(sal_uInt32 a(0); a < nHalfSize; a++) 581 { 582 ::std::swap(*aStart, *aEnd); 583 aStart++; 584 aEnd--; 585 } 586 } 587 } 588 589 void transform(const basegfx::B3DHomMatrix& rMatrix) 590 { 591 NormalsData3DVector::iterator aStart(maVector.begin()); 592 NormalsData3DVector::iterator aEnd(maVector.end()); 593 594 for(; aStart != aEnd; aStart++) 595 { 596 (*aStart) *= rMatrix; 597 } 598 } 599 }; 600 601 ////////////////////////////////////////////////////////////////////////////// 602 603 class TextureCoordinate2D 604 { 605 typedef ::std::vector< ::basegfx::B2DPoint > TextureData2DVector; 606 607 TextureData2DVector maVector; 608 sal_uInt32 mnUsedEntries; 609 610 public: 611 explicit TextureCoordinate2D(sal_uInt32 nCount) 612 : maVector(nCount), 613 mnUsedEntries(0L) 614 { 615 } 616 617 explicit TextureCoordinate2D(const TextureCoordinate2D& rOriginal) 618 : maVector(rOriginal.maVector), 619 mnUsedEntries(rOriginal.mnUsedEntries) 620 { 621 } 622 623 TextureCoordinate2D(const TextureCoordinate2D& rOriginal, sal_uInt32 nIndex, sal_uInt32 nCount) 624 : maVector(), 625 mnUsedEntries(0L) 626 { 627 TextureData2DVector::const_iterator aStart(rOriginal.maVector.begin()); 628 aStart += nIndex; 629 TextureData2DVector::const_iterator aEnd(aStart); 630 aEnd += nCount; 631 maVector.reserve(nCount); 632 633 for(; aStart != aEnd; aStart++) 634 { 635 if(!aStart->equalZero()) 636 mnUsedEntries++; 637 638 maVector.push_back(*aStart); 639 } 640 } 641 642 ~TextureCoordinate2D() 643 { 644 } 645 646 sal_uInt32 count() const 647 { 648 return maVector.size(); 649 } 650 651 bool operator==(const TextureCoordinate2D& rCandidate) const 652 { 653 return (maVector == rCandidate.maVector); 654 } 655 656 bool isUsed() const 657 { 658 return (0L != mnUsedEntries); 659 } 660 661 const ::basegfx::B2DPoint& getTextureCoordinate(sal_uInt32 nIndex) const 662 { 663 return maVector[nIndex]; 664 } 665 666 void setTextureCoordinate(sal_uInt32 nIndex, const ::basegfx::B2DPoint& rValue) 667 { 668 bool bWasUsed(mnUsedEntries && !maVector[nIndex].equalZero()); 669 bool bIsUsed(!rValue.equalZero()); 670 671 if(bWasUsed) 672 { 673 if(bIsUsed) 674 { 675 maVector[nIndex] = rValue; 676 } 677 else 678 { 679 maVector[nIndex] = ::basegfx::B2DPoint::getEmptyPoint(); 680 mnUsedEntries--; 681 } 682 } 683 else 684 { 685 if(bIsUsed) 686 { 687 maVector[nIndex] = rValue; 688 mnUsedEntries++; 689 } 690 } 691 } 692 693 void insert(sal_uInt32 nIndex, const ::basegfx::B2DPoint& rValue, sal_uInt32 nCount) 694 { 695 if(nCount) 696 { 697 // add nCount copies of rValue 698 TextureData2DVector::iterator aIndex(maVector.begin()); 699 aIndex += nIndex; 700 maVector.insert(aIndex, nCount, rValue); 701 702 if(!rValue.equalZero()) 703 mnUsedEntries += nCount; 704 } 705 } 706 707 void insert(sal_uInt32 nIndex, const TextureCoordinate2D& rSource) 708 { 709 const sal_uInt32 nCount(rSource.maVector.size()); 710 711 if(nCount) 712 { 713 // insert data 714 TextureData2DVector::iterator aIndex(maVector.begin()); 715 aIndex += nIndex; 716 TextureData2DVector::const_iterator aStart(rSource.maVector.begin()); 717 TextureData2DVector::const_iterator aEnd(rSource.maVector.end()); 718 maVector.insert(aIndex, aStart, aEnd); 719 720 for(; aStart != aEnd; aStart++) 721 { 722 if(!aStart->equalZero()) 723 mnUsedEntries++; 724 } 725 } 726 } 727 728 void remove(sal_uInt32 nIndex, sal_uInt32 nCount) 729 { 730 if(nCount) 731 { 732 const TextureData2DVector::iterator aDeleteStart(maVector.begin() + nIndex); 733 const TextureData2DVector::iterator aDeleteEnd(aDeleteStart + nCount); 734 TextureData2DVector::const_iterator aStart(aDeleteStart); 735 736 for(; mnUsedEntries && aStart != aDeleteEnd; aStart++) 737 { 738 if(!aStart->equalZero()) 739 mnUsedEntries--; 740 } 741 742 // remove point data 743 maVector.erase(aDeleteStart, aDeleteEnd); 744 } 745 } 746 747 void flip() 748 { 749 if(maVector.size() > 1) 750 { 751 const sal_uInt32 nHalfSize(maVector.size() >> 1L); 752 TextureData2DVector::iterator aStart(maVector.begin()); 753 TextureData2DVector::iterator aEnd(maVector.end() - 1L); 754 755 for(sal_uInt32 a(0); a < nHalfSize; a++) 756 { 757 ::std::swap(*aStart, *aEnd); 758 aStart++; 759 aEnd--; 760 } 761 } 762 } 763 764 void transform(const ::basegfx::B2DHomMatrix& rMatrix) 765 { 766 TextureData2DVector::iterator aStart(maVector.begin()); 767 TextureData2DVector::iterator aEnd(maVector.end()); 768 769 for(; aStart != aEnd; aStart++) 770 { 771 (*aStart) *= rMatrix; 772 } 773 } 774 }; 775 776 ////////////////////////////////////////////////////////////////////////////// 777 778 class ImplB3DPolygon 779 { 780 // The point vector. This vector exists always and defines the 781 // count of members. 782 CoordinateDataArray3D maPoints; 783 784 // The BColor vector. This vectors are created on demand 785 // and may be zero. 786 BColorArray* mpBColors; 787 788 // The Normals vector. This vectors are created on demand 789 // and may be zero. 790 NormalsArray3D* mpNormals; 791 792 // The TextureCoordinates vector. This vectors are created on demand 793 // and may be zero. 794 TextureCoordinate2D* mpTextureCoordiantes; 795 796 // The calculated plane normal. mbPlaneNormalValid says if it's valid. 797 ::basegfx::B3DVector maPlaneNormal; 798 799 // bitfield 800 // flag which decides if this polygon is opened or closed 801 unsigned mbIsClosed : 1; 802 803 // flag which says if maPlaneNormal is up-to-date 804 unsigned mbPlaneNormalValid : 1; 805 806 protected: 807 void invalidatePlaneNormal() 808 { 809 if(mbPlaneNormalValid) 810 { 811 mbPlaneNormalValid = false; 812 } 813 } 814 815 public: 816 // This constructor is only used from the static identity polygon, thus 817 // the RefCount is set to 1 to never 'delete' this static incarnation. 818 ImplB3DPolygon() 819 : maPoints(0L), 820 mpBColors(0L), 821 mpNormals(0L), 822 mpTextureCoordiantes(0L), 823 maPlaneNormal(::basegfx::B3DVector::getEmptyVector()), 824 mbIsClosed(false), 825 mbPlaneNormalValid(true) 826 { 827 // complete initialization with defaults 828 } 829 830 ImplB3DPolygon(const ImplB3DPolygon& rToBeCopied) 831 : maPoints(rToBeCopied.maPoints), 832 mpBColors(0L), 833 mpNormals(0L), 834 mpTextureCoordiantes(0L), 835 maPlaneNormal(rToBeCopied.maPlaneNormal), 836 mbIsClosed(rToBeCopied.mbIsClosed), 837 mbPlaneNormalValid(rToBeCopied.mbPlaneNormalValid) 838 { 839 // complete initialization using copy 840 if(rToBeCopied.mpBColors && rToBeCopied.mpBColors->isUsed()) 841 { 842 mpBColors = new BColorArray(*rToBeCopied.mpBColors); 843 } 844 845 if(rToBeCopied.mpNormals && rToBeCopied.mpNormals->isUsed()) 846 { 847 mpNormals = new NormalsArray3D(*rToBeCopied.mpNormals); 848 } 849 850 if(rToBeCopied.mpTextureCoordiantes && rToBeCopied.mpTextureCoordiantes->isUsed()) 851 { 852 mpTextureCoordiantes = new TextureCoordinate2D(*rToBeCopied.mpTextureCoordiantes); 853 } 854 } 855 856 ImplB3DPolygon(const ImplB3DPolygon& rToBeCopied, sal_uInt32 nIndex, sal_uInt32 nCount) 857 : maPoints(rToBeCopied.maPoints, nIndex, nCount), 858 mpBColors(0L), 859 mpNormals(0L), 860 mpTextureCoordiantes(0L), 861 maPlaneNormal(::basegfx::B3DVector::getEmptyVector()), 862 mbIsClosed(rToBeCopied.mbIsClosed), 863 mbPlaneNormalValid(false) 864 { 865 // complete initialization using partly copy 866 if(rToBeCopied.mpBColors && rToBeCopied.mpBColors->isUsed()) 867 { 868 mpBColors = new BColorArray(*rToBeCopied.mpBColors, nIndex, nCount); 869 870 if(!mpBColors->isUsed()) 871 { 872 delete mpBColors; 873 mpBColors = 0L; 874 } 875 } 876 877 if(rToBeCopied.mpNormals && rToBeCopied.mpNormals->isUsed()) 878 { 879 mpNormals = new NormalsArray3D(*rToBeCopied.mpNormals, nIndex, nCount); 880 881 if(!mpNormals->isUsed()) 882 { 883 delete mpNormals; 884 mpNormals = 0L; 885 } 886 } 887 888 if(rToBeCopied.mpTextureCoordiantes && rToBeCopied.mpTextureCoordiantes->isUsed()) 889 { 890 mpTextureCoordiantes = new TextureCoordinate2D(*rToBeCopied.mpTextureCoordiantes, nIndex, nCount); 891 892 if(!mpTextureCoordiantes->isUsed()) 893 { 894 delete mpTextureCoordiantes; 895 mpTextureCoordiantes = 0L; 896 } 897 } 898 } 899 900 ~ImplB3DPolygon() 901 { 902 if(mpBColors) 903 { 904 delete mpBColors; 905 mpBColors = 0L; 906 } 907 908 if(mpNormals) 909 { 910 delete mpNormals; 911 mpNormals = 0L; 912 } 913 914 if(mpTextureCoordiantes) 915 { 916 delete mpTextureCoordiantes; 917 mpTextureCoordiantes = 0L; 918 } 919 } 920 921 sal_uInt32 count() const 922 { 923 return maPoints.count(); 924 } 925 926 bool isClosed() const 927 { 928 return mbIsClosed; 929 } 930 931 void setClosed(bool bNew) 932 { 933 if(bNew != (bool)mbIsClosed) 934 { 935 mbIsClosed = bNew; 936 } 937 } 938 939 inline bool impBColorsAreEqual(const ImplB3DPolygon& rCandidate) const 940 { 941 bool bBColorsAreEqual(true); 942 943 if(mpBColors) 944 { 945 if(rCandidate.mpBColors) 946 { 947 bBColorsAreEqual = (*mpBColors == *rCandidate.mpBColors); 948 } 949 else 950 { 951 // candidate has no BColors, so it's assumed all unused. 952 bBColorsAreEqual = !mpBColors->isUsed(); 953 } 954 } 955 else 956 { 957 if(rCandidate.mpBColors) 958 { 959 // we have no TextureCoordiantes, so it's assumed all unused. 960 bBColorsAreEqual = !rCandidate.mpBColors->isUsed(); 961 } 962 } 963 964 return bBColorsAreEqual; 965 } 966 967 inline bool impNormalsAreEqual(const ImplB3DPolygon& rCandidate) const 968 { 969 bool bNormalsAreEqual(true); 970 971 if(mpNormals) 972 { 973 if(rCandidate.mpNormals) 974 { 975 bNormalsAreEqual = (*mpNormals == *rCandidate.mpNormals); 976 } 977 else 978 { 979 // candidate has no normals, so it's assumed all unused. 980 bNormalsAreEqual = !mpNormals->isUsed(); 981 } 982 } 983 else 984 { 985 if(rCandidate.mpNormals) 986 { 987 // we have no normals, so it's assumed all unused. 988 bNormalsAreEqual = !rCandidate.mpNormals->isUsed(); 989 } 990 } 991 992 return bNormalsAreEqual; 993 } 994 995 inline bool impTextureCoordinatesAreEqual(const ImplB3DPolygon& rCandidate) const 996 { 997 bool bTextureCoordinatesAreEqual(true); 998 999 if(mpTextureCoordiantes) 1000 { 1001 if(rCandidate.mpTextureCoordiantes) 1002 { 1003 bTextureCoordinatesAreEqual = (*mpTextureCoordiantes == *rCandidate.mpTextureCoordiantes); 1004 } 1005 else 1006 { 1007 // candidate has no TextureCoordinates, so it's assumed all unused. 1008 bTextureCoordinatesAreEqual = !mpTextureCoordiantes->isUsed(); 1009 } 1010 } 1011 else 1012 { 1013 if(rCandidate.mpTextureCoordiantes) 1014 { 1015 // we have no TextureCoordiantes, so it's assumed all unused. 1016 bTextureCoordinatesAreEqual = !rCandidate.mpTextureCoordiantes->isUsed(); 1017 } 1018 } 1019 1020 return bTextureCoordinatesAreEqual; 1021 } 1022 1023 bool operator==(const ImplB3DPolygon& rCandidate) const 1024 { 1025 if(mbIsClosed == rCandidate.mbIsClosed) 1026 { 1027 if(maPoints == rCandidate.maPoints) 1028 { 1029 if(impBColorsAreEqual(rCandidate)) 1030 { 1031 if(impNormalsAreEqual(rCandidate)) 1032 { 1033 if(impTextureCoordinatesAreEqual(rCandidate)) 1034 { 1035 return true; 1036 } 1037 } 1038 } 1039 } 1040 } 1041 1042 return false; 1043 } 1044 1045 const ::basegfx::B3DPoint& getPoint(sal_uInt32 nIndex) const 1046 { 1047 return maPoints.getCoordinate(nIndex); 1048 } 1049 1050 void setPoint(sal_uInt32 nIndex, const ::basegfx::B3DPoint& rValue) 1051 { 1052 maPoints.setCoordinate(nIndex, rValue); 1053 invalidatePlaneNormal(); 1054 } 1055 1056 void insert(sal_uInt32 nIndex, const ::basegfx::B3DPoint& rPoint, sal_uInt32 nCount) 1057 { 1058 if(nCount) 1059 { 1060 CoordinateData3D aCoordinate(rPoint); 1061 maPoints.insert(nIndex, aCoordinate, nCount); 1062 invalidatePlaneNormal(); 1063 1064 if(mpBColors) 1065 { 1066 mpBColors->insert(nIndex, ::basegfx::BColor::getEmptyBColor(), nCount); 1067 } 1068 1069 if(mpNormals) 1070 { 1071 mpNormals->insert(nIndex, ::basegfx::B3DVector::getEmptyVector(), nCount); 1072 } 1073 1074 if(mpTextureCoordiantes) 1075 { 1076 mpTextureCoordiantes->insert(nIndex, ::basegfx::B2DPoint::getEmptyPoint(), nCount); 1077 } 1078 } 1079 } 1080 1081 const ::basegfx::BColor& getBColor(sal_uInt32 nIndex) const 1082 { 1083 if(mpBColors) 1084 { 1085 return mpBColors->getBColor(nIndex); 1086 } 1087 else 1088 { 1089 return ::basegfx::BColor::getEmptyBColor(); 1090 } 1091 } 1092 1093 void setBColor(sal_uInt32 nIndex, const ::basegfx::BColor& rValue) 1094 { 1095 if(!mpBColors) 1096 { 1097 if(!rValue.equalZero()) 1098 { 1099 mpBColors = new BColorArray(maPoints.count()); 1100 mpBColors->setBColor(nIndex, rValue); 1101 } 1102 } 1103 else 1104 { 1105 mpBColors->setBColor(nIndex, rValue); 1106 1107 if(!mpBColors->isUsed()) 1108 { 1109 delete mpBColors; 1110 mpBColors = 0L; 1111 } 1112 } 1113 } 1114 1115 bool areBColorsUsed() const 1116 { 1117 return (mpBColors && mpBColors->isUsed()); 1118 } 1119 1120 void clearBColors() 1121 { 1122 if(mpBColors) 1123 { 1124 delete mpBColors; 1125 mpBColors = 0L; 1126 } 1127 } 1128 1129 const ::basegfx::B3DVector& getNormal() const 1130 { 1131 if(!mbPlaneNormalValid) 1132 { 1133 const_cast< ImplB3DPolygon* >(this)->maPlaneNormal = maPoints.getNormal(); 1134 const_cast< ImplB3DPolygon* >(this)->mbPlaneNormalValid = true; 1135 } 1136 1137 return maPlaneNormal; 1138 } 1139 1140 const ::basegfx::B3DVector& getNormal(sal_uInt32 nIndex) const 1141 { 1142 if(mpNormals) 1143 { 1144 return mpNormals->getNormal(nIndex); 1145 } 1146 else 1147 { 1148 return ::basegfx::B3DVector::getEmptyVector(); 1149 } 1150 } 1151 1152 void setNormal(sal_uInt32 nIndex, const ::basegfx::B3DVector& rValue) 1153 { 1154 if(!mpNormals) 1155 { 1156 if(!rValue.equalZero()) 1157 { 1158 mpNormals = new NormalsArray3D(maPoints.count()); 1159 mpNormals->setNormal(nIndex, rValue); 1160 } 1161 } 1162 else 1163 { 1164 mpNormals->setNormal(nIndex, rValue); 1165 1166 if(!mpNormals->isUsed()) 1167 { 1168 delete mpNormals; 1169 mpNormals = 0L; 1170 } 1171 } 1172 } 1173 1174 void transformNormals(const ::basegfx::B3DHomMatrix& rMatrix) 1175 { 1176 if(mpNormals) 1177 { 1178 mpNormals->transform(rMatrix); 1179 } 1180 } 1181 1182 bool areNormalsUsed() const 1183 { 1184 return (mpNormals && mpNormals->isUsed()); 1185 } 1186 1187 void clearNormals() 1188 { 1189 if(mpNormals) 1190 { 1191 delete mpNormals; 1192 mpNormals = 0L; 1193 } 1194 } 1195 1196 const ::basegfx::B2DPoint& getTextureCoordinate(sal_uInt32 nIndex) const 1197 { 1198 if(mpTextureCoordiantes) 1199 { 1200 return mpTextureCoordiantes->getTextureCoordinate(nIndex); 1201 } 1202 else 1203 { 1204 return ::basegfx::B2DPoint::getEmptyPoint(); 1205 } 1206 } 1207 1208 void setTextureCoordinate(sal_uInt32 nIndex, const ::basegfx::B2DPoint& rValue) 1209 { 1210 if(!mpTextureCoordiantes) 1211 { 1212 if(!rValue.equalZero()) 1213 { 1214 mpTextureCoordiantes = new TextureCoordinate2D(maPoints.count()); 1215 mpTextureCoordiantes->setTextureCoordinate(nIndex, rValue); 1216 } 1217 } 1218 else 1219 { 1220 mpTextureCoordiantes->setTextureCoordinate(nIndex, rValue); 1221 1222 if(!mpTextureCoordiantes->isUsed()) 1223 { 1224 delete mpTextureCoordiantes; 1225 mpTextureCoordiantes = 0L; 1226 } 1227 } 1228 } 1229 1230 bool areTextureCoordinatesUsed() const 1231 { 1232 return (mpTextureCoordiantes && mpTextureCoordiantes->isUsed()); 1233 } 1234 1235 void clearTextureCoordinates() 1236 { 1237 if(mpTextureCoordiantes) 1238 { 1239 delete mpTextureCoordiantes; 1240 mpTextureCoordiantes = 0L; 1241 } 1242 } 1243 1244 void transformTextureCoordinates(const ::basegfx::B2DHomMatrix& rMatrix) 1245 { 1246 if(mpTextureCoordiantes) 1247 { 1248 mpTextureCoordiantes->transform(rMatrix); 1249 } 1250 } 1251 1252 void insert(sal_uInt32 nIndex, const ImplB3DPolygon& rSource) 1253 { 1254 const sal_uInt32 nCount(rSource.maPoints.count()); 1255 1256 if(nCount) 1257 { 1258 maPoints.insert(nIndex, rSource.maPoints); 1259 invalidatePlaneNormal(); 1260 1261 if(rSource.mpBColors && rSource.mpBColors->isUsed()) 1262 { 1263 if(!mpBColors) 1264 { 1265 mpBColors = new BColorArray(maPoints.count()); 1266 } 1267 1268 mpBColors->insert(nIndex, *rSource.mpBColors); 1269 } 1270 else 1271 { 1272 if(mpBColors) 1273 { 1274 mpBColors->insert(nIndex, ::basegfx::BColor::getEmptyBColor(), nCount); 1275 } 1276 } 1277 1278 if(rSource.mpNormals && rSource.mpNormals->isUsed()) 1279 { 1280 if(!mpNormals) 1281 { 1282 mpNormals = new NormalsArray3D(maPoints.count()); 1283 } 1284 1285 mpNormals->insert(nIndex, *rSource.mpNormals); 1286 } 1287 else 1288 { 1289 if(mpNormals) 1290 { 1291 mpNormals->insert(nIndex, ::basegfx::B3DVector::getEmptyVector(), nCount); 1292 } 1293 } 1294 1295 if(rSource.mpTextureCoordiantes && rSource.mpTextureCoordiantes->isUsed()) 1296 { 1297 if(!mpTextureCoordiantes) 1298 { 1299 mpTextureCoordiantes = new TextureCoordinate2D(maPoints.count()); 1300 } 1301 1302 mpTextureCoordiantes->insert(nIndex, *rSource.mpTextureCoordiantes); 1303 } 1304 else 1305 { 1306 if(mpTextureCoordiantes) 1307 { 1308 mpTextureCoordiantes->insert(nIndex, ::basegfx::B2DPoint::getEmptyPoint(), nCount); 1309 } 1310 } 1311 } 1312 } 1313 1314 void remove(sal_uInt32 nIndex, sal_uInt32 nCount) 1315 { 1316 if(nCount) 1317 { 1318 maPoints.remove(nIndex, nCount); 1319 invalidatePlaneNormal(); 1320 1321 if(mpBColors) 1322 { 1323 mpBColors->remove(nIndex, nCount); 1324 1325 if(!mpBColors->isUsed()) 1326 { 1327 delete mpBColors; 1328 mpBColors = 0L; 1329 } 1330 } 1331 1332 if(mpNormals) 1333 { 1334 mpNormals->remove(nIndex, nCount); 1335 1336 if(!mpNormals->isUsed()) 1337 { 1338 delete mpNormals; 1339 mpNormals = 0L; 1340 } 1341 } 1342 1343 if(mpTextureCoordiantes) 1344 { 1345 mpTextureCoordiantes->remove(nIndex, nCount); 1346 1347 if(!mpTextureCoordiantes->isUsed()) 1348 { 1349 delete mpTextureCoordiantes; 1350 mpTextureCoordiantes = 0L; 1351 } 1352 } 1353 } 1354 } 1355 1356 void flip() 1357 { 1358 if(maPoints.count() > 1) 1359 { 1360 maPoints.flip(); 1361 1362 if(mbPlaneNormalValid) 1363 { 1364 // mirror plane normal 1365 maPlaneNormal = -maPlaneNormal; 1366 } 1367 1368 if(mpBColors) 1369 { 1370 mpBColors->flip(); 1371 } 1372 1373 if(mpNormals) 1374 { 1375 mpNormals->flip(); 1376 } 1377 1378 if(mpTextureCoordiantes) 1379 { 1380 mpTextureCoordiantes->flip(); 1381 } 1382 } 1383 } 1384 1385 bool hasDoublePoints() const 1386 { 1387 if(mbIsClosed) 1388 { 1389 // check for same start and end point 1390 const sal_uInt32 nIndex(maPoints.count() - 1L); 1391 1392 if(maPoints.getCoordinate(0L) == maPoints.getCoordinate(nIndex)) 1393 { 1394 const bool bBColorEqual(!mpBColors || (mpBColors->getBColor(0L) == mpBColors->getBColor(nIndex))); 1395 1396 if(bBColorEqual) 1397 { 1398 const bool bNormalsEqual(!mpNormals || (mpNormals->getNormal(0L) == mpNormals->getNormal(nIndex))); 1399 1400 if(bNormalsEqual) 1401 { 1402 const bool bTextureCoordinatesEqual(!mpTextureCoordiantes || (mpTextureCoordiantes->getTextureCoordinate(0L) == mpTextureCoordiantes->getTextureCoordinate(nIndex))); 1403 1404 if(bTextureCoordinatesEqual) 1405 { 1406 return true; 1407 } 1408 } 1409 } 1410 } 1411 } 1412 1413 // test for range 1414 for(sal_uInt32 a(0L); a < maPoints.count() - 1L; a++) 1415 { 1416 if(maPoints.getCoordinate(a) == maPoints.getCoordinate(a + 1L)) 1417 { 1418 const bool bBColorEqual(!mpBColors || (mpBColors->getBColor(a) == mpBColors->getBColor(a + 1L))); 1419 1420 if(bBColorEqual) 1421 { 1422 const bool bNormalsEqual(!mpNormals || (mpNormals->getNormal(a) == mpNormals->getNormal(a + 1L))); 1423 1424 if(bNormalsEqual) 1425 { 1426 const bool bTextureCoordinatesEqual(!mpTextureCoordiantes || (mpTextureCoordiantes->getTextureCoordinate(a) == mpTextureCoordiantes->getTextureCoordinate(a + 1L))); 1427 1428 if(bTextureCoordinatesEqual) 1429 { 1430 return true; 1431 } 1432 } 1433 } 1434 } 1435 } 1436 1437 return false; 1438 } 1439 1440 void removeDoublePointsAtBeginEnd() 1441 { 1442 // Only remove DoublePoints at Begin and End when poly is closed 1443 if(mbIsClosed) 1444 { 1445 bool bRemove; 1446 1447 do 1448 { 1449 bRemove = false; 1450 1451 if(maPoints.count() > 1L) 1452 { 1453 const sal_uInt32 nIndex(maPoints.count() - 1L); 1454 bRemove = (maPoints.getCoordinate(0L) == maPoints.getCoordinate(nIndex)); 1455 1456 if(bRemove && mpBColors && !(mpBColors->getBColor(0L) == mpBColors->getBColor(nIndex))) 1457 { 1458 bRemove = false; 1459 } 1460 1461 if(bRemove && mpNormals && !(mpNormals->getNormal(0L) == mpNormals->getNormal(nIndex))) 1462 { 1463 bRemove = false; 1464 } 1465 1466 if(bRemove && mpTextureCoordiantes && !(mpTextureCoordiantes->getTextureCoordinate(0L) == mpTextureCoordiantes->getTextureCoordinate(nIndex))) 1467 { 1468 bRemove = false; 1469 } 1470 } 1471 1472 if(bRemove) 1473 { 1474 const sal_uInt32 nIndex(maPoints.count() - 1L); 1475 remove(nIndex, 1L); 1476 } 1477 } while(bRemove); 1478 } 1479 } 1480 1481 void removeDoublePointsWholeTrack() 1482 { 1483 sal_uInt32 nIndex(0L); 1484 1485 // test as long as there are at least two points and as long as the index 1486 // is smaller or equal second last point 1487 while((maPoints.count() > 1L) && (nIndex <= maPoints.count() - 2L)) 1488 { 1489 const sal_uInt32 nNextIndex(nIndex + 1L); 1490 bool bRemove(maPoints.getCoordinate(nIndex) == maPoints.getCoordinate(nNextIndex)); 1491 1492 if(bRemove && mpBColors && !(mpBColors->getBColor(nIndex) == mpBColors->getBColor(nNextIndex))) 1493 { 1494 bRemove = false; 1495 } 1496 1497 if(bRemove && mpNormals && !(mpNormals->getNormal(nIndex) == mpNormals->getNormal(nNextIndex))) 1498 { 1499 bRemove = false; 1500 } 1501 1502 if(bRemove && mpTextureCoordiantes && !(mpTextureCoordiantes->getTextureCoordinate(nIndex) == mpTextureCoordiantes->getTextureCoordinate(nNextIndex))) 1503 { 1504 bRemove = false; 1505 } 1506 1507 if(bRemove) 1508 { 1509 // if next is same as index and the control vectors are unused, delete index 1510 remove(nIndex, 1L); 1511 } 1512 else 1513 { 1514 // if different, step forward 1515 nIndex++; 1516 } 1517 } 1518 } 1519 1520 void transform(const ::basegfx::B3DHomMatrix& rMatrix) 1521 { 1522 maPoints.transform(rMatrix); 1523 1524 // Here, it seems to be possible to transform a valid plane normal and to avoid 1525 // invalidation, but it's not true. If the transformation contains shears or e.g. 1526 // perspective projection, the orthogonality to the transformed plane will not 1527 // be preserved. It may be possible to test that at the matrix to not invalidate in 1528 // all cases or to extract a matrix which does not 'shear' the vector which is 1529 // a normal in this case. As long as this is not sure, i will just invalidate. 1530 invalidatePlaneNormal(); 1531 } 1532 }; 1533 1534 ////////////////////////////////////////////////////////////////////////////// 1535 1536 namespace basegfx 1537 { 1538 namespace { struct DefaultPolygon : public rtl::Static< B3DPolygon::ImplType, 1539 DefaultPolygon > {}; } 1540 1541 B3DPolygon::B3DPolygon() : 1542 mpPolygon(DefaultPolygon::get()) 1543 { 1544 } 1545 1546 B3DPolygon::B3DPolygon(const B3DPolygon& rPolygon) : 1547 mpPolygon(rPolygon.mpPolygon) 1548 { 1549 } 1550 1551 B3DPolygon::B3DPolygon(const B3DPolygon& rPolygon, sal_uInt32 nIndex, sal_uInt32 nCount) : 1552 mpPolygon(ImplB3DPolygon(*rPolygon.mpPolygon, nIndex, nCount)) 1553 { 1554 // TODO(P2): one extra temporary here (cow_wrapper copies 1555 // given ImplB3DPolygon into its internal impl_t wrapper type) 1556 OSL_ENSURE(nIndex + nCount > rPolygon.mpPolygon->count(), "B3DPolygon constructor outside range (!)"); 1557 } 1558 1559 B3DPolygon::~B3DPolygon() 1560 { 1561 } 1562 1563 B3DPolygon& B3DPolygon::operator=(const B3DPolygon& rPolygon) 1564 { 1565 mpPolygon = rPolygon.mpPolygon; 1566 return *this; 1567 } 1568 1569 void B3DPolygon::makeUnique() 1570 { 1571 mpPolygon.make_unique(); 1572 } 1573 1574 bool B3DPolygon::operator==(const B3DPolygon& rPolygon) const 1575 { 1576 if(mpPolygon.same_object(rPolygon.mpPolygon)) 1577 return true; 1578 1579 return (*mpPolygon == *rPolygon.mpPolygon); 1580 } 1581 1582 bool B3DPolygon::operator!=(const B3DPolygon& rPolygon) const 1583 { 1584 return !(*this == rPolygon); 1585 } 1586 1587 sal_uInt32 B3DPolygon::count() const 1588 { 1589 return mpPolygon->count(); 1590 } 1591 1592 basegfx::B3DPoint B3DPolygon::getB3DPoint(sal_uInt32 nIndex) const 1593 { 1594 OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)"); 1595 1596 return mpPolygon->getPoint(nIndex); 1597 } 1598 1599 void B3DPolygon::setB3DPoint(sal_uInt32 nIndex, const basegfx::B3DPoint& rValue) 1600 { 1601 OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)"); 1602 1603 if(getB3DPoint(nIndex) != rValue) 1604 mpPolygon->setPoint(nIndex, rValue); 1605 } 1606 1607 BColor B3DPolygon::getBColor(sal_uInt32 nIndex) const 1608 { 1609 OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)"); 1610 1611 return mpPolygon->getBColor(nIndex); 1612 } 1613 1614 void B3DPolygon::setBColor(sal_uInt32 nIndex, const BColor& rValue) 1615 { 1616 OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)"); 1617 1618 if(mpPolygon->getBColor(nIndex) != rValue) 1619 mpPolygon->setBColor(nIndex, rValue); 1620 } 1621 1622 bool B3DPolygon::areBColorsUsed() const 1623 { 1624 return mpPolygon->areBColorsUsed(); 1625 } 1626 1627 void B3DPolygon::clearBColors() 1628 { 1629 if(mpPolygon->areBColorsUsed()) 1630 mpPolygon->clearBColors(); 1631 } 1632 1633 B3DVector B3DPolygon::getNormal() const 1634 { 1635 return mpPolygon->getNormal(); 1636 } 1637 1638 B3DVector B3DPolygon::getNormal(sal_uInt32 nIndex) const 1639 { 1640 OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)"); 1641 1642 return mpPolygon->getNormal(nIndex); 1643 } 1644 1645 void B3DPolygon::setNormal(sal_uInt32 nIndex, const B3DVector& rValue) 1646 { 1647 OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)"); 1648 1649 if(mpPolygon->getNormal(nIndex) != rValue) 1650 mpPolygon->setNormal(nIndex, rValue); 1651 } 1652 1653 void B3DPolygon::transformNormals(const B3DHomMatrix& rMatrix) 1654 { 1655 if(mpPolygon->areNormalsUsed() && !rMatrix.isIdentity()) 1656 mpPolygon->transformNormals(rMatrix); 1657 } 1658 1659 bool B3DPolygon::areNormalsUsed() const 1660 { 1661 return mpPolygon->areNormalsUsed(); 1662 } 1663 1664 void B3DPolygon::clearNormals() 1665 { 1666 if(mpPolygon->areNormalsUsed()) 1667 mpPolygon->clearNormals(); 1668 } 1669 1670 B2DPoint B3DPolygon::getTextureCoordinate(sal_uInt32 nIndex) const 1671 { 1672 OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)"); 1673 1674 return mpPolygon->getTextureCoordinate(nIndex); 1675 } 1676 1677 void B3DPolygon::setTextureCoordinate(sal_uInt32 nIndex, const B2DPoint& rValue) 1678 { 1679 OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)"); 1680 1681 if(mpPolygon->getTextureCoordinate(nIndex) != rValue) 1682 mpPolygon->setTextureCoordinate(nIndex, rValue); 1683 } 1684 1685 void B3DPolygon::transformTextureCoordiantes(const B2DHomMatrix& rMatrix) 1686 { 1687 if(mpPolygon->areTextureCoordinatesUsed() && !rMatrix.isIdentity()) 1688 mpPolygon->transformTextureCoordinates(rMatrix); 1689 } 1690 1691 bool B3DPolygon::areTextureCoordinatesUsed() const 1692 { 1693 return mpPolygon->areTextureCoordinatesUsed(); 1694 } 1695 1696 void B3DPolygon::clearTextureCoordinates() 1697 { 1698 if(mpPolygon->areTextureCoordinatesUsed()) 1699 mpPolygon->clearTextureCoordinates(); 1700 } 1701 1702 void B3DPolygon::insert(sal_uInt32 nIndex, const ::basegfx::B3DPoint& rPoint, sal_uInt32 nCount) 1703 { 1704 OSL_ENSURE(nIndex <= mpPolygon->count(), "B3DPolygon Insert outside range (!)"); 1705 1706 if(nCount) 1707 mpPolygon->insert(nIndex, rPoint, nCount); 1708 } 1709 1710 void B3DPolygon::append(const basegfx::B3DPoint& rPoint, sal_uInt32 nCount) 1711 { 1712 if(nCount) 1713 mpPolygon->insert(mpPolygon->count(), rPoint, nCount); 1714 } 1715 1716 void B3DPolygon::insert(sal_uInt32 nIndex, const B3DPolygon& rPoly, sal_uInt32 nIndex2, sal_uInt32 nCount) 1717 { 1718 OSL_ENSURE(nIndex <= mpPolygon->count(), "B3DPolygon Insert outside range (!)"); 1719 1720 if(rPoly.count()) 1721 { 1722 if(!nCount) 1723 { 1724 nCount = rPoly.count(); 1725 } 1726 1727 if(0L == nIndex2 && nCount == rPoly.count()) 1728 { 1729 mpPolygon->insert(nIndex, *rPoly.mpPolygon); 1730 } 1731 else 1732 { 1733 OSL_ENSURE(nIndex2 + nCount <= rPoly.mpPolygon->count(), "B3DPolygon Insert outside range (!)"); 1734 ImplB3DPolygon aTempPoly(*rPoly.mpPolygon, nIndex2, nCount); 1735 mpPolygon->insert(nIndex, aTempPoly); 1736 } 1737 } 1738 } 1739 1740 void B3DPolygon::append(const B3DPolygon& rPoly, sal_uInt32 nIndex, sal_uInt32 nCount) 1741 { 1742 if(rPoly.count()) 1743 { 1744 if(!nCount) 1745 { 1746 nCount = rPoly.count(); 1747 } 1748 1749 if(0L == nIndex && nCount == rPoly.count()) 1750 { 1751 mpPolygon->insert(mpPolygon->count(), *rPoly.mpPolygon); 1752 } 1753 else 1754 { 1755 OSL_ENSURE(nIndex + nCount <= rPoly.mpPolygon->count(), "B3DPolygon Append outside range (!)"); 1756 ImplB3DPolygon aTempPoly(*rPoly.mpPolygon, nIndex, nCount); 1757 mpPolygon->insert(mpPolygon->count(), aTempPoly); 1758 } 1759 } 1760 } 1761 1762 void B3DPolygon::remove(sal_uInt32 nIndex, sal_uInt32 nCount) 1763 { 1764 OSL_ENSURE(nIndex + nCount <= mpPolygon->count(), "B3DPolygon Remove outside range (!)"); 1765 1766 if(nCount) 1767 mpPolygon->remove(nIndex, nCount); 1768 } 1769 1770 void B3DPolygon::clear() 1771 { 1772 mpPolygon = DefaultPolygon::get(); 1773 } 1774 1775 bool B3DPolygon::isClosed() const 1776 { 1777 return mpPolygon->isClosed(); 1778 } 1779 1780 void B3DPolygon::setClosed(bool bNew) 1781 { 1782 if(isClosed() != bNew) 1783 mpPolygon->setClosed(bNew); 1784 } 1785 1786 void B3DPolygon::flip() 1787 { 1788 if(count() > 1) 1789 mpPolygon->flip(); 1790 } 1791 1792 bool B3DPolygon::hasDoublePoints() const 1793 { 1794 return (mpPolygon->count() > 1L && mpPolygon->hasDoublePoints()); 1795 } 1796 1797 void B3DPolygon::removeDoublePoints() 1798 { 1799 if(hasDoublePoints()) 1800 { 1801 mpPolygon->removeDoublePointsAtBeginEnd(); 1802 mpPolygon->removeDoublePointsWholeTrack(); 1803 } 1804 } 1805 1806 void B3DPolygon::transform(const basegfx::B3DHomMatrix& rMatrix) 1807 { 1808 if(mpPolygon->count() && !rMatrix.isIdentity()) 1809 { 1810 mpPolygon->transform(rMatrix); 1811 } 1812 } 1813 } // end of namespace basegfx 1814 1815 ////////////////////////////////////////////////////////////////////////////// 1816 // eof 1817