Fix paste transformed not correcting tangent arcs when mirrored (#833)
This commit is contained in:
parent
679e2b9202
commit
96958f4663
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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 {
|
||||||
|
Loading…
Reference in New Issue
Block a user