Skip to content

Commit

Permalink
Sketcher Ellipse and ArcOfEllipse: Extra features and bug fixes
Browse files Browse the repository at this point in the history
- Minor changes to alignment constraint selection to avoid to create objects just for simple calculations
- Equality constraint of Ellipse, ArcOfEllipse and combinations of those elements
- Bugfix for internalalignment creation of major and minor of ellipse and extension to arcofellipse
- Trim support for ellipses
- Solver threshold for rank calculation set at 1e-13.
- Trim support for arc of ellipse
- Ellipses and ArcOfEllipses as external geometry
- Validate Sketch now supports arcs of ellipse
- Tangents of Ellipse or ArcOfEllipse to any of ArcOfcircle, circle and Ellipse (using construction elements)
- Perpendicularity constraint
- Bug fix: Show/hide internal geometry not working for external geometry
- Visualization of Internal alignment constraints when selecting in the constraint widget
- Equality for ellipses and arc of ellipses
  • Loading branch information
abdullahtahiriyo authored and wwmayer committed Dec 20, 2014
1 parent 21354e9 commit a067a7c
Show file tree
Hide file tree
Showing 11 changed files with 858 additions and 92 deletions.
20 changes: 20 additions & 0 deletions src/Mod/Sketcher/App/Sketch.cpp
Expand Up @@ -1761,6 +1761,26 @@ int Sketch::addEqualConstraint(int geoId1, int geoId2)
GCSsys.addConstraintEqualRadius(a1, a2, tag);
return ConstraintsCounter;
}

if (Geoms[geoId2].type == ArcOfEllipse) {
if (Geoms[geoId1].type == ArcOfEllipse) {
GCS::ArcOfEllipse &a1 = ArcsOfEllipse[Geoms[geoId1].index];
GCS::ArcOfEllipse &a2 = ArcsOfEllipse[Geoms[geoId2].index];
int tag = ++ConstraintsCounter;
GCSsys.addConstraintEqualRadii(a1, a2, tag);
return ConstraintsCounter;
}
}

if (Geoms[geoId1].type == Ellipse) {
GCS::Ellipse &e1 = Ellipses[Geoms[geoId1].index];
if (Geoms[geoId2].type == ArcOfEllipse) {
GCS::ArcOfEllipse &a2 = ArcsOfEllipse[Geoms[geoId2].index];
int tag = ++ConstraintsCounter;
GCSsys.addConstraintEqualRadii(a2, e1, tag);
return ConstraintsCounter;
}
}

Base::Console().Warning("Equality constraints between %s and %s are not supported.\n",
nameByType(Geoms[geoId1].type), nameByType(Geoms[geoId2].type));
Expand Down
290 changes: 289 additions & 1 deletion src/Mod/Sketcher/App/SketchObject.cpp

Large diffs are not rendered by default.

34 changes: 33 additions & 1 deletion src/Mod/Sketcher/App/freegcs/Constraints.cpp
Expand Up @@ -1792,7 +1792,7 @@ double ConstraintInternalAlignmentPoint2Ellipse::grad(double *param)
}

// ConstraintEqualMajorAxesEllipse
ConstraintEqualMajorAxesEllipse:: ConstraintEqualMajorAxesEllipse(Ellipse &e1, Ellipse &e2)
ConstraintEqualMajorAxesEllipse:: ConstraintEqualMajorAxesEllipse(Ellipse &e1, Ellipse &e2)
{
pvec.push_back(e1.center.x);
pvec.push_back(e1.center.y);
Expand All @@ -1808,6 +1808,38 @@ double ConstraintInternalAlignmentPoint2Ellipse::grad(double *param)
rescale();
}

ConstraintEqualMajorAxesEllipse:: ConstraintEqualMajorAxesEllipse(ArcOfEllipse &a1, Ellipse &e2)
{
pvec.push_back(a1.center.x);
pvec.push_back(a1.center.y);
pvec.push_back(a1.focus1X);
pvec.push_back(a1.focus1Y);
pvec.push_back(a1.radmin);
pvec.push_back(e2.center.x);
pvec.push_back(e2.center.y);
pvec.push_back(e2.focus1X);
pvec.push_back(e2.focus1Y);
pvec.push_back(e2.radmin);
origpvec = pvec;
rescale();
}

