{
painter->SetBrush(QBrush(Qt::NoBrush));
Polyline * pl = (Polyline *)obj;
- Point lastp;
- double lastbump;
- for(VPVectorIter i=pl->points.begin(); i!=pl->points.end(); i++)
+ for(long unsigned int i=0; i<(pl->points.size()-1); i++)
{
- if (i != pl->points.begin())
- {
- Point p = ((Object *)(*i))->p[0];
- double bump = ((Object *)(*i))->length;
-
- if (lastbump == 0)
- painter->DrawLine(lastp, p);
- else
- {
- Arc a = Geometry::Unpack(lastp, p, lastbump);
- painter->DrawArc(a.p[0], a.radius[0], a.angle[0], a.angle[1]);
- }
+ Point p1 = pl->points[i];
+ Point p2 = pl->points[i + 1];
- lastp = p;
- lastbump = bump;
- }
+ if (p1.b == 0)
+ painter->DrawLine(p1, p2);
else
{
- lastp = ((Object *)(*i))->p[0];
- lastbump = ((Object *)(*i))->length;
+ Arc a = Geometry::Unpack(p1, p2, p1.b);
+ painter->DrawArc(a.p[0], a.radius[0], a.angle[0], a.angle[1]);
}
}
point.y = floor(point.y);
point.z = 0; // Make *sure* Z doesn't go anywhere!!!
point *= Global::gridSpacing;
+
return point;
}
case OTArc:
{
Arc * a = (Arc *)obj;
+ rect = a->Bounds();
+ break;
+ }
- double start = a->angle[0];
- double end = start + a->angle[1];
-
- // Swap 'em if the span is negative...
- if (a->angle[1] < 0)
- {
- end = a->angle[0];
- start = end + a->angle[1];
- }
-
- rect = Rect(Point(cos(start), sin(start)), Point(cos(end), sin(end)));
-
- // 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°.
-*/
-#if 1
- int quadStart = (int)(a->angle[0] / QTR_TAU);
- double qsRemain = a->angle[0] - ((double)quadStart * QTR_TAU);
- int numAxes = (int)((a->angle[1] + qsRemain) / QTR_TAU);
-
- double axis[4] = { 0, 0, 0, 0 };
- axis[0] = rect.t, axis[1] = rect.l, axis[2] = rect.b, axis[3] = rect.r;
- double box[4] = { 1.0, -1.0, -1.0, 1.0 };
-
- for(int i=0; i<numAxes; i++)
- axis[(quadStart + i) % 4] = box[(quadStart + i) % 4];
-
- // The rect is constructed the same way we traverse the axes: TLBR
- Rect r2(axis[0], axis[1], axis[2], axis[3]);
-
- rect |= r2;
-#else
- // Adjust the bounds depending on which axes are crossed
- if ((start < QTR_TAU) && (end > QTR_TAU))
- rect.t = 1.0;
-
- if ((start < HALF_TAU) && (end > HALF_TAU))
- rect.l = -1.0;
-
- if ((start < THREE_QTR_TAU) && (end > THREE_QTR_TAU))
- rect.b = -1.0;
-
- if ((start < TAU) && (end > TAU))
- rect.r = 1.0;
-
- if ((start < (TAU + QTR_TAU)) && (end > (TAU + QTR_TAU)))
- rect.t = 1.0;
-
- if ((start < (TAU + HALF_TAU)) && (end > (TAU + HALF_TAU)))
- rect.l = -1.0;
-
- if ((start < (TAU + THREE_QTR_TAU)) && (end > (TAU + THREE_QTR_TAU)))
- rect.b = -1.0;
-#endif
-
- rect *= a->radius[0];
- rect.Translate(a->p[0]);
+ case OTPolyline:
+ {
+ Polyline * p = (Polyline *)obj;
+ rect = p->Bounds();
break;
}
case OTArc:
{
Arc * a = (Arc *)obj;
-
- double start = a->angle[0];
- double end = start + a->angle[1];
-
- // Swap 'em if the span is negative...
- if (a->angle[1] < 0)
- {
- end = a->angle[0];
- start = end + a->angle[1];
- }
-
- // If the end of the arc is before the beginning, add 360 degrees
- // to it
- if (end < start)
- end += TAU;
-
-#if 1
- int quadStart = (int)(a->angle[0] / QTR_TAU);
- double qsRemain = a->angle[0] - ((double)quadStart * QTR_TAU);
- int numAxes = (int)((a->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];
-#else
- // Adjust the bounds depending on which axes are crossed
- if ((start < QTR_TAU) && (end > QTR_TAU))
- bounds.t = 1.0;
-
- if ((start < HALF_TAU) && (end > HALF_TAU))
- bounds.l = -1.0;
-
- if ((start < THREE_QTR_TAU) && (end > THREE_QTR_TAU))
- bounds.b = -1.0;
-
- if ((start < TAU) && (end > TAU))
- bounds.r = 1.0;
-
- if ((start < (TAU + QTR_TAU)) && (end > (TAU + QTR_TAU)))
- bounds.t = 1.0;
-
- if ((start < (TAU + HALF_TAU)) && (end > (TAU + HALF_TAU)))
- bounds.l = -1.0;
-
- if ((start < (TAU + THREE_QTR_TAU)) && (end > (TAU + THREE_QTR_TAU)))
- bounds.b = -1.0;
-#endif
-
- bounds *= a->radius[0];
- bounds.Translate(a->p[0]);
+ Rect bounds = a->Bounds();
if (selection.Contains(bounds))
a->selected = true;
case OTPolyline:
{
Polyline * pl = (Polyline *)obj;
- Rect r(((Object *)(pl->points[0]))->p[0]);
+ Rect bounds = pl->Bounds();
- for(int i=0; i<(pl->points.size()-1); i++)
- {
- r += ((Object *)(pl->points[i]))->p[0];
- r += ((Object *)(pl->points[i + 1]))->p[0];
- }
-
- if (selection.Contains(r))
+ if (selection.Contains(bounds))
pl->selected = true;
break;
else if ((distance * Global::zoom) < 5.0)
obj->hitObject = true;
- obj->hovered = (obj->hitPoint[0] || obj->hitPoint[1] || obj->hitObject ? true : false);
+ obj->hovered = (obj->hitPoint[0] || obj->hitPoint[1] || obj->hitObject);
if ((oldHP0 != obj->hitPoint[0]) || (oldHP1 != obj->hitPoint[1]) || (oldHO != obj->hitObject))
needUpdate = true;
else if ((fabs(length - obj->radius[0]) * Global::zoom) < 2.0)
obj->hitObject = true;
- obj->hovered = (obj->hitPoint[0] || obj->hitObject ? true : false);
+ obj->hovered = (obj->hitPoint[0] || obj->hitObject);
if ((oldHP != obj->hitPoint[0]) || (oldHO != obj->hitObject))
needUpdate = true;
// Get the span that we're pointing at...
double span = angle - obj->angle[0];
- // N.B.: Still need to hit test the arc start & arc span handles...
+ // N.B.: Still need to hit test the arc start & arc span handles... [looks like it's DONE?]
double spanAngle = obj->angle[0] + obj->angle[1];
Point handle1 = obj->p[0] + (Vector(cos(obj->angle[0]), sin(obj->angle[0])) * obj->radius[0]);
Point handle2 = obj->p[0] + (Vector(cos(spanAngle), sin(spanAngle)) * obj->radius[0]);
else if (((fabs(length - obj->radius[0]) * Global::zoom) < 2.0) && (span < obj->angle[1]))
obj->hitObject = true;
- obj->hovered = (obj->hitPoint[0] || obj->hitPoint[1] || obj->hitPoint[2] || obj->hitObject ? true : false);
+ obj->hovered = (obj->hitPoint[0] || obj->hitPoint[1] || obj->hitPoint[2] || obj->hitObject);
if ((oldHP0 != obj->hitPoint[0]) || (oldHP1 != obj->hitPoint[1]) || (oldHP2 != obj->hitPoint[2]) || (oldHO != obj->hitObject))
needUpdate = true;
break;
}
+ case OTPolyline:
+ {
+ Polyline * pl = (Polyline *)obj;
+ bool oldHP0 = pl->hitPoint[0], oldHO = pl->hitObject;
+ pl->hitPoint[0] = pl->hitObject = false;
+
+ for(long unsigned int i=0; i<(pl->points.size()-1); i++)
+ {
+ Point p1 = pl->points[i];
+ Point p2 = pl->points[i + 1];
+
+ double dist1 = Vector::Magnitude(p1, point) * Global::zoom;
+ double dist2 = Vector::Magnitude(p2, point) * Global::zoom;
+
+ // Check for endpoints of lines and/or arcs first
+ if (dist1 < 8.0)
+ {
+ pl->hitPoint[0] = true;
+ hoverPoint = p1;
+ hoverPointValid = true;
+ pl->ptNum = i;
+ }
+ else if (dist2 < 8.0)
+ {
+ pl->hitPoint[0] = true;
+ hoverPoint = p2;
+ hoverPointValid = true;
+ pl->ptNum = i + 1;
+ }
+ // Check for object (line/arc) last
+ else if (p1.b == 0)
+ {
+ double t = Geometry::ParameterOfLineAndPoint(p1, p2, point);
+ double objDist;
+
+ // No bump == check for line proximity
+ if (t < 0.0)
+ objDist = dist1;
+ else if (t > 1.0)
+ objDist = dist2;
+ else
+ {
+ Line l(p1, p2);
+ Vector v1 = l.Vect();
+ Vector v2(p1, point);
+ objDist = fabs((v1.x * v2.y - v2.x * v1.y) / l.Length()) * Global::zoom;
+ }
+
+ if (objDist < 5.0)
+ pl->hitObject = true;
+ }
+ else
+ {
+ // We have a bump == check for arc proximity
+ Arc a = Geometry::Unpack(p1, p2, p1.b);
+ double length = Vector::Magnitude(a.p[0], point);
+ double angle = Vector::Angle(a.p[0], point);
+ double span = angle - a.angle[0];
+
+ // Ensure point span is positive if we have a positive arc span
+ if (span < 0 && a.angle[1] > 0)
+ span += TAU;
+
+ // Ensure point span is negative if we have a negative arc span
+ if (span > 0 && a.angle[1] < 0)
+ span -= TAU;
+
+ if (((fabs(length - a.radius[0]) * Global::zoom) < 2.5) && (fabs(span) < fabs(a.angle[1])))
+ pl->hitObject = true;
+ }
+ }
+
+ pl->hovered = (pl->hitPoint[0] || pl->hitObject);
+
+ if ((oldHP0 != pl->hitPoint[0]) || (oldHO != pl->hitObject))
+ needUpdate = true;
+
+ break;
+ }
+
case OTDimension:
{
bool oldHP0 = obj->hitPoint[0], oldHP1 = obj->hitPoint[1], oldHP2 = obj->hitPoint[2], oldHP3 = obj->hitPoint[3], oldHP4 = obj->hitPoint[4], oldHO = obj->hitObject;
else if ((hCS2Point.Magnitude() * Global::zoom) < 8.0)
obj->hitPoint[4] = true;
- obj->hovered = (obj->hitPoint[0] || obj->hitPoint[1] || obj->hitPoint[2] || obj->hitPoint[3] || obj->hitPoint[4] || obj->hitObject ? true : false);
+ obj->hovered = (obj->hitPoint[0] || obj->hitPoint[1] || obj->hitPoint[2] || obj->hitPoint[3] || obj->hitPoint[4] || obj->hitObject);
if ((oldHP0 != obj->hitPoint[0]) || (oldHP1 != obj->hitPoint[1]) || (oldHP2 != obj->hitPoint[2]) || (oldHP3 != obj->hitPoint[3]) || (oldHP4 != obj->hitPoint[4]) || (oldHO != obj->hitObject))
needUpdate = true;
if (r.Contains(point))
obj->hitObject = true;
- obj->hovered = (obj->hitObject ? true : false);
+ obj->hovered = obj->hitObject;
if (oldHO != obj->hitObject)
needUpdate = true;
obj->p[0] = point;
else if (obj->hitObject)
{
- double oldRadius = obj->length;
- obj->radius[0] = Vector::Magnitude(obj->p[0], point);
+ if (shiftDown)
+ {
+ double oldRadius = obj->length;
+ obj->radius[0] = Vector::Magnitude(obj->p[0], point);
- QString text = QObject::tr("Radius: %1\nScale: %2%");
- informativeText = text.arg(obj->radius[0], 0, 'f', 4).arg(obj->radius[0] / oldRadius * 100.0, 0, 'f', 0);
+ QString text = QObject::tr("Radius: %1\nScale: %2%");
+ informativeText = text.arg(obj->radius[0], 0, 'f', 4).arg(obj->radius[0] / oldRadius * 100.0, 0, 'f', 0);
+ }
+ else
+ obj->p[0] += delta;
}
break;
{
if (shiftDown)
{
- return;
+ obj->radius[0] = Vector::Magnitude(obj->p[0], point);
+ QString text = QObject::tr("Radius: %1");
+ informativeText = text.arg(obj->radius[0], 0, 'f', 4);
}
-
- obj->radius[0] = Vector::Magnitude(obj->p[0], point);
- QString text = QObject::tr("Radius: %1");
- informativeText = text.arg(obj->radius[0], 0, 'f', 4);
+ else
+ obj->p[0] += delta;
}
break;
+ case OTPolyline:
+ {
+#if 1
+ // Do this for now...
+ ((Polyline *)obj)->Translate(delta);
+// Polyline * pl = (Polyline *)obj;
+
+// for(long unsigned int i=0; i<pl->points.size(); i++)
+// pl->points[i] += delta;
+#else
+ Polyline * pl = (Polyline *)obj;
+
+ for(long unsigned int i=0; i<(pl->points.size()-1); i++)
+#endif
+
+ break;
+ }
+
case OTDimension:
if (obj->hitPoint[0])
obj->p[0] = point;
else if (strcmp(buffer, "POLYLINE") == 0)
{
long int size;
- obj = (Object *)new Polyline();
+ std::vector<Point> pts;
+ uint32_t color;
+ float thickness;
+ int style;
+
fscanf(file, "(%li)", &size);
- fscanf(file, " (%i, %f, %i)\n", &obj->color, &obj->thickness, &obj->style);
+ fscanf(file, " (%i, %f, %i)\n", &color, &thickness, &style);
for(int i=0; i<size; i++)
{
- Object * po = new Object();
- fscanf(file, "(%lf,%lf,%lf)\n", &po->p[0].x, &po->p[0].y, &po->length);
- ((Polyline *)obj)->Add(po);
+ Point p;
+ fscanf(file, "(%lf,%lf,%lf)\n", &p.x, &p.y, &p.b);
+ pts.push_back(p);
}
+
+ obj = (Object *)new Polyline(pts, thickness, color, style);
}
else if (strcmp(buffer, "TEXT") == 0)
{
fprintf(file, "POLYLINE %i (%li)", p->layer, p->points.size());
fprintf(file, " (%i, %f, %i)\n", obj->color, obj->thickness, obj->style);
- for(VPVectorIter i=p->points.begin(); i!=p->points.end(); i++)
+ for(long unsigned int i=0; i<p->points.size(); i++)
{
- Object * po = (Object *)(*i);
- fprintf(file, "(%.16lf,%.16lf,%.16lf)\n", po->p[0].x, po->p[0].y, po->length);
+ fprintf(file, "(%.16lf,%.16lf,%.16lf)\n", p->points[i].x, p->points[i].y, p->points[i].b);
}
}
break;
{
double length = Vector::Magnitude(tail, head) / 2.0;
double bumpLen = length * fabs(bump);
- Point midpoint = Vector::Midpoint(tail, head);
+ Point midpoint = (tail + head) / 2.0;
Vector mpNormal = Vector::Normal(tail, head); // Normal points to the left
// Flip the normal if the bump is pointing left
s += QString("Center: <%1, %2><br>Radius: %3<br>Start: %4°<br>Span: %5°<br>").arg(obj->p[0].x).arg(obj->p[0].y).arg(obj->radius[0]).arg(obj->angle[0] * RADIANS_TO_DEGREES).arg(obj->angle[1] * RADIANS_TO_DEGREES);
break;
- case OTPolygon:
- break;
-
case OTDimension:
{
Dimension * d = (Dimension *)obj;
break;
}
+ case OTPolyline:
+ break;
+
case OTSpline:
break;
--- /dev/null
+//
+// 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;
+ }
+ }*/
#define __STRUCTS_H__
#include <stdint.h>
-#include <vector>
#include <string>
+#include <vector>
#include "global.h"
#include "rect.h"
#include "vector.h"
-enum ObjectType { OTNone = 0, OTLine, OTCircle, OTEllipse, OTArc, OTPolygon, OTDimension, OTSpline, OTText, OTContainer, OTPolyline, OTCount };
+enum ObjectType { OTNone = 0, OTLine, OTCircle, OTEllipse, OTArc, OTDimension, OTPolyline, OTSpline, OTText, OTContainer, OTCount };
enum DimensionType { DTLinear = 0, DTLinearVert, DTLinearHorz, DTRadial, DTDiametric, DTCircumferential, DTAngular, DTLeader, DTCount };
enum BasicUnit { BUInch = 0, BUFoot, BUYard, BUMile, BUMM, BUCM, BUM, BUKM, BUCount };
-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 };
+extern const char objName[OTCount][16];
+extern const char dimName[DTCount][32];
+extern const char buShortName[BUCount][8];
+extern const double buInInches[BUCount];
#define OBJECT_COMMON \
int type; \
struct Line {
OBJECT_COMMON;
- Line(): type(OTLine), id(Global::objectID++), selected(false), hovered(false), hitObject(false) { hitPoint[0] = hitPoint[1] = false; }
- 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 Vect(void) { return Vector(p[0], p[1]); }
- Vector Unit(void) { return Vector(p[0], p[1]).Unit(); }
- double Length(void) { return Vector(p[0], p[1]).Magnitude(); }
+ Line();
+ Line(Vector pt1, Vector pt2, float th = 1.0, uint32_t c = 0, int l = LSSolid);
+ Vector Vect(void);
+ Vector Unit(void);
+ double Length(void);
};
struct Circle {
OBJECT_COMMON;
- Circle(): type(OTCircle), id(Global::objectID++) {}
- 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; }
+ Circle();
+ Circle(Vector pt1, double r, float th = 1.0, uint32_t c = 0, int l = LSSolid);
};
struct Ellipse {
OBJECT_COMMON;
- Ellipse(): type(OTEllipse), id(Global::objectID++) {}
- 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; }
+ Ellipse();
+ Ellipse(Vector pt1, Vector pt2, double r1, double r2, float th = 1.0, uint32_t c = 0, int l = LSSolid);
};
struct Arc {
OBJECT_COMMON;
- Arc(): type(OTArc), id(Global::objectID++) {}
- 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; }
+ Arc();
+ Arc(Vector pt1, double r, double a1, double a2, float th = 1.0, uint32_t c = 0, int l = LSSolid);
+ Rect Bounds(void);
};
struct Dimension {
Point lp[2]; // Line point, the actual dimension line
Object * obj[2]; // Pointer to attached objects (circle, lines for angle)
- Dimension(): type(OTDimension), id(Global::objectID++), selected(false),
- hovered(false), hitObject(false)
- { hitPoint[0] = hitPoint[1] = hitPoint[2] = hitPoint[3] = hitPoint[4] = false; }
- 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; }
+ Dimension();
+ Dimension(Vector pt1, Vector pt2, DimensionType dt = DTLinear, double offs = 0, float th = 1.0, uint32_t c = 0x0000FF, int l = LSSolid);
};
struct Text {
bool measured;
std::string s;
- Text(): type(OTText), id(Global::objectID++) {}
- 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...
-struct Polygon {
- OBJECT_COMMON;
- int sides;
-
- Polygon(): type(OTPolygon), id(Global::objectID++) {}
+ Text();
+ Text(Vector pt1, const char * str, float th = 10.0, uint32_t c = 0);
};
struct Polyline {
OBJECT_COMMON;
- VPVector points;
-//need this? could just repeat the endpoint as well...
-// bool closed;
- Object * clicked;
-
- Polyline(): type(OTPolyline), id(Global::objectID++), selected(false), hovered(false), hitObject(false), clicked(NULL) {}
- void Add(void * obj) { points.push_back(obj); }
- void Add(VPVector objs) { points.insert(points.end(), objs.begin(), objs.end()); }
+ std::vector<Point> points;
+// bool closed; //need this? could just repeat the endpoint as well...
+// Object * clicked;
+ int ptNum;
+
+ Polyline(float th = 1.0, uint32_t c = 0, int l = LSSolid);
+ Polyline(std::vector<Point>, float th = 1.0, uint32_t c = 0, int l = LSSolid);
+ void Add(Point);
+ void Add(std::vector<Point>);
+ Rect Bounds(void);
+ void Translate(Point);
};
struct Spline {
OBJECT_COMMON;
- Spline(): type(OTSpline), id(Global::objectID++) {}
+ Spline();
};
struct Container {
int decimalPrecision; // 0-5, which, +1, is # of decimal places
int fractionalPrecision; // 0-5, which, +1, is 1/(2^n)
- 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 Add(void * obj) { objects.push_back(obj); }
- void 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;
- }
- }*/
+ Container(bool tl = false);
+ void Add(void * obj);
+ void Add(VPVector objs);
};
#endif // __STRUCTS_H__
newObject = new Dimension();
memcpy(newObject, obj, sizeof(Dimension));
break;
+ case OTPolyline:
+ newObject = new Polyline();
+ memcpy(newObject, obj, sizeof(Polyline));
+ ((Polyline *)newObject)->points = ((Polyline *)obj)->points;
+ break;
case OTSpline:
newObject = new Spline();
memcpy(newObject, obj, sizeof(Spline));
memcpy(newObject, obj, sizeof(Dimension));
break;
+ case OTPolyline:
+ newObject = new Polyline();
+ memcpy(newObject, obj, sizeof(Polyline));
+ ((Polyline *)newObject)->points = ((Polyline *)obj)->points;
+ break;
+
case OTSpline:
newObject = new Spline();
memcpy(newObject, obj, sizeof(Spline));
for(VPVectorIter i=c->objects.begin(); i!=c->objects.end(); i++)
TranslateObject((Object *)*i, delta);
}
+ else if (obj->type == OTPolyline)
+ ((Polyline *)obj)->Translate(delta);
obj->p[0] += delta;
obj->p[1] += delta;
Container * c = (Container *)obj;
TranslateObjects(c->objects, delta);
}
+ else if (obj->type == OTPolyline)
+ {
+ ((Polyline *)obj)->Translate(delta);
+ }
}
}
#include "vector.h"
-#include <math.h> // For sqrt()
+#include <math.h> // For sqrt()
#include "mathconstants.h"
// Vector implementation
-Vector::Vector(double xx/*= 0*/, double yy/*= 0*/, double zz/*= 0*/): x(xx), y(yy), z(zz)
+Vector::Vector(double xx/*= 0*/, double yy/*= 0*/, double zz/*= 0*/): x(xx), y(yy), z(zz), b(0)
{
}
-Vector::Vector(Vector tail, Vector head): x(head.x - tail.x), y(head.y - tail.y), z(head.z - tail.z)
+Vector::Vector(Vector tail, Vector head): x(head.x - tail.x), y(head.y - tail.y), z(head.z - tail.z), b(0)
{
}
-Vector::Vector(const Vector &v): x(v.x), y(v.y), z(v.z)
+Vector::Vector(const Vector &v): x(v.x), y(v.y), z(v.z), b(v.b)
{
}
Vector Vector::operator=(Vector const v)
{
- x = v.x, y = v.y, z = v.z;
+ x = v.x, y = v.y, z = v.z, b = v.b;
return *this;
}
return Vector(-v.y, v.x);
}
-/*static*/ double Vector::AngleBetween(Vector a, Vector b)
+/*static*/ double Vector::AngleBetween(Vector a1, Vector a2)
{
// This is done using the following formula:
// (a . b) = ||a|| ||b|| cos(theta)
// Also, the vectors a & b have to be non-zero.
// Also, have to check using an epsilon because acos will not return an
// exact value if the vectors are orthogonal.
- if (a.isZero() || b.isZero())
+ if (a1.isZero() || a2.isZero())
return 0;
- return acos(a.Dot(b) / (a.Magnitude() * b.Magnitude()));
+ return acos(a1.Dot(a2) / (a1.Magnitude() * a2.Magnitude()));
}
/*static*/ Point Vector::Midpoint(Point p1, Point p2)
static double Angle(Point p1, Point p2);
static double Parameter(Vector v1, Vector v2, Vector p);
static Vector Normal(Vector v1, Vector v2);
- static double AngleBetween(Vector a, Vector b);
+ static double AngleBetween(Vector a1, Vector a2);
static Point Midpoint(Point p1, Point p2);
public:
- double x, y, z;
+ double x, y, z, b; // "b" is an extra used mainly for arc bumps
};
#endif // __VECTOR_H__