Sketcher: support perpendicularity constraint for arcs and circles
This commit is contained in:
parent
f96675ba02
commit
17ac6da079
|
@ -138,15 +138,20 @@ int ConstraintPy::PyInit(PyObject* args, PyObject* /*kwd*/)
|
|||
if (PyInt_Check(index_or_value)) {
|
||||
FirstPos = any_index;
|
||||
SecondIndex = PyInt_AsLong(index_or_value);
|
||||
if (strcmp("Tangent", ConstraintType) == 0) {
|
||||
this->getConstraintPtr()->Type = Tangent;
|
||||
this->getConstraintPtr()->First = FirstIndex;
|
||||
this->getConstraintPtr()->FirstPos = (Sketcher::PointPos) FirstPos;
|
||||
this->getConstraintPtr()->Second = SecondIndex;
|
||||
return 0;
|
||||
bool valid = false;
|
||||
if (strcmp("Perpendicular", ConstraintType) == 0) {
|
||||
this->getConstraintPtr()->Type = Perpendicular;
|
||||
valid = true;
|
||||
}
|
||||
if (strcmp("PointOnObject", ConstraintType) == 0) {
|
||||
else if (strcmp("Tangent", ConstraintType) == 0) {
|
||||
this->getConstraintPtr()->Type = Tangent;
|
||||
valid = true;
|
||||
}
|
||||
else if (strcmp("PointOnObject", ConstraintType) == 0) {
|
||||
this->getConstraintPtr()->Type = PointOnObject;
|
||||
valid = true;
|
||||
}
|
||||
if (valid) {
|
||||
this->getConstraintPtr()->First = FirstIndex;
|
||||
this->getConstraintPtr()->FirstPos = (Sketcher::PointPos) FirstPos;
|
||||
this->getConstraintPtr()->Second = SecondIndex;
|
||||
|
@ -212,6 +217,10 @@ int ConstraintPy::PyInit(PyObject* args, PyObject* /*kwd*/)
|
|||
this->getConstraintPtr()->Type = Vertical;
|
||||
valid = true;
|
||||
}
|
||||
else if (strcmp("Perpendicular", ConstraintType) == 0) {
|
||||
this->getConstraintPtr()->Type = Perpendicular;
|
||||
valid = true;
|
||||
}
|
||||
else if (strcmp("Tangent", ConstraintType) == 0) {
|
||||
this->getConstraintPtr()->Type = Tangent;
|
||||
valid = true;
|
||||
|
|
|
@ -474,7 +474,16 @@ int Sketch::addConstraint(const Constraint *constraint)
|
|||
rtn = addParallelConstraint(constraint->First,constraint->Second);
|
||||
break;
|
||||
case Perpendicular:
|
||||
rtn = addPerpendicularConstraint(constraint->First,constraint->Second);
|
||||
if (constraint->SecondPos != none) // perpendicularity at common point
|
||||
rtn = addPerpendicularConstraint(constraint->First,constraint->FirstPos,
|
||||
constraint->Second,constraint->SecondPos);
|
||||
else if (constraint->Second != Constraint::GeoUndef) {
|
||||
if (constraint->FirstPos != none) // "First" is a connecting point
|
||||
rtn = addPerpendicularConstraint(constraint->First,constraint->FirstPos,
|
||||
constraint->Second);
|
||||
else // simple perpendicularity
|
||||
rtn = addPerpendicularConstraint(constraint->First,constraint->Second);
|
||||
}
|
||||
break;
|
||||
case Tangent:
|
||||
if (constraint->SecondPos != none) // tangency at common point
|
||||
|
@ -760,8 +769,13 @@ int Sketch::addParallelConstraint(int geoId1, int geoId2)
|
|||
return ConstraintsCounter;
|
||||
}
|
||||
|
||||
// simple perpendicularity constraint
|
||||
int Sketch::addPerpendicularConstraint(int geoId1, int geoId2)
|
||||
{
|
||||
// accepts the following combinations:
|
||||
// 1) Line1, Line2/Circle2/Arc2
|
||||
// 2) Circle1, Line2 (converted to case #1)
|
||||
// 3) Arc1, Line2 (converted to case #1)
|
||||
geoId1 = checkGeoId(geoId1);
|
||||
geoId2 = checkGeoId(geoId2);
|
||||
|
||||
|
@ -778,17 +792,12 @@ int Sketch::addPerpendicularConstraint(int geoId1, int geoId2)
|
|||
}
|
||||
|
||||
if (Geoms[geoId1].type == Line) {
|
||||
GCS::Line &l = Lines[Geoms[geoId1].index];
|
||||
if (Geoms[geoId2].type == Arc) {
|
||||
GCS::Arc &a = Arcs[Geoms[geoId2].index];
|
||||
//GCSsys.addConstraintPerpendicular(l, a);
|
||||
Base::Console().Warning("Perpendicular constraints between lines and arcs are not implemented yet.\n");
|
||||
return -1;
|
||||
} else if (Geoms[geoId2].type == Circle) {
|
||||
GCS::Circle &c = Circles[Geoms[geoId2].index];
|
||||
//GCSsys.addConstraintPerpendicular(l, c);
|
||||
Base::Console().Warning("Perpendicular constraints between lines and circles are not implemented yet.\n");
|
||||
return -1;
|
||||
GCS::Line &l1 = Lines[Geoms[geoId1].index];
|
||||
if (Geoms[geoId2].type == Arc || Geoms[geoId2].type == Circle) {
|
||||
GCS::Point &p2 = Points[Geoms[geoId2].midPointId];
|
||||
int tag = ++ConstraintsCounter;
|
||||
GCSsys.addConstraintPointOnLine(p2, l1, tag);
|
||||
return ConstraintsCounter;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -797,15 +806,182 @@ int Sketch::addPerpendicularConstraint(int geoId1, int geoId2)
|
|||
return -1;
|
||||
}
|
||||
|
||||
// perpendicularity at specific point constraint
|
||||
int Sketch::addPerpendicularConstraint(int geoId1, PointPos pos1, int geoId2)
|
||||
{
|
||||
// accepts the following combinations:
|
||||
// 1) Line1, start/end, Line2/Circle2/Arc2
|
||||
// 2) Arc1, start/end, Line2/Circle2/Arc2
|
||||
geoId1 = checkGeoId(geoId1);
|
||||
geoId2 = checkGeoId(geoId2);
|
||||
|
||||
int pointId1 = getPointId(geoId1, pos1);
|
||||
|
||||
if (pointId1 < 0 || pointId1 >= int(Points.size()))
|
||||
return addPerpendicularConstraint(geoId1, geoId2);
|
||||
|
||||
GCS::Point &p1 = Points[pointId1];
|
||||
if (Geoms[geoId1].type == Line) {
|
||||
GCS::Line &l1 = Lines[Geoms[geoId1].index];
|
||||
if (Geoms[geoId2].type == Line) {
|
||||
GCS::Line &l2 = Lines[Geoms[geoId2].index];
|
||||
int tag = ++ConstraintsCounter;
|
||||
GCSsys.addConstraintPointOnLine(p1, l2, tag);
|
||||
GCSsys.addConstraintPerpendicular(l1, l2, tag);
|
||||
return ConstraintsCounter;
|
||||
}
|
||||
else if (Geoms[geoId2].type == Arc) {
|
||||
GCS::Arc &a2 = Arcs[Geoms[geoId2].index];
|
||||
GCS::Point &p2 = Points[Geoms[geoId2].midPointId];
|
||||
int tag = ++ConstraintsCounter;
|
||||
GCSsys.addConstraintPointOnArc(p1, a2, tag);
|
||||
GCSsys.addConstraintPointOnLine(p2, l1, tag);
|
||||
return ConstraintsCounter;
|
||||
}
|
||||
else if (Geoms[geoId2].type == Circle) {
|
||||
GCS::Circle &c2 = Circles[Geoms[geoId2].index];
|
||||
GCS::Point &p2 = Points[Geoms[geoId2].midPointId];
|
||||
int tag = ++ConstraintsCounter;
|
||||
GCSsys.addConstraintPointOnCircle(p1, c2, tag);
|
||||
GCSsys.addConstraintPointOnLine(p2, l1, tag);
|
||||
return ConstraintsCounter;
|
||||
}
|
||||
}
|
||||
else if (Geoms[geoId1].type == Arc) {
|
||||
GCS::Arc &a1 = Arcs[Geoms[geoId1].index];
|
||||
if (Geoms[geoId2].type == Line) {
|
||||
GCS::Line &l2 = Lines[Geoms[geoId2].index];
|
||||
int tag = ++ConstraintsCounter;
|
||||
GCSsys.addConstraintPointOnLine(p1, l2, tag);
|
||||
GCSsys.addConstraintPointOnLine(a1.center, l2, tag);
|
||||
return ConstraintsCounter;
|
||||
}
|
||||
else if (Geoms[geoId2].type == Arc || Geoms[geoId2].type == Circle) {
|
||||
int tag = ++ConstraintsCounter;
|
||||
GCS::Point ¢er = Points[Geoms[geoId2].midPointId];
|
||||
double *radius;
|
||||
if (Geoms[geoId2].type == Arc) {
|
||||
GCS::Arc &a2 = Arcs[Geoms[geoId2].index];
|
||||
radius = a2.rad;
|
||||
}
|
||||
else {
|
||||
GCS::Circle &c2 = Circles[Geoms[geoId2].index];
|
||||
radius = c2.rad;
|
||||
}
|
||||
if (pos1 == start)
|
||||
GCSsys.addConstraintPerpendicularCircle2Arc(center, radius, a1, tag);
|
||||
else if (pos1 == end)
|
||||
GCSsys.addConstraintPerpendicularArc2Circle(a1, center, radius, tag);
|
||||
return ConstraintsCounter;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// perpendicularity at common point constraint
|
||||
int Sketch::addPerpendicularConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2)
|
||||
{
|
||||
// accepts the following combinations:
|
||||
// 1) Line1, start/end, Line2/Arc2, start/end
|
||||
// 2) Arc1, start/end, Line2, start/end (converted to case #1)
|
||||
// 3) Arc1, start/end, Arc2, start/end
|
||||
geoId1 = checkGeoId(geoId1);
|
||||
geoId2 = checkGeoId(geoId2);
|
||||
|
||||
int pointId1 = getPointId(geoId1, pos1);
|
||||
int pointId2 = getPointId(geoId2, pos2);
|
||||
|
||||
if (pointId1 < 0 || pointId1 >= int(Points.size()) ||
|
||||
pointId2 < 0 || pointId2 >= int(Points.size()))
|
||||
return -1;
|
||||
|
||||
GCS::Point &p1 = Points[pointId1];
|
||||
GCS::Point &p2 = Points[pointId2];
|
||||
if (Geoms[geoId2].type == Line) {
|
||||
if (Geoms[geoId1].type == Line) {
|
||||
GCS::Line &l1 = Lines[Geoms[geoId1].index];
|
||||
GCS::Line &l2 = Lines[Geoms[geoId2].index];
|
||||
int tag = ++ConstraintsCounter;
|
||||
GCSsys.addConstraintP2PCoincident(p1, p2, tag);
|
||||
GCSsys.addConstraintPerpendicular(l1, l2, tag);
|
||||
return ConstraintsCounter;
|
||||
}
|
||||
else {
|
||||
std::swap(geoId1, geoId2);
|
||||
std::swap(pos1, pos2);
|
||||
std::swap(pointId1, pointId2);
|
||||
p1 = Points[pointId1];
|
||||
p2 = Points[pointId2];
|
||||
}
|
||||
}
|
||||
|
||||
if (Geoms[geoId1].type == Line) {
|
||||
GCS::Line &l1 = Lines[Geoms[geoId1].index];
|
||||
if (Geoms[geoId2].type == Arc) {
|
||||
GCS::Arc &a2 = Arcs[Geoms[geoId2].index];
|
||||
if (pos2 == start) {
|
||||
if (pos1 == start) {
|
||||
int tag = ++ConstraintsCounter;
|
||||
GCSsys.addConstraintPerpendicularLine2Arc(l1.p2, l1.p1, a2, tag);
|
||||
return ConstraintsCounter;
|
||||
}
|
||||
else if (pos1 == end) {
|
||||
int tag = ++ConstraintsCounter;
|
||||
GCSsys.addConstraintPerpendicularLine2Arc(l1.p1, l1.p2, a2, tag);
|
||||
return ConstraintsCounter;
|
||||
}
|
||||
}
|
||||
else if (pos2 == end) {
|
||||
if (pos1 == start) {
|
||||
int tag = ++ConstraintsCounter;
|
||||
GCSsys.addConstraintPerpendicularArc2Line(a2, l1.p1, l1.p2, tag);
|
||||
return ConstraintsCounter;
|
||||
}
|
||||
else if (pos1 == end) {
|
||||
int tag = ++ConstraintsCounter;
|
||||
GCSsys.addConstraintPerpendicularArc2Line(a2, l1.p2, l1.p1, tag);
|
||||
return ConstraintsCounter;
|
||||
}
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if (Geoms[geoId1].type == Arc) {
|
||||
GCS::Arc &a1 = Arcs[Geoms[geoId1].index];
|
||||
if (Geoms[geoId2].type == Arc) {
|
||||
GCS::Arc &a2 = Arcs[Geoms[geoId2].index];
|
||||
if (pos1 == start && (pos2 == start || pos2 == end)) {
|
||||
int tag = ++ConstraintsCounter;
|
||||
if (pos2 == start)
|
||||
GCSsys.addConstraintPerpendicularArc2Arc(a1, true, a2, false, tag);
|
||||
else // if (pos2 == end)
|
||||
GCSsys.addConstraintPerpendicularArc2Arc(a1, true, a2, true, tag);
|
||||
// GCSsys.addConstraintTangentArc2Arc(a2, false, a1, false, tag);
|
||||
return ConstraintsCounter;
|
||||
}
|
||||
else if (pos1 == end && (pos2 == start || pos2 == end)) {
|
||||
int tag = ++ConstraintsCounter;
|
||||
if (pos2 == start)
|
||||
GCSsys.addConstraintPerpendicularArc2Arc(a1, false, a2, false, tag);
|
||||
else // if (pos2 == end)
|
||||
GCSsys.addConstraintPerpendicularArc2Arc(a1, false, a2, true, tag);
|
||||
return ConstraintsCounter;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// simple tangency constraint
|
||||
int Sketch::addTangentConstraint(int geoId1, int geoId2)
|
||||
{
|
||||
// accepts the following combinations:
|
||||
// 1) Line1, Line2/Circle2/Arc2
|
||||
// 2) Circle1, Line2 (converted to case #1)
|
||||
// Circle1, Circle2/Arc2 (not implemented yet)
|
||||
// Circle1, Circle2/Arc2
|
||||
// 3) Arc1, Line2 (converted to case #1)
|
||||
// Arc1, Circle2/Arc2 (not implemented yet)
|
||||
// Arc1, Circle2/Arc2
|
||||
geoId1 = checkGeoId(geoId1);
|
||||
geoId2 = checkGeoId(geoId2);
|
||||
|
||||
|
@ -871,12 +1047,8 @@ int Sketch::addTangentConstraint(int geoId1, int geoId2)
|
|||
int Sketch::addTangentConstraint(int geoId1, PointPos pos1, int geoId2)
|
||||
{
|
||||
// accepts the following combinations:
|
||||
// 1) Line1, start/end/mid, Line2
|
||||
// 2) Line1, start/end/mid, Circle2
|
||||
// 3) Line1, start/end/mid, Arc2
|
||||
// 4) Arc1, start/end, Line2
|
||||
// 5) Arc1, start/end, Circle2
|
||||
// 6) Arc1, start/end, Arc2
|
||||
// 1) Line1, start/end, Line2/Circle2/Arc2
|
||||
// 2) Arc1, start/end, Line2/Circle2/Arc2
|
||||
geoId1 = checkGeoId(geoId1);
|
||||
geoId2 = checkGeoId(geoId2);
|
||||
|
||||
|
@ -947,10 +1119,9 @@ int Sketch::addTangentConstraint(int geoId1, PointPos pos1, int geoId2)
|
|||
int Sketch::addTangentConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2)
|
||||
{
|
||||
// accepts the following combinations:
|
||||
// 1) Line1, start/end/mid, Line2, start/end/mid
|
||||
// 2) Line1, start/end/mid, Arc2, start/end
|
||||
// 3) Arc1, start/end, Line2, start/end/mid (converted to case #2)
|
||||
// 4) Arc1, start/end, Arc2, start/end
|
||||
// 1) Line1, start/end, Line2/Arc2, start/end
|
||||
// 2) Arc1, start/end, Line2, start/end (converted to case #1)
|
||||
// 3) Arc1, start/end, Arc2, start/end
|
||||
geoId1 = checkGeoId(geoId1);
|
||||
geoId2 = checkGeoId(geoId2);
|
||||
|
||||
|
@ -983,14 +1154,7 @@ int Sketch::addTangentConstraint(int geoId1, PointPos pos1, int geoId2, PointPos
|
|||
|
||||
if (Geoms[geoId1].type == Line) {
|
||||
GCS::Line &l1 = Lines[Geoms[geoId1].index];
|
||||
if (Geoms[geoId2].type == Line) {
|
||||
GCS::Line &l2 = Lines[Geoms[geoId2].index];
|
||||
int tag = ++ConstraintsCounter;
|
||||
GCSsys.addConstraintP2PCoincident(p1, p2, tag);
|
||||
GCSsys.addConstraintParallel(l1, l2, tag);
|
||||
return ConstraintsCounter;
|
||||
}
|
||||
else if (Geoms[geoId2].type == Arc) {
|
||||
if (Geoms[geoId2].type == Arc) {
|
||||
GCS::Arc &a2 = Arcs[Geoms[geoId2].index];
|
||||
if (pos2 == start) {
|
||||
if (pos1 == start) {
|
||||
|
@ -1003,12 +1167,6 @@ int Sketch::addTangentConstraint(int geoId1, PointPos pos1, int geoId2, PointPos
|
|||
GCSsys.addConstraintTangentLine2Arc(l1.p1, l1.p2, a2, tag);
|
||||
return ConstraintsCounter;
|
||||
}
|
||||
else if (pos1 == mid) { // FIXME: coincidence with midpoint of line??
|
||||
int tag = ++ConstraintsCounter;
|
||||
GCSsys.addConstraintP2PCoincident(p1, p2, tag);
|
||||
GCSsys.addConstraintTangent(l1, a2, tag);
|
||||
return ConstraintsCounter;
|
||||
}
|
||||
}
|
||||
else if (pos2 == end) {
|
||||
if (pos1 == start) {
|
||||
|
@ -1021,12 +1179,6 @@ int Sketch::addTangentConstraint(int geoId1, PointPos pos1, int geoId2, PointPos
|
|||
GCSsys.addConstraintTangentArc2Line(a2, l1.p2, l1.p1, tag);
|
||||
return ConstraintsCounter;
|
||||
}
|
||||
else if (pos1 == mid) { // FIXME: coincidence with midpoint of line??
|
||||
int tag = ++ConstraintsCounter;
|
||||
GCSsys.addConstraintP2PCoincident(p1, p2, tag);
|
||||
GCSsys.addConstraintTangent(l1, a2, tag);
|
||||
return ConstraintsCounter;
|
||||
}
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
|
|
|
@ -152,6 +152,8 @@ public:
|
|||
int addParallelConstraint(int geoIndex1, int geoIndex2);
|
||||
/// add a perpendicular constraint between two lines
|
||||
int addPerpendicularConstraint(int geoIndex1, int geoIndex2);
|
||||
int addPerpendicularConstraint(int geoIndex1, PointPos pos1, int geoIndex2);
|
||||
int addPerpendicularConstraint(int geoIndex1, PointPos pos1, int geoIndex2, PointPos pos2);
|
||||
/// add a tangency constraint between two geometries
|
||||
int addTangentConstraint(int geoIndex1, int geoIndex2);
|
||||
int addTangentConstraint(int geoIndex1, PointPos pos1, int geoIndex2);
|
||||
|
|
|
@ -350,6 +350,67 @@ int System::addConstraintPointOnArc(Point &p, Arc &a, int tagId)
|
|||
return addConstraintP2PDistance(p, a.center, a.rad, tagId);
|
||||
}
|
||||
|
||||
int System::addConstraintPerpendicularLine2Arc(Point &p1, Point &p2, Arc &a,
|
||||
int tagId)
|
||||
{
|
||||
addConstraintP2PCoincident(p2, a.start, tagId);
|
||||
double dx = *(p2.x) - *(p1.x);
|
||||
double dy = *(p2.y) - *(p1.y);
|
||||
if (dx * cos(*(a.startAngle)) + dy * sin(*(a.startAngle)) > 0)
|
||||
return addConstraintP2PAngle(p1, p2, a.startAngle, 0, tagId);
|
||||
else
|
||||
return addConstraintP2PAngle(p1, p2, a.startAngle, M_PI, tagId);
|
||||
}
|
||||
|
||||
int System::addConstraintPerpendicularArc2Line(Arc &a, Point &p1, Point &p2,
|
||||
int tagId)
|
||||
{
|
||||
addConstraintP2PCoincident(p1, a.end, tagId);
|
||||
double dx = *(p2.x) - *(p1.x);
|
||||
double dy = *(p2.y) - *(p1.y);
|
||||
if (dx * cos(*(a.endAngle)) + dy * sin(*(a.endAngle)) > 0)
|
||||
return addConstraintP2PAngle(p1, p2, a.endAngle, 0, tagId);
|
||||
else
|
||||
return addConstraintP2PAngle(p1, p2, a.endAngle, M_PI, tagId);
|
||||
}
|
||||
|
||||
int System::addConstraintPerpendicularCircle2Arc(Point ¢er, double *radius,
|
||||
Arc &a, int tagId)
|
||||
{
|
||||
addConstraintP2PDistance(a.start, center, radius, tagId);
|
||||
double incr_angle = *(a.startAngle) < *(a.endAngle) ? M_PI/2 : -M_PI/2;
|
||||
double tang_angle = *a.startAngle + incr_angle;
|
||||
double dx = *(a.start.x) - *(center.x);
|
||||
double dy = *(a.start.y) - *(center.y);
|
||||
if (dx * cos(tang_angle) + dy * sin(tang_angle) > 0)
|
||||
return addConstraintP2PAngle(center, a.start, a.startAngle, incr_angle, tagId);
|
||||
else
|
||||
return addConstraintP2PAngle(center, a.start, a.startAngle, -incr_angle, tagId);
|
||||
}
|
||||
|
||||
int System::addConstraintPerpendicularArc2Circle(Arc &a, Point ¢er,
|
||||
double *radius, int tagId)
|
||||
{
|
||||
addConstraintP2PDistance(a.end, center, radius, tagId);
|
||||
double incr_angle = *(a.startAngle) < *(a.endAngle) ? -M_PI/2 : M_PI/2;
|
||||
double tang_angle = *a.endAngle + incr_angle;
|
||||
double dx = *(a.end.x) - *(center.x);
|
||||
double dy = *(a.end.y) - *(center.y);
|
||||
if (dx * cos(tang_angle) + dy * sin(tang_angle) > 0)
|
||||
return addConstraintP2PAngle(center, a.end, a.endAngle, incr_angle, tagId);
|
||||
else
|
||||
return addConstraintP2PAngle(center, a.end, a.endAngle, -incr_angle, tagId);
|
||||
}
|
||||
|
||||
int System::addConstraintPerpendicularArc2Arc(Arc &a1, bool reverse1,
|
||||
Arc &a2, bool reverse2, int tagId)
|
||||
{
|
||||
Point &p1 = reverse1 ? a1.start : a1.end;
|
||||
Point &p2 = reverse2 ? a2.end : a2.start;
|
||||
addConstraintP2PCoincident(p1, p2, tagId);
|
||||
return addConstraintPerpendicular(a1.center, p1, a2.center, p2, tagId);
|
||||
}
|
||||
|
||||
int System::addConstraintTangent(Line &l, Circle &c, int tagId)
|
||||
{
|
||||
return addConstraintP2LDistance(c.center, l, c.rad, tagId);
|
||||
|
|
|
@ -115,6 +115,16 @@ namespace GCS
|
|||
int addConstraintArcRules(Arc &a, int tagId=0);
|
||||
int addConstraintPointOnCircle(Point &p, Circle &c, int tagId=0);
|
||||
int addConstraintPointOnArc(Point &p, Arc &a, int tagId=0);
|
||||
int addConstraintPerpendicularLine2Arc(Point &p1, Point &p2, Arc &a,
|
||||
int tagId=0);
|
||||
int addConstraintPerpendicularArc2Line(Arc &a, Point &p1, Point &p2,
|
||||
int tagId=0);
|
||||
int addConstraintPerpendicularCircle2Arc(Point ¢er, double *radius, Arc &a,
|
||||
int tagId=0);
|
||||
int addConstraintPerpendicularArc2Circle(Arc &a, Point ¢er, double *radius,
|
||||
int tagId=0);
|
||||
int addConstraintPerpendicularArc2Arc(Arc &a1, bool reverse1,
|
||||
Arc &a2, bool reverse2, int tagId=0);
|
||||
int addConstraintTangent(Line &l, Circle &c, int tagId=0);
|
||||
int addConstraintTangent(Line &l, Arc &a, int tagId=0);
|
||||
int addConstraintTangent(Circle &c1, Circle &c2, int tagId=0);
|
||||
|
|
|
@ -1198,7 +1198,7 @@ void CmdSketcherConstrainPerpendicular::activated(int iMsg)
|
|||
// only one sketch with its subelements are allowed to be selected
|
||||
if (selection.size() != 1) {
|
||||
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
|
||||
QObject::tr("Select two lines from the sketch."));
|
||||
QObject::tr("Select two entities from the sketch."));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1208,7 +1208,7 @@ void CmdSketcherConstrainPerpendicular::activated(int iMsg)
|
|||
|
||||
if (SubNames.size() != 2) {
|
||||
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
|
||||
QObject::tr("Select exactly two lines from the sketch."));
|
||||
QObject::tr("Select exactly two entities from the sketch."));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1216,37 +1216,102 @@ void CmdSketcherConstrainPerpendicular::activated(int iMsg)
|
|||
getIdsFromName(SubNames[0], GeoId1, VtId1);
|
||||
getIdsFromName(SubNames[1], GeoId2, VtId2);
|
||||
|
||||
if (checkBothExternal(GeoId1, GeoId2))
|
||||
return;
|
||||
else if (GeoId1 == Constraint::GeoUndef || GeoId2 == Constraint::GeoUndef) {
|
||||
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
|
||||
QObject::tr("Select exactly two lines from the sketch."));
|
||||
Sketcher::PointPos PosId1,PosId2;
|
||||
if (VtId1 >= 0 && VtId2 >= 0) { // perpendicularity at common point
|
||||
Obj->getGeoVertexIndex(VtId1,GeoId1,PosId1);
|
||||
Obj->getGeoVertexIndex(VtId2,GeoId2,PosId2);
|
||||
|
||||
if (checkBothExternal(GeoId1, GeoId2))
|
||||
return;
|
||||
|
||||
const Part::Geometry *geo1 = Obj->getGeometry(GeoId1);
|
||||
const Part::Geometry *geo2 = Obj->getGeometry(GeoId2);
|
||||
if ((PosId1 != Sketcher::start && PosId1 != Sketcher::end) ||
|
||||
(PosId2 != Sketcher::start && PosId2 != Sketcher::end) ||
|
||||
(geo1->getTypeId() != Part::GeomLineSegment::getClassTypeId() &&
|
||||
geo1->getTypeId() != Part::GeomArcOfCircle::getClassTypeId()) ||
|
||||
(geo2->getTypeId() != Part::GeomLineSegment::getClassTypeId() &&
|
||||
geo2->getTypeId() != Part::GeomArcOfCircle::getClassTypeId())) {
|
||||
|
||||
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
|
||||
QObject::tr("The selected points should be end points of arcs and lines."));
|
||||
return;
|
||||
}
|
||||
|
||||
openCommand("add perpendicular constraint");
|
||||
Gui::Command::doCommand(
|
||||
Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('Perpendicular',%d,%d,%d,%d)) ",
|
||||
selection[0].getFeatName(),GeoId1,PosId1,GeoId2,PosId2);
|
||||
commitCommand();
|
||||
updateActive();
|
||||
getSelection().clearSelection();
|
||||
return;
|
||||
}
|
||||
else if ((VtId1 >= 0 && GeoId2 != Constraint::GeoUndef) ||
|
||||
(VtId2 >= 0 && GeoId1 != Constraint::GeoUndef)) { // VtId1 is a connecting point
|
||||
if (VtId2 >= 0 && GeoId1 != Constraint::GeoUndef) {
|
||||
VtId1 = VtId2;
|
||||
VtId2 = -1;
|
||||
GeoId2 = GeoId1;
|
||||
GeoId1 = -1;
|
||||
}
|
||||
Obj->getGeoVertexIndex(VtId1,GeoId1,PosId1);
|
||||
|
||||
const Part::Geometry *geo1 = Obj->getGeometry(GeoId1);
|
||||
const Part::Geometry *geo2 = Obj->getGeometry(GeoId2);
|
||||
if (checkBothExternal(GeoId1, GeoId2))
|
||||
return;
|
||||
|
||||
if (geo1->getTypeId() != Part::GeomLineSegment::getClassTypeId() ||
|
||||
geo2->getTypeId() != Part::GeomLineSegment::getClassTypeId()) {
|
||||
const Part::Geometry *geo1 = Obj->getGeometry(GeoId1);
|
||||
const Part::Geometry *geo2 = Obj->getGeometry(GeoId2);
|
||||
if ((PosId1 != Sketcher::start && PosId1 != Sketcher::end) ||
|
||||
(geo1->getTypeId() != Part::GeomLineSegment::getClassTypeId() &&
|
||||
geo1->getTypeId() != Part::GeomArcOfCircle::getClassTypeId())) {
|
||||
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
|
||||
QObject::tr("The selected point should be an end point of an arc or line."));
|
||||
return;
|
||||
}
|
||||
else if (geo2->getTypeId() != Part::GeomLineSegment::getClassTypeId() &&
|
||||
geo2->getTypeId() != Part::GeomArcOfCircle::getClassTypeId() &&
|
||||
geo2->getTypeId() != Part::GeomCircle::getClassTypeId()) {
|
||||
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
|
||||
QObject::tr("The selected edge should be an arc, line or circle."));
|
||||
return;
|
||||
}
|
||||
|
||||
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
|
||||
QObject::tr("Select exactly two lines from the sketch."));
|
||||
openCommand("add perpendicularity constraint");
|
||||
Gui::Command::doCommand(
|
||||
Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('Perpendicular',%d,%d,%d)) ",
|
||||
selection[0].getFeatName(),GeoId1,PosId1,GeoId2);
|
||||
commitCommand();
|
||||
updateActive();
|
||||
getSelection().clearSelection();
|
||||
return;
|
||||
}
|
||||
else if (GeoId1 != Constraint::GeoUndef && GeoId2 != Constraint::GeoUndef) { // simple perpendicularity between GeoId1 and GeoId2
|
||||
|
||||
// undo command open
|
||||
openCommand("add perpendicular constraint");
|
||||
Gui::Command::doCommand(
|
||||
Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('Perpendicular',%d,%d)) ",
|
||||
selection[0].getFeatName(),GeoId1,GeoId2);
|
||||
if (checkBothExternal(GeoId1, GeoId2))
|
||||
return;
|
||||
|
||||
// finish the transaction and update
|
||||
commitCommand();
|
||||
updateActive();
|
||||
const Part::Geometry *geo1 = Obj->getGeometry(GeoId1);
|
||||
const Part::Geometry *geo2 = Obj->getGeometry(GeoId2);
|
||||
if (geo1->getTypeId() != Part::GeomLineSegment::getClassTypeId() &&
|
||||
geo2->getTypeId() != Part::GeomLineSegment::getClassTypeId()) {
|
||||
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
|
||||
QObject::tr("One of the selected edges should be a line."));
|
||||
return;
|
||||
}
|
||||
|
||||
// clear the selection (convenience)
|
||||
getSelection().clearSelection();
|
||||
openCommand("add perpendicular constraint");
|
||||
Gui::Command::doCommand(
|
||||
Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('Perpendicular',%d,%d)) ",
|
||||
selection[0].getFeatName(),GeoId1,GeoId2);
|
||||
commitCommand();
|
||||
updateActive();
|
||||
getSelection().clearSelection();
|
||||
return;
|
||||
}
|
||||
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
|
||||
QObject::tr("Select exactly two entities from the sketch."));
|
||||
return;
|
||||
}
|
||||
|
||||
bool CmdSketcherConstrainPerpendicular::isActive(void)
|
||||
|
@ -1674,7 +1739,7 @@ void CmdSketcherConstrainEqual::activated(int iMsg)
|
|||
circSel = true;
|
||||
else {
|
||||
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
|
||||
QObject::tr("Select two or more edges of similar type"));
|
||||
QObject::tr("Select two or more edges of similar type"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1683,7 +1748,7 @@ void CmdSketcherConstrainEqual::activated(int iMsg)
|
|||
|
||||
if (lineSel && (arcSel || circSel)) {
|
||||
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
|
||||
QObject::tr("Select two or more edges of similar type"));
|
||||
QObject::tr("Select two or more edges of similar type"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1766,7 +1831,7 @@ void CmdSketcherConstrainSymmetric::activated(int iMsg)
|
|||
|
||||
if ((GeoId1 < 0 && GeoId2 < 0) || (GeoId1 < 0 && GeoId3 < 0) || (GeoId2 < 0 && GeoId3 < 0)) {
|
||||
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
|
||||
QObject::tr("Cannot add a constraint between external geometries!"));
|
||||
QObject::tr("Cannot add a constraint between external geometries!"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -1497,7 +1497,9 @@ void ViewProviderSketch::drawConstraintIcons()
|
|||
break;
|
||||
case Perpendicular:
|
||||
icoType = QString::fromAscii("small/Constraint_Perpendicular_sm");
|
||||
index2 = 4;
|
||||
// second icon is available only when there is no common point
|
||||
if ((*it)->FirstPos == Sketcher::none)
|
||||
index2 = 4;
|
||||
break;
|
||||
case Equal:
|
||||
icoType = QString::fromAscii("small/Constraint_EqualLength_sm");
|
||||
|
@ -1824,8 +1826,93 @@ Restart:
|
|||
|
||||
}
|
||||
break;
|
||||
case Parallel:
|
||||
case Perpendicular:
|
||||
{
|
||||
assert(Constr->First >= -extGeoCount && Constr->First < intGeoCount);
|
||||
assert(Constr->Second >= -extGeoCount && Constr->Second < intGeoCount);
|
||||
// get the geometry
|
||||
const Part::Geometry *geo1 = GeoById(*geomlist, Constr->First);
|
||||
const Part::Geometry *geo2 = GeoById(*geomlist, Constr->Second);
|
||||
|
||||
Base::Vector3d midpos1, dir1, norm1;
|
||||
Base::Vector3d midpos2, dir2, norm2;
|
||||
|
||||
if (Constr->FirstPos == Sketcher::none) {
|
||||
if (geo1->getTypeId() == Part::GeomLineSegment::getClassTypeId()) {
|
||||
const Part::GeomLineSegment *lineSeg1 = dynamic_cast<const Part::GeomLineSegment *>(geo1);
|
||||
midpos1 = ((lineSeg1->getEndPoint()+lineSeg1->getStartPoint())/2);
|
||||
dir1 = (lineSeg1->getEndPoint()-lineSeg1->getStartPoint()).Normalize();
|
||||
norm1 = Base::Vector3d(-dir1.y,dir1.x,0.);
|
||||
} else if (geo1->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) {
|
||||
const Part::GeomArcOfCircle *arc = dynamic_cast<const Part::GeomArcOfCircle *>(geo1);
|
||||
double startangle, endangle, midangle;
|
||||
arc->getRange(startangle, endangle);
|
||||
midangle = (startangle + endangle)/2;
|
||||
norm1 = Base::Vector3d(cos(midangle),sin(midangle),0);
|
||||
dir1 = Base::Vector3d(-norm1.y,norm1.x,0);
|
||||
midpos1 = arc->getCenter() + arc->getRadius() * norm1;
|
||||
} else if (geo1->getTypeId() == Part::GeomCircle::getClassTypeId()) {
|
||||
const Part::GeomCircle *circle = dynamic_cast<const Part::GeomCircle *>(geo1);
|
||||
norm1 = Base::Vector3d(cos(M_PI/4),sin(M_PI/4),0);
|
||||
dir1 = Base::Vector3d(-norm1.y,norm1.x,0);
|
||||
midpos1 = circle->getCenter() + circle->getRadius() * norm1;
|
||||
} else
|
||||
break;
|
||||
|
||||
if (geo2->getTypeId() == Part::GeomLineSegment::getClassTypeId()) {
|
||||
const Part::GeomLineSegment *lineSeg2 = dynamic_cast<const Part::GeomLineSegment *>(geo2);
|
||||
midpos2 = ((lineSeg2->getEndPoint()+lineSeg2->getStartPoint())/2);
|
||||
dir2 = (lineSeg2->getEndPoint()-lineSeg2->getStartPoint()).Normalize();
|
||||
norm2 = Base::Vector3d(-dir2.y,dir2.x,0.);
|
||||
} else if (geo2->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) {
|
||||
const Part::GeomArcOfCircle *arc = dynamic_cast<const Part::GeomArcOfCircle *>(geo2);
|
||||
double startangle, endangle, midangle;
|
||||
arc->getRange(startangle, endangle);
|
||||
midangle = (startangle + endangle)/2;
|
||||
norm2 = Base::Vector3d(cos(midangle),sin(midangle),0);
|
||||
dir2 = Base::Vector3d(-norm2.y,norm2.x,0);
|
||||
midpos2 = arc->getCenter() + arc->getRadius() * norm2;
|
||||
} else if (geo2->getTypeId() == Part::GeomCircle::getClassTypeId()) {
|
||||
const Part::GeomCircle *circle = dynamic_cast<const Part::GeomCircle *>(geo2);
|
||||
norm2 = Base::Vector3d(cos(M_PI/4),sin(M_PI/4),0);
|
||||
dir2 = Base::Vector3d(-norm2.y,norm2.x,0);
|
||||
midpos2 = circle->getCenter() + circle->getRadius() * norm2;
|
||||
} else
|
||||
break;
|
||||
|
||||
} else {
|
||||
if (temp)
|
||||
midpos1 = edit->ActSketch.getPoint(Constr->First, Constr->FirstPos);
|
||||
else
|
||||
midpos1 = getSketchObject()->getPoint(Constr->First, Constr->FirstPos);
|
||||
norm1 = Base::Vector3d(0,1,0);
|
||||
dir1 = Base::Vector3d(1,0,0);
|
||||
}
|
||||
|
||||
// Get Current Scale Factor
|
||||
float scale = dynamic_cast<SoZoomTranslation *>(sep->getChild(1))->getScaleFactor();
|
||||
|
||||
Base::Vector3d constrPos1 = midpos1 + (norm1 * 2.5 * scale);
|
||||
constrPos1 = seekConstraintPosition(constrPos1, dir1, scale * 2.5, edit->constrGroup->getChild(i));
|
||||
|
||||
// Translate the Icon based on calculated position
|
||||
Base::Vector3d relPos1 = (constrPos1 - midpos1) / scale ; // Relative Position of Icons to Midpoint1
|
||||
dynamic_cast<SoZoomTranslation *>(sep->getChild(1))->abPos = SbVec3f(midpos1.x, midpos1.y, zConstr);
|
||||
dynamic_cast<SoZoomTranslation *>(sep->getChild(1))->translation = SbVec3f(relPos1.x, relPos1.y, 0);
|
||||
|
||||
if (Constr->FirstPos == Sketcher::none) {
|
||||
Base::Vector3d constrPos2 = midpos2 + (norm2 * 2.5 * scale);
|
||||
constrPos2 = seekConstraintPosition(constrPos2, dir2, 2.5 * scale, edit->constrGroup->getChild(i));
|
||||
|
||||
Base::Vector3d relPos2 = (constrPos2 - midpos2) / scale ; // Relative Position of Icons to Midpoint2
|
||||
Base::Vector3d secondPos = midpos2 - midpos1;
|
||||
dynamic_cast<SoZoomTranslation *>(sep->getChild(3))->abPos = SbVec3f(secondPos.x, secondPos.y, zConstr);
|
||||
dynamic_cast<SoZoomTranslation *>(sep->getChild(3))->translation = SbVec3f(relPos2.x -relPos1.x, relPos2.y -relPos1.y, 0);
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
case Parallel:
|
||||
case Equal:
|
||||
{
|
||||
assert(Constr->First >= -extGeoCount && Constr->First < intGeoCount);
|
||||
|
@ -1877,7 +1964,7 @@ Restart:
|
|||
norm2 = Base::Vector3d(cos(angle2),sin(angle2),0);
|
||||
dir2 = Base::Vector3d(-norm2.y,norm2.x,0);
|
||||
midpos2 += r2*norm2;
|
||||
} else // Parallel or Perpendicular can only apply to a GeomLineSegment
|
||||
} else // Parallel can only apply to a GeomLineSegment
|
||||
break;
|
||||
} else {
|
||||
const Part::GeomLineSegment *lineSeg1 = dynamic_cast<const Part::GeomLineSegment *>(geo1);
|
||||
|
|
Loading…
Reference in New Issue
Block a user