ConstraintEqualMajorAxesEllipse:: ConstraintEqualMajorAxesEllipse(ArcOfEllipse &a1, ArcOfEllipse &a2)
{
pvec.push_back(a1.center.x);
pvec.push_back(a1.center.y);
pvec.push_back(a1.focus1X);
pvec.push_back(a1.focus1Y);
pvec.push_back(a1.radmin);
pvec.push_back(a2.center.x);
pvec.push_back(a2.center.y);
pvec.push_back(a2.focus1X);
pvec.push_back(a2.focus1Y);
pvec.push_back(a2.radmin);
origpvec = pvec;
rescale();
}

ConstraintType ConstraintEqualMajorAxesEllipse::getTypeId()
{
return EqualMajorAxesEllipse;
Expand Down
2 changes: 2 additions & 0 deletions src/Mod/Sketcher/App/freegcs/Constraints.h
Expand Up @@ -400,6 +400,8 @@ namespace GCS
inline double* e2rmin() { return pvec[9]; }
public:
ConstraintEqualMajorAxesEllipse(Ellipse &e1, Ellipse &e2);
ConstraintEqualMajorAxesEllipse(ArcOfEllipse &a1, Ellipse &e2);
ConstraintEqualMajorAxesEllipse(ArcOfEllipse &a1, ArcOfEllipse &a2);
virtual ConstraintType getTypeId();
virtual void rescale(double coef=1.);
virtual double error();
Expand Down
210 changes: 150 additions & 60 deletions src/Mod/Sketcher/App/freegcs/GCS.cpp
Expand Up @@ -798,6 +798,24 @@ int System::addConstraintEqualRadii(Ellipse &e1, Ellipse &e2, int tagId)
return addConstraint(constr);
}

int System::addConstraintEqualRadii(ArcOfEllipse &a1, ArcOfEllipse &a2, int tagId)
{
addConstraintEqual(a1.radmin, a2.radmin, tagId);

Constraint *constr = new ConstraintEqualMajorAxesEllipse(a1,a2);
constr->setTag(tagId);
return addConstraint(constr);
}

int System::addConstraintEqualRadii(ArcOfEllipse &a1, Ellipse &e2, int tagId)
{
addConstraintEqual(a1.radmin, e2.radmin, tagId);

Constraint *constr = new ConstraintEqualMajorAxesEllipse(a1,e2);
constr->setTag(tagId);
return addConstraint(constr);
}

int System::addConstraintEqualRadius(Circle &c1, Arc &a2, int tagId)
{
return addConstraintEqual(c1.rad, a2.rad, tagId);
Expand Down Expand Up @@ -828,71 +846,81 @@ int System::addConstraintInternalAlignmentPoint2Ellipse(Ellipse &e, Point &p1, I
}

int System::addConstraintInternalAlignmentEllipseMajorDiameter(Ellipse &e, Point &p1, Point &p2, int tagId)
{
//chechk which of the points is closer to satisfying positivemajor
double err1=0.0, err2=0.0;
{
ConstraintInternalAlignmentPoint2Ellipse constr (e,p1,EllipsePositiveMajorX);
err1+=abs(constr.error());
};
{
ConstraintInternalAlignmentPoint2Ellipse constr (e,p1,EllipsePositiveMajorY);
err1+=abs(constr.error());
};
{
ConstraintInternalAlignmentPoint2Ellipse constr (e,p2,EllipsePositiveMajorX);
err2+=abs(constr.error());
};
{
ConstraintInternalAlignmentPoint2Ellipse constr (e,p2,EllipsePositiveMajorY);
err2+=abs(constr.error());
};
if(err1<=err2){
{
double X_1=*p1.x;
double Y_1=*p1.y;
double X_2=*p2.x;
double Y_2=*p2.y;
double X_c=*e.center.x;
double Y_c=*e.center.y;
double X_F1=*e.focus1X;
double Y_F1=*e.focus1Y;
double b=*e.radmin;

// P1=vector([X_1,Y_1])
// P2=vector([X_2,Y_2])
// dF1= (F1-C)/sqrt((F1-C)*(F1-C))
// print "these are the extreme points of the major axis"
// PA = C + a * dF1
// PN = C - a * dF1
// print "this is a simple function to know which point is closer to the positive edge of the ellipse"
// DMC=(P1-PA)*(P1-PA)-(P2-PA)*(P2-PA)
double closertopositivemajor=pow(X_1 - X_c - (X_F1 - X_c)*sqrt(pow(b, 2) + pow(X_F1 - X_c,
2) + pow(Y_F1 - Y_c, 2))/sqrt(pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2)),
2) - pow(X_2 - X_c - (X_F1 - X_c)*sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) +
pow(Y_F1 - Y_c, 2))/sqrt(pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2)), 2) +
pow(Y_1 - Y_c - (Y_F1 - Y_c)*sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) +
pow(Y_F1 - Y_c, 2))/sqrt(pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2)), 2) -
pow(Y_2 - Y_c - (Y_F1 - Y_c)*sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) +
pow(Y_F1 - Y_c, 2))/sqrt(pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2)), 2);

