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 1831575 : class CoordinateData3D
32 : {
33 : basegfx::B3DPoint maPoint;
34 :
35 : public:
36 0 : CoordinateData3D()
37 0 : : maPoint()
38 : {
39 0 : }
40 :
41 236783 : explicit CoordinateData3D(const basegfx::B3DPoint& rData)
42 236783 : : maPoint(rData)
43 : {
44 236783 : }
45 :
46 1346713 : const basegfx::B3DPoint& getCoordinate() const
47 : {
48 1346713 : 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 161219 : bool operator==(const CoordinateData3D& rData) const
58 : {
59 161219 : return (maPoint == rData.getCoordinate());
60 : }
61 :
62 202765 : void transform(const basegfx::B3DHomMatrix& rMatrix)
63 : {
64 202765 : maPoint *= rMatrix;
65 202765 : }
66 : };
67 :
68 : class CoordinateDataArray3D
69 : {
70 : typedef ::std::vector< CoordinateData3D > CoordinateData3DVector;
71 :
72 : CoordinateData3DVector maVector;
73 :
74 : public:
75 5 : explicit CoordinateDataArray3D(sal_uInt32 nCount)
76 5 : : maVector(nCount)
77 : {
78 5 : }
79 :
80 178941 : explicit CoordinateDataArray3D(const CoordinateDataArray3D& rOriginal)
81 178941 : : maVector(rOriginal.maVector)
82 : {
83 178941 : }
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 178946 : ~CoordinateDataArray3D()
91 178946 : {
92 178946 : }
93 :
94 43908 : ::basegfx::B3DVector getNormal() const
95 : {
96 43908 : ::basegfx::B3DVector aRetval;
97 43908 : const sal_uInt32 nPointCount(maVector.size());
98 :
99 43908 : if(nPointCount > 2)
100 : {
101 43908 : sal_uInt32 nISmallest(0);
102 43908 : sal_uInt32 a(0);
103 43908 : const basegfx::B3DPoint* pSmallest(&maVector[0].getCoordinate());
104 43908 : const basegfx::B3DPoint* pNext(0);
105 43908 : const basegfx::B3DPoint* pPrev(0);
106 :
107 : // To guarantee a correctly oriented point, choose an outmost one
108 : // which then cannot be concave
109 166504 : for(a = 1; a < nPointCount; a++)
110 : {
111 122596 : const basegfx::B3DPoint& rCandidate = maVector[a].getCoordinate();
112 :
113 245192 : if((rCandidate.getX() < pSmallest->getX())
114 78908 : || (rCandidate.getX() == pSmallest->getX() && rCandidate.getY() < pSmallest->getY())
115 200100 : || (rCandidate.getX() == pSmallest->getX() && rCandidate.getY() == pSmallest->getY() && rCandidate.getZ() < pSmallest->getZ()))
116 : {
117 45256 : nISmallest = a;
118 45256 : pSmallest = &rCandidate;
119 : }
120 : }
121 :
122 : // look for a next point different from minimal one
123 45591 : for(a = (nISmallest + 1) % nPointCount; a != nISmallest; a = (a + 1) % nPointCount)
124 : {
125 45591 : const basegfx::B3DPoint& rCandidate = maVector[a].getCoordinate();
126 :
127 45591 : if(!rCandidate.equal(*pSmallest))
128 : {
129 43908 : pNext = &rCandidate;
130 43908 : break;
131 : }
132 : }
133 :
134 : // look for a previous point different from minimal one
135 43908 : for(a = (nISmallest + nPointCount - 1) % nPointCount; a != nISmallest; a = (a + nPointCount - 1) % nPointCount)
136 : {
137 43908 : const basegfx::B3DPoint& rCandidate = maVector[a].getCoordinate();
138 :
139 43908 : if(!rCandidate.equal(*pSmallest))
140 : {
141 43908 : pPrev = &rCandidate;
142 43908 : 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 43908 : if(pNext && pPrev)
149 : {
150 43908 : const basegfx::B3DVector aPrev(*pPrev - *pSmallest);
151 87816 : const basegfx::B3DVector aNext(*pNext - *pSmallest);
152 :
153 43908 : aRetval = cross(aPrev, aNext);
154 87816 : aRetval.normalize();
155 : }
156 : }
157 :
158 43908 : return aRetval;
159 : }
160 :
161 866946 : sal_uInt32 count() const
162 : {
163 866946 : return maVector.size();
164 : }
165 :
166 70952 : bool operator==(const CoordinateDataArray3D& rCandidate) const
167 : {
168 70952 : return (maVector == rCandidate.maVector);
169 : }
170 :
171 929491 : const basegfx::B3DPoint& getCoordinate(sal_uInt32 nIndex) const
172 : {
173 929491 : 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 236783 : void insert(sal_uInt32 nIndex, const CoordinateData3D& rValue, sal_uInt32 nCount)
182 : {
183 236783 : if(nCount)
184 : {
185 : // add nCount copies of rValue
186 236783 : CoordinateData3DVector::iterator aIndex(maVector.begin());
187 236783 : aIndex += nIndex;
188 236783 : maVector.insert(aIndex, nCount, rValue);
189 : }
190 236783 : }
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 7228 : void remove(sal_uInt32 nIndex, sal_uInt32 nCount)
208 : {
209 7228 : if(nCount)
210 : {
211 : // remove point data
212 7228 : CoordinateData3DVector::iterator aStart(maVector.begin());
213 7228 : aStart += nIndex;
214 7228 : const CoordinateData3DVector::iterator aEnd(aStart + nCount);
215 7228 : maVector.erase(aStart, aEnd);
216 : }
217 7228 : }
218 :
219 5618 : void flip()
220 : {
221 5618 : if(maVector.size() > 1)
222 : {
223 5618 : const sal_uInt32 nHalfSize(maVector.size() >> 1L);
224 5618 : CoordinateData3DVector::iterator aStart(maVector.begin());
225 5618 : CoordinateData3DVector::iterator aEnd(maVector.end() - 1L);
226 :
227 14992 : for(sal_uInt32 a(0); a < nHalfSize; a++)
228 : {
229 9374 : ::std::swap(*aStart, *aEnd);
230 9374 : ++aStart;
231 9374 : --aEnd;
232 : }
233 : }
234 5618 : }
235 :
236 58164 : void transform(const ::basegfx::B3DHomMatrix& rMatrix)
237 : {
238 58164 : CoordinateData3DVector::iterator aStart(maVector.begin());
239 58164 : CoordinateData3DVector::iterator aEnd(maVector.end());
240 :
241 260929 : for(; aStart != aEnd; ++aStart)
242 : {
243 202765 : aStart->transform(rMatrix);
244 : }
245 58164 : }
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 164 : explicit BColorArray(sal_uInt32 nCount)
257 : : maVector(nCount),
258 164 : mnUsedEntries(0L)
259 : {
260 164 : }
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 164 : ~BColorArray()
289 164 : {
290 164 : }
291 :
292 0 : bool operator==(const BColorArray& rCandidate) const
293 : {
294 0 : return (maVector == rCandidate.maVector);
295 : }
296 :
297 1312 : bool isUsed() const
298 : {
299 1312 : return (0L != mnUsedEntries);
300 : }
301 :
302 1804 : const ::basegfx::BColor& getBColor(sal_uInt32 nIndex) const
303 : {
304 1804 : return maVector[nIndex];
305 : }
306 :
307 656 : void setBColor(sal_uInt32 nIndex, const ::basegfx::BColor& rValue)
308 : {
309 656 : bool bWasUsed(mnUsedEntries && !maVector[nIndex].equalZero());
310 656 : bool bIsUsed(!rValue.equalZero());
311 :
312 656 : 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 656 : if(bIsUsed)
327 : {
328 656 : maVector[nIndex] = rValue;
329 656 : mnUsedEntries++;
330 : }
331 : }
332 656 : }
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 77719 : explicit NormalsArray3D(sal_uInt32 nCount)
415 : : maVector(nCount),
416 77719 : mnUsedEntries(0L)
417 : {
418 77719 : }
419 :
420 53094 : explicit NormalsArray3D(const NormalsArray3D& rOriginal)
421 : : maVector(rOriginal.maVector),
422 53094 : mnUsedEntries(rOriginal.mnUsedEntries)
423 : {
424 53094 : }
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 130813 : ~NormalsArray3D()
446 130813 : {
447 130813 : }
448 :
449 19010 : bool operator==(const NormalsArray3D& rCandidate) const
450 : {
451 19010 : return (maVector == rCandidate.maVector);
452 : }
453 :
454 362443 : bool isUsed() const
455 : {
456 362443 : return (0L != mnUsedEntries);
457 : }
458 :
459 258317 : const ::basegfx::B3DVector& getNormal(sal_uInt32 nIndex) const
460 : {
461 258317 : return maVector[nIndex];
462 : }
463 :
464 218645 : void setNormal(sal_uInt32 nIndex, const ::basegfx::B3DVector& rValue)
465 : {
466 218645 : bool bWasUsed(mnUsedEntries && !maVector[nIndex].equalZero());
467 218645 : bool bIsUsed(!rValue.equalZero());
468 :
469 218645 : if(bWasUsed)
470 : {
471 12904 : if(bIsUsed)
472 : {
473 12904 : maVector[nIndex] = rValue;
474 : }
475 : else
476 : {
477 0 : maVector[nIndex] = ::basegfx::B3DVector::getEmptyVector();
478 0 : mnUsedEntries--;
479 : }
480 : }
481 : else
482 : {
483 205741 : if(bIsUsed)
484 : {
485 205741 : maVector[nIndex] = rValue;
486 205741 : mnUsedEntries++;
487 : }
488 : }
489 218645 : }
490 :
491 400 : void insert(sal_uInt32 nIndex, const ::basegfx::B3DVector& rValue, sal_uInt32 nCount)
492 : {
493 400 : if(nCount)
494 : {
495 : // add nCount copies of rValue
496 400 : NormalsData3DVector::iterator aIndex(maVector.begin());
497 400 : aIndex += nIndex;
498 400 : maVector.insert(aIndex, nCount, rValue);
499 :
500 400 : if(!rValue.equalZero())
501 0 : mnUsedEntries += nCount;
502 : }
503 400 : }
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 3756 : void flip()
546 : {
547 3756 : if(maVector.size() > 1)
548 : {
549 3756 : const sal_uInt32 nHalfSize(maVector.size() >> 1L);
550 3756 : NormalsData3DVector::iterator aStart(maVector.begin());
551 3756 : NormalsData3DVector::iterator aEnd(maVector.end() - 1L);
552 :
553 11268 : for(sal_uInt32 a(0); a < nHalfSize; a++)
554 : {
555 7512 : ::std::swap(*aStart, *aEnd);
556 7512 : ++aStart;
557 7512 : --aEnd;
558 : }
559 : }
560 3756 : }
561 :
562 164 : void transform(const basegfx::B3DHomMatrix& rMatrix)
563 : {
564 164 : const NormalsData3DVector::const_iterator aEnd(maVector.end());
565 :
566 820 : for(NormalsData3DVector::iterator aStart(maVector.begin()); aStart != aEnd; ++aStart)
567 : {
568 656 : (*aStart) *= rMatrix;
569 : }
570 164 : }
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 11821 : explicit TextureCoordinate2D(sal_uInt32 nCount)
582 : : maVector(nCount),
583 11821 : mnUsedEntries(0L)
584 : {
585 11821 : }
586 :
587 4773 : explicit TextureCoordinate2D(const TextureCoordinate2D& rOriginal)
588 : : maVector(rOriginal.maVector),
589 4773 : mnUsedEntries(rOriginal.mnUsedEntries)
590 : {
591 4773 : }
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 16594 : ~TextureCoordinate2D()
613 16594 : {
614 16594 : }
615 :
616 3496 : bool operator==(const TextureCoordinate2D& rCandidate) const
617 : {
618 3496 : return (maVector == rCandidate.maVector);
619 : }
620 :
621 65151 : bool isUsed() const
622 : {
623 65151 : return (0L != mnUsedEntries);
624 : }
625 :
626 36195 : const ::basegfx::B2DPoint& getTextureCoordinate(sal_uInt32 nIndex) const
627 : {
628 36195 : return maVector[nIndex];
629 : }
630 :
631 42903 : void setTextureCoordinate(sal_uInt32 nIndex, const ::basegfx::B2DPoint& rValue)
632 : {
633 42903 : bool bWasUsed(mnUsedEntries && !maVector[nIndex].equalZero());
634 42903 : bool bIsUsed(!rValue.equalZero());
635 :
636 42903 : if(bWasUsed)
637 : {
638 0 : if(bIsUsed)
639 : {
640 0 : maVector[nIndex] = rValue;
641 : }
642 : else
643 : {
644 0 : maVector[nIndex] = ::basegfx::B2DPoint::getEmptyPoint();
645 0 : mnUsedEntries--;
646 : }
647 : }
648 : else
649 : {
650 42903 : if(bIsUsed)
651 : {
652 42903 : maVector[nIndex] = rValue;
653 42903 : mnUsedEntries++;
654 : }
655 : }
656 42903 : }
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 3679 : void flip()
713 : {
714 3679 : if(maVector.size() > 1)
715 : {
716 3679 : const sal_uInt32 nHalfSize(maVector.size() >> 1L);
717 3679 : TextureData2DVector::iterator aStart(maVector.begin());
718 3679 : TextureData2DVector::iterator aEnd(maVector.end() - 1L);
719 :
720 11037 : for(sal_uInt32 a(0); a < nHalfSize; a++)
721 : {
722 7358 : ::std::swap(*aStart, *aEnd);
723 7358 : ++aStart;
724 7358 : --aEnd;
725 : }
726 : }
727 3679 : }
728 :
729 15957 : void transform(const ::basegfx::B2DHomMatrix& rMatrix)
730 : {
731 15957 : const TextureData2DVector::const_iterator aEnd(maVector.end());
732 :
733 79785 : for(TextureData2DVector::iterator aStart(maVector.begin()); aStart != aEnd; ++aStart)
734 : {
735 63828 : (*aStart) *= rMatrix;
736 : }
737 15957 : }
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 302175 : void invalidatePlaneNormal()
770 : {
771 302175 : if(mbPlaneNormalValid)
772 : {
773 84944 : mbPlaneNormalValid = false;
774 : }
775 302175 : }
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 5 : ImplB3DPolygon()
781 : : maPoints(0L),
782 : mpBColors(0L),
783 : mpNormals(0L),
784 : mpTextureCoordiantes(0L),
785 5 : maPlaneNormal(::basegfx::B3DVector::getEmptyVector()),
786 : mbIsClosed(false),
787 10 : mbPlaneNormalValid(true)
788 : {
789 : // complete initialization with defaults
790 5 : }
791 :
792 178941 : 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 178941 : mbPlaneNormalValid(rToBeCopied.mbPlaneNormalValid)
800 : {
801 : // complete initialization using copy
802 178941 : if(rToBeCopied.mpBColors && rToBeCopied.mpBColors->isUsed())
803 : {
804 0 : mpBColors = new BColorArray(*rToBeCopied.mpBColors);
805 : }
806 :
807 178941 : if(rToBeCopied.mpNormals && rToBeCopied.mpNormals->isUsed())
808 : {
809 53094 : mpNormals = new NormalsArray3D(*rToBeCopied.mpNormals);
810 : }
811 :
812 178941 : if(rToBeCopied.mpTextureCoordiantes && rToBeCopied.mpTextureCoordiantes->isUsed())
813 : {
814 4773 : mpTextureCoordiantes = new TextureCoordinate2D(*rToBeCopied.mpTextureCoordiantes);
815 : }
816 178941 : }
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 178946 : ~ImplB3DPolygon()
863 178946 : {
864 178946 : if(mpBColors)
865 : {
866 164 : delete mpBColors;
867 164 : mpBColors = 0L;
868 : }
869 :
870 178946 : if(mpNormals)
871 : {
872 94055 : delete mpNormals;
873 94055 : mpNormals = 0L;
874 : }
875 :
876 178946 : if(mpTextureCoordiantes)
877 : {
878 12480 : delete mpTextureCoordiantes;
879 12480 : mpTextureCoordiantes = 0L;
880 : }
881 178946 : }
882 :
883 757656 : sal_uInt32 count() const
884 : {
885 757656 : return maPoints.count();
886 : }
887 :
888 104567 : bool isClosed() const
889 : {
890 104567 : return mbIsClosed;
891 : }
892 :
893 40936 : void setClosed(bool bNew)
894 : {
895 40936 : if(bNew != (bool)mbIsClosed)
896 : {
897 40936 : mbIsClosed = bNew;
898 : }
899 40936 : }
900 :
901 70832 : inline bool impBColorsAreEqual(const ImplB3DPolygon& rCandidate) const
902 : {
903 70832 : bool bBColorsAreEqual(true);
904 :
905 70832 : 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 70832 : if(rCandidate.mpBColors)
920 : {
921 : // we have no TextureCoordiantes, so it's assumed all unused.
922 164 : bBColorsAreEqual = !rCandidate.mpBColors->isUsed();
923 : }
924 : }
925 :
926 70832 : return bBColorsAreEqual;
927 : }
928 :
929 70668 : inline bool impNormalsAreEqual(const ImplB3DPolygon& rCandidate) const
930 : {
931 70668 : bool bNormalsAreEqual(true);
932 :
933 70668 : if(mpNormals)
934 : {
935 19010 : if(rCandidate.mpNormals)
936 : {
937 19010 : 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 51658 : if(rCandidate.mpNormals)
948 : {
949 : // we have no normals, so it's assumed all unused.
950 50067 : bNormalsAreEqual = !rCandidate.mpNormals->isUsed();
951 : }
952 : }
953 :
954 70668 : return bNormalsAreEqual;
955 : }
956 :
957 14303 : inline bool impTextureCoordinatesAreEqual(const ImplB3DPolygon& rCandidate) const
958 : {
959 14303 : bool bTextureCoordinatesAreEqual(true);
960 :
961 14303 : if(mpTextureCoordiantes)
962 : {
963 3496 : if(rCandidate.mpTextureCoordiantes)
964 : {
965 3496 : 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 10807 : 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 14303 : return bTextureCoordinatesAreEqual;
983 : }
984 :
985 70952 : bool operator==(const ImplB3DPolygon& rCandidate) const
986 : {
987 70952 : if(mbIsClosed == rCandidate.mbIsClosed)
988 : {
989 70952 : if(maPoints == rCandidate.maPoints)
990 : {
991 70832 : if(impBColorsAreEqual(rCandidate))
992 : {
993 70668 : if(impNormalsAreEqual(rCandidate))
994 : {
995 14303 : if(impTextureCoordinatesAreEqual(rCandidate))
996 : {
997 14303 : return true;
998 : }
999 : }
1000 : }
1001 : }
1002 : }
1003 :
1004 56649 : return false;
1005 : }
1006 :
1007 914131 : const ::basegfx::B3DPoint& getPoint(sal_uInt32 nIndex) const
1008 : {
1009 914131 : 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 236783 : void insert(sal_uInt32 nIndex, const ::basegfx::B3DPoint& rPoint, sal_uInt32 nCount)
1019 : {
1020 236783 : if(nCount)
1021 : {
1022 236783 : CoordinateData3D aCoordinate(rPoint);
1023 236783 : maPoints.insert(nIndex, aCoordinate, nCount);
1024 236783 : invalidatePlaneNormal();
1025 :
1026 236783 : if(mpBColors)
1027 : {
1028 0 : mpBColors->insert(nIndex, ::basegfx::BColor::getEmptyBColor(), nCount);
1029 : }
1030 :
1031 236783 : if(mpNormals)
1032 : {
1033 400 : mpNormals->insert(nIndex, ::basegfx::B3DVector::getEmptyVector(), nCount);
1034 : }
1035 :
1036 236783 : if(mpTextureCoordiantes)
1037 : {
1038 0 : mpTextureCoordiantes->insert(nIndex, ::basegfx::B2DPoint::getEmptyPoint(), nCount);
1039 236783 : }
1040 : }
1041 236783 : }
1042 :
1043 1968 : const ::basegfx::BColor& getBColor(sal_uInt32 nIndex) const
1044 : {
1045 1968 : if(mpBColors)
1046 : {
1047 1804 : return mpBColors->getBColor(nIndex);
1048 : }
1049 : else
1050 : {
1051 164 : return ::basegfx::BColor::getEmptyBColor();
1052 : }
1053 : }
1054 :
1055 656 : void setBColor(sal_uInt32 nIndex, const ::basegfx::BColor& rValue)
1056 : {
1057 656 : if(!mpBColors)
1058 : {
1059 164 : if(!rValue.equalZero())
1060 : {
1061 164 : mpBColors = new BColorArray(maPoints.count());
1062 164 : mpBColors->setBColor(nIndex, rValue);
1063 : }
1064 : }
1065 : else
1066 : {
1067 492 : mpBColors->setBColor(nIndex, rValue);
1068 :
1069 492 : if(!mpBColors->isUsed())
1070 : {
1071 0 : delete mpBColors;
1072 0 : mpBColors = 0L;
1073 : }
1074 : }
1075 656 : }
1076 :
1077 65022 : bool areBColorsUsed() const
1078 : {
1079 65022 : 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 73827 : const ::basegfx::B3DVector& getNormal() const
1092 : {
1093 73827 : if(!mbPlaneNormalValid)
1094 : {
1095 43908 : const_cast< ImplB3DPolygon* >(this)->maPlaneNormal = maPoints.getNormal();
1096 43908 : const_cast< ImplB3DPolygon* >(this)->mbPlaneNormalValid = true;
1097 : }
1098 :
1099 73827 : return maPlaneNormal;
1100 : }
1101 :
1102 336036 : const ::basegfx::B3DVector& getNormal(sal_uInt32 nIndex) const
1103 : {
1104 336036 : if(mpNormals)
1105 : {
1106 258317 : return mpNormals->getNormal(nIndex);
1107 : }
1108 : else
1109 : {
1110 77719 : return ::basegfx::B3DVector::getEmptyVector();
1111 : }
1112 : }
1113 :
1114 218645 : void setNormal(sal_uInt32 nIndex, const ::basegfx::B3DVector& rValue)
1115 : {
1116 218645 : if(!mpNormals)
1117 : {
1118 77719 : if(!rValue.equalZero())
1119 : {
1120 77719 : mpNormals = new NormalsArray3D(maPoints.count());
1121 77719 : mpNormals->setNormal(nIndex, rValue);
1122 : }
1123 : }
1124 : else
1125 : {
1126 140926 : mpNormals->setNormal(nIndex, rValue);
1127 :
1128 140926 : if(!mpNormals->isUsed())
1129 : {
1130 0 : delete mpNormals;
1131 0 : mpNormals = 0L;
1132 : }
1133 : }
1134 218645 : }
1135 :
1136 164 : void transformNormals(const ::basegfx::B3DHomMatrix& rMatrix)
1137 : {
1138 164 : if(mpNormals)
1139 : {
1140 164 : mpNormals->transform(rMatrix);
1141 : }
1142 164 : }
1143 :
1144 147880 : bool areNormalsUsed() const
1145 : {
1146 147880 : return (mpNormals && mpNormals->isUsed());
1147 : }
1148 :
1149 36758 : void clearNormals()
1150 : {
1151 36758 : if(mpNormals)
1152 : {
1153 36758 : delete mpNormals;
1154 36758 : mpNormals = 0L;
1155 : }
1156 36758 : }
1157 :
1158 50924 : const ::basegfx::B2DPoint& getTextureCoordinate(sal_uInt32 nIndex) const
1159 : {
1160 50924 : if(mpTextureCoordiantes)
1161 : {
1162 36195 : return mpTextureCoordiantes->getTextureCoordinate(nIndex);
1163 : }
1164 : else
1165 : {
1166 14729 : return ::basegfx::B2DPoint::getEmptyPoint();
1167 : }
1168 : }
1169 :
1170 42903 : void setTextureCoordinate(sal_uInt32 nIndex, const ::basegfx::B2DPoint& rValue)
1171 : {
1172 42903 : if(!mpTextureCoordiantes)
1173 : {
1174 11821 : if(!rValue.equalZero())
1175 : {
1176 11821 : mpTextureCoordiantes = new TextureCoordinate2D(maPoints.count());
1177 11821 : mpTextureCoordiantes->setTextureCoordinate(nIndex, rValue);
1178 : }
1179 : }
1180 : else
1181 : {
1182 31082 : mpTextureCoordiantes->setTextureCoordinate(nIndex, rValue);
1183 :
1184 31082 : if(!mpTextureCoordiantes->isUsed())
1185 : {
1186 0 : delete mpTextureCoordiantes;
1187 0 : mpTextureCoordiantes = 0L;
1188 : }
1189 : }
1190 42903 : }
1191 :
1192 89963 : bool areTextureCoordinatesUsed() const
1193 : {
1194 89963 : return (mpTextureCoordiantes && mpTextureCoordiantes->isUsed());
1195 : }
1196 :
1197 4114 : void clearTextureCoordinates()
1198 : {
1199 4114 : if(mpTextureCoordiantes)
1200 : {
1201 4114 : delete mpTextureCoordiantes;
1202 4114 : mpTextureCoordiantes = 0L;
1203 : }
1204 4114 : }
1205 :
1206 15957 : void transformTextureCoordinates(const ::basegfx::B2DHomMatrix& rMatrix)
1207 : {
1208 15957 : if(mpTextureCoordiantes)
1209 : {
1210 15957 : mpTextureCoordiantes->transform(rMatrix);
1211 : }
1212 15957 : }
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 7228 : void remove(sal_uInt32 nIndex, sal_uInt32 nCount)
1277 : {
1278 7228 : if(nCount)
1279 : {
1280 7228 : maPoints.remove(nIndex, nCount);
1281 7228 : invalidatePlaneNormal();
1282 :
1283 7228 : 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 7228 : 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 7228 : 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 7228 : }
1317 :
1318 5618 : void flip()
1319 : {
1320 5618 : if(maPoints.count() > 1)
1321 : {
1322 5618 : maPoints.flip();
1323 :
1324 5618 : if(mbPlaneNormalValid)
1325 : {
1326 : // mirror plane normal
1327 77 : maPlaneNormal = -maPlaneNormal;
1328 : }
1329 :
1330 5618 : if(mpBColors)
1331 : {
1332 0 : mpBColors->flip();
1333 : }
1334 :
1335 5618 : if(mpNormals)
1336 : {
1337 3756 : mpNormals->flip();
1338 : }
1339 :
1340 5618 : if(mpTextureCoordiantes)
1341 : {
1342 3679 : mpTextureCoordiantes->flip();
1343 : }
1344 : }
1345 5618 : }
1346 :
1347 240 : bool hasDoublePoints() const
1348 : {
1349 240 : if(mbIsClosed)
1350 : {
1351 : // check for same start and end point
1352 240 : const sal_uInt32 nIndex(maPoints.count() - 1L);
1353 :
1354 240 : if(maPoints.getCoordinate(0L) == maPoints.getCoordinate(nIndex))
1355 : {
1356 96 : const bool bBColorEqual(!mpBColors || (mpBColors->getBColor(0L) == mpBColors->getBColor(nIndex)));
1357 :
1358 96 : if(bBColorEqual)
1359 : {
1360 96 : const bool bNormalsEqual(!mpNormals || (mpNormals->getNormal(0L) == mpNormals->getNormal(nIndex)));
1361 :
1362 96 : if(bNormalsEqual)
1363 : {
1364 96 : const bool bTextureCoordinatesEqual(!mpTextureCoordiantes || (mpTextureCoordiantes->getTextureCoordinate(0L) == mpTextureCoordiantes->getTextureCoordinate(nIndex)));
1365 :
1366 96 : if(bTextureCoordinatesEqual)
1367 : {
1368 96 : return true;
1369 : }
1370 : }
1371 : }
1372 : }
1373 : }
1374 :
1375 : // test for range
1376 4608 : for(sal_uInt32 a(0L); a < maPoints.count() - 1L; a++)
1377 : {
1378 4464 : 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 144 : return false;
1400 : }
1401 :
1402 96 : void removeDoublePointsAtBeginEnd()
1403 : {
1404 : // Only remove DoublePoints at Begin and End when poly is closed
1405 96 : if(mbIsClosed)
1406 : {
1407 : bool bRemove;
1408 :
1409 3072 : do
1410 : {
1411 3072 : bRemove = false;
1412 :
1413 3072 : if(maPoints.count() > 1L)
1414 : {
1415 2976 : const sal_uInt32 nIndex(maPoints.count() - 1L);
1416 2976 : bRemove = (maPoints.getCoordinate(0L) == maPoints.getCoordinate(nIndex));
1417 :
1418 2976 : if(bRemove && mpBColors && !(mpBColors->getBColor(0L) == mpBColors->getBColor(nIndex)))
1419 : {
1420 0 : bRemove = false;
1421 : }
1422 :
1423 2976 : if(bRemove && mpNormals && !(mpNormals->getNormal(0L) == mpNormals->getNormal(nIndex)))
1424 : {
1425 0 : bRemove = false;
1426 : }
1427 :
1428 2976 : if(bRemove && mpTextureCoordiantes && !(mpTextureCoordiantes->getTextureCoordinate(0L) == mpTextureCoordiantes->getTextureCoordinate(nIndex)))
1429 : {
1430 0 : bRemove = false;
1431 : }
1432 : }
1433 :
1434 3072 : if(bRemove)
1435 : {
1436 2976 : const sal_uInt32 nIndex(maPoints.count() - 1L);
1437 2976 : remove(nIndex, 1L);
1438 : }
1439 : } while(bRemove);
1440 : }
1441 96 : }
1442 :
1443 96 : void removeDoublePointsWholeTrack()
1444 : {
1445 96 : 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 192 : 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 96 : }
1481 :
1482 58164 : void transform(const ::basegfx::B3DHomMatrix& rMatrix)
1483 : {
1484 58164 : 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 58164 : invalidatePlaneNormal();
1493 58164 : }
1494 : };
1495 :
1496 : namespace basegfx
1497 : {
1498 : namespace { struct DefaultPolygon : public rtl::Static< B3DPolygon::ImplType,
1499 : DefaultPolygon > {}; }
1500 :
1501 59842 : B3DPolygon::B3DPolygon() :
1502 59842 : mpPolygon(DefaultPolygon::get())
1503 : {
1504 59842 : }
1505 :
1506 695904 : B3DPolygon::B3DPolygon(const B3DPolygon& rPolygon) :
1507 695904 : mpPolygon(rPolygon.mpPolygon)
1508 : {
1509 695904 : }
1510 :
1511 755746 : B3DPolygon::~B3DPolygon()
1512 : {
1513 755746 : }
1514 :
1515 60208 : B3DPolygon& B3DPolygon::operator=(const B3DPolygon& rPolygon)
1516 : {
1517 60208 : mpPolygon = rPolygon.mpPolygon;
1518 60208 : return *this;
1519 : }
1520 :
1521 73682 : bool B3DPolygon::operator==(const B3DPolygon& rPolygon) const
1522 : {
1523 73682 : if(mpPolygon.same_object(rPolygon.mpPolygon))
1524 2730 : return true;
1525 :
1526 70952 : return (*mpPolygon == *rPolygon.mpPolygon);
1527 : }
1528 :
1529 65937 : bool B3DPolygon::operator!=(const B3DPolygon& rPolygon) const
1530 : {
1531 65937 : return !(*this == rPolygon);
1532 : }
1533 :
1534 462469 : sal_uInt32 B3DPolygon::count() const
1535 : {
1536 462469 : return mpPolygon->count();
1537 : }
1538 :
1539 914131 : basegfx::B3DPoint B3DPolygon::getB3DPoint(sal_uInt32 nIndex) const
1540 : {
1541 : OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)");
1542 :
1543 914131 : 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 1312 : BColor B3DPolygon::getBColor(sal_uInt32 nIndex) const
1555 : {
1556 : OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)");
1557 :
1558 1312 : return mpPolygon->getBColor(nIndex);
1559 : }
1560 :
1561 656 : void B3DPolygon::setBColor(sal_uInt32 nIndex, const BColor& rValue)
1562 : {
1563 : OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)");
1564 :
1565 656 : if(mpPolygon->getBColor(nIndex) != rValue)
1566 656 : mpPolygon->setBColor(nIndex, rValue);
1567 656 : }
1568 :
1569 64904 : bool B3DPolygon::areBColorsUsed() const
1570 : {
1571 64904 : return mpPolygon->areBColorsUsed();
1572 : }
1573 :
1574 118 : void B3DPolygon::clearBColors()
1575 : {
1576 118 : if(mpPolygon->areBColorsUsed())
1577 0 : mpPolygon->clearBColors();
1578 118 : }
1579 :
1580 73827 : B3DVector B3DPolygon::getNormal() const
1581 : {
1582 73827 : return mpPolygon->getNormal();
1583 : }
1584 :
1585 95280 : B3DVector B3DPolygon::getNormal(sal_uInt32 nIndex) const
1586 : {
1587 : OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)");
1588 :
1589 95280 : return mpPolygon->getNormal(nIndex);
1590 : }
1591 :
1592 240756 : void B3DPolygon::setNormal(sal_uInt32 nIndex, const B3DVector& rValue)
1593 : {
1594 : OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)");
1595 :
1596 240756 : if(mpPolygon->getNormal(nIndex) != rValue)
1597 218645 : mpPolygon->setNormal(nIndex, rValue);
1598 240756 : }
1599 :
1600 164 : void B3DPolygon::transformNormals(const B3DHomMatrix& rMatrix)
1601 : {
1602 164 : if(mpPolygon->areNormalsUsed() && !rMatrix.isIdentity())
1603 164 : mpPolygon->transformNormals(rMatrix);
1604 164 : }
1605 :
1606 110840 : bool B3DPolygon::areNormalsUsed() const
1607 : {
1608 110840 : return mpPolygon->areNormalsUsed();
1609 : }
1610 :
1611 36876 : void B3DPolygon::clearNormals()
1612 : {
1613 36876 : if(mpPolygon->areNormalsUsed())
1614 36758 : mpPolygon->clearNormals();
1615 36876 : }
1616 :
1617 3640 : B2DPoint B3DPolygon::getTextureCoordinate(sal_uInt32 nIndex) const
1618 : {
1619 : OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)");
1620 :
1621 3640 : return mpPolygon->getTextureCoordinate(nIndex);
1622 : }
1623 :
1624 47284 : void B3DPolygon::setTextureCoordinate(sal_uInt32 nIndex, const B2DPoint& rValue)
1625 : {
1626 : OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)");
1627 :
1628 47284 : if(mpPolygon->getTextureCoordinate(nIndex) != rValue)
1629 42903 : mpPolygon->setTextureCoordinate(nIndex, rValue);
1630 47284 : }
1631 :
1632 15957 : void B3DPolygon::transformTextureCoordiantes(const B2DHomMatrix& rMatrix)
1633 : {
1634 15957 : if(mpPolygon->areTextureCoordinatesUsed() && !rMatrix.isIdentity())
1635 15957 : mpPolygon->transformTextureCoordinates(rMatrix);
1636 15957 : }
1637 :
1638 69774 : bool B3DPolygon::areTextureCoordinatesUsed() const
1639 : {
1640 69774 : return mpPolygon->areTextureCoordinatesUsed();
1641 : }
1642 :
1643 4232 : void B3DPolygon::clearTextureCoordinates()
1644 : {
1645 4232 : if(mpPolygon->areTextureCoordinatesUsed())
1646 4114 : mpPolygon->clearTextureCoordinates();
1647 4232 : }
1648 :
1649 236783 : void B3DPolygon::append(const basegfx::B3DPoint& rPoint, sal_uInt32 nCount)
1650 : {
1651 236783 : if(nCount)
1652 236783 : mpPolygon->insert(mpPolygon->count(), rPoint, nCount);
1653 236783 : }
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 4252 : void B3DPolygon::remove(sal_uInt32 nIndex, sal_uInt32 nCount)
1678 : {
1679 : OSL_ENSURE(nIndex + nCount <= mpPolygon->count(), "B3DPolygon Remove outside range (!)");
1680 :
1681 4252 : if(nCount)
1682 4252 : mpPolygon->remove(nIndex, nCount);
1683 4252 : }
1684 :
1685 18432 : void B3DPolygon::clear()
1686 : {
1687 18432 : mpPolygon = DefaultPolygon::get();
1688 18432 : }
1689 :
1690 104567 : bool B3DPolygon::isClosed() const
1691 : {
1692 104567 : return mpPolygon->isClosed();
1693 : }
1694 :
1695 52332 : void B3DPolygon::setClosed(bool bNew)
1696 : {
1697 52332 : if(isClosed() != bNew)
1698 40936 : mpPolygon->setClosed(bNew);
1699 52332 : }
1700 :
1701 9342 : void B3DPolygon::flip()
1702 : {
1703 9342 : if(count() > 1)
1704 5618 : mpPolygon->flip();
1705 9342 : }
1706 :
1707 240 : bool B3DPolygon::hasDoublePoints() const
1708 : {
1709 240 : return (mpPolygon->count() > 1L && mpPolygon->hasDoublePoints());
1710 : }
1711 :
1712 240 : void B3DPolygon::removeDoublePoints()
1713 : {
1714 240 : if(hasDoublePoints())
1715 : {
1716 96 : mpPolygon->removeDoublePointsAtBeginEnd();
1717 96 : mpPolygon->removeDoublePointsWholeTrack();
1718 : }
1719 240 : }
1720 :
1721 58164 : void B3DPolygon::transform(const basegfx::B3DHomMatrix& rMatrix)
1722 : {
1723 58164 : if(mpPolygon->count() && !rMatrix.isIdentity())
1724 : {
1725 58164 : mpPolygon->transform(rMatrix);
1726 : }
1727 58164 : }
1728 : } // end of namespace basegfx
1729 :
1730 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|