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