if(closertopositivemajor>0){
//p2 is closer to positivemajor. Assign constraints back-to-front.
addConstraintInternalAlignmentPoint2Ellipse(e,p2,EllipsePositiveMajorX,tagId);
addConstraintInternalAlignmentPoint2Ellipse(e,p2,EllipsePositiveMajorY,tagId);
addConstraintInternalAlignmentPoint2Ellipse(e,p1,EllipseNegativeMajorX,tagId);
return addConstraintInternalAlignmentPoint2Ellipse(e,p1,EllipseNegativeMajorY,tagId);
}
else{
//p1 is closer to positivemajor
addConstraintInternalAlignmentPoint2Ellipse(e,p1,EllipsePositiveMajorX,tagId);
addConstraintInternalAlignmentPoint2Ellipse(e,p1,EllipsePositiveMajorY,tagId);
addConstraintInternalAlignmentPoint2Ellipse(e,p2,EllipseNegativeMajorX,tagId);
return addConstraintInternalAlignmentPoint2Ellipse(e,p2,EllipseNegativeMajorY,tagId);
} else {
//p2 is closer to positivemajor. Assign constraints back-to-front.
addConstraintInternalAlignmentPoint2Ellipse(e,p2,EllipsePositiveMajorX,tagId);
addConstraintInternalAlignmentPoint2Ellipse(e,p2,EllipsePositiveMajorY,tagId);
addConstraintInternalAlignmentPoint2Ellipse(e,p1,EllipseNegativeMajorX,tagId);
return addConstraintInternalAlignmentPoint2Ellipse(e,p1,EllipseNegativeMajorY,tagId);
}
}

int System::addConstraintInternalAlignmentEllipseMinorDiameter(Ellipse &e, Point &p1, Point &p2, int tagId)
{
//chechk which of the points is closer to satisfying positivemajor
double err1=0.0, err2=0.0;
{
ConstraintInternalAlignmentPoint2Ellipse constr (e,p1,EllipsePositiveMinorX);
err1+=abs(constr.error());
};
{
ConstraintInternalAlignmentPoint2Ellipse constr (e,p1,EllipsePositiveMinorY);
err1+=abs(constr.error());
};
{
ConstraintInternalAlignmentPoint2Ellipse constr (e,p2,EllipsePositiveMinorX);
err2+=abs(constr.error());
};
{
ConstraintInternalAlignmentPoint2Ellipse constr (e,p2,EllipsePositiveMinorY);
err2+=abs(constr.error());
};
if(err1<=err2){
double X_1=*p1.x;
double Y_1=*p1.y;
double X_2=*p2.x;
double Y_2=*p2.y;
double X_c=*e.center.x;
double Y_c=*e.center.y;
double X_F1=*e.focus1X;
double Y_F1=*e.focus1Y;
double b=*e.radmin;

// Same idea as for major above, but for minor
// DMC=(P1-PA)*(P1-PA)-(P2-PA)*(P2-PA)
double closertopositiveminor= pow(X_1 - X_c + b*(Y_F1 - Y_c)/sqrt(pow(X_F1 - X_c, 2) +
pow(Y_F1 - Y_c, 2)), 2) - pow(X_2 - X_c + b*(Y_F1 - Y_c)/sqrt(pow(X_F1 -
X_c, 2) + pow(Y_F1 - Y_c, 2)), 2) + pow(-Y_1 + Y_c + b*(X_F1 -
X_c)/sqrt(pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2)), 2) - pow(-Y_2 + Y_c
+ b*(X_F1 - X_c)/sqrt(pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2)), 2);

