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 : * SPDX-License-Identifier: MIT
13 : ****************************************************************************/
14 :
15 : #include "ogr_dxf.h"
16 :
17 : /************************************************************************/
18 : /* Mathematical helpers */
19 : /************************************************************************/
20 :
21 63 : static double Det2x2(double a, double b, double c, double d)
22 : {
23 63 : return a * d - b * c;
24 : }
25 :
26 3868 : static void CrossProduct(const double *a, const double *b, double *vResult)
27 : {
28 3868 : vResult[0] = a[1] * b[2] - a[2] * b[1];
29 3868 : vResult[1] = a[2] * b[0] - a[0] * b[2];
30 3868 : vResult[2] = a[0] * b[1] - a[1] * b[0];
31 3868 : }
32 :
33 5802 : static void Scale2Unit(double *adfV)
34 : {
35 : double dfLen =
36 5802 : sqrt(adfV[0] * adfV[0] + adfV[1] * adfV[1] + adfV[2] * adfV[2]);
37 5802 : if (dfLen != 0)
38 : {
39 5802 : adfV[0] /= dfLen;
40 5802 : adfV[1] /= dfLen;
41 5802 : adfV[2] /= dfLen;
42 : }
43 5802 : }
44 :
45 : /************************************************************************/
46 : /* OGRDXFOCSTransformer() */
47 : /************************************************************************/
48 :
49 1934 : OGRDXFOCSTransformer::OGRDXFOCSTransformer(double adfNIn[3],
50 1934 : bool bInverse /* = false */)
51 40614 : : aadfInverse()
52 : {
53 : static const double dSmall = 1.0 / 64.0;
54 : static const double adfWZ[3] = {0.0, 0.0, 1.0};
55 : static const double adfWY[3] = {0.0, 1.0, 0.0};
56 :
57 1934 : dfDeterminant = 0.0;
58 1934 : Scale2Unit(adfNIn);
59 1934 : memcpy(adfN, adfNIn, sizeof(double) * 3);
60 :
61 1934 : if ((std::abs(adfN[0]) < dSmall) && (std::abs(adfN[1]) < dSmall))
62 1871 : CrossProduct(adfWY, adfN, adfAX);
63 : else
64 63 : CrossProduct(adfWZ, adfN, adfAX);
65 :
66 1934 : Scale2Unit(adfAX);
67 1934 : CrossProduct(adfN, adfAX, adfAY);
68 1934 : Scale2Unit(adfAY);
69 :
70 1934 : if (bInverse == true)
71 : {
72 7 : const double a[4] = {0.0, adfAX[0], adfAY[0], adfN[0]};
73 7 : const double b[4] = {0.0, adfAX[1], adfAY[1], adfN[1]};
74 7 : const double c[4] = {0.0, adfAX[2], adfAY[2], adfN[2]};
75 :
76 7 : dfDeterminant = a[1] * b[2] * c[3] - a[1] * b[3] * c[2] +
77 7 : a[2] * b[3] * c[1] - a[2] * b[1] * c[3] +
78 7 : a[3] * b[1] * c[2] - a[3] * b[2] * c[1];
79 :
80 7 : if (dfDeterminant != 0.0)
81 : {
82 7 : const double k = 1.0 / dfDeterminant;
83 7 : const double a11 = adfAX[0];
84 7 : const double a12 = adfAY[0];
85 7 : const double a13 = adfN[0];
86 7 : const double a21 = adfAX[1];
87 7 : const double a22 = adfAY[1];
88 7 : const double a23 = adfN[1];
89 7 : const double a31 = adfAX[2];
90 7 : const double a32 = adfAY[2];
91 7 : const double a33 = adfN[2];
92 :
93 7 : aadfInverse[1][1] = k * Det2x2(a22, a23, a32, a33);
94 7 : aadfInverse[1][2] = k * Det2x2(a13, a12, a33, a32);
95 7 : aadfInverse[1][3] = k * Det2x2(a12, a13, a22, a23);
96 :
97 7 : aadfInverse[2][1] = k * Det2x2(a23, a21, a33, a31);
98 7 : aadfInverse[2][2] = k * Det2x2(a11, a13, a31, a33);
99 7 : aadfInverse[2][3] = k * Det2x2(a13, a11, a23, a21);
100 :
101 7 : aadfInverse[3][1] = k * Det2x2(a21, a22, a31, a32);
102 7 : aadfInverse[3][2] = k * Det2x2(a12, a11, a32, a31);
103 7 : aadfInverse[3][3] = k * Det2x2(a11, a12, a21, a22);
104 : }
105 : }
106 1934 : }
107 :
108 : /************************************************************************/
109 : /* Transform() */
110 : /************************************************************************/
111 :
112 1961 : int OGRDXFOCSTransformer::Transform(size_t nCount, double *adfX, double *adfY,
113 : double *adfZ, double * /* adfT */,
114 : int *pabSuccess /* = nullptr */)
115 : {
116 13525 : for (size_t i = 0; i < nCount; i++)
117 : {
118 11564 : const double x = adfX[i];
119 11564 : const double y = adfY[i];
120 11564 : const double z = adfZ[i];
121 :
122 11564 : adfX[i] = x * adfAX[0] + y * adfAY[0] + z * adfN[0];
123 11564 : adfY[i] = x * adfAX[1] + y * adfAY[1] + z * adfN[1];
124 11564 : adfZ[i] = x * adfAX[2] + y * adfAY[2] + z * adfN[2];
125 :
126 11564 : if (pabSuccess)
127 11564 : pabSuccess[i] = TRUE;
128 : }
129 1961 : return TRUE;
130 : }
131 :
132 : /************************************************************************/
133 : /* InverseTransform() */
134 : /************************************************************************/
135 :
136 14 : int OGRDXFOCSTransformer::InverseTransform(size_t nCount, double *adfX,
137 : double *adfY, double *adfZ)
138 : {
139 14 : if (dfDeterminant == 0.0)
140 0 : return FALSE;
141 :
142 28 : for (size_t i = 0; i < nCount; i++)
143 : {
144 14 : const double x = adfX[i];
145 14 : const double y = adfY[i];
146 14 : const double z = adfZ[i];
147 :
148 14 : adfX[i] = x * aadfInverse[1][1] + y * aadfInverse[1][2] +
149 14 : z * aadfInverse[1][3];
150 14 : adfY[i] = x * aadfInverse[2][1] + y * aadfInverse[2][2] +
151 14 : z * aadfInverse[2][3];
152 14 : adfZ[i] = x * aadfInverse[3][1] + y * aadfInverse[3][2] +
153 14 : z * aadfInverse[3][3];
154 : }
155 14 : return TRUE;
156 : }
157 :
158 : /************************************************************************/
159 : /* ComposeOnto() */
160 : /* */
161 : /* Applies this transformer to the given affine transformer. */
162 : /************************************************************************/
163 :
164 3 : void OGRDXFOCSTransformer::ComposeOnto(OGRDXFAffineTransform &oCT) const
165 : {
166 : double adfNew[12];
167 :
168 3 : adfNew[0] = adfAX[0] * oCT.adfData[0] + adfAY[0] * oCT.adfData[1] +
169 3 : adfN[0] * oCT.adfData[2];
170 3 : adfNew[1] = adfAX[1] * oCT.adfData[0] + adfAY[1] * oCT.adfData[1] +
171 3 : adfN[1] * oCT.adfData[2];
172 3 : adfNew[2] = adfAX[2] * oCT.adfData[0] + adfAY[2] * oCT.adfData[1] +
173 3 : adfN[2] * oCT.adfData[2];
174 :
175 3 : adfNew[3] = adfAX[0] * oCT.adfData[3] + adfAY[0] * oCT.adfData[4] +
176 3 : adfN[0] * oCT.adfData[5];
177 3 : adfNew[4] = adfAX[1] * oCT.adfData[3] + adfAY[1] * oCT.adfData[4] +
178 3 : adfN[1] * oCT.adfData[5];
179 3 : adfNew[5] = adfAX[2] * oCT.adfData[3] + adfAY[2] * oCT.adfData[4] +
180 3 : adfN[2] * oCT.adfData[5];
181 :
182 3 : adfNew[6] = adfAX[0] * oCT.adfData[6] + adfAY[0] * oCT.adfData[7] +
183 3 : adfN[0] * oCT.adfData[8];
184 3 : adfNew[7] = adfAX[1] * oCT.adfData[6] + adfAY[1] * oCT.adfData[7] +
185 3 : adfN[1] * oCT.adfData[8];
186 3 : adfNew[8] = adfAX[2] * oCT.adfData[6] + adfAY[2] * oCT.adfData[7] +
187 3 : adfN[2] * oCT.adfData[8];
188 :
189 3 : adfNew[9] = adfAX[0] * oCT.adfData[9] + adfAY[0] * oCT.adfData[10] +
190 3 : adfN[0] * oCT.adfData[11];
191 3 : adfNew[10] = adfAX[1] * oCT.adfData[9] + adfAY[1] * oCT.adfData[10] +
192 3 : adfN[1] * oCT.adfData[11];
193 3 : adfNew[11] = adfAX[2] * oCT.adfData[9] + adfAY[2] * oCT.adfData[10] +
194 3 : adfN[2] * oCT.adfData[11];
195 :
196 3 : memcpy(oCT.adfData, adfNew, sizeof(adfNew));
197 3 : }
|