diff --git a/src/Mod/Sketcher/App/Constraint.h b/src/Mod/Sketcher/App/Constraint.h index e4492adb4..30bcdcbfa 100644 --- a/src/Mod/Sketcher/App/Constraint.h +++ b/src/Mod/Sketcher/App/Constraint.h @@ -63,7 +63,10 @@ enum InternalAlignmentType { EllipseMajorDiameter = 1, EllipseMinorDiameter = 2, EllipseFocus1 = 3, - EllipseFocus2 = 4 + EllipseFocus2 = 4, + HyperbolaMajor = 5, + HyperbolaMinor = 6, + HyperbolaFocus = 7 }; /// define if you want to use the end or start point diff --git a/src/Mod/Sketcher/App/Sketch.cpp b/src/Mod/Sketcher/App/Sketch.cpp index bdb6de799..ab9777d94 100644 --- a/src/Mod/Sketcher/App/Sketch.cpp +++ b/src/Mod/Sketcher/App/Sketch.cpp @@ -991,6 +991,15 @@ int Sketch::addConstraint(const Constraint *constraint) case EllipseFocus2: rtn = addInternalAlignmentEllipseFocus2(constraint->First,constraint->Second); break; + case HyperbolaMajor: + rtn = addInternalAlignmentHyperbolaMajorDiameter(constraint->First,constraint->Second); + break; + case HyperbolaMinor: + rtn = addInternalAlignmentHyperbolaMinorDiameter(constraint->First,constraint->Second); + break; + case HyperbolaFocus: + rtn = addInternalAlignmentHyperbolaFocus(constraint->First,constraint->Second); + break; default: break; } @@ -1944,26 +1953,26 @@ int Sketch::addInternalAlignmentEllipseMajorDiameter(int geoId1, int geoId2) int Sketch::addInternalAlignmentEllipseMinorDiameter(int geoId1, int geoId2) { std::swap(geoId1, geoId2); - + geoId1 = checkGeoId(geoId1); geoId2 = checkGeoId(geoId2); - + if (Geoms[geoId1].type != Ellipse && Geoms[geoId1].type != ArcOfEllipse) return -1; if (Geoms[geoId2].type != Line) return -1; - + int pointId1 = getPointId(geoId2, start); int pointId2 = getPointId(geoId2, end); - + if (pointId1 >= 0 && pointId1 < int(Points.size()) && pointId2 >= 0 && pointId2 < int(Points.size())) { GCS::Point &p1 = Points[pointId1]; GCS::Point &p2 = Points[pointId2]; - + if(Geoms[geoId1].type == Ellipse) { GCS::Ellipse &e1 = Ellipses[Geoms[geoId1].index]; - + // constraints // 1. start point with ellipse -a // 2. end point with ellipse +a @@ -1973,7 +1982,7 @@ int Sketch::addInternalAlignmentEllipseMinorDiameter(int geoId1, int geoId2) } else { GCS::ArcOfEllipse &a1 = ArcsOfEllipse[Geoms[geoId1].index]; - + int tag = ++ConstraintsCounter; GCSsys.addConstraintInternalAlignmentEllipseMinorDiameter(a1, p1, p2, tag); return ConstraintsCounter; @@ -1985,23 +1994,23 @@ int Sketch::addInternalAlignmentEllipseMinorDiameter(int geoId1, int geoId2) int Sketch::addInternalAlignmentEllipseFocus1(int geoId1, int geoId2) { std::swap(geoId1, geoId2); - + geoId1 = checkGeoId(geoId1); geoId2 = checkGeoId(geoId2); - + if (Geoms[geoId1].type != Ellipse && Geoms[geoId1].type != ArcOfEllipse) return -1; if (Geoms[geoId2].type != Point) return -1; - + int pointId1 = getPointId(geoId2, start); - + if (pointId1 >= 0 && pointId1 < int(Points.size())) { GCS::Point &p1 = Points[pointId1]; - + if(Geoms[geoId1].type == Ellipse) { GCS::Ellipse &e1 = Ellipses[Geoms[geoId1].index]; - + // constraints // 1. start point with ellipse -a // 2. end point with ellipse +a @@ -2011,7 +2020,7 @@ int Sketch::addInternalAlignmentEllipseFocus1(int geoId1, int geoId2) } else { GCS::ArcOfEllipse &a1 = ArcsOfEllipse[Geoms[geoId1].index]; - + int tag = ++ConstraintsCounter; GCSsys.addConstraintInternalAlignmentEllipseFocus1(a1, p1, tag); return ConstraintsCounter; @@ -2059,6 +2068,95 @@ int Sketch::addInternalAlignmentEllipseFocus2(int geoId1, int geoId2) return -1; } + +int Sketch::addInternalAlignmentHyperbolaMajorDiameter(int geoId1, int geoId2) +{ + std::swap(geoId1, geoId2); + + geoId1 = checkGeoId(geoId1); + geoId2 = checkGeoId(geoId2); + + if (Geoms[geoId1].type != ArcOfHyperbola) + return -1; + if (Geoms[geoId2].type != Line) + return -1; + + int pointId1 = getPointId(geoId2, start); + int pointId2 = getPointId(geoId2, end); + + if (pointId1 >= 0 && pointId1 < int(Points.size()) && + pointId2 >= 0 && pointId2 < int(Points.size())) { + + GCS::Point &p1 = Points[pointId1]; + GCS::Point &p2 = Points[pointId2]; + + GCS::ArcOfHyperbola &a1 = ArcsOfHyperbola[Geoms[geoId1].index]; + + int tag = ++ConstraintsCounter; + GCSsys.addConstraintInternalAlignmentHyperbolaMajorDiameter(a1, p1, p2, tag); + return ConstraintsCounter; + } + + return -1; +} + +int Sketch::addInternalAlignmentHyperbolaMinorDiameter(int geoId1, int geoId2) +{ + std::swap(geoId1, geoId2); + + geoId1 = checkGeoId(geoId1); + geoId2 = checkGeoId(geoId2); + + if (Geoms[geoId1].type != ArcOfHyperbola) + return -1; + if (Geoms[geoId2].type != Line) + return -1; + + int pointId1 = getPointId(geoId2, start); + int pointId2 = getPointId(geoId2, end); + + if (pointId1 >= 0 && pointId1 < int(Points.size()) && + pointId2 >= 0 && pointId2 < int(Points.size())) { + + GCS::Point &p1 = Points[pointId1]; + GCS::Point &p2 = Points[pointId2]; + + GCS::ArcOfHyperbola &a1 = ArcsOfHyperbola[Geoms[geoId1].index]; + + int tag = ++ConstraintsCounter; + GCSsys.addConstraintInternalAlignmentHyperbolaMinorDiameter(a1, p1, p2, tag); + return ConstraintsCounter; + } + + return -1; +} + +int Sketch::addInternalAlignmentHyperbolaFocus(int geoId1, int geoId2) +{ + std::swap(geoId1, geoId2); + + geoId1 = checkGeoId(geoId1); + geoId2 = checkGeoId(geoId2); + + if (Geoms[geoId1].type != ArcOfHyperbola) + return -1; + if (Geoms[geoId2].type != Point) + return -1; + + int pointId1 = getPointId(geoId2, start); + + if (pointId1 >= 0 && pointId1 < int(Points.size())) { + GCS::Point &p1 = Points[pointId1]; + + GCS::ArcOfHyperbola &a1 = ArcsOfHyperbola[Geoms[geoId1].index]; + + int tag = ++ConstraintsCounter; + GCSsys.addConstraintInternalAlignmentHyperbolaFocus(a1, p1, tag); + return ConstraintsCounter; + } + return -1; +} + double Sketch::calculateAngleViaPoint(int geoId1, int geoId2, double px, double py) { geoId1 = checkGeoId(geoId1); diff --git a/src/Mod/Sketcher/App/Sketch.h b/src/Mod/Sketcher/App/Sketch.h index f245bd915..185f8085c 100644 --- a/src/Mod/Sketcher/App/Sketch.h +++ b/src/Mod/Sketcher/App/Sketch.h @@ -305,6 +305,10 @@ public: int addInternalAlignmentEllipseMinorDiameter(int geoId1, int geoId2); int addInternalAlignmentEllipseFocus1(int geoId1, int geoId2); int addInternalAlignmentEllipseFocus2(int geoId1, int geoId2); + /// add InternalAlignmentHyperbolaMajorRadius to a line and a hyperbola + int addInternalAlignmentHyperbolaMajorDiameter(int geoId1, int geoId2); + int addInternalAlignmentHyperbolaMinorDiameter(int geoId1, int geoId2); + int addInternalAlignmentHyperbolaFocus(int geoId1, int geoId2); //@} public: //This func is to be used during angle-via-point constraint creation. It calculates diff --git a/src/Mod/Sketcher/App/planegcs/Constraints.cpp b/src/Mod/Sketcher/App/planegcs/Constraints.cpp index ca131ea68..3f9476157 100644 --- a/src/Mod/Sketcher/App/planegcs/Constraints.cpp +++ b/src/Mod/Sketcher/App/planegcs/Constraints.cpp @@ -1300,21 +1300,35 @@ void ConstraintInternalAlignmentPoint2Hyperbola::errorgrad(double *err, double * DeriVector2 poa;//point to align to bool by_y_not_by_x = false;//a flag to indicate if the alignment error function is for y (false - x, true - y). - poa = c.sum(emaj.multD(a, da)); - switch(AlignmentType){ case HyperbolaPositiveMajorX: case HyperbolaPositiveMajorY: + poa = c.sum(emaj.multD(a, da)); by_y_not_by_x = AlignmentType == HyperbolaPositiveMajorY; break; + case HyperbolaNegativeMajorX: + case HyperbolaNegativeMajorY: + poa = c.sum(emaj.multD(-a, -da)); + by_y_not_by_x = AlignmentType == HyperbolaNegativeMajorY; + break; case HyperbolaPositiveMinorX: case HyperbolaPositiveMinorY: { - DeriVector2 A(poa.x,poa.y); + DeriVector2 pa = c.sum(emaj.multD(a, da)); + DeriVector2 A(pa.x,pa.y); poa = A.sum(emin.multD(b, db)); by_y_not_by_x = AlignmentType == HyperbolaPositiveMinorY; break; } + case HyperbolaNegativeMinorX: + case HyperbolaNegativeMinorY: + { + DeriVector2 pa = c.sum(emaj.multD(a, da)); + DeriVector2 A(pa.x,pa.y); + poa = A.sum(emin.multD(-b, -db)); + by_y_not_by_x = AlignmentType == HyperbolaNegativeMinorY; + break; + } default: //shouldn't happen poa = pv;//align to the point itself, doing nothing essentially diff --git a/src/Mod/Sketcher/App/planegcs/Constraints.h b/src/Mod/Sketcher/App/planegcs/Constraints.h index 10e091f07..cafb554b9 100644 --- a/src/Mod/Sketcher/App/planegcs/Constraints.h +++ b/src/Mod/Sketcher/App/planegcs/Constraints.h @@ -81,8 +81,12 @@ namespace GCS EllipseFocus2Y = 9, HyperbolaPositiveMajorX = 10, HyperbolaPositiveMajorY = 11, - HyperbolaPositiveMinorX = 12, - HyperbolaPositiveMinorY = 13 + HyperbolaNegativeMajorX = 12, + HyperbolaNegativeMajorY = 13, + HyperbolaPositiveMinorX = 14, + HyperbolaPositiveMinorY = 15, + HyperbolaNegativeMinorX = 16, + HyperbolaNegativeMinorY = 17 }; class Constraint diff --git a/src/Mod/Sketcher/App/planegcs/GCS.cpp b/src/Mod/Sketcher/App/planegcs/GCS.cpp index e24f0ee7a..c13897a0f 100644 --- a/src/Mod/Sketcher/App/planegcs/GCS.cpp +++ b/src/Mod/Sketcher/App/planegcs/GCS.cpp @@ -793,6 +793,13 @@ int System::addConstraintInternalAlignmentPoint2Ellipse(Ellipse &e, Point &p1, I return addConstraint(constr); } +int System::addConstraintInternalAlignmentPoint2Hyperbola(Hyperbola &e, Point &p1, InternalAlignmentType alignmentType, int tagId) +{ + Constraint *constr = new ConstraintInternalAlignmentPoint2Hyperbola(e, p1, alignmentType); + constr->setTag(tagId); + return addConstraint(constr); +} + int System::addConstraintInternalAlignmentEllipseMajorDiameter(Ellipse &e, Point &p1, Point &p2, int tagId) { double X_1=*p1.x; @@ -883,6 +890,97 @@ int System::addConstraintInternalAlignmentEllipseFocus2(Ellipse &e, Point &p1, i return addConstraintInternalAlignmentPoint2Ellipse(e,p1,EllipseFocus2Y,tagId); } +int System::addConstraintInternalAlignmentHyperbolaMajorDiameter(Hyperbola &e, Point &p1, Point &p2, int tagId) +{ + 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.focus1.x; + double Y_F1=*e.focus1.y; + 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)*(-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)*(-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)*(-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)*(-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. + addConstraintInternalAlignmentPoint2Hyperbola(e,p2,HyperbolaPositiveMajorX,tagId); + addConstraintInternalAlignmentPoint2Hyperbola(e,p2,HyperbolaPositiveMajorY,tagId); + addConstraintInternalAlignmentPoint2Hyperbola(e,p1,HyperbolaNegativeMajorX,tagId); + return addConstraintInternalAlignmentPoint2Hyperbola(e,p1,HyperbolaNegativeMajorY,tagId); + } + else{ + //p1 is closer to positivemajor + addConstraintInternalAlignmentPoint2Hyperbola(e,p1,HyperbolaPositiveMajorX,tagId); + addConstraintInternalAlignmentPoint2Hyperbola(e,p1,HyperbolaPositiveMajorY,tagId); + addConstraintInternalAlignmentPoint2Hyperbola(e,p2,HyperbolaNegativeMajorX,tagId); + return addConstraintInternalAlignmentPoint2Hyperbola(e,p2,HyperbolaNegativeMajorY,tagId); + } +} + +int System::addConstraintInternalAlignmentHyperbolaMinorDiameter(Hyperbola &e, Point &p1, Point &p2, int tagId) +{ + 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.focus1.x; + double Y_F1=*e.focus1.y; + 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)) + (X_F1 - X_c)*(-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 + b*(Y_F1 - Y_c)/sqrt(pow(X_F1 - X_c, 2) + pow(Y_F1 - + Y_c, 2)) + (X_F1 - X_c)*(-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 - b*(X_F1 - X_c)/sqrt(pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2)) + + (Y_F1 - Y_c)*(-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 - + b*(X_F1 - X_c)/sqrt(pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2)) + (Y_F1 - + Y_c)*(-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(closertopositiveminor>0){ + addConstraintInternalAlignmentPoint2Hyperbola(e,p2,HyperbolaPositiveMinorX,tagId); + addConstraintInternalAlignmentPoint2Hyperbola(e,p2,HyperbolaPositiveMinorY,tagId); + addConstraintInternalAlignmentPoint2Hyperbola(e,p1,HyperbolaNegativeMinorX,tagId); + return addConstraintInternalAlignmentPoint2Hyperbola(e,p1,HyperbolaNegativeMinorY,tagId); + } else { + addConstraintInternalAlignmentPoint2Hyperbola(e,p1,HyperbolaPositiveMinorX,tagId); + addConstraintInternalAlignmentPoint2Hyperbola(e,p1,HyperbolaPositiveMinorY,tagId); + addConstraintInternalAlignmentPoint2Hyperbola(e,p2,HyperbolaNegativeMinorX,tagId); + return addConstraintInternalAlignmentPoint2Hyperbola(e,p2,HyperbolaNegativeMinorY,tagId); + } +} + +int System::addConstraintInternalAlignmentHyperbolaFocus(Hyperbola &e, Point &p1, int tagId) +{ + addConstraintEqual(e.focus1.x, p1.x, tagId); + return addConstraintEqual(e.focus1.y, p1.y, tagId); +} + //calculates angle between two curves at point of their intersection p. If two //points are supplied, p is used for first curve and p2 for second, yielding a diff --git a/src/Mod/Sketcher/App/planegcs/GCS.h b/src/Mod/Sketcher/App/planegcs/GCS.h index 5a69b2a16..e6ee58ac4 100644 --- a/src/Mod/Sketcher/App/planegcs/GCS.h +++ b/src/Mod/Sketcher/App/planegcs/GCS.h @@ -225,6 +225,10 @@ namespace GCS int addConstraintInternalAlignmentEllipseMinorDiameter(Ellipse &e, Point &p1, Point &p2, int tagId=0); int addConstraintInternalAlignmentEllipseFocus1(Ellipse &e, Point &p1, int tagId=0); int addConstraintInternalAlignmentEllipseFocus2(Ellipse &e, Point &p1, int tagId=0); + int addConstraintInternalAlignmentPoint2Hyperbola(Hyperbola &e, Point &p1, InternalAlignmentType alignmentType, int tagId=0); + int addConstraintInternalAlignmentHyperbolaMajorDiameter(Hyperbola &e, Point &p1, Point &p2, int tagId=0); + int addConstraintInternalAlignmentHyperbolaMinorDiameter(Hyperbola &e, Point &p1, Point &p2, int tagId=0); + int addConstraintInternalAlignmentHyperbolaFocus(Hyperbola &e, Point &p1, int tagId=0); double calculateAngleViaPoint(Curve &crv1, Curve &crv2, Point &p); double calculateAngleViaPoint(Curve &crv1, Curve &crv2, Point &p1, Point &p2);