if(closertopositiveminor>0){
addConstraintInternalAlignmentPoint2Ellipse(e,p2,EllipsePositiveMinorX,tagId);
addConstraintInternalAlignmentPoint2Ellipse(e,p2,EllipsePositiveMinorY,tagId);
addConstraintInternalAlignmentPoint2Ellipse(e,p1,EllipseNegativeMinorX,tagId);
return addConstraintInternalAlignmentPoint2Ellipse(e,p1,EllipseNegativeMinorY,tagId);
} else {
addConstraintInternalAlignmentPoint2Ellipse(e,p1,EllipsePositiveMinorX,tagId);
addConstraintInternalAlignmentPoint2Ellipse(e,p1,EllipsePositiveMinorY,tagId);
addConstraintInternalAlignmentPoint2Ellipse(e,p2,EllipseNegativeMinorX,tagId);
return addConstraintInternalAlignmentPoint2Ellipse(e,p2,EllipseNegativeMinorY,tagId);
} else {
addConstraintInternalAlignmentPoint2Ellipse(e,p2,EllipsePositiveMinorX,tagId);
addConstraintInternalAlignmentPoint2Ellipse(e,p2,EllipsePositiveMinorY,tagId);
addConstraintInternalAlignmentPoint2Ellipse(e,p1,EllipseNegativeMinorX,tagId);
return addConstraintInternalAlignmentPoint2Ellipse(e,p1,EllipseNegativeMinorY,tagId);
};
}
}

int System::addConstraintInternalAlignmentEllipseFocus1(Ellipse &e, Point &p1, int tagId)
Expand All @@ -916,18 +944,80 @@ int System::addConstraintInternalAlignmentPoint2Ellipse(ArcOfEllipse &a, Point &

int System::addConstraintInternalAlignmentEllipseMajorDiameter(ArcOfEllipse &a, Point &p1, Point &p2, int tagId)
{
addConstraintInternalAlignmentPoint2Ellipse(a,p1,EllipsePositiveMajorX,tagId);
addConstraintInternalAlignmentPoint2Ellipse(a,p1,EllipsePositiveMajorY,tagId);
addConstraintInternalAlignmentPoint2Ellipse(a,p2,EllipseNegativeMajorX,tagId);
return addConstraintInternalAlignmentPoint2Ellipse(a,p2,EllipseNegativeMajorY,tagId);
double X_1=*p1.x;
double Y_1=*p1.y;
double X_2=*p2.x;
double Y_2=*p2.y;
double X_c=*a.center.x;
double Y_c=*a.center.y;
double X_F1=*a.focus1X;
double Y_F1=*a.focus1Y;
double b=*a.radmin;

// P1=vector([X_1,Y_1])
// P2=vector([X_2,Y_2])
// dF1= (F1-C)/sqrt((F1-C)*(F1-C))
// print "these are the extreme points of the major axis"
// PA = C + a * dF1
// PN = C - a * dF1
// print "this is a simple function to know which point is closer to the positive edge of the ellipse"
// DMC=(P1-PA)*(P1-PA)-(P2-PA)*(P2-PA)
double closertopositivemajor=pow(X_1 - X_c - (X_F1 - X_c)*sqrt(pow(b, 2) + pow(X_F1 - X_c,
2) + pow(Y_F1 - Y_c, 2))/sqrt(pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2)),
2) - pow(X_2 - X_c - (X_F1 - X_c)*sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) +
pow(Y_F1 - Y_c, 2))/sqrt(pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2)), 2) +
pow(Y_1 - Y_c - (Y_F1 - Y_c)*sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) +
pow(Y_F1 - Y_c, 2))/sqrt(pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2)), 2) -
pow(Y_2 - Y_c - (Y_F1 - Y_c)*sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) +
pow(Y_F1 - Y_c, 2))/sqrt(pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2)), 2);

if(closertopositivemajor>0){
//p2 is closer to positivemajor. Assign constraints back-to-front.
addConstraintInternalAlignmentPoint2Ellipse(a,p2,EllipsePositiveMajorX,tagId);
addConstraintInternalAlignmentPoint2Ellipse(a,p2,EllipsePositiveMajorY,tagId);
addConstraintInternalAlignmentPoint2Ellipse(a,p1,EllipseNegativeMajorX,tagId);
return addConstraintInternalAlignmentPoint2Ellipse(a,p1,EllipseNegativeMajorY,tagId);
}
else{
//p1 is closer to positivemajor
addConstraintInternalAlignmentPoint2Ellipse(a,p1,EllipsePositiveMajorX,tagId);
addConstraintInternalAlignmentPoint2Ellipse(a,p1,EllipsePositiveMajorY,tagId);
addConstraintInternalAlignmentPoint2Ellipse(a,p2,EllipseNegativeMajorX,tagId);
return addConstraintInternalAlignmentPoint2Ellipse(a,p2,EllipseNegativeMajorY,tagId);
}
}

