1 /*****************************************************************************/
2 /* LibreDWG - free implementation of the DWG file format */
3 /* */
4 /* Copyright (C) 2019 Free Software Foundation, Inc. */
5 /* */
6 /* This library is free software, licensed under the terms of the GNU */
7 /* General Public License as published by the Free Software Foundation, */
8 /* either version 3 of the License, or (at your option) any later version. */
9 /* You should have received a copy of the GNU General Public License */
10 /* along with this program. If not, see <http://www.gnu.org/licenses/>. */
11 /*****************************************************************************/
12
13 /*
14 * geom.c: geometric projections from OCS
15 * Note: There are certainly bugs lurking here. Not thoroughly tested yet.
16 * written by Reini Urban
17 */
18
19 #include "../src/config.h"
20 #include <math.h>
21 #include <dwg.h>
22 #include "geom.h"
23
24 void
normalize(BITCODE_3DPOINT * out,BITCODE_3DPOINT pt)25 normalize (BITCODE_3DPOINT *out, BITCODE_3DPOINT pt)
26 {
27 double l = sqrt ((pt.x * pt.x) + (pt.y * pt.y) + (pt.z * pt.z));
28 *out = pt;
29 if (l != 1.0 && l != 0.0)
30 {
31 out->x = pt.x / l;
32 out->y = pt.y / l;
33 out->z = pt.z / l;
34 }
35 }
36
37 void
cross(BITCODE_3DPOINT * out,BITCODE_3DPOINT pt1,BITCODE_3DPOINT pt2)38 cross (BITCODE_3DPOINT *out, BITCODE_3DPOINT pt1, BITCODE_3DPOINT pt2)
39 {
40 out->x = pt1.y * pt2.z - pt1.z * pt2.y;
41 out->y = pt1.z * pt2.x - pt1.x * pt2.z;
42 out->z = pt1.x * pt2.y - pt1.y * pt2.x;
43 }
44
45 // transform a 2D point via its OCS (extrusion or normal) to 2D
46 void
transform_OCS_2d(BITCODE_2DPOINT * out,BITCODE_2DPOINT pt,BITCODE_BE ext)47 transform_OCS_2d (BITCODE_2DPOINT *out, BITCODE_2DPOINT pt, BITCODE_BE ext)
48 {
49 if (ext.x == 0.0 && ext.y == 0.0 && ext.z == 1.0)
50 {
51 *out = pt;
52 }
53 else if (ext.x == 0.0 && ext.y == 0.0 && ext.z == -1.0)
54 {
55 *out = pt;
56 out->x = - out->x;
57 }
58 else
59 {
60 /* This is called the "Arbitrary Axis Algorithm" to calculate
61 the OCS x-axis from the extrusion z-vector (the "normal") */
62 BITCODE_3DPOINT ax, ay, az, be;
63 be = (BITCODE_3DPOINT)ext;
64 normalize (&az, be);
65 if ((fabs (az.x) < 1 / 64.0) && (fabs (az.y) < 1 / 64.0))
66 {
67 BITCODE_3DPOINT tmp = { 0.0, 1.0, 0.0 };
68 cross (&tmp, tmp, az);
69 normalize (&ax, tmp);
70 }
71 else
72 {
73 BITCODE_3DPOINT tmp = { 0.0, 0.0, 1.0 };
74 cross (&tmp, tmp, az);
75 normalize (&ax, tmp);
76 }
77 cross (&ay, az, ax);
78 normalize (&ay, ay);
79 out->x = pt.x * ax.x + pt.y * ax.y;
80 out->y = pt.x * ay.x + pt.y * ay.y;
81 }
82 return;
83 }
84
85 // transform a 3D point via its OCS (extrusion or normal) to 3D
86 void
transform_OCS(BITCODE_3DPOINT * out,BITCODE_3DPOINT pt,BITCODE_BE ext)87 transform_OCS (BITCODE_3DPOINT *out, BITCODE_3DPOINT pt, BITCODE_BE ext)
88 {
89 if (ext.x == 0.0 && ext.y == 0.0 && ext.z == 1.0)
90 {
91 *out = pt;
92 }
93 else if (ext.x == 0.0 && ext.y == 0.0 && ext.z == -1.0)
94 {
95 *out = pt;
96 out->x = - out->x;
97 }
98 else
99 {
100 /* This is called the "Arbitrary Axis Algorithm" to calculate
101 the OCS x-axis from the extrusion z-vector */
102 BITCODE_3DPOINT ax, ay, az, be;
103 be = (BITCODE_3DPOINT)ext;
104 normalize (&az, be);
105 if ((fabs (az.x) < 1 / 64.0) && (fabs (az.y) < 1 / 64.0))
106 {
107 BITCODE_3DPOINT tmp = { 0.0, 1.0, 0.0 };
108 cross (&tmp, tmp, az);
109 normalize (&ax, tmp);
110 }
111 else
112 {
113 BITCODE_3DPOINT tmp = { 0.0, 0.0, 1.0 };
114 cross (&tmp, tmp, az);
115 normalize (&ax, tmp);
116 }
117 cross (&ay, az, ax);
118 normalize (&ay, ay);
119 out->x = pt.x * ax.x + pt.y * ax.y + pt.z * ax.z;
120 out->y = pt.x * ay.x + pt.y * ay.y + pt.z * ay.z;
121 out->z = pt.x * az.x + pt.y * az.y + pt.z * az.z;
122 }
123 return;
124 }
125
126 // TODO: bulge -> arc for svg and ps.
127 // Segmentation of arc,curves into plines for geojson.
128