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