]> Shamusworld >> Repos - architektonas/blob - src/structs.cpp
b731fae75a767c99d05962e639190ff863875caa
[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 pt1, 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] = pt1; radius[0] = r; angle[0] = a1, angle[1] = a2; hitPoint[0] = hitPoint[1] = hitPoint[2] = false;
103 }
104
105 Rect Arc::Bounds(void)
106 {
107         // Swap start & end angles if the span is negative...
108         double start = (angle[1] > 0 ? angle[0] : angle[0] + angle[1]);
109         double end = (angle[1] > 0 ? angle[0] + angle[1] : angle[0]);
110
111         // If the end of the arc is before the beginning, add 360 degrees
112         // to it
113         if (end < start)
114                 end += TAU;
115
116         // Find which quadrant the start angle is in (consider the beginning of
117         // the 90° angle to be in the quadrant, the end to be in the next
118         // quadrant).  Then, divide the span into 90° segments.  The integer
119         // portion is the definite axis crossings; the remainder needs more
120         // scrutiny.  There will be an additional axis crossing if the the sum of
121         // the start angle and the remainder is > 90°.
122         int quadStart = (int)(start / QTR_TAU);
123         double qsRemain = start - ((double)quadStart * QTR_TAU);
124         int numAxes = (int)((fabs(angle[1]) + qsRemain) / QTR_TAU);
125
126         Rect bounds(sin(start), cos(start), sin(end), cos(end));
127         const double box[4] = { 1.0, -1.0, -1.0, 1.0 };
128
129         for(int i=0; i<numAxes; i++)
130                 bounds[(quadStart + i) % 4] = box[(quadStart + i) % 4];
131
132         bounds *= radius[0];
133         bounds.Translate(p[0]);
134
135         return bounds;
136 }
137
138 //
139 // struct Dimension
140 //
141 Dimension::Dimension(): type(OTDimension), id(Global::objectID++), selected(false), hovered(false), hitObject(false)
142 {
143         hitPoint[0] = hitPoint[1] = hitPoint[2] = hitPoint[3] = hitPoint[4] = false;
144 }
145
146 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)
147 {
148         p[0] = pt1;
149         p[1] = pt2;
150         hitPoint[0] = hitPoint[1] = hitPoint[2] = hitPoint[3] = hitPoint[4] = false;
151 }
152
153 //
154 // struct Text
155 //
156 Text::Text(): type(OTText), id(Global::objectID++)
157 {
158 }
159
160 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)
161 {
162         p[0] = pt1;
163         angle[0] = 0;
164 }
165
166 //prolly don't need this, as this just a special case of a polyline...
167 #if 0
168 //struct Polygon {
169         Polygon(): type(OTPolygon), id(Global::objectID++) {}
170 #endif
171
172 //
173 // struct Polyline
174 //
175 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)
176 {
177 }
178
179 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)
180 {
181         points = pts;
182 }
183
184 void Polyline::Add(Point p)
185 {
186         points.push_back(p);
187 }
188
189 void Polyline::Add(std::vector<Point> pts)
190 {
191         points.insert(points.end(), pts.begin(), pts.end());
192 }
193
194 Rect Polyline::Bounds(void)
195 {
196         Rect bounds(points[0]);
197
198         for(long unsigned int i=0; i<(points.size()-1); i++)
199         {
200 /*
201 Need to check for arc bounds as well here...
202 */
203 //              bounds += points[i];
204                 bounds += points[i + 1];
205         }
206
207         return bounds;
208 }
209
210 void Polyline::Translate(Point delta)
211 {
212         for(long unsigned int i=0; i<points.size(); i++)
213                 points[i] += delta;
214 }
215
216 //
217 // struct Spline
218 //
219 Spline::Spline(): type(OTSpline), id(Global::objectID++)
220 {
221 }
222
223 //
224 // struct Container
225 //
226 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)
227 {
228 }
229
230 void Container::Add(void * obj)
231 {
232         objects.push_back(obj);
233 }
234
235 void Container::Add(VPVector objs)
236 {
237         objects.insert(objects.end(), objs.begin(), objs.end());
238 }
239
240 //      void DeleteContents(void) {}
241 /*      void DeleteContents(Container * c)
242         {
243                 std::vector<void *>::iterator i;
244
245                 for(i=c->objects.begin(); i!=c->objects.end(); i++)
246                 {
247                         Object * obj = (Object *)(*i);
248
249                         if (obj->type == OTContainer)
250                                 DeleteContainer((Container *)obj);
251
252                         delete *i;
253                 }
254         }*/