1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: _xpoly.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svx.hxx"
33 #include <osl/endian.h>
34 #include <tools/stream.hxx>
35 #include <tools/debug.hxx>
36 #include <tools/poly.hxx>
38 #include <svx/xpoly.hxx>
39 #include "xpolyimp.hxx"
40 #include <basegfx/polygon/b2dpolygon.hxx>
41 #include <basegfx/point/b2dpoint.hxx>
42 #include <basegfx/vector/b2dvector.hxx>
43 #include <basegfx/polygon/b2dpolygontools.hxx>
44 #include <vcl/salbtype.hxx> // FRound
45 #include <basegfx/range/b2drange.hxx>
46 #include <basegfx/numeric/ftools.hxx>
48 #define GLOBALOVERFLOW
51 DBG_NAME(XPolyPolygon
);
53 /*************************************************************************
55 |* ImpXPolygon::ImpXPolygon()
58 |* Ersterstellung 08.11.94
59 |* Letzte Aenderung 12.01.95 ESO
61 *************************************************************************/
63 ImpXPolygon::ImpXPolygon( USHORT nInitSize
, USHORT _nResize
)
67 bDeleteOldPoints
= FALSE
;
76 /*************************************************************************
78 |* ImpXPolygon::ImpXPolygon()
81 |* Ersterstellung 08.11.94
82 |* Letzte Aenderung 12.01.95 ESO
84 *************************************************************************/
86 ImpXPolygon::ImpXPolygon( const ImpXPolygon
& rImpXPoly
)
88 ( (ImpXPolygon
&) rImpXPoly
).CheckPointDelete();
92 bDeleteOldPoints
= FALSE
;
94 ImpXPolygon::nResize
= rImpXPoly
.nResize
;
98 Resize( rImpXPoly
.nSize
);
101 nPoints
= rImpXPoly
.nPoints
;
102 memcpy( pPointAry
, rImpXPoly
.pPointAry
, nSize
*sizeof( Point
) );
103 memcpy( pFlagAry
, rImpXPoly
.pFlagAry
, nSize
);
106 /*************************************************************************
108 |* ImpXPolygon::~ImpXPolygon()
111 |* Ersterstellung 08.11.94
112 |* Letzte Aenderung 12.01.95 ESO
114 *************************************************************************/
116 ImpXPolygon::~ImpXPolygon()
118 delete[] (char*) pPointAry
;
120 if ( bDeleteOldPoints
)
121 delete[] (char*) pOldPointAry
;
124 /*************************************************************************
126 |* ImpXPolygon::operator==()
128 |* Ersterstellung Joe 26-09-95
131 *************************************************************************/
134 bool ImpXPolygon::operator==(const ImpXPolygon
& rImpXPoly
) const
136 return nPoints
==rImpXPoly
.nPoints
&&
138 (memcmp(pPointAry
,rImpXPoly
.pPointAry
,nPoints
*sizeof(Point
))==0 &&
139 memcmp(pFlagAry
,rImpXPoly
.pFlagAry
,nPoints
)==0));
142 /*************************************************************************
144 |* ImpXPolygon::Resize()
146 |* !!! Polygongroesse aendern - wenn bDeletePoints FALSE, dann den
147 |* Point-Array nicht loeschen, sondern in pOldPointAry sichern und
148 |* das Flag bDeleteOldPoints setzen. Beim naechsten Zugriff wird
149 |* das Array dann geloescht.
150 |* Damit wird verhindert, dass bei XPoly[n] = XPoly[0] durch ein
151 |* Resize der fuer den rechten Ausdruck verwendete Point-Array
152 |* vorzeitig geloescht wird.
153 |* Ersterstellung 08.11.94
154 |* Letzte Aenderung 12.01.95 ESO
156 *************************************************************************/
158 void ImpXPolygon::Resize( USHORT nNewSize
, BOOL bDeletePoints
)
160 if( nNewSize
== nSize
)
163 BYTE
* pOldFlagAry
= pFlagAry
;
164 USHORT nOldSize
= nSize
;
167 pOldPointAry
= pPointAry
;
169 // Neue Groesse auf vielfaches von nResize runden, sofern Objekt
170 // nicht neu angelegt wurde (nSize != 0)
171 if ( nSize
!= 0 && nNewSize
> nSize
)
173 DBG_ASSERT(nResize
, "Resize-Versuch trotz nResize = 0 !");
174 nNewSize
= nSize
+ ((nNewSize
-nSize
-1) / nResize
+ 1) * nResize
;
176 // Punkt Array erzeugen
178 pPointAry
= (Point
*)new char[ nSize
*sizeof( Point
) ];
179 memset( pPointAry
, 0, nSize
*sizeof( Point
) );
181 // Flag Array erzeugen
182 pFlagAry
= new BYTE
[ nSize
];
183 memset( pFlagAry
, 0, nSize
);
185 // Eventuell umkopieren
188 if( nOldSize
< nSize
)
190 memcpy( pPointAry
, pOldPointAry
, nOldSize
*sizeof( Point
) );
191 memcpy( pFlagAry
, pOldFlagAry
, nOldSize
);
195 memcpy( pPointAry
, pOldPointAry
, nSize
*sizeof( Point
) );
196 memcpy( pFlagAry
, pOldFlagAry
, nSize
);
198 // Anzahl der gueltigen Punkte anpassen
199 if( nPoints
> nSize
)
202 if ( bDeletePoints
) delete[] (char*) pOldPointAry
;
203 else bDeleteOldPoints
= TRUE
;
204 delete[] pOldFlagAry
;
209 /*************************************************************************
211 |* ImpXPolygon::InsertSpace()
214 |* Ersterstellung 08.11.94
215 |* Letzte Aenderung 29.03.95 ESO
217 *************************************************************************/
219 void ImpXPolygon::InsertSpace( USHORT nPos
, USHORT nCount
)
223 if ( nPos
> nPoints
)
226 // Wenn Polygon zu klein dann groesser machen
227 if( (nPoints
+ nCount
) > nSize
)
228 Resize( nPoints
+ nCount
);
230 // Wenn nicht hinter dem letzten Punkt eingefuegt wurde,
231 // den Rest nach hinten schieben
234 USHORT nMove
= nPoints
- nPos
;
235 memmove( &pPointAry
[nPos
+nCount
], &pPointAry
[nPos
],
236 nMove
* sizeof(Point
) );
237 memmove( &pFlagAry
[nPos
+nCount
], &pFlagAry
[nPos
], nMove
);
239 memset( &pPointAry
[nPos
], 0, nCount
* sizeof( Point
) );
240 memset( &pFlagAry
[nPos
], 0, nCount
);
242 nPoints
= nPoints
+ nCount
;
246 /*************************************************************************
248 |* ImpXPolygon::Remove()
251 |* Ersterstellung 08.11.94
252 |* Letzte Aenderung 12.01.94 ESO
254 *************************************************************************/
256 void ImpXPolygon::Remove( USHORT nPos
, USHORT nCount
)
260 if( (nPos
+ nCount
) <= nPoints
)
262 USHORT nMove
= nPoints
- nPos
- nCount
;
266 memmove( &pPointAry
[nPos
], &pPointAry
[nPos
+nCount
],
267 nMove
* sizeof(Point
) );
268 memmove( &pFlagAry
[nPos
], &pFlagAry
[nPos
+nCount
], nMove
);
270 memset( &pPointAry
[nPoints
- nCount
], 0, nCount
* sizeof( Point
) );
271 memset( &pFlagAry
[nPoints
- nCount
], 0, nCount
);
272 nPoints
= nPoints
- nCount
;
277 /*************************************************************************
279 |* XPolygon::XPolygon()
282 |* Ersterstellung 08.11.94
283 |* Letzte Aenderung 08.11.94
285 *************************************************************************/
287 XPolygon::XPolygon( USHORT nSize
, USHORT nResize
)
289 DBG_CTOR(XPolygon
,NULL
);
290 pImpXPolygon
= new ImpXPolygon( nSize
, nResize
);
293 /*************************************************************************
295 |* XPolygon::XPolygon()
298 |* Ersterstellung 08.11.94
299 |* Letzte Aenderung 08.11.94
301 *************************************************************************/
303 XPolygon::XPolygon( const XPolygon
& rXPoly
)
305 DBG_CTOR(XPolygon
,NULL
);
306 pImpXPolygon
= rXPoly
.pImpXPolygon
;
307 pImpXPolygon
->nRefCount
++;
310 /*************************************************************************
312 |* XPolygon::XPolygon()
314 |* XPolygon aus einem Standardpolygon erstellen
315 |* Ersterstellung 18.01.95 ESO
316 |* Letzte Aenderung 18.01.95 ESO
318 *************************************************************************/
320 XPolygon::XPolygon( const Polygon
& rPoly
)
322 DBG_CTOR(XPolygon
,NULL
);
324 USHORT nSize
= rPoly
.GetSize();
325 pImpXPolygon
= new ImpXPolygon( nSize
);
326 pImpXPolygon
->nPoints
= nSize
;
328 for( USHORT i
= 0; i
< nSize
; i
++ )
330 pImpXPolygon
->pPointAry
[i
] = rPoly
[i
];
331 pImpXPolygon
->pFlagAry
[i
] = (BYTE
) rPoly
.GetFlags( i
);
335 /*************************************************************************
337 |* XPolygon::XPolygon()
339 |* Rechteck (auch mit abgerundeten Ecken) als Bezierpolygon erzeugen
340 |* Ersterstellung 09.01.95 ESO
341 |* Letzte Aenderung 09.01.95 ESO
343 *************************************************************************/
345 XPolygon::XPolygon(const Rectangle
& rRect
, long nRx
, long nRy
)
347 DBG_CTOR(XPolygon
,NULL
);
348 pImpXPolygon
= new ImpXPolygon(17);
349 long nWh
= (rRect
.GetWidth() - 1) / 2;
350 long nHh
= (rRect
.GetHeight() - 1) / 2;
352 if ( nRx
> nWh
) nRx
= nWh
;
353 if ( nRy
> nHh
) nRy
= nHh
;
355 // Rx negativ, damit Umlauf im Uhrzeigersinn erfolgt
358 // Faktor fuer Kontrollpunkte der Bezierkurven: 8/3 * (sin(45g) - 0.5)
359 long nXHdl
= (long)(0.552284749 * nRx
);
360 long nYHdl
= (long)(0.552284749 * nRy
);
367 for (USHORT nQuad
= 0; nQuad
< 4; nQuad
++)
371 case 0: aCenter
= rRect
.TopLeft();
375 case 1: aCenter
= rRect
.TopRight();
379 case 2: aCenter
= rRect
.BottomRight();
383 case 3: aCenter
= rRect
.BottomLeft();
388 GenBezArc(aCenter
, nRx
, nRy
, nXHdl
, nYHdl
, 0, 900, nQuad
, nPos
);
389 pImpXPolygon
->pFlagAry
[nPos
] = (BYTE
) XPOLY_SMOOTH
;
390 pImpXPolygon
->pFlagAry
[nPos
+3] = (BYTE
) XPOLY_SMOOTH
;
396 pImpXPolygon
->pPointAry
[nPos
++] = rRect
.TopLeft();
397 pImpXPolygon
->pPointAry
[nPos
++] = rRect
.TopRight();
398 pImpXPolygon
->pPointAry
[nPos
++] = rRect
.BottomRight();
399 pImpXPolygon
->pPointAry
[nPos
++] = rRect
.BottomLeft();
401 pImpXPolygon
->pPointAry
[nPos
] = pImpXPolygon
->pPointAry
[0];
402 pImpXPolygon
->nPoints
= nPos
+ 1;
405 /*************************************************************************
407 |* XPolygon::XPolygon()
409 |* Ellipsen(bogen) als Bezierpolygon erzeugen
410 |* Ersterstellung 09.01.95
411 |* Letzte Aenderung 09.01.95
413 *************************************************************************/
415 XPolygon::XPolygon(const Point
& rCenter
, long nRx
, long nRy
,
416 USHORT nStartAngle
, USHORT nEndAngle
, BOOL bClose
)
418 DBG_CTOR(XPolygon
,NULL
);
419 pImpXPolygon
= new ImpXPolygon(17);
422 if ( nEndAngle
> 3600 ) nEndAngle
%= 3600;
423 BOOL bFull
= (nStartAngle
== 0 && nEndAngle
== 3600);
425 // Faktor fuer Kontrollpunkte der Bezierkurven: 8/3 * (sin(45g) - 0.5)
426 long nXHdl
= (long)(0.552284749 * nRx
);
427 long nYHdl
= (long)(0.552284749 * nRy
);
429 BOOL bLoopEnd
= FALSE
;
434 USHORT nQuad
= nStartAngle
/ 900;
435 if ( nQuad
== 4 ) nQuad
= 0;
436 bLoopEnd
= CheckAngles(nStartAngle
, nEndAngle
, nA1
, nA2
);
437 GenBezArc(rCenter
, nRx
, nRy
, nXHdl
, nYHdl
, nA1
, nA2
, nQuad
, nPos
);
440 pImpXPolygon
->pFlagAry
[nPos
] = (BYTE
) XPOLY_SMOOTH
;
442 } while ( !bLoopEnd
);
444 // Wenn kein Vollkreis, dann ggf. Enden mit Mittelpunkt verbinden
445 if ( !bFull
&& bClose
)
446 pImpXPolygon
->pPointAry
[++nPos
] = rCenter
;
450 pImpXPolygon
->pFlagAry
[0 ] = (BYTE
) XPOLY_SMOOTH
;
451 pImpXPolygon
->pFlagAry
[nPos
] = (BYTE
) XPOLY_SMOOTH
;
453 pImpXPolygon
->nPoints
= nPos
+ 1;
456 /*************************************************************************
458 |* XPolygon::~XPolygon()
461 |* Ersterstellung 08.11.94
462 |* Letzte Aenderung 08.11.94
464 *************************************************************************/
466 XPolygon::~XPolygon()
468 DBG_DTOR(XPolygon
,NULL
);
469 if( pImpXPolygon
->nRefCount
> 1 )
470 pImpXPolygon
->nRefCount
--;
475 /*************************************************************************
477 |* XPolygon::CheckReference()
479 |* Referenzzaehler desImpXPoly pruefen und ggf. von diesem abkoppeln
480 |* Ersterstellung 17.01.95 ESO
481 |* Letzte Aenderung 17.01.95 ESO
483 *************************************************************************/
485 void XPolygon::CheckReference()
487 if( pImpXPolygon
->nRefCount
> 1 )
489 pImpXPolygon
->nRefCount
--;
490 pImpXPolygon
= new ImpXPolygon( *pImpXPolygon
);
494 /*************************************************************************
496 |* XPolygon::SetSize()
499 |* Ersterstellung 08.11.94
500 |* Letzte Aenderung 08.11.94
502 *************************************************************************/
504 void XPolygon::SetSize( USHORT nNewSize
)
507 pImpXPolygon
->Resize( nNewSize
);
510 /*************************************************************************
512 |* XPolygon::GetSize()
515 |* Ersterstellung 08.11.94
516 |* Letzte Aenderung 12.01.95 ESO
518 *************************************************************************/
520 USHORT
XPolygon::GetSize() const
522 pImpXPolygon
->CheckPointDelete();
523 return pImpXPolygon
->nSize
;
526 /*************************************************************************
528 |* XPolygon::SetPointCount()
531 |* Ersterstellung 08.11.94
532 |* Letzte Aenderung 12.01.95 ESO
534 *************************************************************************/
536 void XPolygon::SetPointCount( USHORT nPoints
)
538 pImpXPolygon
->CheckPointDelete();
541 if( pImpXPolygon
->nSize
< nPoints
)
542 pImpXPolygon
->Resize( nPoints
);
544 if ( nPoints
< pImpXPolygon
->nPoints
)
546 USHORT nSize
= pImpXPolygon
->nPoints
- nPoints
;
547 memset( &pImpXPolygon
->pPointAry
[nPoints
], 0, nSize
* sizeof( Point
) );
548 memset( &pImpXPolygon
->pFlagAry
[nPoints
], 0, nSize
);
550 pImpXPolygon
->nPoints
= nPoints
;
553 /*************************************************************************
555 |* XPolygon::GetPointCount()
558 |* Ersterstellung 08.11.94
559 |* Letzte Aenderung 12.01.95 ESO
561 *************************************************************************/
563 USHORT
XPolygon::GetPointCount() const
565 pImpXPolygon
->CheckPointDelete();
566 return pImpXPolygon
->nPoints
;
569 /*************************************************************************
571 |* XPolygon::Insert()
574 |* Ersterstellung 08.11.94
575 |* Letzte Aenderung 08.11.94
577 *************************************************************************/
579 void XPolygon::Insert( USHORT nPos
, const Point
& rPt
, XPolyFlags eFlags
)
582 if (nPos
>pImpXPolygon
->nPoints
) nPos
=pImpXPolygon
->nPoints
;
583 pImpXPolygon
->InsertSpace( nPos
, 1 );
584 pImpXPolygon
->pPointAry
[nPos
] = rPt
;
585 pImpXPolygon
->pFlagAry
[nPos
] = (BYTE
)eFlags
;
588 /*************************************************************************
590 |* XPolygon::Insert()
593 |* Ersterstellung 08.11.94
594 |* Letzte Aenderung 08.11.94
596 *************************************************************************/
598 void XPolygon::Insert( USHORT nPos
, const XPolygon
& rXPoly
)
601 if (nPos
>pImpXPolygon
->nPoints
) nPos
=pImpXPolygon
->nPoints
;
603 USHORT nPoints
= rXPoly
.GetPointCount();
605 pImpXPolygon
->InsertSpace( nPos
, nPoints
);
607 memcpy( &(pImpXPolygon
->pPointAry
[nPos
]),
608 rXPoly
.pImpXPolygon
->pPointAry
,
609 nPoints
*sizeof( Point
) );
610 memcpy( &(pImpXPolygon
->pFlagAry
[nPos
]),
611 rXPoly
.pImpXPolygon
->pFlagAry
,
615 /*************************************************************************
617 |* XPolygon::Insert()
620 |* Ersterstellung 08.11.94
621 |* Letzte Aenderung 08.11.94
623 *************************************************************************/
625 void XPolygon::Insert( USHORT nPos
, const Polygon
& rPoly
)
628 if (nPos
>pImpXPolygon
->nPoints
) nPos
=pImpXPolygon
->nPoints
;
630 USHORT nPoints
= rPoly
.GetSize();
632 pImpXPolygon
->InsertSpace( nPos
, nPoints
);
635 for( i
=0; i
< nPoints
; i
++ )
636 pImpXPolygon
->pPointAry
[i
] = rPoly
[i
];
638 // Die Flags sind durch das InsertSpace bereits auf 0 gesetzt
641 /*************************************************************************
643 |* XPolygon::Remove()
646 |* Ersterstellung 08.11.94
647 |* Letzte Aenderung 08.11.94
649 *************************************************************************/
651 void XPolygon::Remove( USHORT nPos
, USHORT nCount
)
654 pImpXPolygon
->Remove( nPos
, nCount
);
657 /*************************************************************************
662 |* Ersterstellung 09.11.94
663 |* Letzte Aenderung 09.11.94
665 *************************************************************************/
667 void XPolygon::Move( long nHorzMove
, long nVertMove
)
669 if ( !nHorzMove
&& !nVertMove
)
674 // Punkte verschieben
675 USHORT nCount
= pImpXPolygon
->nPoints
;
676 for ( USHORT i
= 0; i
< nCount
; i
++ )
678 Point
* pPt
= &(pImpXPolygon
->pPointAry
[i
]);
679 pPt
->X() += nHorzMove
;
680 pPt
->Y() += nVertMove
;
684 /*************************************************************************
686 |* XPolygon::GetBoundRect()
689 |* Ersterstellung 09.11.94
690 |* Letzte Aenderung 12.01.95 ESO
692 *************************************************************************/
694 Rectangle
XPolygon::GetBoundRect() const
696 pImpXPolygon
->CheckPointDelete();
699 if(pImpXPolygon
->nPoints
)
702 // For historical reasons the control points are not part of the
703 // BoundRect. This makes it necessary to subdivide the polygon to
704 // get a relatively correct BoundRect. Numerically, this is not
705 // correct and never was.
707 const basegfx::B2DRange
aPolygonRange(basegfx::tools::getRange(getB2DPolygon()));
709 FRound(aPolygonRange
.getMinX()), FRound(aPolygonRange
.getMinY()),
710 FRound(aPolygonRange
.getMaxX()), FRound(aPolygonRange
.getMaxY()));
716 /*************************************************************************
718 |* XPolygon::operator[]()
721 |* Ersterstellung 08.11.94
722 |* Letzte Aenderung 12.01.95
724 *************************************************************************/
726 const Point
& XPolygon::operator[]( USHORT nPos
) const
728 DBG_ASSERT(nPos
< pImpXPolygon
->nPoints
, "Ungueltiger Index bei const-Arrayzugriff auf XPolygon");
730 pImpXPolygon
->CheckPointDelete();
731 return pImpXPolygon
->pPointAry
[nPos
];
734 /*************************************************************************
736 |* XPolygon::operator[]()
739 |* Ersterstellung 08.11.94
740 |* Letzte Aenderung 12.01.95 ESO
742 *************************************************************************/
744 Point
& XPolygon::operator[]( USHORT nPos
)
746 pImpXPolygon
->CheckPointDelete();
749 if( nPos
>= pImpXPolygon
->nSize
)
751 DBG_ASSERT(pImpXPolygon
->nResize
, "Ungueltiger Index bei Arrayzugriff auf XPolygon");
752 pImpXPolygon
->Resize(nPos
+ 1, FALSE
);
754 if( nPos
>= pImpXPolygon
->nPoints
)
755 pImpXPolygon
->nPoints
= nPos
+ 1;
757 return pImpXPolygon
->pPointAry
[nPos
];
760 /*************************************************************************
762 |* XPolygon::operator=()
764 |* Beschreibung Zuweisungsoperator
765 |* Ersterstellung ESO 22.11.94
766 |* Letzte Aenderung ESO 12.01.95
768 *************************************************************************/
770 XPolygon
& XPolygon::operator=( const XPolygon
& rXPoly
)
772 pImpXPolygon
->CheckPointDelete();
774 rXPoly
.pImpXPolygon
->nRefCount
++;
776 if( pImpXPolygon
->nRefCount
> 1 )
777 pImpXPolygon
->nRefCount
--;
781 pImpXPolygon
= rXPoly
.pImpXPolygon
;
785 /*************************************************************************
787 |* XPolygon::operator==()
789 |* Beschreibung Gleichheitsoperator
790 |* Ersterstellung ESO 22.11.94
791 |* Letzte Aenderung Joe 26.09.95
793 *************************************************************************/
795 BOOL
XPolygon::operator==( const XPolygon
& rXPoly
) const
797 pImpXPolygon
->CheckPointDelete();
798 if (rXPoly
.pImpXPolygon
==pImpXPolygon
) return TRUE
;
799 return *rXPoly
.pImpXPolygon
== *pImpXPolygon
;
802 /*************************************************************************
804 |* XPolygon::operator!=()
806 |* Beschreibung Ungleichheitsoperator
807 |* Ersterstellung ESO 22.11.94
808 |* Letzte Aenderung Joe 26.09.95
810 *************************************************************************/
812 BOOL
XPolygon::operator!=( const XPolygon
& rXPoly
) const
814 pImpXPolygon
->CheckPointDelete();
815 if (rXPoly
.pImpXPolygon
==pImpXPolygon
) return FALSE
;
816 return *rXPoly
.pImpXPolygon
!= *pImpXPolygon
;
819 /*************************************************************************
821 |* XPolygon::GetFlags()
823 |* Flags fuer den Punkt an der Position nPos zurueckgeben
824 |* Ersterstellung ESO 11.11.94
825 |* Letzte Aenderung ESO 12.01.95
827 *************************************************************************/
829 XPolyFlags
XPolygon::GetFlags( USHORT nPos
) const
831 pImpXPolygon
->CheckPointDelete();
832 return (XPolyFlags
) pImpXPolygon
->pFlagAry
[nPos
];
835 /*************************************************************************
837 |* XPolygon::SetFlags()
839 |* Flags fuer den Punkt an der Position nPos setzen
840 |* Ersterstellung ESO 11.11.94
841 |* Letzte Aenderung ESO 12.01.95
843 *************************************************************************/
845 void XPolygon::SetFlags( USHORT nPos
, XPolyFlags eFlags
)
847 pImpXPolygon
->CheckPointDelete();
849 pImpXPolygon
->pFlagAry
[nPos
] = (BYTE
) eFlags
;
852 /*************************************************************************
854 |* XPolygon::IsControl()
856 |* Kurzform zur Abfrage des CONTROL-Flags
857 |* Ersterstellung ESO 09.01.95
858 |* Letzte Aenderung ESO 12.01.95
860 *************************************************************************/
862 BOOL
XPolygon::IsControl(USHORT nPos
) const
864 return ( (XPolyFlags
) pImpXPolygon
->pFlagAry
[nPos
] == XPOLY_CONTROL
);
867 /*************************************************************************
869 |* XPolygon::IsSmooth()
871 |* Kurzform zur Abfrage von SMOOTH- und SYMMTR-Flag
872 |* Ersterstellung ESO 18.04.95
873 |* Letzte Aenderung ESO 18.04.95
875 *************************************************************************/
877 BOOL
XPolygon::IsSmooth(USHORT nPos
) const
879 XPolyFlags eFlag
= (XPolyFlags
) pImpXPolygon
->pFlagAry
[nPos
];
880 return ( eFlag
== XPOLY_SMOOTH
|| eFlag
== XPOLY_SYMMTR
);
883 /*************************************************************************
885 |* XPolygon::CalcDistance()
887 |* Abstand zwischen zwei Punkten berechnen
888 |* Ersterstellung ESO 09.01.95
889 |* Letzte Aenderung ESO 09.01.95
891 *************************************************************************/
893 double XPolygon::CalcDistance(USHORT nP1
, USHORT nP2
)
895 const Point
& rP1
= pImpXPolygon
->pPointAry
[nP1
];
896 const Point
& rP2
= pImpXPolygon
->pPointAry
[nP2
];
897 double fDx
= rP2
.X() - rP1
.X();
898 double fDy
= rP2
.Y() - rP1
.Y();
899 return sqrt(fDx
* fDx
+ fDy
* fDy
);
902 /*************************************************************************
904 |* XPolygon::SubdivideBezier()
906 |* Bezierkurve unterteilen
907 |* Ersterstellung ESO 09.01.95
908 |* Letzte Aenderung ESO 09.01.95
910 *************************************************************************/
912 void XPolygon::SubdivideBezier(USHORT nPos
, BOOL bCalcFirst
, double fT
)
914 Point
* pPoints
= pImpXPolygon
->pPointAry
;
915 double fT2
= fT
* fT
;
916 double fT3
= fT
* fT2
;
917 double fU
= 1.0 - fT
;
918 double fU2
= fU
* fU
;
919 double fU3
= fU
* fU2
;
921 short nPosInc
, nIdxInc
;
934 pPoints
[nPos
].X() = (long) (fU3
* pPoints
[nIdx
].X() +
935 fT
* fU2
* pPoints
[nIdx
+1].X() * 3 +
936 fT2
* fU
* pPoints
[nIdx
+2].X() * 3 +
937 fT3
* pPoints
[nIdx
+3].X());
938 pPoints
[nPos
].Y() = (long) (fU3
* pPoints
[nIdx
].Y() +
939 fT
* fU2
* pPoints
[nIdx
+1].Y() * 3 +
940 fT2
* fU
* pPoints
[nIdx
+2].Y() * 3 +
941 fT3
* pPoints
[nIdx
+3].Y());
942 nPos
= nPos
+ nPosInc
;
943 nIdx
= nIdx
+ nIdxInc
;
944 pPoints
[nPos
].X() = (long) (fU2
* pPoints
[nIdx
].X() +
945 fT
* fU
* pPoints
[nIdx
+1].X() * 2 +
946 fT2
* pPoints
[nIdx
+2].X());
947 pPoints
[nPos
].Y() = (long) (fU2
* pPoints
[nIdx
].Y() +
948 fT
* fU
* pPoints
[nIdx
+1].Y() * 2 +
949 fT2
* pPoints
[nIdx
+2].Y());
950 nPos
= nPos
+ nPosInc
;
951 nIdx
= nIdx
+ nIdxInc
;
952 pPoints
[nPos
].X() = (long) (fU
* pPoints
[nIdx
].X() +
953 fT
* pPoints
[nIdx
+1].X());
954 pPoints
[nPos
].Y() = (long) (fU
* pPoints
[nIdx
].Y() +
955 fT
* pPoints
[nIdx
+1].Y());
958 /************************************************************************/
960 void XPolygon::GenBezArc(const Point
& rCenter
, long nRx
, long nRy
,
961 long nXHdl
, long nYHdl
, USHORT nStart
, USHORT nEnd
,
962 USHORT nQuad
, USHORT nFirst
)
964 Point
* pPoints
= pImpXPolygon
->pPointAry
;
965 pPoints
[nFirst
] = rCenter
;
966 pPoints
[nFirst
+3] = rCenter
;
968 if ( nQuad
== 1 || nQuad
== 2 )
970 nRx
= -nRx
; nXHdl
= -nXHdl
;
972 if ( nQuad
== 0 || nQuad
== 1 )
974 nRy
= -nRy
; nYHdl
= -nYHdl
;
977 if ( nQuad
== 0 || nQuad
== 2 )
979 pPoints
[nFirst
].X() += nRx
; pPoints
[nFirst
+3].Y() += nRy
;
983 pPoints
[nFirst
].Y() += nRy
; pPoints
[nFirst
+3].X() += nRx
;
985 pPoints
[nFirst
+1] = pPoints
[nFirst
];
986 pPoints
[nFirst
+2] = pPoints
[nFirst
+3];
988 if ( nQuad
== 0 || nQuad
== 2 )
990 pPoints
[nFirst
+1].Y() += nYHdl
; pPoints
[nFirst
+2].X() += nXHdl
;
994 pPoints
[nFirst
+1].X() += nXHdl
; pPoints
[nFirst
+2].Y() += nYHdl
;
997 SubdivideBezier(nFirst
, FALSE
, (double)nStart
/ 900);
999 SubdivideBezier(nFirst
, TRUE
, (double)(nEnd
-nStart
) / (900-nStart
));
1000 SetFlags(nFirst
+1, XPOLY_CONTROL
);
1001 SetFlags(nFirst
+2, XPOLY_CONTROL
);
1004 /************************************************************************/
1006 BOOL
XPolygon::CheckAngles(USHORT
& nStart
, USHORT nEnd
, USHORT
& nA1
, USHORT
& nA2
)
1008 if ( nStart
== 3600 ) nStart
= 0;
1009 if ( nEnd
== 0 ) nEnd
= 3600;
1010 USHORT nStPrev
= nStart
;
1011 USHORT nMax
= (nStart
/ 900 + 1) * 900;
1012 USHORT nMin
= nMax
- 900;
1014 if ( nEnd
>= nMax
|| nEnd
<= nStart
) nA2
= 900;
1015 else nA2
= nEnd
- nMin
;
1016 nA1
= nStart
- nMin
;
1019 // TRUE zurueck, falls letztes Segment berechnet wurde
1020 return (nStPrev
< nEnd
&& nStart
>= nEnd
);
1023 /*************************************************************************
1025 |* XPolygon::CalcSmoothJoin()
1027 |* glatten Uebergang zu einer Bezierkurve berechnen, indem der
1028 |* entsprechende Punkt auf die Verbindungslinie von zwei anderen
1029 |* Punkten projiziert wird
1030 |* Center = End- bzw. Anfangspunkt der Bezierkurve
1031 |* Drag = der bewegte Punkt, der die Verschiebung von Pnt vorgibt
1032 |* Pnt = der zu modifizierende Punkt
1033 |* Wenn Center am Anfang bzw. Ende des Polygons liegt, wird Pnt
1034 |* auf die entgegengesetzte Seite verlegt
1035 |* Ersterstellung ESO 09.01.95
1036 |* Letzte Aenderung ESO 18.04.95
1038 \************************************************************************/
1040 void XPolygon::CalcSmoothJoin(USHORT nCenter
, USHORT nDrag
, USHORT nPnt
)
1044 // USHORT nMaxPnt = pImpXPolygon->nPoints - 1;
1046 // if ( nCenter == nMaxPnt ) nPnt = 1;
1047 // else if ( nCenter == 0 ) nPnt = nMaxPnt - 1;
1049 // Wenn nPnt kein Control-Punkt, d.h. nicht verschiebbar, dann
1050 // statt dessen nDrag auf der Achse nCenter-nPnt verschieben
1051 if ( !IsControl(nPnt
) )
1053 USHORT nTmp
= nDrag
;
1057 Point
* pPoints
= pImpXPolygon
->pPointAry
;
1058 Point aDiff
= pPoints
[nDrag
] - pPoints
[nCenter
];
1059 double fDiv
= CalcDistance(nCenter
, nDrag
);
1063 double fRatio
= CalcDistance(nCenter
, nPnt
) / fDiv
;
1064 // bei SMOOTH bisherige Laenge beibehalten
1065 if ( GetFlags(nCenter
) == XPOLY_SMOOTH
|| !IsControl(nDrag
) )
1067 aDiff
.X() = (long) (fRatio
* aDiff
.X());
1068 aDiff
.Y() = (long) (fRatio
* aDiff
.Y());
1070 pPoints
[nPnt
] = pPoints
[nCenter
] - aDiff
;
1074 /*************************************************************************
1076 |* XPolygon::CalcTangent()
1078 |* Tangente fuer den Uebergang zwischen zwei Bezierkurven berechnen
1079 |* Center = End- bzw. Anfangspunkt der Bezierkurven
1080 |* Prev = vorheriger Zugpunkt
1081 |* Next = naechster Zugpunkt
1082 |* Ersterstellung ESO 09.01.95
1083 |* Letzte Aenderung ESO 18.04.95
1085 \************************************************************************/
1087 void XPolygon::CalcTangent(USHORT nCenter
, USHORT nPrev
, USHORT nNext
)
1091 double fAbsLen
= CalcDistance(nNext
, nPrev
);
1095 const Point
& rCenter
= pImpXPolygon
->pPointAry
[nCenter
];
1096 Point
& rNext
= pImpXPolygon
->pPointAry
[nNext
];
1097 Point
& rPrev
= pImpXPolygon
->pPointAry
[nPrev
];
1098 Point aDiff
= rNext
- rPrev
;
1099 double fNextLen
= CalcDistance(nCenter
, nNext
) / fAbsLen
;
1100 double fPrevLen
= CalcDistance(nCenter
, nPrev
) / fAbsLen
;
1102 // bei SYMMTR gleiche Laenge fuer beide Seiten
1103 if ( GetFlags(nCenter
) == XPOLY_SYMMTR
)
1105 fPrevLen
= (fNextLen
+ fPrevLen
) / 2;
1106 fNextLen
= fPrevLen
;
1108 rNext
.X() = rCenter
.X() + (long) (fNextLen
* aDiff
.X());
1109 rNext
.Y() = rCenter
.Y() + (long) (fNextLen
* aDiff
.Y());
1110 rPrev
.X() = rCenter
.X() - (long) (fPrevLen
* aDiff
.X());
1111 rPrev
.Y() = rCenter
.Y() - (long) (fPrevLen
* aDiff
.Y());
1115 /*************************************************************************
1117 |* XPolygon::PointsToBezier()
1119 |* wandelt vier Polygonpunkte in eine Bezierkurve durch diese Punkte um
1120 |* Ersterstellung ESO 09.01.95
1121 |* Letzte Aenderung ESO 09.01.95
1123 \************************************************************************/
1125 void XPolygon::PointsToBezier(USHORT nFirst
)
1127 double nFullLength
, nPart1Length
, nPart2Length
;
1128 double fX0
, fY0
, fX1
, fY1
, fX2
, fY2
, fX3
, fY3
;
1129 double fTx1
, fTx2
, fTy1
, fTy2
;
1130 double fT1
, fU1
, fT2
, fU2
, fV
;
1131 Point
* pPoints
= pImpXPolygon
->pPointAry
;
1133 if ( nFirst
> pImpXPolygon
->nPoints
- 4 || IsControl(nFirst
) ||
1134 IsControl(nFirst
+1) || IsControl(nFirst
+2) || IsControl(nFirst
+3) )
1139 fTx1
= pPoints
[nFirst
+1].X();
1140 fTy1
= pPoints
[nFirst
+1].Y();
1141 fTx2
= pPoints
[nFirst
+2].X();
1142 fTy2
= pPoints
[nFirst
+2].Y();
1143 fX0
= pPoints
[nFirst
].X();
1144 fY0
= pPoints
[nFirst
].Y();
1145 fX3
= pPoints
[nFirst
+3].X();
1146 fY3
= pPoints
[nFirst
+3].Y();
1148 nPart1Length
= CalcDistance(nFirst
, nFirst
+1);
1149 nPart2Length
= nPart1Length
+ CalcDistance(nFirst
+1, nFirst
+2);
1150 nFullLength
= nPart2Length
+ CalcDistance(nFirst
+2, nFirst
+3);
1151 if ( nFullLength
< 20 )
1154 if ( nPart2Length
== nFullLength
)
1156 if ( nPart1Length
== nFullLength
)
1157 nPart1Length
= nPart2Length
- 1;
1158 if ( nPart1Length
<= 0 )
1160 if ( nPart2Length
<= 0 || nPart2Length
== nPart1Length
)
1161 nPart2Length
= nPart1Length
+ 1;
1163 fT1
= nPart1Length
/ nFullLength
;
1165 fT2
= nPart2Length
/ nFullLength
;
1167 fV
= 3 * (1.0 - (fT1
* fU2
) / (fT2
* fU1
));
1169 fX1
= fTx1
/ (fT1
* fU1
* fU1
) - fTx2
* fT1
/ (fT2
* fT2
* fU1
* fU2
);
1171 fX1
-= fX0
* ( fU1
/ fT1
+ fU2
/ fT2
) / 3;
1172 fX1
+= fX3
* ( fT1
* fT2
/ (fU1
* fU2
)) / 3;
1174 fY1
= fTy1
/ (fT1
* fU1
* fU1
) - fTy2
* fT1
/ (fT2
* fT2
* fU1
* fU2
);
1176 fY1
-= fY0
* ( fU1
/ fT1
+ fU2
/ fT2
) / 3;
1177 fY1
+= fY3
* ( fT1
* fT2
/ (fU1
* fU2
)) / 3;
1179 fX2
= fTx2
/ (fT2
* fT2
* fU2
* 3) - fX0
* fU2
* fU2
/ ( fT2
* fT2
* 3);
1180 fX2
-= fX1
* fU2
/ fT2
;
1181 fX2
-= fX3
* fT2
/ (fU2
* 3);
1183 fY2
= fTy2
/ (fT2
* fT2
* fU2
* 3) - fY0
* fU2
* fU2
/ ( fT2
* fT2
* 3);
1184 fY2
-= fY1
* fU2
/ fT2
;
1185 fY2
-= fY3
* fT2
/ (fU2
* 3);
1187 pPoints
[nFirst
+1] = Point((long) fX1
, (long) fY1
);
1188 pPoints
[nFirst
+2] = Point((long) fX2
, (long) fY2
);
1189 SetFlags(nFirst
+1, XPOLY_CONTROL
);
1190 SetFlags(nFirst
+2, XPOLY_CONTROL
);
1193 /*************************************************************************
1195 |* XPolygon::Translate()
1197 |* Polygon auf den uebergebenen Punkt verschieben
1198 |* Ersterstellung ESO 17.01.95
1199 |* Letzte Aenderung ESO 17.01.95
1201 *************************************************************************/
1203 void XPolygon::Translate(const Point
& rTrans
)
1205 pImpXPolygon
->CheckPointDelete();
1208 USHORT nPntCnt
= pImpXPolygon
->nPoints
;
1210 for (USHORT i
= 0; i
< nPntCnt
; i
++)
1211 pImpXPolygon
->pPointAry
[i
] += rTrans
;
1214 /*************************************************************************
1216 |* XPolygon::Rotate()
1218 |* Alle Punkte um den Punkt rCenter drehen, Sinus und Cosinus
1219 |* muessen uebergeben werden
1220 |* Ersterstellung ESO 09.01.95
1221 |* Letzte Aenderung ESO 17.01.95
1223 *************************************************************************/
1225 void XPolygon::Rotate(const Point
& rCenter
, double fSin
, double fCos
)
1227 pImpXPolygon
->CheckPointDelete();
1234 long nCenterX
= rCenter
.X();
1235 long nCenterY
= rCenter
.Y();
1237 USHORT nPntCnt
= pImpXPolygon
->nPoints
;
1239 for (USHORT i
= 0; i
< nPntCnt
; i
++)
1241 Point
*pPt
= &(pImpXPolygon
->pPointAry
[i
]);
1242 nX
= pPt
->X()-nCenterX
;
1243 nY
= pPt
->Y()-nCenterY
;
1244 nNewX
= (long)floor(fCos
* nX
+ fSin
* nY
+ 0.5);
1245 nNewY
= -(long)floor(fSin
* nX
- fCos
* nY
+ 0.5);
1246 pPt
->X() = nNewX
+ nCenterX
;
1247 pPt
->Y() = nNewY
+ nCenterY
;
1249 /* und so stand das in einem anderen File auf T:
1250 dass ich am 29-11-1995 gegettet habe. Joe M.
1251 USHORT nPntCnt = pImpXPolygon->nPoints;
1253 for (USHORT i = 0; i < nPntCnt; i++)
1255 Point P = pImpXPolygon->pPointAry[i] - rCenter;
1258 P.X() = (long)floor(fCos * X + fSin * Y + 0.5);
1259 P.Y() = -(long)floor(fSin * X - fCos * Y + 0.5);
1260 pImpXPolygon->pPointAry[i] = P + rCenter;
1265 /*************************************************************************
1267 |* XPolygon::Rotate()
1269 |* Alle Punkte um den Punkt rCenter mit dem Winkel nAngle drehen
1270 |* Winkel in 10tel Grad, Wertebereich 0 - 3600
1271 |* Ersterstellung ESO 17.01.95
1272 |* Letzte Aenderung ESO 17.01.95
1274 *************************************************************************/
1276 void XPolygon::Rotate(const Point
& rCenter
, USHORT nAngle
)
1282 double fAngle
= F_PI
* nAngle
/ 1800;
1283 double fSin
= sin(fAngle
);
1284 double fCos
= cos(fAngle
);
1285 Rotate(rCenter
, fSin
, fCos
);
1289 /*************************************************************************
1291 |* XPolygon::Scale()
1293 |* XPolygon in X- und/oder Y-Richtung skalieren
1294 |* Ersterstellung ESO 01.02.95
1295 |* Letzte Aenderung ESO 01.02.95
1297 *************************************************************************/
1299 void XPolygon::Scale(double fSx
, double fSy
)
1301 pImpXPolygon
->CheckPointDelete();
1304 USHORT nPntCnt
= pImpXPolygon
->nPoints
;
1306 for (USHORT i
= 0; i
< nPntCnt
; i
++)
1308 Point
& rPnt
= pImpXPolygon
->pPointAry
[i
];
1309 rPnt
.X() = (long)(fSx
* rPnt
.X());
1310 rPnt
.Y() = (long)(fSy
* rPnt
.Y());
1314 /*************************************************************************
1316 |* XPolygon::SlantX()
1318 |* XPolygon in X-Richtung um einen beliebigen Winkel kippen,
1319 |* bezogen auf eine Referenz-Y-Koordinate
1320 |* Ersterstellung ESO 01.02.95
1321 |* Letzte Aenderung ESO 01.02.95
1323 *************************************************************************/
1325 void XPolygon::SlantX(long nYRef
, double fSin
, double fCos
)
1327 pImpXPolygon
->CheckPointDelete();
1330 USHORT nPntCnt
= pImpXPolygon
->nPoints
;
1332 for (USHORT i
= 0; i
< nPntCnt
; i
++)
1334 Point
& rPnt
= pImpXPolygon
->pPointAry
[i
];
1335 long nDy
= rPnt
.Y() - nYRef
;
1336 rPnt
.X() += (long)(fSin
* nDy
);
1337 rPnt
.Y() = nYRef
+ (long)(fCos
* nDy
);
1341 /*************************************************************************
1343 |* XPolygon::SlantY()
1345 |* XPolygon in Y-Richtung um einen beliebigen Winkel kippen,
1346 |* bezogen auf eine Referenz-X-Koordinate
1347 |* Ersterstellung ESO 01.02.95
1348 |* Letzte Aenderung ESO 01.02.95
1350 *************************************************************************/
1352 void XPolygon::SlantY(long nXRef
, double fSin
, double fCos
)
1354 pImpXPolygon
->CheckPointDelete();
1357 USHORT nPntCnt
= pImpXPolygon
->nPoints
;
1359 for (USHORT i
= 0; i
< nPntCnt
; i
++)
1361 Point
& rPnt
= pImpXPolygon
->pPointAry
[i
];
1362 long nDx
= rPnt
.X() - nXRef
;
1363 rPnt
.X() = nXRef
+ (long)(fCos
* nDx
);
1364 rPnt
.Y() -= (long)(fSin
* nDx
);
1368 /*************************************************************************
1370 |* XPolygon::Distort()
1372 |* XPolygon verzerren, indem die Koordinaten relativ zu einem
1373 |* Referenzrechteck in ein beliebiges Viereck skaliert werden
1374 |* Zuordnung der Viereck-Punkte im Polygon zum Referenzrechteck:
1375 |* 0: links oben 0----1
1376 |* 1: rechts oben | |
1377 |* 2: rechts unten 3----2
1379 |* Ersterstellung ESO 07.07.95
1380 |* Letzte Aenderung ESO 07.07.95
1382 *************************************************************************/
1384 void XPolygon::Distort(const Rectangle
& rRefRect
,
1385 const XPolygon
& rDistortedRect
)
1387 pImpXPolygon
->CheckPointDelete();
1390 long Xr
, Wr
, X1
, X2
, X3
, X4
;
1391 long Yr
, Hr
, Y1
, Y2
, Y3
, Y4
;
1392 double fTx
, fTy
, fUx
, fUy
;
1394 Xr
= rRefRect
.Left();
1395 Yr
= rRefRect
.Top();
1396 Wr
= rRefRect
.GetWidth();
1397 Hr
= rRefRect
.GetHeight();
1401 DBG_ASSERT(rDistortedRect
.pImpXPolygon
->nPoints
>= 4,
1402 "Distort-Rechteck zu klein");
1404 X1
= rDistortedRect
[0].X();
1405 Y1
= rDistortedRect
[0].Y();
1406 X2
= rDistortedRect
[1].X();
1407 Y2
= rDistortedRect
[1].Y();
1408 X3
= rDistortedRect
[3].X();
1409 Y3
= rDistortedRect
[3].Y();
1410 X4
= rDistortedRect
[2].X();
1411 Y4
= rDistortedRect
[2].Y();
1413 USHORT nPntCnt
= pImpXPolygon
->nPoints
;
1415 for (USHORT i
= 0; i
< nPntCnt
; i
++)
1417 Point
& rPnt
= pImpXPolygon
->pPointAry
[i
];
1419 fTx
= (double)(rPnt
.X() - Xr
) / Wr
;
1420 fTy
= (double)(rPnt
.Y() - Yr
) / Hr
;
1424 rPnt
.X() = (long) ( fUy
* (fUx
* X1
+ fTx
* X2
) +
1425 fTy
* (fUx
* X3
+ fTx
* X4
) );
1426 rPnt
.Y() = (long) ( fUx
* (fUy
* Y1
+ fTy
* Y3
) +
1427 fTx
* (fUy
* Y2
+ fTy
* Y4
) );
1432 /*************************************************************************
1434 |* Bestimme den linken, unteren Punkt des Polygons und richte das
1435 |* Polygon so aus, dass dieser Punkt auf dem Index 0 liegt
1437 \************************************************************************/
1439 void XPolygon::Rotate20()
1441 pImpXPolygon
->CheckPointDelete();
1444 double fMinY
= pImpXPolygon
->pPointAry
->Y();
1445 double fMinX
= pImpXPolygon
->pPointAry
->X();
1446 long nPntCnt
= pImpXPolygon
->nPoints
;
1449 for (long nPoints
= 1;
1453 Point
&rPnt
= pImpXPolygon
->pPointAry
[nPoints
];
1455 if ((rPnt
.X () < fMinX
) || (fMinX
== rPnt
.X ()) &&
1456 (fMinY
>= rPnt
.Y ()))
1464 if (nIndex0
< nPntCnt
)
1466 Point
*pTemp
= new Point
[nIndex0
];
1467 memcpy (pTemp
, pImpXPolygon
->pPointAry
, nIndex0
* sizeof (Point
));
1468 memcpy (pImpXPolygon
->pPointAry
, &pImpXPolygon
->pPointAry
[nIndex0
], (nPntCnt
- nIndex0
) * sizeof (Point
));
1469 memcpy (&pImpXPolygon
->pPointAry
[nIndex0
], pTemp
, nIndex0
* sizeof (Point
));
1474 basegfx::B2DPolygon
XPolygon::getB2DPolygon() const
1476 // #i74631# use tools Polygon class for conversion to not have the code doubled
1477 // here. This needs one more conversion but avoids different convertors in
1479 DBG_ASSERT(pImpXPolygon
!= 0, "XPolygon::getB2DPolygon(): XPolygon has no implementation incarnated (!)");
1480 const Polygon
aSource(GetPointCount(), pImpXPolygon
->pPointAry
, pImpXPolygon
->pFlagAry
);
1482 return aSource
.getB2DPolygon();
1485 XPolygon::XPolygon(const basegfx::B2DPolygon
& rPolygon
)
1487 // #i74631# use tools Polygon class for conversion to not have the code doubled
1488 // here. This needs one more conversion but avoids different convertors in
1490 DBG_CTOR(XPolygon
,NULL
);
1492 const Polygon
aSource(rPolygon
);
1493 USHORT nSize
= aSource
.GetSize();
1494 pImpXPolygon
= new ImpXPolygon( nSize
);
1495 pImpXPolygon
->nPoints
= nSize
;
1497 for( USHORT i
= 0; i
< nSize
; i
++ )
1499 pImpXPolygon
->pPointAry
[i
] = aSource
[i
];
1500 pImpXPolygon
->pFlagAry
[i
] = (BYTE
) aSource
.GetFlags( i
);
1504 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1505 //+--------------- XPolyPolygon -----------------------------------------+
1506 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1508 /*************************************************************************
1510 |* ImpXPolyPolygon::ImpXPolyPolygon()
1512 |* Beschreibung Erzeugt das XPolygon-Array
1513 |* Ersterstellung CL 09.11.94
1514 |* Letzte Aenderung MM 09.11.94
1516 *************************************************************************/
1518 ImpXPolyPolygon::ImpXPolyPolygon( const ImpXPolyPolygon
& rImpXPolyPoly
) :
1519 aXPolyList( rImpXPolyPoly
.aXPolyList
)
1523 // Einzelne Elemente duplizieren
1524 XPolygon
* pXPoly
= aXPolyList
.First();
1527 aXPolyList
.Replace( new XPolygon( *(aXPolyList
.GetCurObject()) ) );
1528 pXPoly
= aXPolyList
.Next();
1533 /*************************************************************************
1535 |* ImpXPolyPolygon::~ImpXPolyPolygon()
1537 |* Beschreibung Loescht das Polygon-Array
1538 |* Ersterstellung CL 09.06.93
1539 |* Letzte Aenderung CL 09.06.93
1541 *************************************************************************/
1543 ImpXPolyPolygon::~ImpXPolyPolygon()
1545 XPolygon
* pXPoly
= aXPolyList
.First();
1549 pXPoly
= aXPolyList
.Next();
1553 /*************************************************************************
1555 |* ImpXPolyPolygon::operator==()
1557 |* Ersterstellung Joe 26-09-95
1560 *************************************************************************/
1563 bool ImpXPolyPolygon::operator==(const ImpXPolyPolygon
& rImpXPolyPoly
) const
1565 USHORT nAnz
=(USHORT
)aXPolyList
.Count();
1566 const XPolygonList
& rCmpList
=rImpXPolyPoly
.aXPolyList
;
1567 if (nAnz
!=(USHORT
)rCmpList
.Count()) return FALSE
;
1569 for (USHORT i
=nAnz
; i
>0 && bEq
;) {
1571 bEq
= *aXPolyList
.GetObject(i
) == *rCmpList
.GetObject(i
);
1576 /*************************************************************************
1578 |* XPolyPolygon::XPolyPolygon()
1580 |* Beschreibung POLY.SDW
1581 |* Ersterstellung CL 27.01.93
1582 |* Letzte Aenderung CL 27.01.93
1584 *************************************************************************/
1586 XPolyPolygon::XPolyPolygon( USHORT nInitSize
, USHORT nResize
)
1588 DBG_CTOR(XPolyPolygon
,NULL
);
1589 pImpXPolyPolygon
= new ImpXPolyPolygon( nInitSize
, nResize
);
1593 /*************************************************************************
1595 |* XPolyPolygon::XPolyPolygon()
1597 |* Beschreibung POLY.SDW
1598 |* Ersterstellung CL 27.01.93
1599 |* Letzte Aenderung CL 27.01.93
1601 *************************************************************************/
1603 XPolyPolygon::XPolyPolygon( const XPolygon
& rXPoly
)
1605 DBG_CTOR(XPolyPolygon
,NULL
);
1606 pImpXPolyPolygon
= new ImpXPolyPolygon
;
1607 pImpXPolyPolygon
->aXPolyList
.Insert( new XPolygon( rXPoly
) );
1610 /*************************************************************************
1612 |* XPolyPolygon::XPolyPolygon()
1614 |* Beschreibung POLY.SDW
1615 |* Ersterstellung CL 27.01.93
1616 |* Letzte Aenderung CL 27.01.93
1618 *************************************************************************/
1620 XPolyPolygon::XPolyPolygon( const XPolyPolygon
& rXPolyPoly
)
1622 DBG_CTOR(XPolyPolygon
,NULL
);
1623 pImpXPolyPolygon
= rXPolyPoly
.pImpXPolyPolygon
;
1624 pImpXPolyPolygon
->nRefCount
++;
1627 /*************************************************************************
1629 |* XPolyPolygon::XPolyPolygon()
1631 |* XPolyPolygon aus einen Standard-PolyPolygon erzeugen
1632 |* Ersterstellung 18.01.95 ESO
1633 |* Letzte Aenderung 18.01.95 ESO
1635 *************************************************************************/
1637 XPolyPolygon::XPolyPolygon( const PolyPolygon
& rPolyPoly
)
1639 DBG_CTOR(XPolyPolygon
,NULL
);
1640 pImpXPolyPolygon
= new ImpXPolyPolygon
;
1642 for (USHORT i
= 0; i
< rPolyPoly
.Count(); i
++)
1643 pImpXPolyPolygon
->aXPolyList
.Insert(
1644 new XPolygon(rPolyPoly
.GetObject(i
)) );
1647 /*************************************************************************
1649 |* XPolyPolygon::~XPolyPolygon()
1651 |* Beschreibung POLY.SDW
1652 |* Ersterstellung CL 27.01.93
1653 |* Letzte Aenderung CL 27.01.93
1655 *************************************************************************/
1657 XPolyPolygon::~XPolyPolygon()
1659 DBG_DTOR(XPolyPolygon
,NULL
);
1660 if( pImpXPolyPolygon
->nRefCount
> 1 )
1661 pImpXPolyPolygon
->nRefCount
--;
1663 delete pImpXPolyPolygon
;
1666 /*************************************************************************
1668 |* XPolygon::CheckReference()
1670 |* Referenzzaehler desImpXPolyPoly pruefen und ggf. von diesem abkoppeln
1671 |* Ersterstellung 18.01.95 ESO
1672 |* Letzte Aenderung 18.01.95 ESO
1674 *************************************************************************/
1676 void XPolyPolygon::CheckReference()
1678 if( pImpXPolyPolygon
->nRefCount
> 1 )
1680 pImpXPolyPolygon
->nRefCount
--;
1681 pImpXPolyPolygon
= new ImpXPolyPolygon( *pImpXPolyPolygon
);
1685 /*************************************************************************
1687 |* XPolyPolygon::Insert()
1689 |* Beschreibung POLY.SDW
1690 |* Ersterstellung CL 27.01.93
1691 |* Letzte Aenderung CL 27.01.93
1693 *************************************************************************/
1695 void XPolyPolygon::Insert( const XPolygon
& rXPoly
, USHORT nPos
)
1698 XPolygon
* pXPoly
= new XPolygon( rXPoly
);
1699 pImpXPolyPolygon
->aXPolyList
.Insert( pXPoly
, nPos
);
1702 /*************************************************************************
1704 |* XPolyPolygon::Insert()
1706 |* saemtliche XPolygone aus einem XPolyPolygon einfuegen
1707 |* Ersterstellung 18.01.95 ESO
1708 |* Letzte Aenderung 18.01.95 ESO
1710 *************************************************************************/
1712 void XPolyPolygon::Insert( const XPolyPolygon
& rXPolyPoly
, USHORT nPos
)
1716 for (USHORT i
= 0; i
< rXPolyPoly
.Count(); i
++)
1718 XPolygon
* pXPoly
= new XPolygon(rXPolyPoly
[i
]);
1719 pImpXPolyPolygon
->aXPolyList
.Insert(pXPoly
, nPos
);
1720 if ( nPos
!= XPOLYPOLY_APPEND
)
1725 /*************************************************************************
1727 |* XPolyPolygon::Remove()
1729 |* Beschreibung POLY.SDW
1730 |* Ersterstellung CL 27.01.93
1731 |* Letzte Aenderung CL 27.01.93
1733 *************************************************************************/
1735 XPolygon
XPolyPolygon::Remove( USHORT nPos
)
1738 XPolygon
* pTmpXPoly
= pImpXPolyPolygon
->aXPolyList
.Remove( nPos
);
1739 XPolygon
aXPoly( *pTmpXPoly
);
1745 /*************************************************************************
1747 |* XPolyPolygon::Replace()
1749 |* Beschreibung POLY.SDW
1750 |* Ersterstellung CL 27.01.93
1751 |* Letzte Aenderung CL 27.01.93
1753 *************************************************************************/
1755 XPolygon
XPolyPolygon::Replace( const XPolygon
& rXPoly
, USHORT nPos
)
1758 XPolygon
* pXPoly
= new XPolygon( rXPoly
);
1759 XPolygon
* pTmpXPoly
= pImpXPolyPolygon
->aXPolyList
.Replace( pXPoly
, nPos
);
1760 XPolygon
aXPoly( *pTmpXPoly
);
1766 /*************************************************************************
1768 |* XPolyPolygon::GetObject()
1770 |* Beschreibung POLY.SDW
1771 |* Ersterstellung CL 27.01.93
1772 |* Letzte Aenderung CL 27.01.93
1774 *************************************************************************/
1776 const XPolygon
& XPolyPolygon::GetObject( USHORT nPos
) const
1778 return *(pImpXPolyPolygon
->aXPolyList
.GetObject( nPos
));
1782 /*************************************************************************
1784 |* XPolyPolygon::Clear()
1786 |* Beschreibung POLY.SDW
1787 |* Ersterstellung CL 27.01.93
1788 |* Letzte Aenderung TH 17.10.94
1790 *************************************************************************/
1792 void XPolyPolygon::Clear()
1794 if ( pImpXPolyPolygon
->nRefCount
> 1 )
1796 pImpXPolyPolygon
->nRefCount
--;
1797 pImpXPolyPolygon
= new ImpXPolyPolygon();
1801 XPolygon
* pXPoly
= pImpXPolyPolygon
->aXPolyList
.First();
1805 pXPoly
= pImpXPolyPolygon
->aXPolyList
.Next();
1807 pImpXPolyPolygon
->aXPolyList
.Clear();
1812 /*************************************************************************
1814 |* XPolyPolygon::Count()
1817 |* Ersterstellung CL 27.01.93
1818 |* Letzte Aenderung CL 27.01.93
1820 *************************************************************************/
1822 USHORT
XPolyPolygon::Count() const
1824 return (USHORT
)(pImpXPolyPolygon
->aXPolyList
.Count());
1828 /*************************************************************************
1830 |* XPolyPolygon::Move()
1832 |* Beschreibung POLY.SDW
1833 |* Ersterstellung TH 04.10.94
1834 |* Letzte Aenderung TH 04.10.94
1836 *************************************************************************/
1838 void XPolyPolygon::Move( long nHorzMove
, long nVertMove
)
1840 // Diese Abfrage sollte man fuer die DrawEngine durchfuehren
1841 if ( !nHorzMove
&& !nVertMove
)
1844 // Referenzcounter beruecksichtigen
1847 // Punkte verschieben
1848 XPolygon
* pXPoly
= pImpXPolyPolygon
->aXPolyList
.First();
1851 pXPoly
->Move( nHorzMove
, nVertMove
);
1852 pXPoly
= pImpXPolyPolygon
->aXPolyList
.Next();
1856 /*************************************************************************
1858 |* XPolyPolygon::GetBoundRect()
1860 |* Beschreibung POLY.SDW
1861 |* Ersterstellung TH 04.10.94
1862 |* Letzte Aenderung TH 04.10.94
1864 *************************************************************************/
1866 Rectangle
XPolyPolygon::GetBoundRect() const
1868 USHORT nXPoly
= (USHORT
)pImpXPolyPolygon
->aXPolyList
.Count();
1871 for ( USHORT n
= 0; n
< nXPoly
; n
++ )
1873 const XPolygon
* pXPoly
= pImpXPolyPolygon
->aXPolyList
.GetObject( n
);
1874 aRect
.Union( pXPoly
->GetBoundRect() );
1881 /*************************************************************************
1883 |* XPolyPolygon::operator[]()
1885 |* Beschreibung POLY.SDW
1886 |* Ersterstellung TH 28.10.94
1887 |* Letzte Aenderung TH 28.10.94
1889 *************************************************************************/
1891 XPolygon
& XPolyPolygon::operator[]( USHORT nPos
)
1894 return *(pImpXPolyPolygon
->aXPolyList
.GetObject( nPos
));
1897 /*************************************************************************
1899 |* XPolyPolygon::operator=()
1901 |* Beschreibung POLY.SDW
1902 |* Ersterstellung CL 27.01.93
1903 |* Letzte Aenderung CL 27.01.93
1905 *************************************************************************/
1907 XPolyPolygon
& XPolyPolygon::operator=( const XPolyPolygon
& rXPolyPoly
)
1909 rXPolyPoly
.pImpXPolyPolygon
->nRefCount
++;
1911 if( pImpXPolyPolygon
->nRefCount
> 1 )
1912 pImpXPolyPolygon
->nRefCount
--;
1914 delete pImpXPolyPolygon
;
1916 pImpXPolyPolygon
= rXPolyPoly
.pImpXPolyPolygon
;
1921 /*************************************************************************
1923 |* XPolyPolygon::operator==()
1925 |* Beschreibung POLY.SDW
1926 |* Ersterstellung CL 27.01.93
1927 |* Letzte Aenderung Joe 27.01.93
1929 *************************************************************************/
1931 BOOL
XPolyPolygon::operator==( const XPolyPolygon
& rXPolyPoly
) const
1933 if (pImpXPolyPolygon
==rXPolyPoly
.pImpXPolyPolygon
) return TRUE
;
1934 return *pImpXPolyPolygon
== *rXPolyPoly
.pImpXPolyPolygon
;
1938 /*************************************************************************
1940 |* XPolyPolygon::operator!=()
1942 |* Beschreibung POLY.SDW
1943 |* Ersterstellung CL 27.01.93
1944 |* Letzte Aenderung Joe 27.01.93
1946 *************************************************************************/
1948 BOOL
XPolyPolygon::operator!=( const XPolyPolygon
& rXPolyPoly
) const
1950 if (pImpXPolyPolygon
==rXPolyPoly
.pImpXPolyPolygon
) return FALSE
;
1951 return *pImpXPolyPolygon
!= *rXPolyPoly
.pImpXPolyPolygon
;
1954 /*************************************************************************
1956 |* XPolyPolygon::Translate()
1958 |* Alle Polygone auf den uebergebenen Punkt verschieben
1959 |* Ersterstellung ESO 25.01.95
1960 |* Letzte Aenderung ESO 25.01.95
1962 *************************************************************************/
1964 void XPolyPolygon::Translate(const Point
& rTrans
)
1968 for (USHORT i
= 0; i
< Count(); i
++)
1969 pImpXPolyPolygon
->aXPolyList
.GetObject(i
)->Translate(rTrans
);
1972 /*************************************************************************
1974 |* XPolyPolygon::Rotate()
1976 |* Alle Polygone um den Punkt rCenter drehen, Sinus und Cosinus
1977 |* muessen uebergeben werden
1978 |* Ersterstellung ESO 25.01.95
1979 |* Letzte Aenderung ESO 25.01.95
1981 *************************************************************************/
1983 void XPolyPolygon::Rotate(const Point
& rCenter
, double fSin
, double fCos
)
1987 for (USHORT i
= 0; i
< Count(); i
++)
1988 pImpXPolyPolygon
->aXPolyList
.GetObject(i
)->Rotate(rCenter
, fSin
, fCos
);
1991 /*************************************************************************
1993 |* Bestimme den linken, unteren Punkt des Polygons und richte das
1994 |* Polygon so aus, dass dieser Punkt auf dem Index 0 liegt
1996 \************************************************************************/
1998 void XPolyPolygon::Rotate20()
2002 for (USHORT i
= 0; i
< Count(); i
++)
2003 pImpXPolyPolygon
->aXPolyList
.GetObject(i
)->Rotate20();
2006 /*************************************************************************
2008 |* XPolyPolygon::Rotate()
2010 |* Alle Poylgone um den Punkt rCenter mit dem Winkel nAngle drehen
2011 |* Winkel in 10tel Grad, Wertebereich 0 - 3600
2012 |* Ersterstellung ESO 25.01.95
2013 |* Letzte Aenderung ESO 25.01.95
2015 *************************************************************************/
2017 void XPolyPolygon::Rotate(const Point
& rCenter
, USHORT nAngle
)
2023 double fAngle
= F_PI
* nAngle
/ 1800;
2024 double fSin
= sin(fAngle
);
2025 double fCos
= cos(fAngle
);
2026 Rotate(rCenter
, fSin
, fCos
);
2030 /*************************************************************************
2032 |* XPolyPolygon::Scale()
2034 |* Alle Polygone in X- und/oder Y-Richtung skalieren
2035 |* Ersterstellung ESO 01.02.95
2036 |* Letzte Aenderung ESO 01.02.95
2038 *************************************************************************/
2040 void XPolyPolygon::Scale(double fSx
, double fSy
)
2044 for (USHORT i
= 0; i
< Count(); i
++)
2045 pImpXPolyPolygon
->aXPolyList
.GetObject(i
)->Scale(fSx
, fSy
);
2048 /*************************************************************************
2050 |* XPolyPolygon::SlantX()
2052 |* Alle Polygone in X-Richtung um einen beliebigen Winkel kippen,
2053 |* bezogen auf eine Referenz-Y-Koordinate
2054 |* Ersterstellung ESO 01.02.95
2055 |* Letzte Aenderung ESO 01.02.95
2057 *************************************************************************/
2059 void XPolyPolygon::SlantX(long nYRef
, double fSin
, double fCos
)
2063 for (USHORT i
= 0; i
< Count(); i
++)
2064 pImpXPolyPolygon
->aXPolyList
.GetObject(i
)->SlantX(nYRef
, fSin
, fCos
);
2067 /*************************************************************************
2069 |* XPolyPolygon::SlantY()
2071 |* Alle Polygone in Y-Richtung um einen beliebigen Winkel kippen,
2072 |* bezogen auf eine Referenz-X-Koordinate
2073 |* Ersterstellung ESO 01.02.95
2074 |* Letzte Aenderung ESO 01.02.95
2076 *************************************************************************/
2078 void XPolyPolygon::SlantY(long nXRef
, double fSin
, double fCos
)
2082 for (USHORT i
= 0; i
< Count(); i
++)
2083 pImpXPolyPolygon
->aXPolyList
.GetObject(i
)->SlantY(nXRef
, fSin
, fCos
);
2086 /*************************************************************************
2088 |* XPolygon::Distort()
2090 |* XPolygon verzerren, indem die Koordinaten relativ zu einem
2091 |* Referenzrechteck in ein beliebiges Viereck skaliert werden
2092 |* Zuordnung der Viereck-Punkte im Polygon zum Referenzrechteck:
2093 |* 0: links oben 0----1
2094 |* 1: rechts oben | |
2095 |* 2: rechts unten 3----2
2097 |* Ersterstellung ESO 07.07.95
2098 |* Letzte Aenderung ESO 07.07.95
2100 *************************************************************************/
2102 void XPolyPolygon::Distort(const Rectangle
& rRefRect
,
2103 const XPolygon
& rDistortedRect
)
2107 for (USHORT i
= 0; i
< Count(); i
++)
2108 pImpXPolyPolygon
->aXPolyList
.GetObject(i
)->Distort(rRefRect
,
2112 basegfx::B2DPolyPolygon
XPolyPolygon::getB2DPolyPolygon() const
2114 basegfx::B2DPolyPolygon aRetval
;
2116 for(sal_uInt16
a(0L); a
< Count(); a
++)
2118 const XPolygon
& rPoly
= (*this)[a
];
2119 aRetval
.append(rPoly
.getB2DPolygon());
2125 XPolyPolygon::XPolyPolygon(const basegfx::B2DPolyPolygon
& rPolyPolygon
)
2127 DBG_CTOR(XPolyPolygon
,NULL
);
2128 pImpXPolyPolygon
= new ImpXPolyPolygon( 16, 16 );
2130 for(sal_uInt32
a(0L); a
< rPolyPolygon
.count(); a
++)
2132 basegfx::B2DPolygon aCandidate
= rPolyPolygon
.getB2DPolygon(a
);
2133 XPolygon
aNewPoly(aCandidate
);