Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: DXF Translator
4 : * Purpose: Implements the OCS to WCS transformer used in DXF files.
5 : * Author: Frank Warmerdam, warmerdam@pobox.com
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2009, Frank Warmerdam <warmerdam@pobox.com>
9 : * Copyright (c) 2010-2013, Even Rouault <even dot rouault at spatialys.com>
10 : * Copyright (c) 2018, Alan Thomas <alant@outlook.com.au>
11 : *
12 : * Permission is hereby granted, free of charge, to any person obtaining a
13 : * copy of this software and associated documentation files (the "Software"),
14 : * to deal in the Software without restriction, including without limitation
15 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16 : * and/or sell copies of the Software, and to permit persons to whom the
17 : * Software is furnished to do so, subject to the following conditions:
18 : *
19 : * The above copyright notice and this permission notice shall be included
20 : * in all copies or substantial portions of the Software.
21 : *
22 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28 : * DEALINGS IN THE SOFTWARE.
29 : ****************************************************************************/
30 :
31 : #include "ogr_dxf.h"
32 :
33 : /************************************************************************/
34 : /* Mathematical helpers */
35 : /************************************************************************/
36 :
37 63 : static double Det2x2(double a, double b, double c, double d)
38 : {
39 63 : return a * d - b * c;
40 : }
41 :
42 3776 : static void CrossProduct(const double *a, const double *b, double *vResult)
43 : {
44 3776 : vResult[0] = a[1] * b[2] - a[2] * b[1];
45 3776 : vResult[1] = a[2] * b[0] - a[0] * b[2];
46 3776 : vResult[2] = a[0] * b[1] - a[1] * b[0];
47 3776 : }
48 :
49 5664 : static void Scale2Unit(double *adfV)
50 : {
51 : double dfLen =
52 5664 : sqrt(adfV[0] * adfV[0] + adfV[1] * adfV[1] + adfV[2] * adfV[2]);
53 5664 : if (dfLen != 0)
54 : {
55 5664 : adfV[0] /= dfLen;
56 5664 : adfV[1] /= dfLen;
57 5664 : adfV[2] /= dfLen;
58 : }
59 5664 : }
60 :
61 : /************************************************************************/
62 : /* OGRDXFOCSTransformer() */
63 : /************************************************************************/
64 :
65 1888 : OGRDXFOCSTransformer::OGRDXFOCSTransformer(double adfNIn[3],
66 1888 : bool bInverse /* = false */)
67 39648 : : aadfInverse()
68 : {
69 : static const double dSmall = 1.0 / 64.0;
70 : static const double adfWZ[3] = {0.0, 0.0, 1.0};
71 : static const double adfWY[3] = {0.0, 1.0, 0.0};
72 :
73 1888 : dfDeterminant = 0.0;
74 1888 : Scale2Unit(adfNIn);
75 1888 : memcpy(adfN, adfNIn, sizeof(double) * 3);
76 :
77 1888 : if ((std::abs(adfN[0]) < dSmall) && (std::abs(adfN[1]) < dSmall))
78 1825 : CrossProduct(adfWY, adfN, adfAX);
79 : else
80 63 : CrossProduct(adfWZ, adfN, adfAX);
81 :
82 1888 : Scale2Unit(adfAX);
83 1888 : CrossProduct(adfN, adfAX, adfAY);
84 1888 : Scale2Unit(adfAY);
85 :
86 1888 : if (bInverse == true)
87 : {
88 7 : const double a[4] = {0.0, adfAX[0], adfAY[0], adfN[0]};
89 7 : const double b[4] = {0.0, adfAX[1], adfAY[1], adfN[1]};
90 7 : const double c[4] = {0.0, adfAX[2], adfAY[2], adfN[2]};
91 :
92 7 : dfDeterminant = a[1] * b[2] * c[3] - a[1] * b[3] * c[2] +
93 7 : a[2] * b[3] * c[1] - a[2] * b[1] * c[3] +
94 7 : a[3] * b[1] * c[2] - a[3] * b[2] * c[1];
95 :
96 7 : if (dfDeterminant != 0.0)
97 : {
98 7 : const double k = 1.0 / dfDeterminant;
99 7 : const double a11 = adfAX[0];
100 7 : const double a12 = adfAY[0];
101 7 : const double a13 = adfN[0];
102 7 : const double a21 = adfAX[1];
103 7 : const double a22 = adfAY[1];
104 7 : const double a23 = adfN[1];
105 7 : const double a31 = adfAX[2];
106 7 : const double a32 = adfAY[2];
107 7 : const double a33 = adfN[2];
108 :
109 7 : aadfInverse[1][1] = k * Det2x2(a22, a23, a32, a33);
110 7 : aadfInverse[1][2] = k * Det2x2(a13, a12, a33, a32);
111 7 : aadfInverse[1][3] = k * Det2x2(a12, a13, a22, a23);
112 :
113 7 : aadfInverse[2][1] = k * Det2x2(a23, a21, a33, a31);
114 7 : aadfInverse[2][2] = k * Det2x2(a11, a13, a31, a33);
115 7 : aadfInverse[2][3] = k * Det2x2(a13, a11, a23, a21);
116 :
117 7 : aadfInverse[3][1] = k * Det2x2(a21, a22, a31, a32);
118 7 : aadfInverse[3][2] = k * Det2x2(a12, a11, a32, a31);
119 7 : aadfInverse[3][3] = k * Det2x2(a11, a12, a21, a22);
120 : }
121 : }
122 1888 : }
123 :
124 : /************************************************************************/
125 : /* Transform() */
126 : /************************************************************************/
127 :
128 1915 : int OGRDXFOCSTransformer::Transform(size_t nCount, double *adfX, double *adfY,
129 : double *adfZ, double * /* adfT */,
130 : int *pabSuccess /* = nullptr */)
131 : {
132 13295 : for (size_t i = 0; i < nCount; i++)
133 : {
134 11380 : const double x = adfX[i];
135 11380 : const double y = adfY[i];
136 11380 : const double z = adfZ[i];
137 :
138 11380 : adfX[i] = x * adfAX[0] + y * adfAY[0] + z * adfN[0];
139 11380 : adfY[i] = x * adfAX[1] + y * adfAY[1] + z * adfN[1];
140 11380 : adfZ[i] = x * adfAX[2] + y * adfAY[2] + z * adfN[2];
141 :
142 11380 : if (pabSuccess)
143 11380 : pabSuccess[i] = TRUE;
144 : }
145 1915 : return TRUE;
146 : }
147 :
148 : /************************************************************************/
149 : /* InverseTransform() */
150 : /************************************************************************/
151 :
152 14 : int OGRDXFOCSTransformer::InverseTransform(size_t nCount, double *adfX,
153 : double *adfY, double *adfZ)
154 : {
155 14 : if (dfDeterminant == 0.0)
156 0 : return FALSE;
157 :
158 28 : for (size_t i = 0; i < nCount; i++)
159 : {
160 14 : const double x = adfX[i];
161 14 : const double y = adfY[i];
162 14 : const double z = adfZ[i];
163 :
164 14 : adfX[i] = x * aadfInverse[1][1] + y * aadfInverse[1][2] +
165 14 : z * aadfInverse[1][3];
166 14 : adfY[i] = x * aadfInverse[2][1] + y * aadfInverse[2][2] +
167 14 : z * aadfInverse[2][3];
168 14 : adfZ[i] = x * aadfInverse[3][1] + y * aadfInverse[3][2] +
169 14 : z * aadfInverse[3][3];
170 : }
171 14 : return TRUE;
172 : }
173 :
174 : /************************************************************************/
175 : /* ComposeOnto() */
176 : /* */
177 : /* Applies this transformer to the given affine transformer. */
178 : /************************************************************************/
179 :
180 3 : void OGRDXFOCSTransformer::ComposeOnto(OGRDXFAffineTransform &oCT) const
181 : {
182 : double adfNew[12];
183 :
184 3 : adfNew[0] = adfAX[0] * oCT.adfData[0] + adfAY[0] * oCT.adfData[1] +
185 3 : adfN[0] * oCT.adfData[2];
186 3 : adfNew[1] = adfAX[1] * oCT.adfData[0] + adfAY[1] * oCT.adfData[1] +
187 3 : adfN[1] * oCT.adfData[2];
188 3 : adfNew[2] = adfAX[2] * oCT.adfData[0] + adfAY[2] * oCT.adfData[1] +
189 3 : adfN[2] * oCT.adfData[2];
190 :
191 3 : adfNew[3] = adfAX[0] * oCT.adfData[3] + adfAY[0] * oCT.adfData[4] +
192 3 : adfN[0] * oCT.adfData[5];
193 3 : adfNew[4] = adfAX[1] * oCT.adfData[3] + adfAY[1] * oCT.adfData[4] +
194 3 : adfN[1] * oCT.adfData[5];
195 3 : adfNew[5] = adfAX[2] * oCT.adfData[3] + adfAY[2] * oCT.adfData[4] +
196 3 : adfN[2] * oCT.adfData[5];
197 :
198 3 : adfNew[6] = adfAX[0] * oCT.adfData[6] + adfAY[0] * oCT.adfData[7] +
199 3 : adfN[0] * oCT.adfData[8];
200 3 : adfNew[7] = adfAX[1] * oCT.adfData[6] + adfAY[1] * oCT.adfData[7] +
201 3 : adfN[1] * oCT.adfData[8];
202 3 : adfNew[8] = adfAX[2] * oCT.adfData[6] + adfAY[2] * oCT.adfData[7] +
203 3 : adfN[2] * oCT.adfData[8];
204 :
205 3 : adfNew[9] = adfAX[0] * oCT.adfData[9] + adfAY[0] * oCT.adfData[10] +
206 3 : adfN[0] * oCT.adfData[11];
207 3 : adfNew[10] = adfAX[1] * oCT.adfData[9] + adfAY[1] * oCT.adfData[10] +
208 3 : adfN[1] * oCT.adfData[11];
209 3 : adfNew[11] = adfAX[2] * oCT.adfData[9] + adfAY[2] * oCT.adfData[10] +
210 3 : adfN[2] * oCT.adfData[11];
211 :
212 3 : memcpy(oCT.adfData, adfNew, sizeof(adfNew));
213 3 : }
|