Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
141 changes: 92 additions & 49 deletions src/constraint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,8 @@ bool Constraint::ConstrainCurveCurveTangent(Constraint *c, Entity *eA, Entity *e
}

void Constraint::MenuConstrain(Command id) {
std::vector<Constraint> newcons;

Constraint c = {};
c.group = SS.GW.activeGroup;
c.workplane = SS.GW.ActiveWorkplane();
Expand Down Expand Up @@ -262,7 +264,9 @@ void Constraint::MenuConstrain(Command id) {

c.valA = 0;
c.ModifyToSatisfy();
AddConstraint(&c);
newcons.push_back(c);
for (auto&& nc:newcons)
AddConstraint(&nc);
break;
}

Expand Down Expand Up @@ -297,20 +301,25 @@ void Constraint::MenuConstrain(Command id) {
" * a point and a plane face (point on face)\n"));
return;
}
newcons.push_back(c);
AddConstraint(&c);
break;

case Command::EQUAL:
if(gs.lineSegments == 2 && gs.n == 2) {
if(gs.lineSegments >= 2 && gs.lineSegments == gs.n) {
c.type = Type::EQUAL_LENGTH_LINES;
c.entityA = gs.entity[0];
c.entityB = gs.entity[1];
for (std::vector<hEntity>::size_type k = 1;k < gs.entity.size(); ++k){
c.entityB = gs.entity[k];
newcons.push_back(c);
}
} else if(gs.lineSegments == 2 && gs.points == 2 && gs.n == 4) {
c.type = Type::EQ_PT_LN_DISTANCES;
c.entityA = gs.entity[0];
c.ptA = gs.point[0];
c.entityB = gs.entity[1];
c.ptB = gs.point[1];
newcons.push_back(c);
} else if(gs.lineSegments == 1 && gs.points == 2 && gs.n == 3) {
// The same line segment for the distances, but different
// points.
Expand All @@ -319,27 +328,34 @@ void Constraint::MenuConstrain(Command id) {
c.ptA = gs.point[0];
c.entityB = gs.entity[0];
c.ptB = gs.point[1];
newcons.push_back(c);
} else if(gs.lineSegments == 2 && gs.points == 1 && gs.n == 3) {
c.type = Type::EQ_LEN_PT_LINE_D;
c.entityA = gs.entity[0];
c.entityB = gs.entity[1];
c.ptA = gs.point[0];
newcons.push_back(c);
} else if(gs.vectors == 4 && gs.n == 4) {
c.type = Type::EQUAL_ANGLE;
c.entityA = gs.vector[0];
c.entityB = gs.vector[1];
c.entityC = gs.vector[2];
c.entityD = gs.vector[3];
newcons.push_back(c);
} else if(gs.vectors == 3 && gs.n == 3) {
c.type = Type::EQUAL_ANGLE;
c.entityA = gs.vector[0];
c.entityB = gs.vector[1];
c.entityC = gs.vector[1];
c.entityD = gs.vector[2];
} else if(gs.circlesOrArcs == 2 && gs.n == 2) {
newcons.push_back(c);
} else if(gs.circlesOrArcs >= 2 && gs.circlesOrArcs == gs.n) {
c.type = Type::EQUAL_RADIUS;
c.entityA = gs.entity[0];
c.entityB = gs.entity[1];
for (std::vector<hEntity>::size_type k = 1;k < gs.entity.size(); ++k){
c.entityB = gs.entity[k];
newcons.push_back(c);
}
} else if(gs.arcs == 1 && gs.lineSegments == 1 && gs.n == 2) {
c.type = Type::EQUAL_LINE_ARC_LEN;
if(SK.GetEntity(gs.entity[0])->type == Entity::Type::ARC_OF_CIRCLE) {
Expand All @@ -349,6 +365,7 @@ void Constraint::MenuConstrain(Command id) {
c.entityA = gs.entity[0];
c.entityB = gs.entity[1];
}
newcons.push_back(c);
} else {
Error(_("Bad selection for equal length / radius constraint. "
"This constraint can apply to:\n\n"
Expand All @@ -368,19 +385,21 @@ void Constraint::MenuConstrain(Command id) {
"(line segment length equals arc length)\n"));
return;
}
if(c.type == Type::EQUAL_ANGLE) {
// Infer the nearest supplementary angle from the sketch.
Vector a1 = SK.GetEntity(c.entityA)->VectorGetNum(),
b1 = SK.GetEntity(c.entityB)->VectorGetNum(),
a2 = SK.GetEntity(c.entityC)->VectorGetNum(),
b2 = SK.GetEntity(c.entityD)->VectorGetNum();
double d1 = a1.Dot(b1), d2 = a2.Dot(b2);

if(d1*d2 < 0) {
c.other = true;
for (auto&& nc : newcons){
if(nc.type == Type::EQUAL_ANGLE) {
// Infer the nearest supplementary angle from the sketch.
Vector a1 = SK.GetEntity(c.entityA)->VectorGetNum(),
b1 = SK.GetEntity(c.entityB)->VectorGetNum(),
a2 = SK.GetEntity(c.entityC)->VectorGetNum(),
b2 = SK.GetEntity(c.entityD)->VectorGetNum();
double d1 = a1.Dot(b1), d2 = a2.Dot(b2);

if(d1*d2 < 0) {
nc.other = true;
}
}
AddConstraint(&nc);
}
AddConstraint(&c);
break;

case Command::RATIO:
Expand Down Expand Up @@ -414,6 +433,7 @@ void Constraint::MenuConstrain(Command id) {

c.valA = 0;
c.ModifyToSatisfy();
newcons.push_back(c);
AddConstraint(&c);
break;

Expand Down Expand Up @@ -448,6 +468,7 @@ void Constraint::MenuConstrain(Command id) {

c.valA = 0;
c.ModifyToSatisfy();
newcons.push_back(c);
AddConstraint(&c);
break;

Expand All @@ -461,13 +482,16 @@ void Constraint::MenuConstrain(Command id) {
// it on-line; so auto-remove that. Handle as one undo group.
SS.UndoRemember();
DeleteAllConstraintsFor(Type::PT_ON_LINE, c.entityA, c.ptA);
newcons.push_back(c);
AddConstraint(&c, /*rememberForUndo=*/false);
break;
} else if(gs.lineSegments == 1 && gs.workplanes == 1 && gs.n == 2) {
c.type = Type::AT_MIDPOINT;
int i = SK.GetEntity(gs.entity[0])->IsWorkplane() ? 1 : 0;
c.entityA = gs.entity[i];
c.entityB = gs.entity[1-i];
newcons.push_back(c);
AddConstraint(&c);
} else {
Error(_("Bad selection for at midpoint constraint. This "
"constraint can apply to:\n\n"
Expand All @@ -477,7 +501,7 @@ void Constraint::MenuConstrain(Command id) {
"(line's midpoint on plane)\n"));
return;
}
AddConstraint(&c);

break;

case Command::SYMMETRIC:
Expand Down Expand Up @@ -565,10 +589,12 @@ void Constraint::MenuConstrain(Command id) {
Entity::NO_ENTITY);
DeleteAllConstraintsFor(Type::VERTICAL, (gs.entity[0]),
Entity::NO_ENTITY);
newcons.push_back(c);
AddConstraint(&c, /*rememberForUndo=*/false);
break;
}
}
newcons.push_back(c);
AddConstraint(&c);
break;

Expand All @@ -580,8 +606,16 @@ void Constraint::MenuConstrain(Command id) {
"applying a horizontal or vertical constraint."));
return;
}
if(gs.lineSegments == 1 && gs.n == 1) {
c.entityA = gs.entity[0];
if(gs.lineSegments > 0 && gs.lineSegments == gs.n) {
for (auto enti : gs.entity){
c.entityA = enti;
if(id == Command::HORIZONTAL) {
c.type = Type::HORIZONTAL;
} else {
c.type = Type::VERTICAL;
}
newcons.push_back(c);
}
Entity *e = SK.GetEntity(c.entityA);
Copy link
Member

@phkahler phkahler Dec 30, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do these 3 lines do now? Or what did they do before? the 3 starting at 619.

ha = e->point[0];
hb = e->point[1];
Expand All @@ -595,12 +629,8 @@ void Constraint::MenuConstrain(Command id) {
" * a line segment\n"));
return;
}
if(id == Command::HORIZONTAL) {
c.type = Type::HORIZONTAL;
} else {
c.type = Type::VERTICAL;
}
AddConstraint(&c);
for (auto && nc: newcons)
AddConstraint(&nc);
break;
}

Expand Down Expand Up @@ -640,6 +670,7 @@ void Constraint::MenuConstrain(Command id) {

nfree->NormalForceTo(Quaternion::From(fu, fv));
}
newcons.push_back(c);
AddConstraint(&c, /*rememberForUndo=*/false);
break;
}
Expand Down Expand Up @@ -716,6 +747,7 @@ void Constraint::MenuConstrain(Command id) {
}

c.ModifyToSatisfy();
newcons.push_back(c);
AddConstraint(&c);
break;
}
Expand All @@ -725,10 +757,13 @@ void Constraint::MenuConstrain(Command id) {
c.type = Type::PARALLEL;
c.entityA = gs.face[0];
c.entityB = gs.face[1];
} else if(gs.vectors == 2 && gs.n == 2) {
} else if(gs.vectors > 1 && gs.vectors == gs.n) {
c.type = Type::PARALLEL;
c.entityA = gs.vector[0];
c.entityB = gs.vector[1];
for (std::vector<hEntity>::size_type k = 1; k < gs.vector.size();++k ){
c.entityB = gs.vector[k];
newcons.push_back(c);
}
} else if(gs.lineSegments == 1 && gs.arcs == 1 && gs.n == 2) {
Entity *line = SK.GetEntity(gs.entity[0]),
*arc = SK.GetEntity(gs.entity[1]);
Expand All @@ -741,6 +776,7 @@ void Constraint::MenuConstrain(Command id) {
c.type = Type::ARC_LINE_TANGENT;
c.entityA = arc->h;
c.entityB = line->h;
newcons.push_back(c);
} else if(gs.lineSegments == 1 && gs.cubics == 1 && gs.n == 2) {
Entity *line = SK.GetEntity(gs.entity[0]),
*cubic = SK.GetEntity(gs.entity[1]);
Expand All @@ -753,6 +789,7 @@ void Constraint::MenuConstrain(Command id) {
c.type = Type::CUBIC_LINE_TANGENT;
c.entityA = cubic->h;
c.entityB = line->h;
newcons.push_back(c);
} else if(gs.cubics + gs.arcs == 2 && gs.n == 2) {
if(!SS.GW.LockedInWorkplane()) {
Error(_("Curve-curve tangency must apply in workplane."));
Expand All @@ -766,6 +803,7 @@ void Constraint::MenuConstrain(Command id) {
c.type = Type::CURVE_CURVE_TANGENT;
c.entityA = eA->h;
c.entityB = eB->h;
newcons.push_back(c);
} else {
Error(_("Bad selection for parallel / tangent constraint. This "
"constraint can apply to:\n\n"
Expand All @@ -777,7 +815,8 @@ void Constraint::MenuConstrain(Command id) {
"an endpoint (tangent)\n"));
return;
}
AddConstraint(&c);
for (auto&& nc:newcons)
AddConstraint(&nc);
break;

case Command::PERPENDICULAR:
Expand All @@ -798,6 +837,7 @@ void Constraint::MenuConstrain(Command id) {
" * two normals\n"));
return;
}
newcons.push_back(c);
AddConstraint(&c);
break;

Expand All @@ -811,6 +851,7 @@ void Constraint::MenuConstrain(Command id) {
" * a point\n"));
return;
}
newcons.push_back(c);
AddConstraint(&c);
break;

Expand All @@ -821,6 +862,7 @@ void Constraint::MenuConstrain(Command id) {
c.group = SS.GW.activeGroup;
c.workplane = SS.GW.ActiveWorkplane();
c.comment = _("NEW COMMENT -- DOUBLE-CLICK TO EDIT");
newcons.push_back(c);
AddConstraint(&c);
} else {
SS.GW.pending.operation = GraphicsWindow::Pending::COMMAND;
Expand All @@ -832,31 +874,32 @@ void Constraint::MenuConstrain(Command id) {

default: ssassert(false, "Unexpected menu ID");
}

for(const Constraint &cc : SK.constraint) {
if(c.h != cc.h && c.Equals(cc)) {
// Oops, we already have this exact constraint. Remove the one we just added.
SK.constraint.RemoveById(c.h);
SS.GW.ClearSelection();
// And now select the old one, to give feedback.
SS.GW.MakeSelected(cc.h);
return;
for (auto nc:newcons){
for(const Constraint &cc : SK.constraint) {
if(nc.h != cc.h && nc.Equals(cc)) {
// Oops, we already have this exact constraint. Remove the one we just added.
SK.constraint.RemoveById(nc.h);
SS.GW.ClearSelection();
// And now select the old one, to give feedback.
SS.GW.MakeSelected(cc.h);
return;
}
}
}

if(SK.constraint.FindByIdNoOops(c.h)) {
Constraint *constraint = SK.GetConstraint(c.h);
if(SS.TestRankForGroup(c.group) == SolveResult::REDUNDANT_OKAY &&
!SK.GetGroup(SS.GW.activeGroup)->allowRedundant &&
constraint->HasLabel()) {
constraint->reference = true;
if(SK.constraint.FindByIdNoOops(nc.h)) {
Constraint *constraint = SK.GetConstraint(nc.h);
if(SS.TestRankForGroup(nc.group) == SolveResult::REDUNDANT_OKAY &&
!SK.GetGroup(SS.GW.activeGroup)->allowRedundant &&
constraint->HasLabel()) {
constraint->reference = true;
}
}
}

if((id == Command::DISTANCE_DIA || id == Command::ANGLE ||
id == Command::RATIO || id == Command::DIFFERENCE) &&
SS.immediatelyEditDimension) {
SS.GW.EditConstraint(c.h);
if((id == Command::DISTANCE_DIA || id == Command::ANGLE ||
id == Command::RATIO || id == Command::DIFFERENCE) &&
SS.immediatelyEditDimension) {
SS.GW.EditConstraint(nc.h);
}
}

SS.GW.ClearSelection();
Expand Down