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 : #ifndef INCLUDED_SVX_SVDTRANS_HXX
21 : #define INCLUDED_SVX_SVDTRANS_HXX
22 :
23 : #include <rtl/ustring.hxx>
24 : #include <svx/svxdllapi.h>
25 : #include <tools/fract.hxx>
26 : #include <tools/gen.hxx>
27 : #include <tools/poly.hxx>
28 : #include <vcl/field.hxx>
29 : #include <vcl/mapmod.hxx>
30 :
31 :
32 :
33 : // Winkelangaben der DrawingEngine sind 1/100 Degree
34 : // #i19054# nowhere used, removed // const int nWinkDiv=100;
35 : // Um Winkel der DrawingEngine mit den Trigonometrischen Funktionen
36 : // verarbeiten zu koennen, muessen sie zunaest ins Bogenmass umgerechnet
37 : // werden. Dies gestaltet sich recht einfach mit der folgenden Konstanten
38 : // nPi180. Sei nWink ein Winkel in 1/100 Deg so schreibt man z.B.:
39 : // double nSin=sin(nWink*nPi180);
40 : // Rueckwandlung entsprechend durch Teilen.
41 : const double nPi=3.14159265358979323846;
42 : const double nPi180=0.000174532925199432957692222; // Bei zuweing Stellen ist tan(4500*nPi180)!=1.0
43 :
44 : // Der maximale Shearwinkel
45 : #define SDRMAXSHEAR 8900
46 :
47 : class XPolygon;
48 : class XPolyPolygon;
49 :
50 0 : inline long Round(double a) { return a>0.0 ? (long)(a+0.5) : -(long)((-a)+0.5); }
51 :
52 0 : inline void MoveRect(Rectangle& rRect, const Size& S) { rRect.Move(S.Width(),S.Height()); }
53 0 : inline void MovePoint(Point& rPnt, const Size& S) { rPnt.X()+=S.Width(); rPnt.Y()+=S.Height(); }
54 0 : inline void MovePoly(Polygon& rPoly, const Size& S) { rPoly.Move(S.Width(),S.Height()); }
55 : inline void MovePoly(PolyPolygon& rPoly, const Size& S) { rPoly.Move(S.Width(),S.Height()); }
56 : void MoveXPoly(XPolygon& rPoly, const Size& S);
57 :
58 : SVX_DLLPUBLIC void ResizeRect(Rectangle& rRect, const Point& rRef, const Fraction& xFact, const Fraction& yFact, bool bNoJustify = false);
59 : inline void ResizePoint(Point& rPnt, const Point& rRef, Fraction xFact, Fraction yFact);
60 : void ResizePoly(Polygon& rPoly, const Point& rRef, const Fraction& xFact, const Fraction& yFact);
61 : void ResizeXPoly(XPolygon& rPoly, const Point& rRef, const Fraction& xFact, const Fraction& yFact);
62 :
63 : inline void RotatePoint(Point& rPnt, const Point& rRef, double sn, double cs);
64 : SVX_DLLPUBLIC void RotatePoly(Polygon& rPoly, const Point& rRef, double sn, double cs);
65 : void RotateXPoly(XPolygon& rPoly, const Point& rRef, double sn, double cs);
66 : void RotateXPoly(XPolyPolygon& rPoly, const Point& rRef, double sn, double cs);
67 :
68 : void MirrorPoint(Point& rPnt, const Point& rRef1, const Point& rRef2);
69 : void MirrorPoly(Polygon& rPoly, const Point& rRef1, const Point& rRef2);
70 : void MirrorXPoly(XPolygon& rPoly, const Point& rRef1, const Point& rRef2);
71 :
72 : inline void ShearPoint(Point& rPnt, const Point& rRef, double tn, bool bVShear = false);
73 : SVX_DLLPUBLIC void ShearPoly(Polygon& rPoly, const Point& rRef, double tn, bool bVShear = false);
74 : void ShearXPoly(XPolygon& rPoly, const Point& rRef, double tn, bool bVShear = false);
75 :
76 : // rPnt.X bzw rPnt.Y wird auf rCenter.X bzw. rCenter.Y gesetzt!
77 : // anschliessend muss rPnt nur noch um rCenter gedreht werden.
78 : // Der Rueckgabewinkel ist ausnahmsweise in Rad.
79 : inline double GetCrookAngle(Point& rPnt, const Point& rCenter, const Point& rRad, bool bVertical);
80 : // Die folgenden Methoden behandeln einen Punkt eines XPolygons, wobei die
81 : // benachbarten Kontrollpunkte des eigentlichen Punktes ggf. in pC1/pC2
82 : // uebergeben werden. Ueber rSin/rCos wird gleichzeitig sin(nWink) und cos(nWink)
83 : // zurueckgegeben.
84 : // Der Rueckgabewinkel ist hier ebenfalls in Rad.
85 : double CrookRotateXPoint(Point& rPnt, Point* pC1, Point* pC2, const Point& rCenter,
86 : const Point& rRad, double& rSin, double& rCos, bool bVert);
87 : double CrookSlantXPoint(Point& rPnt, Point* pC1, Point* pC2, const Point& rCenter,
88 : const Point& rRad, double& rSin, double& rCos, bool bVert);
89 : double CrookStretchXPoint(Point& rPnt, Point* pC1, Point* pC2, const Point& rCenter,
90 : const Point& rRad, double& rSin, double& rCos, bool bVert,
91 : const Rectangle rRefRect);
92 :
93 : void CrookRotatePoly(XPolygon& rPoly, const Point& rCenter, const Point& rRad, bool bVert);
94 : void CrookSlantPoly(XPolygon& rPoly, const Point& rCenter, const Point& rRad, bool bVert);
95 : void CrookStretchPoly(XPolygon& rPoly, const Point& rCenter, const Point& rRad, bool bVert, const Rectangle rRefRect);
96 :
97 : void CrookRotatePoly(XPolyPolygon& rPoly, const Point& rCenter, const Point& rRad, bool bVert);
98 : void CrookSlantPoly(XPolyPolygon& rPoly, const Point& rCenter, const Point& rRad, bool bVert);
99 : void CrookStretchPoly(XPolyPolygon& rPoly, const Point& rCenter, const Point& rRad, bool bVert, const Rectangle rRefRect);
100 :
101 : /**************************************************************************************************/
102 : /* Inline */
103 : /**************************************************************************************************/
104 :
105 0 : inline void ResizePoint(Point& rPnt, const Point& rRef, Fraction xFact, Fraction yFact)
106 : {
107 0 : if (xFact.GetDenominator()==0) xFact=Fraction(xFact.GetNumerator(),1); // DivZero abfangen
108 0 : if (yFact.GetDenominator()==0) yFact=Fraction(yFact.GetNumerator(),1); // DivZero abfangen
109 0 : rPnt.X()=rRef.X()+ Round(((double)(rPnt.X()-rRef.X())*xFact.GetNumerator())/xFact.GetDenominator());
110 0 : rPnt.Y()=rRef.Y()+ Round(((double)(rPnt.Y()-rRef.Y())*yFact.GetNumerator())/yFact.GetDenominator());
111 0 : }
112 :
113 0 : inline void RotatePoint(Point& rPnt, const Point& rRef, double sn, double cs)
114 : {
115 0 : long dx=rPnt.X()-rRef.X();
116 0 : long dy=rPnt.Y()-rRef.Y();
117 0 : rPnt.X()=Round(rRef.X()+dx*cs+dy*sn);
118 0 : rPnt.Y()=Round(rRef.Y()+dy*cs-dx*sn);
119 0 : }
120 :
121 0 : inline void ShearPoint(Point& rPnt, const Point& rRef, double tn, bool bVShear)
122 : {
123 0 : if (!bVShear) { // Horizontal
124 0 : if (rPnt.Y()!=rRef.Y()) { // sonst nicht noetig
125 0 : rPnt.X()-=Round((rPnt.Y()-rRef.Y())*tn);
126 : }
127 : } else { // ansonsten vertikal
128 0 : if (rPnt.X()!=rRef.X()) { // sonst nicht noetig
129 0 : rPnt.Y()-=Round((rPnt.X()-rRef.X())*tn);
130 : }
131 : }
132 0 : }
133 :
134 0 : inline double GetCrookAngle(Point& rPnt, const Point& rCenter, const Point& rRad, bool bVertical)
135 : {
136 : double nWink;
137 0 : if (bVertical) {
138 0 : long dy=rPnt.Y()-rCenter.Y();
139 0 : nWink=(double)dy/(double)rRad.Y();
140 0 : rPnt.Y()=rCenter.Y();
141 : } else {
142 0 : long dx=rCenter.X()-rPnt.X();
143 0 : nWink=(double)dx/(double)rRad.X();
144 0 : rPnt.X()=rCenter.X();
145 : }
146 0 : return nWink;
147 : }
148 :
149 : /**************************************************************************************************/
150 : /**************************************************************************************************/
151 :
152 : // Y-Achse zeigt nach unten! Die Funktion negiert bei der
153 : // Winkelberechnung die Y-Achse, sodass GetAngle(Point(0,-1))=90.00deg.
154 : // GetAngle(Point(0,0)) liefert 0.
155 : // Der Rueckgabewert liegt im Bereich -180.00..179.99 Degree und
156 : // ist in 1/100 Degree angegeben.
157 : SVX_DLLPUBLIC long GetAngle(const Point& rPnt);
158 : long NormAngle180(long a); // Winkel normalisieren auf -180.00..179.99
159 : SVX_DLLPUBLIC long NormAngle360(long a); // Winkel normalisieren auf 0.00..359.99
160 : sal_uInt16 GetAngleSector(long nWink); // Sektor im kartesischen Koordinatensystem bestimmen
161 : // Berechnet die Laenge von (0,0) via a^2 + b^2 = c^2
162 : // Zur Vermeidung von Ueberlaeufen werden ggf. einige Stellen ignoriert.
163 : long GetLen(const Point& rPnt);
164 :
165 : /*
166 : Transformation eines Rechtecks in ein Polygon unter ------------
167 : Anwendung der Winkelparameter aus GeoStat. /1 2/
168 : Referenzpunkt ist stets der Punkt 0, also die linke / /
169 : obere Ecke des Ausgangsrects. / /
170 : Bei der Berechnung des Polygons ist die Reihenfolge / /
171 : (erst Shear, dann Rotation vorgegeben). / / \
172 : / / |
173 : A) Ausgangsrechteck aRect B) Nach Anwendung von Shear /0 3/ Rot|
174 : +------------------+ -------------------- ------------ ------
175 : |0 1| \0 1\ C) Nach Anwendung
176 : | | \ \ von Rotate
177 : | | | \ \
178 : |3 2| | \3 2\
179 : +------------------+ | --------------------
180 : |Shr |
181 : Bei Rueckkonvertierung des Polygons in ein Rect ist die Reihenfolge
182 : zwangslaeufig umgekehrt:
183 : - Berechnung des Drehwinkels: Winkel der Strecke 0-1 aus Abb. C) zum Horizont
184 : - Rueckdrehung des geshearten Rects (man erhaelt Abb B))
185 : - Bestimmung der Breite des Rects=Laenge der Strecke 0-1 aus Abb. B)
186 : - Bestimmung der Hoehe des Rects=vertikaler Abstand zwischen den Punkten
187 : 0 und 3 aus Abb. B)
188 : - Bestimmung des Shear-Winkels aus der Strecke 0-3 zur Senkrechten.
189 : Es ist darauf zu achten, dass das Polygon bei einer zwischenzeitlichen
190 : Transformation evtl. gespiegelt wurde (Mirror oder Resize mit neg. Faktor).
191 : In diesem Fall muss zunaecht eine Normalisierung durch Vertauschung der
192 : Punkte (z.B. 0 mit 3 und 1 mit 2) durchgefuehrt werden, damit der
193 : Richtungssinn im Polygon wieder stimmig ist.
194 : Hinweis: Positiver Shear-Winkel bedeutet Shear mit auf dem Bildschirm
195 : sichtbarer positiver Kursivierung. Mathematisch waere dass eine negative
196 : Kursivierung, da die Y-Achse auf dem Bildschirm von oben nach unten verlaeuft.
197 : Drehwinkel: Positiv bedeutet auf dem Bildschirm sichtbare Linksdrehung.
198 : */
199 :
200 : class GeoStat { // Geometrischer Status fuer ein Rect
201 : public:
202 : long nDrehWink;
203 : long nShearWink;
204 : double nTan; // tan(nShearWink)
205 : double nSin; // sin(nDrehWink)
206 : double nCos; // cos(nDrehWink)
207 : bool bMirrored; // Horizontal gespiegelt? (ni)
208 : public:
209 0 : GeoStat(): nDrehWink(0),nShearWink(0),nTan(0.0),nSin(0.0),nCos(1.0),bMirrored(false) {}
210 : void RecalcSinCos();
211 : void RecalcTan();
212 : };
213 :
214 : Polygon Rect2Poly(const Rectangle& rRect, const GeoStat& rGeo);
215 : void Poly2Rect(const Polygon& rPol, Rectangle& rRect, GeoStat& rGeo);
216 :
217 : SVX_DLLPUBLIC void OrthoDistance8(const Point& rPt0, Point& rPt, bool bBigOrtho);
218 : SVX_DLLPUBLIC void OrthoDistance4(const Point& rPt0, Point& rPt, bool bBigOrtho);
219 :
220 : // Multiplikation und anschliessende Division.
221 : // Rechnung und Zwischenergebnis sind BigInt.
222 : SVX_DLLPUBLIC long BigMulDiv(long nVal, long nMul, long nDiv);
223 :
224 : // Fehlerbehaftetes Kuerzen einer Fraction.
225 : // nDigits gibt an, wieviele signifikante Stellen in
226 : // Zaehler/Nenner mindestens erhalten bleiben sollen.
227 : void Kuerzen(Fraction& rF, unsigned nDigits);
228 :
229 :
230 0 : class FrPair {
231 : Fraction aX;
232 : Fraction aY;
233 : public:
234 : FrPair() : aX(0,1),aY(0,1) {}
235 0 : FrPair(const Fraction& rBoth) : aX(rBoth),aY(rBoth) {}
236 0 : FrPair(const Fraction& rX, const Fraction& rY) : aX(rX),aY(rY) {}
237 0 : FrPair(long nMul, long nDiv) : aX(nMul,nDiv),aY(nMul,nDiv) {}
238 0 : FrPair(long xMul, long xDiv, long yMul, long yDiv): aX(xMul,xDiv),aY(yMul,yDiv) {}
239 : const Fraction& X() const { return aX; }
240 : const Fraction& Y() const { return aY; }
241 0 : Fraction& X() { return aX; }
242 0 : Fraction& Y() { return aY; }
243 : };
244 :
245 : // Fuer die Umrechnung von Masseinheiten
246 : SVX_DLLPUBLIC FrPair GetMapFactor(MapUnit eS, MapUnit eD);
247 : FrPair GetMapFactor(FieldUnit eS, FieldUnit eD);
248 :
249 0 : inline bool IsMetric(MapUnit eU) {
250 0 : return (eU==MAP_100TH_MM || eU==MAP_10TH_MM || eU==MAP_MM || eU==MAP_CM);
251 : }
252 :
253 0 : inline bool IsInch(MapUnit eU) {
254 0 : return (eU==MAP_1000TH_INCH || eU==MAP_100TH_INCH || eU==MAP_10TH_INCH || eU==MAP_INCH ||
255 0 : eU==MAP_POINT || eU==MAP_TWIP);
256 : }
257 :
258 0 : inline bool IsMetric(FieldUnit eU) {
259 0 : return (eU==FUNIT_MM || eU==FUNIT_CM || eU==FUNIT_M || eU==FUNIT_KM || eU==FUNIT_100TH_MM);
260 : }
261 :
262 0 : inline bool IsInch(FieldUnit eU) {
263 0 : return (eU==FUNIT_TWIP || eU==FUNIT_POINT || eU==FUNIT_PICA ||
264 0 : eU==FUNIT_INCH || eU==FUNIT_FOOT || eU==FUNIT_MILE);
265 : }
266 :
267 : class SVX_DLLPUBLIC SdrFormatter {
268 : Fraction aScale;
269 : long nMul_;
270 : long nDiv_;
271 : short nKomma_;
272 : bool bSrcFU;
273 : bool bDstFU;
274 : bool bDirty;
275 : MapUnit eSrcMU;
276 : MapUnit eDstMU;
277 : FieldUnit eSrcFU;
278 : FieldUnit eDstFU;
279 : private:
280 : SVX_DLLPRIVATE void Undirty();
281 0 : SVX_DLLPRIVATE void ForceUndirty() const { if (bDirty) ((SdrFormatter*)this)->Undirty(); }
282 : public:
283 0 : SdrFormatter(MapUnit eSrc, MapUnit eDst) { eSrcMU=eSrc; bSrcFU=false; eDstMU=eDst; bDstFU=false; bDirty=true; }
284 : SdrFormatter(MapUnit eSrc, FieldUnit eDst) { eSrcMU=eSrc; bSrcFU=false; eDstFU=eDst; bDstFU=true; bDirty=true; }
285 : SdrFormatter(FieldUnit eSrc, MapUnit eDst) { eSrcFU=eSrc; bSrcFU=true; eDstMU=eDst; bDstFU=false; bDirty=true; }
286 : SdrFormatter(FieldUnit eSrc, FieldUnit eDst) { eSrcFU=eSrc; bSrcFU=true; eDstFU=eDst; bDstFU=true; bDirty=true; }
287 : void SetSourceUnit(MapUnit eSrc) { eSrcMU=eSrc; bSrcFU=false; bDirty=true; }
288 : void SetSourceUnit(FieldUnit eSrc) { eSrcFU=eSrc; bSrcFU=true; bDirty=true; }
289 : void SetDestinationUnit(MapUnit eDst) { eDstMU=eDst; bDstFU=false; bDirty=true; }
290 : void SetDestinationUnit(FieldUnit eDst) { eDstFU=eDst; bDstFU=true; bDirty=true; }
291 : void TakeStr(long nVal, OUString& rStr) const;
292 : static void TakeUnitStr(MapUnit eUnit, OUString& rStr);
293 : static void TakeUnitStr(FieldUnit eUnit, OUString& rStr);
294 : static OUString GetUnitStr(MapUnit eUnit) { OUString aStr; TakeUnitStr(eUnit,aStr); return aStr; }
295 0 : static OUString GetUnitStr(FieldUnit eUnit) { OUString aStr; TakeUnitStr(eUnit,aStr); return aStr; }
296 : };
297 :
298 :
299 :
300 : #endif // INCLUDED_SVX_SVDTRANS_HXX
301 :
302 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|