diff --git a/src/clipboard.cpp b/src/clipboard.cpp index dbcd1df..d43ec45 100644 --- a/src/clipboard.cpp +++ b/src/clipboard.cpp @@ -245,18 +245,41 @@ void GraphicsWindow::PasteClipboard(Vector trans, double theta, double scale) { c.reference = cc->reference; c.disp = cc->disp; c.comment = cc->comment; - bool removeConstraint = false; + bool dontAddConstraint = false; switch(c.type) { case Constraint::Type::COMMENT: c.disp.offset = c.disp.offset.Plus(trans); break; - case Constraint::Type::PT_PT_DISTANCE: case Constraint::Type::PT_LINE_DISTANCE: case Constraint::Type::PROJ_PT_DISTANCE: case Constraint::Type::DIAMETER: c.valA *= fabs(scale); break; + case Constraint::Type::ARC_LINE_TANGENT: { + Entity *line = SK.GetEntity(c.entityB), + *arc = SK.GetEntity(c.entityA); + if(line->type == Entity::Type::ARC_OF_CIRCLE) { + swap(line, arc); + } + Constraint::ConstrainArcLineTangent(&c, line, arc); + break; + } + case Constraint::Type::CUBIC_LINE_TANGENT: { + Entity *line = SK.GetEntity(c.entityB), + *cubic = SK.GetEntity(c.entityA); + if(line->type == Entity::Type::CUBIC) { + swap(line, cubic); + } + Constraint::ConstrainCubicLineTangent(&c, line, cubic); + break; + } + case Constraint::Type::CURVE_CURVE_TANGENT: { + Entity *eA = SK.GetEntity(c.entityA), + *eB = SK.GetEntity(c.entityB); + Constraint::ConstrainCurveCurveTangent(&c, eA, eB); + break; + } case Constraint::Type::HORIZONTAL: case Constraint::Type::VERTICAL: // When rotating 90 or 270 degrees, swap the vertical / horizontal constaints @@ -267,13 +290,13 @@ void GraphicsWindow::PasteClipboard(Vector trans, double theta, double scale) { c.type = Constraint::Type::HORIZONTAL; } } else if (fmod(theta, PI/2) != 0) { - removeConstraint = true; + dontAddConstraint = true; } break; default: break; } - if (!removeConstraint) { + if (!dontAddConstraint) { hConstraint hc = Constraint::AddConstraint(&c, /*rememberForUndo=*/false); if(c.type == Constraint::Type::COMMENT) { MakeSelected(hc); diff --git a/src/constraint.cpp b/src/constraint.cpp index a66f6d3..2acc211 100644 --- a/src/constraint.cpp +++ b/src/constraint.cpp @@ -127,6 +127,66 @@ hConstraint Constraint::ConstrainCoincident(hEntity ptA, hEntity ptB) { Entity::NO_ENTITY, Entity::NO_ENTITY, /*other=*/false, /*other2=*/false); } +void Constraint::ConstrainArcLineTangent(Constraint *c, Entity *line, Entity *arc) { + Vector l0 = SK.GetEntity(line->point[0])->PointGetNum(), + l1 = SK.GetEntity(line->point[1])->PointGetNum(); + Vector a1 = SK.GetEntity(arc->point[1])->PointGetNum(), + a2 = SK.GetEntity(arc->point[2])->PointGetNum(); + if(l0.Equals(a1) || l1.Equals(a1)) { + c->other = false; + } else if(l0.Equals(a2) || l1.Equals(a2)) { + c->other = true; + } else { + Error(_("The tangent arc and line segment must share an " + "endpoint. Constrain them with Constrain -> " + "On Point before constraining tangent.")); + return; + } +} + +void Constraint::ConstrainCubicLineTangent(Constraint *c, Entity *line, Entity *cubic) { + Vector l0 = SK.GetEntity(line->point[0])->PointGetNum(), + l1 = SK.GetEntity(line->point[1])->PointGetNum(); + Vector as = cubic->CubicGetStartNum(), + af = cubic->CubicGetFinishNum(); + + if(l0.Equals(as) || l1.Equals(as)) { + c->other = false; + } else if(l0.Equals(af) || l1.Equals(af)) { + c->other = true; + } else { + Error(_("The tangent cubic and line segment must share an " + "endpoint. Constrain them with Constrain -> " + "On Point before constraining tangent.")); + return; + } +} + +void Constraint::ConstrainCurveCurveTangent(Constraint *c, Entity *eA, Entity *eB) { + Vector as = eA->EndpointStart(), + af = eA->EndpointFinish(), + bs = eB->EndpointStart(), + bf = eB->EndpointFinish(); + if(as.Equals(bs)) { + c->other = false; + c->other2 = false; + } else if(as.Equals(bf)) { + c->other = false; + c->other2 = true; + } else if(af.Equals(bs)) { + c->other = true; + c->other2 = false; + } else if(af.Equals(bf)) { + c->other = true; + c->other2 = true; + } else { + Error(_("The curves must share an endpoint. Constrain them " + "with Constrain -> On Point before constraining " + "tangent.")); + return; + } +} + void Constraint::MenuConstrain(Command id) { Constraint c = {}; c.group = SS.GW.activeGroup; @@ -617,50 +677,22 @@ void Constraint::MenuConstrain(Command id) { c.entityA = gs.vector[0]; c.entityB = gs.vector[1]; } else if(gs.lineSegments == 1 && gs.arcs == 1 && gs.n == 2) { - Entity *line = SK.GetEntity(gs.entity[0]); - Entity *arc = SK.GetEntity(gs.entity[1]); + Entity *line = SK.GetEntity(gs.entity[0]), + *arc = SK.GetEntity(gs.entity[1]); if(line->type == Entity::Type::ARC_OF_CIRCLE) { swap(line, arc); } - Vector l0 = SK.GetEntity(line->point[0])->PointGetNum(), - l1 = SK.GetEntity(line->point[1])->PointGetNum(); - Vector a1 = SK.GetEntity(arc->point[1])->PointGetNum(), - a2 = SK.GetEntity(arc->point[2])->PointGetNum(); - - if(l0.Equals(a1) || l1.Equals(a1)) { - c.other = false; - } else if(l0.Equals(a2) || l1.Equals(a2)) { - c.other = true; - } else { - Error(_("The tangent arc and line segment must share an " - "endpoint. Constrain them with Constrain -> " - "On Point before constraining tangent.")); - return; - } + ConstrainArcLineTangent(&c, line, arc); c.type = Type::ARC_LINE_TANGENT; c.entityA = arc->h; c.entityB = line->h; } else if(gs.lineSegments == 1 && gs.cubics == 1 && gs.n == 2) { - Entity *line = SK.GetEntity(gs.entity[0]); - Entity *cubic = SK.GetEntity(gs.entity[1]); + Entity *line = SK.GetEntity(gs.entity[0]), + *cubic = SK.GetEntity(gs.entity[1]); if(line->type == Entity::Type::CUBIC) { swap(line, cubic); } - Vector l0 = SK.GetEntity(line->point[0])->PointGetNum(), - l1 = SK.GetEntity(line->point[1])->PointGetNum(); - Vector as = cubic->CubicGetStartNum(), - af = cubic->CubicGetFinishNum(); - - if(l0.Equals(as) || l1.Equals(as)) { - c.other = false; - } else if(l0.Equals(af) || l1.Equals(af)) { - c.other = true; - } else { - Error(_("The tangent cubic and line segment must share an " - "endpoint. Constrain them with Constrain -> " - "On Point before constraining tangent.")); - return; - } + ConstrainCubicLineTangent(&c, line, cubic); c.type = Type::CUBIC_LINE_TANGENT; c.entityA = cubic->h; c.entityB = line->h; @@ -671,24 +703,7 @@ void Constraint::MenuConstrain(Command id) { } Entity *eA = SK.GetEntity(gs.entity[0]), *eB = SK.GetEntity(gs.entity[1]); - Vector as = eA->EndpointStart(), - af = eA->EndpointFinish(), - bs = eB->EndpointStart(), - bf = eB->EndpointFinish(); - if(as.Equals(bs)) { - c.other = false; c.other2 = false; - } else if(as.Equals(bf)) { - c.other = false; c.other2 = true; - } else if(af.Equals(bs)) { - c.other = true; c.other2 = false; - } else if(af.Equals(bf)) { - c.other = true; c.other2 = true; - } else { - Error(_("The curves must share an endpoint. Constrain them " - "with Constrain -> On Point before constraining " - "tangent.")); - return; - } + ConstrainCurveCurveTangent(&c, eA, eB); c.type = Type::CURVE_CURVE_TANGENT; c.entityA = eA->h; c.entityB = eB->h; diff --git a/src/sketch.h b/src/sketch.h index 869e0b6..8377374 100644 --- a/src/sketch.h +++ b/src/sketch.h @@ -790,6 +790,9 @@ public: static hConstraint TryConstrain(Constraint::Type type, hEntity ptA, hEntity ptB, hEntity entityA, hEntity entityB = Entity::NO_ENTITY, bool other = false, bool other2 = false); + static void ConstrainArcLineTangent(Constraint *c, Entity *line, Entity *arc); + static void ConstrainCubicLineTangent(Constraint *c, Entity *line, Entity *cubic); + static void ConstrainCurveCurveTangent(Constraint *c, Entity *eA, Entity *eB); }; class hEquation {