]> Shamusworld >> Repos - architektonas/blobdiff - src/structs.cpp
Further progress on Polylines: Polylines can be selected and moved.
[architektonas] / src / structs.cpp
diff --git a/src/structs.cpp b/src/structs.cpp
new file mode 100644 (file)
index 0000000..b731fae
--- /dev/null
@@ -0,0 +1,254 @@
+//
+// structs.cpp: Useful structs to describe objects
+//
+// Part of the Architektonas Project
+// (C) 2022 Underground Software
+// See the README and GPLv3 files for licensing and warranty information
+//
+// JLH = James Hammons <jlhamm@acm.org>
+//
+// WHO  WHEN        WHAT
+// ---  ----------  ------------------------------------------------------------
+// JLH  01/13/2022  Created this file
+
+#include "structs.h"
+#include <math.h>
+#include "mathconstants.h"
+
+const char objName[OTCount][16] = {
+       "None", "Line", "Circle", "Ellipse", "Arc", "Polygon", "Dimension",
+       "Spline", "Text", "Container"
+};
+const char dimName[DTCount][32] = {
+       "Linear", "Vertical", "Horizontal", "Radial", "Diametric",
+       "Circumferential", "Angular", "Leader"
+};
+
+const char buShortName[BUCount][8] = {
+       "in", "ft", "yd", "mi", "mm", "cm", "m", "km"
+};
+
+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 };
+
+//
+// struct Line
+//
+Line::Line(): type(OTLine), id(Global::objectID++), selected(false), hovered(false), hitObject(false)
+{
+       hitPoint[0] = hitPoint[1] = false;
+}
+
+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)
+{
+       p[0] = pt1;
+       p[1] = pt2;
+       hitPoint[0] = hitPoint[1] = false;
+}
+
+Vector Line::Vect(void)
+{
+       return Vector(p[0], p[1]);
+}
+
+Vector Line::Unit(void)
+{
+       return Vector(p[0], p[1]).Unit();
+}
+
+double Line::Length(void)
+{
+       return Vector(p[0], p[1]).Magnitude();
+}
+
+//
+// struct Circle
+//
+Circle::Circle(): type(OTCircle), id(Global::objectID++)
+{
+}
+
+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)
+{
+       p[0] = pt1;
+       radius[0] = r;
+       hitPoint[0] = hitPoint[1] = false;
+}
+
+//
+// struct Ellipse
+//
+Ellipse::Ellipse(): type(OTEllipse), id(Global::objectID++)
+{
+}
+
+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)
+{
+       p[0] = pt1;
+       p[1] = pt2;
+       radius[0] = r1;
+       radius[1] = r2;
+       hitPoint[0] = hitPoint[1] = false;
+}
+
+//
+// struct Arc
+//
+Arc::Arc(): type(OTArc), id(Global::objectID++)
+{
+}
+
+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)
+{
+       p[0] = pt1; radius[0] = r; angle[0] = a1, angle[1] = a2; hitPoint[0] = hitPoint[1] = hitPoint[2] = false;
+}
+
+Rect Arc::Bounds(void)
+{
+       // Swap start & end angles if the span is negative...
+       double start = (angle[1] > 0 ? angle[0] : angle[0] + angle[1]);
+       double end = (angle[1] > 0 ? angle[0] + angle[1] : angle[0]);
+
+       // If the end of the arc is before the beginning, add 360 degrees
+       // to it
+       if (end < start)
+               end += TAU;
+
+       // Find which quadrant the start angle is in (consider the beginning of
+       // the 90° angle to be in the quadrant, the end to be in the next
+       // quadrant).  Then, divide the span into 90° segments.  The integer
+       // portion is the definite axis crossings; the remainder needs more
+       // scrutiny.  There will be an additional axis crossing if the the sum of
+       // the start angle and the remainder is > 90°.
+       int quadStart = (int)(start / QTR_TAU);
+       double qsRemain = start - ((double)quadStart * QTR_TAU);
+       int numAxes = (int)((fabs(angle[1]) + qsRemain) / QTR_TAU);
+
+       Rect bounds(sin(start), cos(start), sin(end), cos(end));
+       const double box[4] = { 1.0, -1.0, -1.0, 1.0 };
+
+       for(int i=0; i<numAxes; i++)
+               bounds[(quadStart + i) % 4] = box[(quadStart + i) % 4];
+
+       bounds *= radius[0];
+       bounds.Translate(p[0]);
+
+       return bounds;
+}
+
+//
+// struct Dimension
+//
+Dimension::Dimension(): type(OTDimension), id(Global::objectID++), selected(false), hovered(false), hitObject(false)
+{
+       hitPoint[0] = hitPoint[1] = hitPoint[2] = hitPoint[3] = hitPoint[4] = false;
+}
+
+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)
+{
+       p[0] = pt1;
+       p[1] = pt2;
+       hitPoint[0] = hitPoint[1] = hitPoint[2] = hitPoint[3] = hitPoint[4] = false;
+}
+
+//
+// struct Text
+//
+Text::Text(): type(OTText), id(Global::objectID++)
+{
+}
+
+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)
+{
+       p[0] = pt1;
+       angle[0] = 0;
+}
+
+//prolly don't need this, as this just a special case of a polyline...
+#if 0
+//struct Polygon {
+       Polygon(): type(OTPolygon), id(Global::objectID++) {}
+#endif
+
+//
+// struct Polyline
+//
+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)
+{
+}
+
+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)
+{
+       points = pts;
+}
+
+void Polyline::Add(Point p)
+{
+       points.push_back(p);
+}
+
+void Polyline::Add(std::vector<Point> pts)
+{
+       points.insert(points.end(), pts.begin(), pts.end());
+}
+
+Rect Polyline::Bounds(void)
+{
+       Rect bounds(points[0]);
+
+       for(long unsigned int i=0; i<(points.size()-1); i++)
+       {
+/*
+Need to check for arc bounds as well here...
+*/
+//             bounds += points[i];
+               bounds += points[i + 1];
+       }
+
+       return bounds;
+}
+
+void Polyline::Translate(Point delta)
+{
+       for(long unsigned int i=0; i<points.size(); i++)
+               points[i] += delta;
+}
+
+//
+// struct Spline
+//
+Spline::Spline(): type(OTSpline), id(Global::objectID++)
+{
+}
+
+//
+// struct Container
+//
+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)
+{
+}
+
+void Container::Add(void * obj)
+{
+       objects.push_back(obj);
+}
+
+void Container::Add(VPVector objs)
+{
+       objects.insert(objects.end(), objs.begin(), objs.end());
+}
+
+//     void DeleteContents(void) {}
+/*     void DeleteContents(Container * c)
+       {
+               std::vector<void *>::iterator i;
+
+               for(i=c->objects.begin(); i!=c->objects.end(); i++)
+               {
+                       Object * obj = (Object *)(*i);
+
+                       if (obj->type == OTContainer)
+                               DeleteContainer((Container *)obj);
+
+                       delete *i;
+               }
+       }*/