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