Fix paste transformed not correcting tangent arcs when mirrored (#833)

This commit is contained in:
Koen Schmeets 2020-12-22 14:09:31 +01:00 committed by GitHub
parent 679e2b9202
commit 96958f4663
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 97 additions and 56 deletions

View File

@ -245,18 +245,41 @@ void GraphicsWindow::PasteClipboard(Vector trans, double theta, double scale) {
c.reference = cc->reference; c.reference = cc->reference;
c.disp = cc->disp; c.disp = cc->disp;
c.comment = cc->comment; c.comment = cc->comment;
bool removeConstraint = false; bool dontAddConstraint = false;
switch(c.type) { switch(c.type) {
case Constraint::Type::COMMENT: case Constraint::Type::COMMENT:
c.disp.offset = c.disp.offset.Plus(trans); c.disp.offset = c.disp.offset.Plus(trans);
break; break;
case Constraint::Type::PT_PT_DISTANCE: case Constraint::Type::PT_PT_DISTANCE:
case Constraint::Type::PT_LINE_DISTANCE: case Constraint::Type::PT_LINE_DISTANCE:
case Constraint::Type::PROJ_PT_DISTANCE: case Constraint::Type::PROJ_PT_DISTANCE:
case Constraint::Type::DIAMETER: case Constraint::Type::DIAMETER:
c.valA *= fabs(scale); c.valA *= fabs(scale);
break; 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::HORIZONTAL:
case Constraint::Type::VERTICAL: case Constraint::Type::VERTICAL:
// When rotating 90 or 270 degrees, swap the vertical / horizontal constaints // 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; c.type = Constraint::Type::HORIZONTAL;
} }
} else if (fmod(theta, PI/2) != 0) { } else if (fmod(theta, PI/2) != 0) {
removeConstraint = true; dontAddConstraint = true;
} }
break; break;
default: default:
break; break;
} }
if (!removeConstraint) { if (!dontAddConstraint) {
hConstraint hc = Constraint::AddConstraint(&c, /*rememberForUndo=*/false); hConstraint hc = Constraint::AddConstraint(&c, /*rememberForUndo=*/false);
if(c.type == Constraint::Type::COMMENT) { if(c.type == Constraint::Type::COMMENT) {
MakeSelected(hc); MakeSelected(hc);

View File

@ -127,6 +127,66 @@ hConstraint Constraint::ConstrainCoincident(hEntity ptA, hEntity ptB) {
Entity::NO_ENTITY, Entity::NO_ENTITY, /*other=*/false, /*other2=*/false); 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) { void Constraint::MenuConstrain(Command id) {
Constraint c = {}; Constraint c = {};
c.group = SS.GW.activeGroup; c.group = SS.GW.activeGroup;
@ -617,50 +677,22 @@ void Constraint::MenuConstrain(Command id) {
c.entityA = gs.vector[0]; c.entityA = gs.vector[0];
c.entityB = gs.vector[1]; c.entityB = gs.vector[1];
} else if(gs.lineSegments == 1 && gs.arcs == 1 && gs.n == 2) { } else if(gs.lineSegments == 1 && gs.arcs == 1 && gs.n == 2) {
Entity *line = SK.GetEntity(gs.entity[0]); Entity *line = SK.GetEntity(gs.entity[0]),
Entity *arc = SK.GetEntity(gs.entity[1]); *arc = SK.GetEntity(gs.entity[1]);
if(line->type == Entity::Type::ARC_OF_CIRCLE) { if(line->type == Entity::Type::ARC_OF_CIRCLE) {
swap(line, arc); swap(line, arc);
} }
Vector l0 = SK.GetEntity(line->point[0])->PointGetNum(), ConstrainArcLineTangent(&c, line, arc);
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;
}
c.type = Type::ARC_LINE_TANGENT; c.type = Type::ARC_LINE_TANGENT;
c.entityA = arc->h; c.entityA = arc->h;
c.entityB = line->h; c.entityB = line->h;
} else if(gs.lineSegments == 1 && gs.cubics == 1 && gs.n == 2) { } else if(gs.lineSegments == 1 && gs.cubics == 1 && gs.n == 2) {
Entity *line = SK.GetEntity(gs.entity[0]); Entity *line = SK.GetEntity(gs.entity[0]),
Entity *cubic = SK.GetEntity(gs.entity[1]); *cubic = SK.GetEntity(gs.entity[1]);
if(line->type == Entity::Type::CUBIC) { if(line->type == Entity::Type::CUBIC) {
swap(line, cubic); swap(line, cubic);
} }
Vector l0 = SK.GetEntity(line->point[0])->PointGetNum(), ConstrainCubicLineTangent(&c, line, cubic);
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;
}
c.type = Type::CUBIC_LINE_TANGENT; c.type = Type::CUBIC_LINE_TANGENT;
c.entityA = cubic->h; c.entityA = cubic->h;
c.entityB = line->h; c.entityB = line->h;
@ -671,24 +703,7 @@ void Constraint::MenuConstrain(Command id) {
} }
Entity *eA = SK.GetEntity(gs.entity[0]), Entity *eA = SK.GetEntity(gs.entity[0]),
*eB = SK.GetEntity(gs.entity[1]); *eB = SK.GetEntity(gs.entity[1]);
Vector as = eA->EndpointStart(), ConstrainCurveCurveTangent(&c, eA, eB);
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;
}
c.type = Type::CURVE_CURVE_TANGENT; c.type = Type::CURVE_CURVE_TANGENT;
c.entityA = eA->h; c.entityA = eA->h;
c.entityB = eB->h; c.entityB = eB->h;

View File

@ -790,6 +790,9 @@ public:
static hConstraint TryConstrain(Constraint::Type type, hEntity ptA, hEntity ptB, static hConstraint TryConstrain(Constraint::Type type, hEntity ptA, hEntity ptB,
hEntity entityA, hEntity entityB = Entity::NO_ENTITY, hEntity entityA, hEntity entityB = Entity::NO_ENTITY,
bool other = false, bool other2 = false); 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 { class hEquation {