src/promptlineedit.cpp \
src/rect.cpp \
src/settingsdialog.cpp \
+ src/structs.cpp \
src/units.cpp \
src/utils.cpp \
src/vector.cpp
QPoint pos = settings.value("pos", QPoint(200, 200)).toPoint();
QSize size = settings.value("size", QSize(400, 400)).toSize();
drawing->useAntialiasing = settings.value("useAntialiasing", true).toBool();
- snapToGridAct->setChecked(settings.value("snapToGrid", true).toBool());
+ Global::snapToGrid = settings.value("snapToGrid", true).toBool();
+ snapToGridAct->setChecked(Global::snapToGrid);
resize(size);
move(pos);
restoreState(settings.value("windowState").toByteArray());
}
if (objDist < 5.0)
+ {
pl->hitObject = true;
+ pl->ptNum = i;
+ }
}
else
{
span -= TAU;
if (((fabs(length - a.radius[0]) * Global::zoom) < 2.5) && (fabs(span) < fabs(a.angle[1])))
+ {
pl->hitObject = true;
+ pl->ptNum = i;
+ }
}
}
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
+ if (!shiftDown)
+ pl->Translate(delta);
+ else
+ {
+ // Move selected point by itself (if hit)
+ if (pl->hitPoint[0])
+ {
+ point.b = pl->points[pl->ptNum].b;
+ pl->points[pl->ptNum] = point;
+ }
+ else if (pl->hitObject)
+ {
+ // move arc radius, or maybe move line segment? :-/
+ int ptNum = pl->ptNum;
+ Arc a = Geometry::FindArcForThreePoints(pl->points[ptNum], pl->points[ptNum + 1], point);
+ pl->points[ptNum].b = Geometry::Pack(&a);
+
+ // This doesn't quite get there... Maybe < 0.001?
+ if (fabs(pl->points[ptNum].b) < EPSILON)
+ pl->points[ptNum].b = 0;
+ }
+ }
break;
}
obj->p[1] = point;
else if (obj->hitObject)
{
- // Move measurement lines in/out
+ // Move extension lines in/out
if (shiftDown)
{
Dimension * d = (Dimension *)obj;
return normal;
}
+//
+// Returns the orientation of the points when traversed in order (from p1 to
+// p2 to p3). +1 = CCW, -1 = CW, 0 = colinear
+//
+int Geometry::Orientation(Point p1, Point p2, Point p3)
+{
+ double xx = p2.x - p1.x, yy = p2.y - p1.y;
+ double aa = p3.x - p1.x, bb = p3.y - p1.y;
+
+ // Mult by -1 if screen coords already transformed
+ double zz = (xx * bb) - (yy * aa);
+
+ return (zz < 0 ? -1 : (zz == 0 ? 0 : 1));
+}
+
Circle Geometry::FindCircleForThreePoints(Point p1, Point p2, Point p3)
{
// We use matrices and determinants to find the center and radius of the
return c;
}
+Arc Geometry::FindArcForThreePoints(Point p1, Point p2, Point p3)
+{
+ int orientation = Orientation(p1, p2, p3);
+
+ // Sanity check: if points are colinear, there is no arc
+ if (orientation == 0)
+ return Arc();
+
+ Circle c = FindCircleForThreePoints(p1, p2, p3);
+ double a1 = Vector::Angle(c.p[0], p1);
+ double a2 = Vector::Angle(c.p[0], p2);
+ double span = a2 - a1;
+
+ if (orientation < 0 && span > 0)
+ span -= TAU;
+ else if (orientation > 0 && span < 0)
+ span += TAU;
+
+ return Arc(c.p[0], c.radius[0], a1, span);
+}
+
double Geometry::Determinant3x3(double a11, double a12, double a13, double a21, double a22, double a23, double a31, double a32, double a33)
{
return (a11 * ((a22 * a33) - (a32 * a23)))
// N.B.: The radius can also be found with r = (a² + h²) / 2h where a is
// the 1/2 length of the line segment and h is the bump length.
-// double radius = (length + (1.0 / length)) / 2.0;
double radius = 0.5 * (((length * length) + (bumpLen * bumpLen)) / bumpLen);
Vector ctrVec = mpNormal * (radius - bumpLen);
Point center = midpoint + ctrVec;
return Arc(center, radius, angle1, span);
}
+
+double Geometry::Pack(Arc * a)
+{
+ Point p1 = a->p[0] + (Vector(cos(a->angle[0]), sin(a->angle[0])) * a->radius[0]);
+ Point p2 = a->p[0] + (Vector(cos(a->angle[0] + a->angle[1]), sin(a->angle[0] + a->angle[1])) * a->radius[0]);
+ double endpointLen = Vector::Magnitude(p1, p2) / 2.0;
+
+ // Bump height can be found with h = r ± sqr(r² - a²) where r is the
+ // radius, and a is the 1/2 length of the endpoint's line segment. The
+ // plus/minus term is positive if the arc span is less than 1/2 TAU,
+ // negative if the arc span is greater than 1/2 TAU.
+ double discriminant = sqrt((a->radius[0] * a->radius[0]) - (endpointLen * endpointLen));
+ double bumpLen = a->radius[0] + (discriminant * (fabs(a->angle[1]) < HALF_TAU ? 1.0 : -1.0));
+
+ return (bumpLen / endpointLen) * (a->angle[1] > 0 ? -1.0 : 1.0);
+}
static void FindTangents(Object *, Object *);
static Point NearestTo(Point, Point, Point);
static Vector GetNormalOfPointAndLine(Point, Line *);
+ static int Orientation(Point, Point, Point);
static Circle FindCircleForThreePoints(Point, Point, Point);
+ static Arc FindArcForThreePoints(Point, Point, Point);
static double Determinant3x3(double, double, double, double, double, double, double, double, double);
static Arc Unpack(Point, Point, double);
+ static double Pack(Arc *);
};
#endif // __GEOMETRY_H__
{
}
-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)
+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)
{
- p[0] = pt1; radius[0] = r; angle[0] = a1, angle[1] = a2; hitPoint[0] = hitPoint[1] = hitPoint[2] = false;
+ p[0] = ctr;
+ radius[0] = r;
+ angle[0] = a1;
+ angle[1] = a2;
+ hitPoint[0] = hitPoint[1] = hitPoint[2] = false;
+}
+
+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)
+{
+ p[0] = ctr;
+ radius[0] = r;
+ angle[0] = Vector::Angle(ctr, p1);
+/*
+s = 10, e = 20, span = 10 (why not -350?)
+s = 20, e = 10, span = -10 (why not 350?)
+s = 10, e = 350, span = 340 (why not -20?)
+s = 350, e = 10, span = -340 (why not 20?)
+
+below is still not right, we need one more point to disambiguate this...
+*/
+ angle[1] = Vector::Angle(ctr, p2) - angle[0];
+ hitPoint[0] = hitPoint[1] = hitPoint[2] = false;
}
Rect Arc::Bounds(void)
OBJECT_COMMON;
Arc();
- Arc(Vector pt1, double r, double a1, double a2, float th = 1.0, uint32_t c = 0, int l = LSSolid);
+ Arc(Vector ctr, double r, double a1, double a2, float th = 1.0, uint32_t c = 0, int l = LSSolid);
+ Arc(Vector ctr, double r, Point p1, Point p2, float th = 1.0, uint32_t c = 0, int l = LSSolid);
Rect Bounds(void);
};