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