int System::addConstraintInternalAlignmentEllipseMinorDiameter(ArcOfEllipse &a, Point &p1, Point &p2, int tagId)
{
addConstraintInternalAlignmentPoint2Ellipse(a,p1,EllipsePositiveMinorX,tagId);
addConstraintInternalAlignmentPoint2Ellipse(a,p1,EllipsePositiveMinorY,tagId);
addConstraintInternalAlignmentPoint2Ellipse(a,p2,EllipseNegativeMinorX,tagId);
return addConstraintInternalAlignmentPoint2Ellipse(a,p2,EllipseNegativeMinorY,tagId);
double X_1=*p1.x;
double Y_1=*p1.y;
double X_2=*p2.x;
double Y_2=*p2.y;
double X_c=*a.center.x;
double Y_c=*a.center.y;
double X_F1=*a.focus1X;
double Y_F1=*a.focus1Y;
double b=*a.radmin;

// Same idea as for major above, but for minor
// DMC=(P1-PA)*(P1-PA)-(P2-PA)*(P2-PA)
double closertopositiveminor= pow(X_1 - X_c + b*(Y_F1 - Y_c)/sqrt(pow(X_F1 - X_c, 2) +
pow(Y_F1 - Y_c, 2)), 2) - pow(X_2 - X_c + b*(Y_F1 - Y_c)/sqrt(pow(X_F1 -
X_c, 2) + pow(Y_F1 - Y_c, 2)), 2) + pow(-Y_1 + Y_c + b*(X_F1 -
X_c)/sqrt(pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2)), 2) - pow(-Y_2 + Y_c
+ b*(X_F1 - X_c)/sqrt(pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2)), 2);

if(closertopositiveminor>0){
addConstraintInternalAlignmentPoint2Ellipse(a,p2,EllipsePositiveMinorX,tagId);
addConstraintInternalAlignmentPoint2Ellipse(a,p2,EllipsePositiveMinorY,tagId);
addConstraintInternalAlignmentPoint2Ellipse(a,p1,EllipseNegativeMinorX,tagId);
return addConstraintInternalAlignmentPoint2Ellipse(a,p1,EllipseNegativeMinorY,tagId);
} else {
addConstraintInternalAlignmentPoint2Ellipse(a,p1,EllipsePositiveMinorX,tagId);
addConstraintInternalAlignmentPoint2Ellipse(a,p1,EllipsePositiveMinorY,tagId);
addConstraintInternalAlignmentPoint2Ellipse(a,p2,EllipseNegativeMinorX,tagId);
return addConstraintInternalAlignmentPoint2Ellipse(a,p2,EllipseNegativeMinorY,tagId);
}
}

int System::addConstraintInternalAlignmentEllipseFocus1(ArcOfEllipse &a, Point &p1, int tagId)
Expand Down Expand Up @@ -1749,7 +1839,7 @@ int System::diagnose()
Eigen::MatrixXd Q = qrJT.matrixQ ();
int paramsNum = qrJT.rows();
int constrNum = qrJT.cols();
qrJT.setThreshold(1e-10);
qrJT.setThreshold(1e-13);
int rank = qrJT.rank();

Eigen::MatrixXd R;
Expand Down
2 changes: 2 additions & 0 deletions src/Mod/Sketcher/App/freegcs/GCS.h
Expand Up @@ -165,6 +165,8 @@ namespace GCS
int addConstraintEqualLength(Line &l1, Line &l2, double *length, int tagId=0);
int addConstraintEqualRadius(Circle &c1, Circle &c2, int tagId=0);
int addConstraintEqualRadii(Ellipse &e1, Ellipse &e2, int tagId=0);
int addConstraintEqualRadii(ArcOfEllipse &a1, ArcOfEllipse &a2, int tagId=0);
int addConstraintEqualRadii(ArcOfEllipse &a1, Ellipse &e2, int tagId=0);
int addConstraintEqualRadius(Circle &c1, Arc &a2, int tagId=0);
int addConstraintEqualRadius(Arc &a1, Arc &a2, int tagId=0);
int addConstraintP2PSymmetric(Point &p1, Point &p2, Line &l, int tagId=0);
Expand Down

0 comments on commit a067a7c

Please sign in to comment.