1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_filter.hxx"
26 
27 #include <math.h>
28 #include <dxfvec.hxx>
29 
30 
31 //---------------------------- DXFVector ---------------------------------------
32 
33 
Abs() const34 double DXFVector::Abs() const
35 {
36 	return sqrt(SProd(*this));
37 }
38 
39 
Unit() const40 DXFVector DXFVector::Unit() const
41 {
42 	double flen;
43 
44 	flen=Abs();
45 	if (flen!=0) return (*this)*(1.0/flen);
46 	else return DXFVector(1.0,0.0,0.0);
47 }
48 
49 
50 //---------------------------- DXFTransform ------------------------------------
51 
52 
DXFTransform()53 DXFTransform::DXFTransform() :
54 	aMX(1.0, 0.0, 0.0),
55 	aMY(0.0, 1.0, 0.0),
56 	aMZ(0.0, 0.0, 1.0),
57 	aMP(0.0, 0.0, 0.0)
58 {
59 }
60 
61 
DXFTransform(double fScaleX,double fScaleY,double fScaleZ,const DXFVector & rShift)62 DXFTransform::DXFTransform(double fScaleX, double fScaleY, double fScaleZ,
63 						   const DXFVector & rShift) :
64 	aMX(fScaleX, 0.0, 0.0),
65 	aMY(0.0, fScaleY, 0.0),
66 	aMZ(0.0, 0.0, fScaleZ),
67 	aMP(rShift)
68 {
69 }
70 
71 
DXFTransform(double fScaleX,double fScaleY,double fScaleZ,double fRotAngle,const DXFVector & rShift)72 DXFTransform::DXFTransform(double fScaleX, double fScaleY, double fScaleZ,
73 						   double fRotAngle,
74 						   const DXFVector & rShift) :
75 	aMX(0.0, 0.0, 0.0),
76 	aMY(0.0, 0.0, 0.0),
77 	aMZ(0.0, 0.0, fScaleZ),
78 	aMP(rShift)
79 {
80 	aMX.fx=cos(3.14159265359/180.0*fRotAngle);
81 	aMX.fy=sin(3.14159265359/180.0*fRotAngle);
82 	aMY.fx=-aMX.fy;
83 	aMY.fy=aMX.fx;
84 	aMX*=fScaleX;
85 	aMY*=fScaleY;
86 }
87 
88 
DXFTransform(const DXFVector & rExtrusion)89 DXFTransform::DXFTransform(const DXFVector & rExtrusion) :
90 	aMX(), aMY(), aMZ(), aMP(0.0, 0.0, 0.0)
91 {
92 	// 'Arbitrary Axis Algorithm' (siehe DXF-Doku von Autodesk)
93 	if ( fabs(rExtrusion.fx) < 1.0/64.0 && fabs(rExtrusion.fy) < 1.0/64.0) {
94 		aMX = DXFVector(0.0, 1.0, 0.0) * rExtrusion;
95 	}
96 	else {
97 		aMX = DXFVector(0.0, 0.0, 1.0) * rExtrusion;
98 	}
99 	aMX=aMX.Unit();
100 	aMY=(rExtrusion*aMX).Unit();
101 	aMZ=rExtrusion.Unit();
102 }
103 
104 
DXFTransform(const DXFVector & rViewDir,const DXFVector & rViewTarget)105 DXFTransform::DXFTransform(const DXFVector & rViewDir, const DXFVector & rViewTarget) :
106 	aMX(), aMY(), aMZ(), aMP()
107 {
108 	DXFVector aV;
109 
110 	aV=rViewDir.Unit();
111 	aMX.fz=aV.fx;
112 	aMY.fz=aV.fy;
113 	aMZ.fz=aV.fz;
114 
115 	aMZ.fx=0;
116 	if (aV.fx==0) aMY.fx=0; else aMY.fx=sqrt(1/(1+aV.fy*aV.fy/(aV.fx*aV.fx)));
117 	aMX.fx=sqrt(1-aMY.fx*aMY.fx);
118 	if (aV.fx*aV.fy*aMY.fx>0) aMX.fx=-aMX.fx;
119 
120 	aV=aV*DXFVector(aMX.fx,aMY.fx,aMZ.fx);
121 	aMX.fy=aV.fx;
122 	aMY.fy=aV.fy;
123 	aMZ.fy=aV.fz;
124 
125 	if (aMZ.fy<0) {
126 		aMX.fy=-aMX.fy;
127 		aMY.fy=-aMY.fy;
128 		aMZ.fy=-aMZ.fy;
129 		aMX.fx=-aMX.fx;
130 		aMY.fx=-aMY.fx;
131 	}
132 
133 	aV=DXFVector(0,0,0)-rViewTarget;
134 	aMP.fx = aV.fx * aMX.fx + aV.fy * aMY.fx + aV.fz * aMZ.fx;
135 	aMP.fy = aV.fx * aMX.fy + aV.fy * aMY.fy + aV.fz * aMZ.fy;
136 	aMP.fz = aV.fx * aMX.fz + aV.fy * aMY.fz + aV.fz * aMZ.fz;
137 }
138 
139 
DXFTransform(const DXFTransform & rT1,const DXFTransform & rT2)140 DXFTransform::DXFTransform(const DXFTransform & rT1, const DXFTransform & rT2) :
141 	aMX(),aMY(),aMZ(),aMP()
142 {
143 	rT2.TransDir(rT1.aMX,aMX);
144 	rT2.TransDir(rT1.aMY,aMY);
145 	rT2.TransDir(rT1.aMZ,aMZ);
146 	rT2.Transform(rT1.aMP,aMP);
147 }
148 
149 
Transform(const DXFVector & rSrc,DXFVector & rTgt) const150 void DXFTransform::Transform(const DXFVector & rSrc, DXFVector & rTgt) const
151 {
152 	rTgt.fx = rSrc.fx * aMX.fx + rSrc.fy * aMY.fx + rSrc.fz * aMZ.fx + aMP.fx;
153 	rTgt.fy = rSrc.fx * aMX.fy + rSrc.fy * aMY.fy + rSrc.fz * aMZ.fy + aMP.fy;
154 	rTgt.fz = rSrc.fx * aMX.fz + rSrc.fy * aMY.fz + rSrc.fz * aMZ.fz + aMP.fz;
155 }
156 
157 
Transform(const DXFVector & rSrc,Point & rTgt) const158 void DXFTransform::Transform(const DXFVector & rSrc, Point & rTgt) const
159 {
160 	rTgt.X()=(long)( rSrc.fx * aMX.fx + rSrc.fy * aMY.fx + rSrc.fz * aMZ.fx + aMP.fx + 0.5 );
161 	rTgt.Y()=(long)( rSrc.fx * aMX.fy + rSrc.fy * aMY.fy + rSrc.fz * aMZ.fy + aMP.fy + 0.5 );
162 }
163 
164 
TransDir(const DXFVector & rSrc,DXFVector & rTgt) const165 void DXFTransform::TransDir(const DXFVector & rSrc, DXFVector & rTgt) const
166 {
167 	rTgt.fx = rSrc.fx * aMX.fx + rSrc.fy * aMY.fx + rSrc.fz * aMZ.fx;
168 	rTgt.fy = rSrc.fx * aMX.fy + rSrc.fy * aMY.fy + rSrc.fz * aMZ.fy;
169 	rTgt.fz = rSrc.fx * aMX.fz + rSrc.fy * aMY.fz + rSrc.fz * aMZ.fz;
170 }
171 
172 
TransCircleToEllipse(double fRadius,double & rEx,double & rEy) const173 sal_Bool DXFTransform::TransCircleToEllipse(double fRadius, double & rEx, double & rEy) const
174 {
175 	double fMXAbs=aMX.Abs();
176 	double fMYAbs=aMY.Abs();
177 	double fNearNull=(fMXAbs+fMYAbs)*0.001;
178 
179 	if (fabs(aMX.fy)<=fNearNull && fabs(aMX.fz)<=fNearNull &&
180 		fabs(aMY.fx)<=fNearNull && fabs(aMY.fz)<=fNearNull)
181 	{
182 		rEx=fabs(aMX.fx*fRadius);
183 		rEy=fabs(aMY.fy*fRadius);
184 		return sal_True;
185 	}
186 	else if (fabs(aMX.fx)<=fNearNull && fabs(aMX.fz)<=fNearNull &&
187 			 fabs(aMY.fy)<=fNearNull && fabs(aMY.fz)<=fNearNull)
188 	{
189 		rEx=fabs(aMY.fx*fRadius);
190 		rEy=fabs(aMX.fy*fRadius);
191 		return sal_True;
192 	}
193 	else if (fabs(fMXAbs-fMYAbs)<=fNearNull &&
194 			 fabs(aMX.fz)<=fNearNull && fabs(aMY.fz)<=fNearNull)
195 	{
196 		rEx=rEy=fabs(((fMXAbs+fMYAbs)/2)*fRadius);
197 		return sal_True;
198 	}
199 	else return sal_False;
200 }
201 
Transform(const DXFLineInfo & aDXFLineInfo) const202 LineInfo DXFTransform::Transform(const DXFLineInfo& aDXFLineInfo) const
203 {
204 	double fex,fey,scale;
205 
206 	fex=sqrt(aMX.fx*aMX.fx + aMX.fy*aMX.fy);
207 	fey=sqrt(aMY.fx*aMY.fx + aMY.fy*aMY.fy);
208 	scale = (fex+fey)/2.0;
209 
210 	LineInfo aLineInfo;
211 
212 	aLineInfo.SetStyle( aDXFLineInfo.eStyle );
213 	aLineInfo.SetWidth( (sal_Int32) (aDXFLineInfo.fWidth * scale + 0.5) );
214 	aLineInfo.SetDashCount( static_cast< sal_uInt16 >( aDXFLineInfo.nDashCount ) );
215 	aLineInfo.SetDashLen( (sal_Int32) (aDXFLineInfo.fDashLen * scale + 0.5) );
216 	aLineInfo.SetDotCount( static_cast< sal_uInt16 >( aDXFLineInfo.nDotCount ) );
217 	aLineInfo.SetDotLen( (sal_Int32) (aDXFLineInfo.fDotLen * scale + 0.5) );
218 	aLineInfo.SetDistance( (sal_Int32) (aDXFLineInfo.fDistance * scale + 0.5) );
219 
220 	if ( aLineInfo.GetDashCount() > 0 && aLineInfo.GetDashLen() == 0 )
221 		aLineInfo.SetDashLen(1);
222 
223 	if ( aLineInfo.GetDotCount() > 0 && aLineInfo.GetDotLen() == 0 )
224 		aLineInfo.SetDotLen(1);
225 
226 	return aLineInfo;
227 }
228 
TransLineWidth(double fW) const229 sal_uLong DXFTransform::TransLineWidth(double fW) const
230 {
231 	double fex,fey;
232 
233 	fex=sqrt(aMX.fx*aMX.fx + aMX.fy*aMX.fy);
234 	fey=sqrt(aMY.fx*aMY.fx + aMY.fy*aMY.fy);
235 	// ###
236 	// printf("fex=%f fey=%f\n", fex, fey);
237 	return (sal_uLong)(fabs(fW)*(fex+fey)/2.0+0.5);
238 }
239 
240 
CalcRotAngle() const241 double DXFTransform::CalcRotAngle() const
242 {
243 	return atan2(aMX.fy,aMX.fx)/3.14159265359*180.0;
244 }
245 
Mirror() const246 sal_Bool DXFTransform::Mirror() const
247 {
248 	if (aMZ.SProd(aMX*aMY)<0) return sal_True; else return sal_False;
249 }
250 
251