From 07f3ab95e49ddcf7dec2e22c41611b0312ef0b57 Mon Sep 17 00:00:00 2001 From: EvilSpirit Date: Mon, 11 Apr 2016 20:21:41 +0600 Subject: [PATCH] Draw extension lines for angle constraints between line segments. --- src/drawconstraint.cpp | 96 ++++++++++++++++++++++++++++++++++-------- src/sketch.h | 2 + 2 files changed, 80 insertions(+), 18 deletions(-) diff --git a/src/drawconstraint.cpp b/src/drawconstraint.cpp index d8539b8..27dac3f 100644 --- a/src/drawconstraint.cpp +++ b/src/drawconstraint.cpp @@ -227,6 +227,13 @@ int Constraint::DoLineTrimmedAgainstBox(Vector ref, Vector a, Vector b) { return within; } +void Constraint::DoArrow(Vector p, Vector dir, Vector n, double width, double angle, double da) { + dir = dir.WithMagnitude(width / cos(angle)); + dir = dir.RotatedAbout(n, da); + LineDrawOrGetDistance(p, p.Plus(dir.RotatedAbout(n, angle))); + LineDrawOrGetDistance(p, p.Plus(dir.RotatedAbout(n, -angle))); +} + //----------------------------------------------------------------------------- // Draw a line with arrows on both ends, and possibly a gap in the middle for // the dimension. We will use these for most length dimensions. The length @@ -271,11 +278,8 @@ void Constraint::DoLineWithArrows(Vector ref, Vector a, Vector b, if(within > 0) LineDrawOrGetDistance(be, be.Plus(seg)); } - LineDrawOrGetDistance(ae, ae.Plus(arrow.RotatedAbout(n, theta))); - LineDrawOrGetDistance(ae, ae.Plus(arrow.RotatedAbout(n, -theta))); - arrow = arrow.ScaledBy(-1); - LineDrawOrGetDistance(be, be.Plus(arrow.RotatedAbout(n, theta))); - LineDrawOrGetDistance(be, be.Plus(arrow.RotatedAbout(n, -theta))); + DoArrow(ae, arrow, n, 13.0 * pixels, theta, 0.0); + DoArrow(be, arrow.Negated(), n, 13.0 * pixels, theta, 0.0); } void Constraint::DoEqualLenTicks(Vector a, Vector b, Vector gn) { @@ -323,6 +327,10 @@ void Constraint::DoArcForAngle(Vector a0, Vector da, Vector b0, Vector db, db = db.ProjectVectorInto(workplane); } + double px = 1.0 / SS.GW.scale; + Vector a1 = a0.Plus(da); + Vector b1 = b0.Plus(db); + bool skew; Vector pi = Vector::AtIntersectionOfLines(a0, a0.Plus(da), b0, b0.Plus(db), &skew); @@ -332,12 +340,13 @@ void Constraint::DoArcForAngle(Vector a0, Vector da, Vector b0, Vector db, // We draw in a coordinate system centered at the intersection point. // One basis vector is da, and the other is normal to da and in // the plane that contains our lines (so normal to its normal). - Vector dna = (da.Cross(db)).Cross(da); - da = da.WithMagnitude(1); dna = dna.WithMagnitude(1); + Vector norm = da.Cross(db); + Vector dna = norm.Cross(da).WithMagnitude(1.0); + da = da.WithMagnitude(1); Vector rm = (*ref).Minus(pi); double rda = rm.Dot(da), rdna = rm.Dot(dna); - double r = sqrt(rda*rda + rdna*rdna); + double r = max(sqrt(rda*rda + rdna*rdna), 15.0 * px); double c = (da.Dot(db))/(da.Magnitude()*db.Magnitude()); double thetaf = acos(c); @@ -348,6 +357,8 @@ void Constraint::DoArcForAngle(Vector a0, Vector da, Vector b0, Vector db, } Vector prev = da.ScaledBy(r).Plus(pi); + Vector apa = prev; + int i, n = 30; for(i = 0; i <= n; i++) { double theta = (i*thetaf)/n; @@ -357,6 +368,20 @@ void Constraint::DoArcForAngle(Vector a0, Vector da, Vector b0, Vector db, prev = p; } + Vector apb = prev; + DoLineExtend(a0, a1, apa, 5.0 * px); + DoLineExtend(b0, b1, apb, 5.0 * px); + + double arrowW = 13 * px; + double arrowA = 18.0 * PI / 180.0; + + // Draw arrows only when we have enough space. + if(apb.Minus(apa).Magnitude() > 2.5 * arrowW) { + double angleCorr = arrowW / (2.0 * r); + DoArrow(apa, dna, norm, arrowW, arrowA, angleCorr); + DoArrow(apb, dna, norm, arrowW, arrowA, thetaf + PI - angleCorr); + } + // The elliptical approximation isn't exactly right, but the correct // calculation (against the bounding box of the text) would be rather // complex and this looks pretty good. @@ -396,10 +421,39 @@ bool Constraint::IsVisible() const { return true; } +bool Constraint::DoLineExtend(Vector p0, Vector p1, Vector pt, double salient) { + Vector dir = p1.Minus(p0); + double k = dir.Dot(pt.Minus(p0)) / dir.Dot(dir); + Vector ptOnLine = p0.Plus(dir.ScaledBy(k)); + + // Draw projection line. + LineDrawOrGetDistance(pt, ptOnLine); + + // Calculate salient direction. + Vector sd = dir.WithMagnitude(1.0).ScaledBy(salient); + + Vector from; + Vector to; + + if(k < 0.0) { + from = p0; + to = ptOnLine.Minus(sd); + } else if(k > 1.0) { + from = p1; + to = ptOnLine.Plus(sd); + } else { + return false; + } + + // Draw extension line. + LineDrawOrGetDistance(from, to); + return true; +} + void Constraint::DrawOrGetDistance(Vector *labelPos) { - + if(!IsVisible()) return; - + // Unit vectors that describe our current view of the scene. One pixel // long, not one actual unit. Vector gr = SS.GW.projRight.ScaledBy(1/SS.GW.scale); @@ -656,16 +710,19 @@ void Constraint::DrawOrGetDistance(Vector *labelPos) { Entity *c = SK.GetEntity(entityC); Entity *d = SK.GetEntity(entityD); - Vector a0 = a->VectorGetRefPoint(); - Vector b0 = b->VectorGetRefPoint(); - Vector c0 = c->VectorGetRefPoint(); - Vector d0 = d->VectorGetRefPoint(); + Vector a0 = a->VectorGetStartPoint(); + Vector b0 = b->VectorGetStartPoint(); + Vector c0 = c->VectorGetStartPoint(); + Vector d0 = d->VectorGetStartPoint(); Vector da = a->VectorGetNum(); Vector db = b->VectorGetNum(); Vector dc = c->VectorGetNum(); Vector dd = d->VectorGetNum(); - if(other) da = da.ScaledBy(-1); + if(other) { + a0 = a0.Plus(da); + da = da.ScaledBy(-1); + } DoArcForAngle(a0, da, b0, db, da.WithMagnitude(40/SS.GW.scale), &ref); @@ -679,11 +736,14 @@ void Constraint::DrawOrGetDistance(Vector *labelPos) { Entity *a = SK.GetEntity(entityA); Entity *b = SK.GetEntity(entityB); - Vector a0 = a->VectorGetRefPoint(); - Vector b0 = b->VectorGetRefPoint(); + Vector a0 = a->VectorGetStartPoint(); + Vector b0 = b->VectorGetStartPoint(); Vector da = a->VectorGetNum(); Vector db = b->VectorGetNum(); - if(other) da = da.ScaledBy(-1); + if(other) { + a0 = a0.Plus(da); + da = da.ScaledBy(-1); + } Vector ref; DoArcForAngle(a0, da, b0, db, disp.offset, &ref); diff --git a/src/sketch.h b/src/sketch.h index b34aeb5..0c7d01a 100644 --- a/src/sketch.h +++ b/src/sketch.h @@ -688,8 +688,10 @@ public: void DrawOrGetDistance(Vector *labelPos); double EllipticalInterpolation(double rx, double ry, double theta); std::string Label(void); + bool DoLineExtend(Vector p0, Vector p1, Vector pt, double salient); void DoArcForAngle(Vector a0, Vector da, Vector b0, Vector db, Vector offset, Vector *ref); + void DoArrow(Vector p, Vector dir, Vector n, double width, double angle, double da); void DoLineWithArrows(Vector ref, Vector a, Vector b, bool onlyOneExt); int DoLineTrimmedAgainstBox(Vector ref, Vector a, Vector b); void DoLabel(Vector ref, Vector *labelPos, Vector gr, Vector gu);