]> Shamusworld >> Repos - architektonas/blob - src/structs.cpp
883e934e20e0d5629b7f664649721ecd8fbdf78f
[architektonas] / src / structs.cpp
1 //
2 // structs.cpp: Useful structs to describe objects
3 //
4 // Part of the Architektonas Project
5 // (C) 2022 Underground Software
6 // See the README and GPLv3 files for licensing and warranty information
7 //
8 // JLH = James Hammons <jlhamm@acm.org>
9 //
10 // WHO  WHEN        WHAT
11 // ---  ----------  ------------------------------------------------------------
12 // JLH  01/13/2022  Created this file
13
14 #include "structs.h"
15 #include <math.h>
16 #include "mathconstants.h"
17
18 const char objName[OTCount][16] = {
19         "None", "Line", "Circle", "Ellipse", "Arc", "Polygon", "Dimension",
20         "Spline", "Text", "Container"
21 };
22 const char dimName[DTCount][32] = {
23         "Linear", "Vertical", "Horizontal", "Radial", "Diametric",
24         "Circumferential", "Angular", "Leader"
25 };
26
27 const char buShortName[BUCount][8] = {
28         "in", "ft", "yd", "mi", "mm", "cm", "m", "km"
29 };
30
31 const double buInInches[BUCount] = { 1.0, 12.0, 36.0, 1.0/25.4, 1.0/2.54, 1.0/0.0254, 1.0/0.0000254 };
32
33 //
34 // struct Line
35 //
36 Line::Line(): type(OTLine), id(Global::objectID++), selected(false), hovered(false), hitObject(false)
37 {
38         hitPoint[0] = hitPoint[1] = false;
39 }
40
41 Line::Line(Vector pt1, Vector pt2, float th/*= 1.0*/, uint32_t c/* = 0*/, int l/*= LSSolid*/): type(OTLine), id(Global::objectID++), layer(0), color(c), thickness(th), style(l), selected(false), hovered(false), hitObject(false)
42 {
43         p[0] = pt1;
44         p[1] = pt2;
45         hitPoint[0] = hitPoint[1] = false;
46 }
47
48 Vector Line::Vect(void)
49 {
50         return Vector(p[0], p[1]);
51 }
52
53 Vector Line::Unit(void)
54 {
55         return Vector(p[0], p[1]).Unit();
56 }
57
58 double Line::Length(void)
59 {
60         return Vector(p[0], p[1]).Magnitude();
61 }
62
63 //
64 // struct Circle
65 //
66 Circle::Circle(): type(OTCircle), id(Global::objectID++)
67 {
68 }
69
70 Circle::Circle(Vector pt1, double r, float th/*= 1.0*/, uint32_t c/*= 0*/, int l/*= LSSolid*/): type(OTCircle), id(Global::objectID++), layer(0), color(c), thickness(th), style(l), selected(false), hovered(false), hitObject(false)
71 {
72         p[0] = pt1;
73         radius[0] = r;
74         hitPoint[0] = hitPoint[1] = false;
75 }
76
77 //
78 // struct Ellipse
79 //
80 Ellipse::Ellipse(): type(OTEllipse), id(Global::objectID++)
81 {
82 }
83
84 Ellipse::Ellipse(Vector pt1, Vector pt2, double r1, double r2, float th/*= 1.0*/, uint32_t c/*= 0*/, int l/*= LSSolid*/): type(OTEllipse), id(Global::objectID++), layer(0), color(c), thickness(th), style(l), selected(false), hovered(false), hitObject(false)
85 {
86         p[0] = pt1;
87         p[1] = pt2;
88         radius[0] = r1;
89         radius[1] = r2;
90         hitPoint[0] = hitPoint[1] = false;
91 }
92
93 //
94 // struct Arc
95 //
96 Arc::Arc(): type(OTArc), id(Global::objectID++)
97 {
98 }
99
100 Arc::Arc(Vector ctr, double r, double a1, double a2, float th/*= 1.0*/, uint32_t c/*= 0*/, int l/*= LSSolid*/): type(OTArc), id(Global::objectID++), layer(0), color(c), thickness(th), style(l), selected(false), hovered(false), hitObject(false)
101 {
102         p[0] = ctr;
103         radius[0] = r;
104         angle[0] = a1;
105         angle[1] = a2;
106         hitPoint[0] = hitPoint[1] = hitPoint[2] = false;
107 }
108
109 Arc::Arc(Vector ctr, double r, Point p1, Point p2, float th/*= 1.0*/, uint32_t c/*= 0*/, int l/*= LSSolid*/): type(OTArc), id(Global::objectID++), layer(0), color(c), thickness(th), style(l), selected(false), hovered(false), hitObject(false)
110 {
111         p[0] = ctr;
112         radius[0] = r;
113         angle[0] = Vector::Angle(ctr, p1);
114 /*
115 s =  10, e =  20, span = 10 (why not -350?)
116 s =  20, e =  10, span = -10 (why not 350?)
117 s =  10, e = 350, span = 340 (why not -20?)
118 s = 350, e =  10, span = -340 (why not 20?)
119
120 below is still not right, we need one more point to disambiguate this...
121 */
122         angle[1] = Vector::Angle(ctr, p2) - angle[0];
123         hitPoint[0] = hitPoint[1] = hitPoint[2] = false;
124 }
125
126 Rect Arc::Bounds(void)
127 {
128         // Swap start & end angles if the span is negative...
129         double start = (angle[1] > 0 ? angle[0] : angle[0] + angle[1]);
130         double end = (angle[1] > 0 ? angle[0] + angle[1] : angle[0]);
131
132         // If the end of the arc is before the beginning, add 360 degrees
133         // to it
134         if (end < start)
135                 end += TAU;
136
137         // Find which quadrant the start angle is in (consider the beginning of
138         // the 90° angle to be in the quadrant, the end to be in the next
139         // quadrant).  Then, divide the span into 90° segments.  The integer
140         // portion is the definite axis crossings; the remainder needs more
141         // scrutiny.  There will be an additional axis crossing if the the sum of
142         // the start angle and the remainder is > 90°.
143         int quadStart = (int)(start / QTR_TAU);
144         double qsRemain = start - ((double)quadStart * QTR_TAU);
145         int numAxes = (int)((fabs(angle[1]) + qsRemain) / QTR_TAU);
146
147         Rect bounds(sin(start), cos(start), sin(end), cos(end));
148         const double box[4] = { 1.0, -1.0, -1.0, 1.0 };
149
150         for(int i=0; i<numAxes; i++)
151                 bounds[(quadStart + i) % 4] = box[(quadStart + i) % 4];
152
153         bounds *= radius[0];
154         bounds.Translate(p[0]);
155
156         return bounds;
157 }
158
159 //
160 // struct Dimension
161 //
162 Dimension::Dimension(): type(OTDimension), id(Global::objectID++), selected(false), hovered(false), hitObject(false)
163 {
164         hitPoint[0] = hitPoint[1] = hitPoint[2] = hitPoint[3] = hitPoint[4] = false;
165 }
166
167 Dimension::Dimension(Vector pt1, Vector pt2, DimensionType dt/*= DTLinear*/, double offs/*= 0*/, float th/*= 1.0*/, uint32_t c/*= 0x0000FF*/, int l/*= LSSolid*/): type(OTDimension), id(Global::objectID++), layer(0), color(c), thickness(th), style(l), selected(false), hovered(false), hitObject(false), subtype(dt), offset(offs)
168 {
169         p[0] = pt1;
170         p[1] = pt2;
171         hitPoint[0] = hitPoint[1] = hitPoint[2] = hitPoint[3] = hitPoint[4] = false;
172 }
173
174 //
175 // struct Text
176 //
177 Text::Text(): type(OTText), id(Global::objectID++)
178 {
179 }
180
181 Text::Text(Vector pt1, const char * str, float th/*= 10.0*/, uint32_t c/*= 0*/): type(OTText), id(Global::objectID++), layer(0), color(c), thickness(th), style(LSSolid), selected(false), hovered(false), hitObject(false), measured(false), s(str)
182 {
183         p[0] = pt1;
184         angle[0] = 0;
185 }
186
187 //prolly don't need this, as this just a special case of a polyline...
188 #if 0
189 //struct Polygon {
190         Polygon(): type(OTPolygon), id(Global::objectID++) {}
191 #endif
192
193 //
194 // struct Polyline
195 //
196 Polyline::Polyline(float th/*= 1.0*/, uint32_t c/*= 0*/, int l/*= LSSolid*/): type(OTPolyline), id(Global::objectID++), layer(0), color(c), thickness(th), style(l), selected(false), hovered(false), hitObject(false)
197 {
198 }
199
200 Polyline::Polyline(std::vector<Point> pts, float th/*= 1.0*/, uint32_t c/*= 0*/, int l/*= LSSolid*/): type(OTPolyline), id(Global::objectID++), layer(0), color(c), thickness(th), style(l), selected(false), hovered(false), hitObject(false)
201 {
202         points = pts;
203 }
204
205 void Polyline::Add(Point p)
206 {
207         points.push_back(p);
208 }
209
210 void Polyline::Add(std::vector<Point> pts)
211 {
212         points.insert(points.end(), pts.begin(), pts.end());
213 }
214
215 Rect Polyline::Bounds(void)
216 {
217         Rect bounds(points[0]);
218
219         for(long unsigned int i=0; i<(points.size()-1); i++)
220         {
221 /*
222 Need to check for arc bounds as well here...
223 */
224 //              bounds += points[i];
225                 bounds += points[i + 1];
226         }
227
228         return bounds;
229 }
230
231 void Polyline::Translate(Point delta)
232 {
233         for(long unsigned int i=0; i<points.size(); i++)
234                 points[i] += delta;
235 }
236
237 //
238 // struct Spline
239 //
240 Spline::Spline(): type(OTSpline), id(Global::objectID++)
241 {
242 }
243
244 //
245 // struct Container
246 //
247 Container::Container(bool tl/*= false*/): type(OTContainer), id(Global::objectID++), selected(false), hovered(false), hitObject(false), topLevel(tl), clicked(NULL), baseUnit(0), unitStyle(0), decimalPrecision(3), fractionalPrecision(4)
248 {
249 }
250
251 void Container::Add(void * obj)
252 {
253         objects.push_back(obj);
254 }
255
256 void Container::Add(VPVector objs)
257 {
258         objects.insert(objects.end(), objs.begin(), objs.end());
259 }
260
261 //      void DeleteContents(void) {}
262 /*      void DeleteContents(Container * c)
263         {
264                 std::vector<void *>::iterator i;
265
266                 for(i=c->objects.begin(); i!=c->objects.end(); i++)
267                 {
268                         Object * obj = (Object *)(*i);
269
270                         if (obj->type == OTContainer)
271                                 DeleteContainer((Container *)obj);
272
273                         delete *i;
274                 }
275         }*/