diff --git a/src/Mod/Sketcher/Gui/CommandConstraints.cpp b/src/Mod/Sketcher/Gui/CommandConstraints.cpp index bf17a5fc01..90d16b2050 100644 --- a/src/Mod/Sketcher/Gui/CommandConstraints.cpp +++ b/src/Mod/Sketcher/Gui/CommandConstraints.cpp @@ -361,13 +361,12 @@ bool SketcherGui::IsPointAlreadyOnCurve(int GeoIdCurve, int GeoIdPoint, Sketcher /// commits or aborts as appropriate. The reason is for compatibility reasons with /// other code e.g. "Autoconstraints" in DrawSketchHandler.cpp void SketcherGui::makeTangentToEllipseviaNewPoint(Sketcher::SketchObject* Obj, - const Part::Geometry *geom1, + const Part::GeomEllipse *ellipse, const Part::Geometry *geom2, int geoId1, int geoId2 ) { - const Part::GeomEllipse *ellipse = static_cast(geom1); Base::Vector3d center=ellipse->getCenter(); double majord=ellipse->getMajorRadius(); @@ -427,13 +426,12 @@ void SketcherGui::makeTangentToEllipseviaNewPoint(Sketcher::SketchObject* Obj, /// commits or aborts as appropriate. The reason is for compatibility reasons with /// other code e.g. "Autoconstraints" in DrawSketchHandler.cpp void SketcherGui::makeTangentToArcOfEllipseviaNewPoint(Sketcher::SketchObject* Obj, - const Part::Geometry *geom1, + const Part::GeomArcOfEllipse *aoe, const Part::Geometry *geom2, int geoId1, int geoId2 ) { - const Part::GeomArcOfEllipse *aoe = static_cast(geom1); Base::Vector3d center=aoe->getCenter(); double majord=aoe->getMajorRadius(); @@ -491,13 +489,12 @@ void SketcherGui::makeTangentToArcOfEllipseviaNewPoint(Sketcher::SketchObject* O /// commits or aborts as appropriate. The reason is for compatibility reasons with /// other code e.g. "Autoconstraints" in DrawSketchHandler.cpp void SketcherGui::makeTangentToArcOfHyperbolaviaNewPoint(Sketcher::SketchObject* Obj, - const Part::Geometry *geom1, + const Part::GeomArcOfHyperbola *aoh, const Part::Geometry *geom2, int geoId1, int geoId2 ) { - const Part::GeomArcOfHyperbola *aoh = static_cast(geom1); Base::Vector3d center=aoh->getCenter(); double majord=aoh->getMajorRadius(); @@ -573,19 +570,13 @@ void SketcherGui::makeTangentToArcOfHyperbolaviaNewPoint(Sketcher::SketchObject* /// commits or aborts as appropriate. The reason is for compatibility reasons with /// other code e.g. "Autoconstraints" in DrawSketchHandler.cpp void SketcherGui::makeTangentToArcOfParabolaviaNewPoint(Sketcher::SketchObject* Obj, - const Part::Geometry *geom1, + const Part::GeomArcOfParabola *aop, const Part::Geometry *geom2, int geoId1, int geoId2 ) { - const Part::GeomArcOfParabola *aop = static_cast(geom1); - //Base::Vector3d center=aop->getCenter(); - - //Base::Vector3d dirx = aop->getXAxisDir(); - //double phi=atan2(dirx.y, dirx.x); - //double df = aop->getFocal(); Base::Vector3d focus = aop->getFocus(); Base::Vector3d center2; @@ -614,15 +605,9 @@ void SketcherGui::makeTangentToArcOfParabolaviaNewPoint(Sketcher::SketchObject* } Base::Vector3d direction = center2-focus; - /*double angle = atan2(direction.y,direction.x)-phi; - double tapprox = 4*df*tan(angle);*/ Base::Vector3d PoP = focus + direction / 2; - - /*Base::Vector3d(center.x + tapprox * tapprox / 4 / df * cos(phi) - tapprox * sin(phi), - center.y + tapprox * tapprox / 4 / df * sin(phi) + tapprox * cos(phi), 0);*/ - try { // Add a point Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.addGeometry(Part.Point(App.Vector(%f,%f,0)))", @@ -4623,19 +4608,22 @@ void CmdSketcherConstrainTangent::activated(int iMsg) geom2->getTypeId() == Part::GeomArcOfCircle::getClassTypeId() ) { Gui::Command::openCommand("add tangent constraint point"); - makeTangentToEllipseviaNewPoint(Obj,geom1,geom2,GeoId1,GeoId2); + makeTangentToEllipseviaNewPoint(Obj,static_cast(geom1), geom2, + GeoId1, GeoId2); getSelection().clearSelection(); return; } else if( geom2->getTypeId() == Part::GeomArcOfHyperbola::getClassTypeId() ) { Gui::Command::openCommand("add tangent constraint point"); - makeTangentToArcOfHyperbolaviaNewPoint(Obj,geom2,geom1,GeoId2,GeoId1); + makeTangentToArcOfHyperbolaviaNewPoint(Obj, static_cast(geom2), + geom1, GeoId2, GeoId1); getSelection().clearSelection(); return; } else if( geom2->getTypeId() == Part::GeomArcOfParabola::getClassTypeId() ) { Gui::Command::openCommand("add tangent constraint point"); - makeTangentToArcOfParabolaviaNewPoint(Obj,geom2,geom1,GeoId2,GeoId1); + makeTangentToArcOfParabolaviaNewPoint(Obj,static_cast(geom2), + geom1, GeoId2, GeoId1); getSelection().clearSelection(); return; } @@ -4658,13 +4646,17 @@ void CmdSketcherConstrainTangent::activated(int iMsg) geom2->getTypeId() == Part::GeomLineSegment::getClassTypeId() ) { Gui::Command::openCommand("add tangent constraint point"); - makeTangentToArcOfEllipseviaNewPoint(Obj,geom1,geom2,GeoId1,GeoId2); + makeTangentToArcOfEllipseviaNewPoint(Obj, + static_cast(geom1), geom2, GeoId1, GeoId2); + getSelection().clearSelection(); return; } else if( geom2->getTypeId() == Part::GeomArcOfParabola::getClassTypeId() ) { Gui::Command::openCommand("add tangent constraint point"); - makeTangentToArcOfParabolaviaNewPoint(Obj,geom2,geom1,GeoId2,GeoId1); + makeTangentToArcOfParabolaviaNewPoint(Obj, + static_cast(geom2), + geom1, GeoId2, GeoId1); getSelection().clearSelection(); return; } @@ -4687,13 +4679,17 @@ void CmdSketcherConstrainTangent::activated(int iMsg) geom2->getTypeId() == Part::GeomLineSegment::getClassTypeId() ) { Gui::Command::openCommand("add tangent constraint point"); - makeTangentToArcOfHyperbolaviaNewPoint(Obj,geom1,geom2,GeoId1,GeoId2); + makeTangentToArcOfHyperbolaviaNewPoint(Obj, + static_cast(geom1), + geom2, GeoId1, GeoId2); getSelection().clearSelection(); return; } else if( geom2->getTypeId() == Part::GeomArcOfParabola::getClassTypeId() ) { Gui::Command::openCommand("add tangent constraint point"); - makeTangentToArcOfParabolaviaNewPoint(Obj,geom2,geom1,GeoId2,GeoId1); + makeTangentToArcOfParabolaviaNewPoint(Obj, + static_cast(geom2), + geom1, GeoId2, GeoId1); getSelection().clearSelection(); return; } @@ -4718,7 +4714,8 @@ void CmdSketcherConstrainTangent::activated(int iMsg) geom2->getTypeId() == Part::GeomLineSegment::getClassTypeId() ) { Gui::Command::openCommand("add tangent constraint point"); - makeTangentToArcOfParabolaviaNewPoint(Obj,geom1,geom2,GeoId1,GeoId2); + makeTangentToArcOfParabolaviaNewPoint(Obj, static_cast(geom1), + geom2, GeoId1, GeoId2); getSelection().clearSelection(); return; } @@ -4797,19 +4794,22 @@ void CmdSketcherConstrainTangent::applyConstraint(std::vector &selSeq geom2->getTypeId() == Part::GeomArcOfCircle::getClassTypeId() ) { Gui::Command::openCommand("add tangent constraint point"); - makeTangentToEllipseviaNewPoint(Obj,geom1,geom2,GeoId1,GeoId2); + makeTangentToEllipseviaNewPoint(Obj, static_cast(geom1), + geom2, GeoId1, GeoId2); getSelection().clearSelection(); return; } else if( geom2->getTypeId() == Part::GeomArcOfHyperbola::getClassTypeId() ) { Gui::Command::openCommand("add tangent constraint point"); - makeTangentToArcOfHyperbolaviaNewPoint(Obj,geom2,geom1,GeoId2,GeoId1); + makeTangentToArcOfHyperbolaviaNewPoint(Obj, static_cast(geom2), + geom1, GeoId2, GeoId1); getSelection().clearSelection(); return; } else if( geom2->getTypeId() == Part::GeomArcOfParabola::getClassTypeId() ) { Gui::Command::openCommand("add tangent constraint point"); - makeTangentToArcOfParabolaviaNewPoint(Obj,geom2,geom1,GeoId2,GeoId1); + makeTangentToArcOfParabolaviaNewPoint(Obj, static_cast(geom2), + geom1, GeoId2, GeoId1); getSelection().clearSelection(); return; } @@ -4832,13 +4832,15 @@ void CmdSketcherConstrainTangent::applyConstraint(std::vector &selSeq geom2->getTypeId() == Part::GeomLineSegment::getClassTypeId() ) { Gui::Command::openCommand("add tangent constraint point"); - makeTangentToArcOfHyperbolaviaNewPoint(Obj,geom1,geom2,GeoId1,GeoId2); + makeTangentToArcOfHyperbolaviaNewPoint(Obj, static_cast(geom1), + geom2, GeoId1, GeoId2); getSelection().clearSelection(); return; } else if( geom2->getTypeId() == Part::GeomArcOfParabola::getClassTypeId() ) { Gui::Command::openCommand("add tangent constraint point"); - makeTangentToArcOfParabolaviaNewPoint(Obj,geom2,geom1,GeoId2,GeoId1); + makeTangentToArcOfParabolaviaNewPoint(Obj, static_cast(geom2), + geom1, GeoId2, GeoId1); getSelection().clearSelection(); return; } @@ -4863,7 +4865,8 @@ void CmdSketcherConstrainTangent::applyConstraint(std::vector &selSeq geom2->getTypeId() == Part::GeomLineSegment::getClassTypeId() ) { Gui::Command::openCommand("add tangent constraint point"); - makeTangentToArcOfParabolaviaNewPoint(Obj,geom1,geom2,GeoId1,GeoId2); + makeTangentToArcOfParabolaviaNewPoint(Obj, static_cast(geom1), + geom2, GeoId1, GeoId2); getSelection().clearSelection(); return; } diff --git a/src/Mod/Sketcher/Gui/CommandConstraints.h b/src/Mod/Sketcher/Gui/CommandConstraints.h index e511a18404..7531fcb633 100644 --- a/src/Mod/Sketcher/Gui/CommandConstraints.h +++ b/src/Mod/Sketcher/Gui/CommandConstraints.h @@ -53,15 +53,15 @@ bool IsPointAlreadyOnCurve(int GeoIdCurve, int GeoIdPoint, Sketcher::PointPos Po // These functions are declared here to promote code reuse from other modules - + /// Makes a tangency constraint using external construction line between /// geom1 => an ellipse /// geom2 => any of an ellipse, an arc of ellipse, a circle, or an arc (of circle) /// NOTE: A command must be opened before calling this function, which this function /// commits or aborts as appropriate. The reason is for compatibility reasons with -/// other code e.g. "Autoconstraints" in DrawSketchHandler.cpp +/// other code e.g. "Autoconstraints" in DrawSketchHandler.cpp void makeTangentToEllipseviaNewPoint(Sketcher::SketchObject* Obj, - const Part::Geometry *geom1, + const Part::GeomEllipse *ellipse, const Part::Geometry *geom2, int geoId1, int geoId2 @@ -71,9 +71,9 @@ void makeTangentToEllipseviaNewPoint(Sketcher::SketchObject* Obj, /// geom2 => any of an arc of ellipse, a circle, or an arc (of circle) /// NOTE: A command must be opened before calling this function, which this function /// commits or aborts as appropriate. The reason is for compatibility reasons with -/// other code e.g. "Autoconstraints" in DrawSketchHandler.cpp +/// other code e.g. "Autoconstraints" in DrawSketchHandler.cpp void makeTangentToArcOfEllipseviaNewPoint(Sketcher::SketchObject* Obj, - const Part::Geometry *geom1, + const Part::GeomArcOfEllipse *aoe, const Part::Geometry *geom2, int geoId1, int geoId2 @@ -84,13 +84,13 @@ void makeTangentToArcOfEllipseviaNewPoint(Sketcher::SketchObject* Obj, /// geom2 => any of an arc of hyperbola, an arc of ellipse, a circle, or an arc (of circle) /// NOTE: A command must be opened before calling this function, which this function /// commits or aborts as appropriate. The reason is for compatibility reasons with -/// other code e.g. "Autoconstraints" in DrawSketchHandler.cpp +/// other code e.g. "Autoconstraints" in DrawSketchHandler.cpp void makeTangentToArcOfHyperbolaviaNewPoint(Sketcher::SketchObject* Obj, - const Part::Geometry *geom1, - const Part::Geometry *geom2, - int geoId1, - int geoId2 -); + const Part::GeomArcOfHyperbola *aoh, + const Part::Geometry *geom2, + int geoId1, + int geoId2 + ); /// Makes a simple tangency constraint using extra point + tangent via point /// geom1 => an arc of parabola @@ -99,11 +99,11 @@ void makeTangentToArcOfHyperbolaviaNewPoint(Sketcher::SketchObject* Obj, /// commits or aborts as appropriate. The reason is for compatibility reasons with /// other code e.g. "Autoconstraints" in DrawSketchHandler.cpp void makeTangentToArcOfParabolaviaNewPoint(Sketcher::SketchObject* Obj, - const Part::Geometry *geom1, - const Part::Geometry *geom2, - int geoId1, - int geoId2 -); + const Part::GeomArcOfParabola *aop, + const Part::Geometry *geom2, + int geoId1, + int geoId2 + ); std::string getStrippedPythonExceptionString(const Base::Exception&); diff --git a/src/Mod/Sketcher/Gui/DrawSketchHandler.cpp b/src/Mod/Sketcher/Gui/DrawSketchHandler.cpp index 474d85774a..a30d1b765e 100644 --- a/src/Mod/Sketcher/Gui/DrawSketchHandler.cpp +++ b/src/Mod/Sketcher/Gui/DrawSketchHandler.cpp @@ -138,7 +138,7 @@ int DrawSketchHandler::seekAutoConstraint(std::vector &suggested return 0; // If Autoconstraints property is not set quit Base::Vector3d hitShapeDir = Base::Vector3d(0,0,0); // direction of hit shape (if it is a line, the direction of the line) - + // Get Preselection int preSelPnt = sketchgui->getPreselectPoint(); int preSelCrv = sketchgui->getPreselectCurve(); @@ -150,12 +150,12 @@ int DrawSketchHandler::seekAutoConstraint(std::vector &suggested else if (preSelCrv != -1){ GeoId = preSelCrv; const Part::Geometry *geom = sketchgui->getSketchObject()->getGeometry(GeoId); - + if(geom->getTypeId() == Part::GeomLineSegment::getClassTypeId()){ const Part::GeomLineSegment *line = static_cast(geom); - hitShapeDir= line->getEndPoint()-line->getStartPoint(); + hitShapeDir= line->getEndPoint()-line->getStartPoint(); } - + } else if (preSelCrs == 0) { // root point GeoId = Sketcher::GeoEnum::RtPnt; @@ -164,7 +164,7 @@ int DrawSketchHandler::seekAutoConstraint(std::vector &suggested else if (preSelCrs == 1){ // x axis GeoId = Sketcher::GeoEnum::HAxis; hitShapeDir = Base::Vector3d(1,0,0); - + } else if (preSelCrs == 2){ // y axis GeoId = Sketcher::GeoEnum::VAxis; @@ -185,24 +185,24 @@ int DrawSketchHandler::seekAutoConstraint(std::vector &suggested constr.Type = Sketcher::PointOnObject; else if (type == AutoConstraint::CURVE && PosId == Sketcher::none) constr.Type = Sketcher::Tangent; - + if(constr.Type == Sketcher::Tangent && Dir.Length() > 1e-8 && hitShapeDir.Length() > 1e-8) { // We are hitting a line and have hitting vector information Base::Vector3d dir3d = Base::Vector3d(Dir.x,Dir.y,0); double cosangle=dir3d.Normalize()*hitShapeDir.Normalize(); - + // the angle between the line and the hitting direction are over around 6 degrees (it is substantially parallel) // or if it is an sketch axis (that can not move to accommodate to the shape), then only if it is around 6 degrees with the normal (around 84 degrees) if (fabs(cosangle) < 0.995f || ((GeoId==Sketcher::GeoEnum::HAxis || GeoId==Sketcher::GeoEnum::VAxis) && fabs(cosangle) < 0.1)) suggestedConstraints.push_back(constr); - - + + return suggestedConstraints.size(); } if (constr.Type != Sketcher::None) suggestedConstraints.push_back(constr); } - + if (Dir.Length() < 1e-8 || type == AutoConstraint::CURVE) // Direction not set so return; return suggestedConstraints.size(); @@ -269,7 +269,7 @@ int DrawSketchHandler::seekAutoConstraint(std::vector &suggested } } else if ((*it)->getTypeId() == Part::GeomEllipse::getClassTypeId()) { - + const Part::GeomEllipse *ellipse = static_cast((*it)); Base::Vector3d center = ellipse->getCenter(); @@ -277,21 +277,21 @@ int DrawSketchHandler::seekAutoConstraint(std::vector &suggested double a = ellipse->getMajorRadius(); double b = ellipse->getMinorRadius(); Base::Vector3d majdir = ellipse->getMajorAxisDir(); - + double cf = sqrt(a*a - b*b); - + Base::Vector3d focus1P = center + cf * majdir; Base::Vector3d focus2P = center - cf * majdir; - + Base::Vector3d norm = Base::Vector3d(Dir.y,-Dir.x).Normalize(); - + double distancetoline = norm*(tmpPos - focus1P); // distance focus1 to line - + Base::Vector3d focus1PMirrored = focus1P + 2*distancetoline*norm; // mirror of focus1 with respect to the line - + double error = fabs((focus1PMirrored-focus2P).Length() - 2*a); - - if ( error< tangDeviation) { + + if ( error< tangDeviation) { tangId = i; tangDeviation = error; } @@ -332,20 +332,20 @@ int DrawSketchHandler::seekAutoConstraint(std::vector &suggested double a = aoe->getMajorRadius(); double b = aoe->getMinorRadius(); Base::Vector3d majdir = aoe->getMajorAxisDir(); - + double cf = sqrt(a*a - b*b); - + Base::Vector3d focus1P = center + cf * majdir; Base::Vector3d focus2P = center - cf * majdir; - + Base::Vector3d norm = Base::Vector3d(Dir.y,-Dir.x).Normalize(); - + double distancetoline = norm*(tmpPos - focus1P); // distance focus1 to line - + Base::Vector3d focus1PMirrored = focus1P + 2*distancetoline*norm; // mirror of focus1 with respect to the line - + double error = fabs((focus1PMirrored-focus2P).Length() - 2*a); - + if ( error< tangDeviation ) { tangId = i; tangDeviation = error; @@ -354,12 +354,12 @@ int DrawSketchHandler::seekAutoConstraint(std::vector &suggested if (error < tangDeviation) { double startAngle, endAngle; aoe->getRange(startAngle, endAngle, /*emulateCCW=*/true); - + double angle = Base::fmod( atan2(-aoe->getMajorRadius()*((tmpPos.x-center.x)*majdir.y-(tmpPos.y-center.y)*majdir.x), aoe->getMinorRadius()*((tmpPos.x-center.x)*majdir.x+(tmpPos.y-center.y)*majdir.y) - )- startAngle, 2.f*M_PI); - + )- startAngle, 2.f*M_PI); + while(angle < startAngle) angle += 2*D_PI; // Bring it to range of arc @@ -392,12 +392,12 @@ void DrawSketchHandler::createAutoConstraints(const std::vector return; // If Autoconstraints property is not set quit if (autoConstrs.size() > 0) { - + if(createowncommand) { // Open the Command Gui::Command::openCommand("Add auto constraints"); } - + // Iterate through constraints std::vector::const_iterator it = autoConstrs.begin(); for (; it != autoConstrs.end(); ++it) { @@ -444,55 +444,58 @@ void DrawSketchHandler::createAutoConstraints(const std::vector } break; case Sketcher::Tangent: { Sketcher::SketchObject* Obj = static_cast(sketchgui->getObject()); - + const Part::Geometry *geom1 = Obj->getGeometry(geoId1); const Part::Geometry *geom2 = Obj->getGeometry(it->GeoId); - + int geoId2 = it->GeoId; - + // ellipse tangency support using construction elements (lines) - if( geom1 && geom2 && + if( geom1 && geom2 && ( geom1->getTypeId() == Part::GeomEllipse::getClassTypeId() || geom2->getTypeId() == Part::GeomEllipse::getClassTypeId() )){ - + if(geom1->getTypeId() != Part::GeomEllipse::getClassTypeId()) std::swap(geoId1,geoId2); - + // geoId1 is the ellipse geom1 = Obj->getGeometry(geoId1); - geom2 = Obj->getGeometry(geoId2); - + geom2 = Obj->getGeometry(geoId2); + if( geom2->getTypeId() == Part::GeomEllipse::getClassTypeId() || geom2->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId() || geom2->getTypeId() == Part::GeomCircle::getClassTypeId() || geom2->getTypeId() == Part::GeomArcOfCircle::getClassTypeId() ) { // in all these cases an intermediate element is needed - makeTangentToEllipseviaNewPoint(Obj,geom1,geom2,geoId1,geoId2); + makeTangentToEllipseviaNewPoint(Obj, + static_cast(geom1), + geom2, geoId1, geoId2); return; } } - + // arc of ellipse tangency support using external elements - if( geom1 && geom2 && + if( geom1 && geom2 && ( geom1->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId() || geom2->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId() )){ - + if(geom1->getTypeId() != Part::GeomArcOfEllipse::getClassTypeId()) std::swap(geoId1,geoId2); - + // geoId1 is the arc of ellipse geom1 = Obj->getGeometry(geoId1); - geom2 = Obj->getGeometry(geoId2); - + geom2 = Obj->getGeometry(geoId2); + if( geom2->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId() || geom2->getTypeId() == Part::GeomCircle::getClassTypeId() || geom2->getTypeId() == Part::GeomArcOfCircle::getClassTypeId() ) { // in all these cases an intermediate element is needed - makeTangentToArcOfEllipseviaNewPoint(Obj,geom1,geom2,geoId1,geoId2); + makeTangentToArcOfEllipseviaNewPoint(Obj, + static_cast(geom1), geom2, geoId1, geoId2); return; } } - + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('Tangent',%i, %i)) " ,sketchgui->getObject()->getNameInDocument() ,geoId1, it->GeoId