diff --git a/src/Mod/Sketcher/Gui/CommandConstraints.cpp b/src/Mod/Sketcher/Gui/CommandConstraints.cpp index 398136d0a..af4ca716b 100644 --- a/src/Mod/Sketcher/Gui/CommandConstraints.cpp +++ b/src/Mod/Sketcher/Gui/CommandConstraints.cpp @@ -552,6 +552,102 @@ void SketcherGui::makeTangentToArcOfHyperbolaviaNewPoint(const Sketcher::SketchO Gui::Command::updateActive(); } +/// Makes a simple tangency constraint using extra point + tangent via point +/// geom1 => an arc of parabola +/// geom2 => any of an arc of parabola, 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 +void SketcherGui::makeTangentToArcOfParabolaviaNewPoint(const Sketcher::SketchObject* Obj, + const Part::Geometry *geom1, + 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; + + if( geom2->getTypeId() == Part::GeomArcOfParabola::getClassTypeId()) + center2= (static_cast(geom2))->getFocus(); + else if( geom2->getTypeId() == Part::GeomArcOfHyperbola::getClassTypeId()){ + const Part::GeomArcOfHyperbola *aoh2 = static_cast(geom2); + Base::Vector3d dirmaj2 = aoh2->getMajorAxisDir(); + double majord2 = aoh2->getMajorRadius(); + double minord2 = aoh2->getMinorRadius(); + double df2 = sqrt(majord2*majord2+minord2*minord2); + center2 = aoh2->getCenter()+df2*dirmaj2; // positive focus + } + else if( geom2->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId()) + center2= (static_cast(geom2))->getCenter(); + else if( geom2->getTypeId() == Part::GeomEllipse::getClassTypeId()) + center2= (static_cast(geom2))->getCenter(); + else if( geom2->getTypeId() == Part::GeomCircle::getClassTypeId()) + center2= (static_cast(geom2))->getCenter(); + else if( geom2->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) + center2= (static_cast(geom2))->getCenter(); + else if( geom2->getTypeId() == Part::GeomLineSegment::getClassTypeId()) { + const Part::GeomLineSegment *l2 = static_cast(geom2); + center2= (l2->getStartPoint() + l2->getEndPoint())/2; + } + + 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)))", + Obj->getNameInDocument(), PoP.x,PoP.y); + int GeoIdPoint = Obj->getHighestCurveIndex(); + + // Point on first object + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('PointOnObject',%d,%d,%d)) ", + Obj->getNameInDocument(),GeoIdPoint,Sketcher::start,geoId1); // constrain major axis + // Point on second object + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('PointOnObject',%d,%d,%d)) ", + Obj->getNameInDocument(),GeoIdPoint,Sketcher::start,geoId2); // constrain major axis + // tangent via point + Gui::Command::doCommand( + Gui::Command::Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('TangentViaPoint',%d,%d,%d,%d))", + Obj->getNameInDocument(), geoId1, geoId2 ,GeoIdPoint, Sketcher::start); + } + catch (const Base::Exception& e) { + Base::Console().Error("%s\n", e.what()); + Gui::Command::abortCommand(); + + ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/Sketcher"); + bool autoRecompute = hGrp->GetBool("AutoRecompute",false); + + if(autoRecompute) // toggling does not modify the DoF of the solver, however it may affect features depending on the sketch + Gui::Command::updateActive(); + + return; + } + + Gui::Command::commitCommand(); + + ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/Sketcher"); + bool autoRecompute = hGrp->GetBool("AutoRecompute",false); + + if(autoRecompute) + Gui::Command::updateActive(); +} + namespace SketcherGui { @@ -2266,6 +2362,12 @@ void CmdSketcherConstrainTangent::activated(int iMsg) getSelection().clearSelection(); return; } + else if( geom2->getTypeId() == Part::GeomArcOfParabola::getClassTypeId() ) { + Gui::Command::openCommand("add tangent constraint point"); + makeTangentToArcOfParabolaviaNewPoint(Obj,geom2,geom1,GeoId2,GeoId1); + getSelection().clearSelection(); + return; + } } else if( geom1 && geom2 && ( geom1->getTypeId() == Part::GeomArcOfHyperbola::getClassTypeId() || @@ -2289,8 +2391,38 @@ void CmdSketcherConstrainTangent::activated(int iMsg) getSelection().clearSelection(); return; } + else if( geom2->getTypeId() == Part::GeomArcOfParabola::getClassTypeId() ) { + Gui::Command::openCommand("add tangent constraint point"); + makeTangentToArcOfParabolaviaNewPoint(Obj,geom2,geom1,GeoId2,GeoId1); + getSelection().clearSelection(); + return; + } } + else if( geom1 && geom2 && + ( geom1->getTypeId() == Part::GeomArcOfParabola::getClassTypeId() || + geom2->getTypeId() == Part::GeomArcOfParabola::getClassTypeId() )){ + + if(geom1->getTypeId() != Part::GeomArcOfParabola::getClassTypeId()) + std::swap(GeoId1,GeoId2); + + // GeoId1 is the arc of hyperbola + geom1 = Obj->getGeometry(GeoId1); + geom2 = Obj->getGeometry(GeoId2); + + if( geom2->getTypeId() == Part::GeomArcOfParabola::getClassTypeId() || + geom2->getTypeId() == Part::GeomArcOfHyperbola::getClassTypeId() || + geom2->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId() || + geom2->getTypeId() == Part::GeomCircle::getClassTypeId() || + geom2->getTypeId() == Part::GeomArcOfCircle::getClassTypeId() || + geom2->getTypeId() == Part::GeomLineSegment::getClassTypeId() ) { + + Gui::Command::openCommand("add tangent constraint point"); + makeTangentToArcOfParabolaviaNewPoint(Obj,geom1,geom2,GeoId1,GeoId2); + getSelection().clearSelection(); + return; + } + } openCommand("add tangent constraint"); Gui::Command::doCommand( diff --git a/src/Mod/Sketcher/Gui/CommandConstraints.h b/src/Mod/Sketcher/Gui/CommandConstraints.h index 3fe2f11f0..2b25ac95f 100644 --- a/src/Mod/Sketcher/Gui/CommandConstraints.h +++ b/src/Mod/Sketcher/Gui/CommandConstraints.h @@ -66,6 +66,18 @@ void makeTangentToArcOfHyperbolaviaNewPoint(const Sketcher::SketchObject* Obj, int geoId2 ); +/// Makes a simple tangency constraint using extra point + tangent via point +/// geom1 => an arc of parabola +/// geom2 => any of an arc of parabola, 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 +void makeTangentToArcOfParabolaviaNewPoint(const Sketcher::SketchObject* Obj, + const Part::Geometry *geom1, + const Part::Geometry *geom2, + int geoId1, + int geoId2 +); } #endif // SKETCHERGUI_DrawSketchHandler_H