diff --git a/src/Mod/Sketcher/App/ConstraintPyImp.cpp b/src/Mod/Sketcher/App/ConstraintPyImp.cpp index 457aee001e..dd33c0a5ca 100644 --- a/src/Mod/Sketcher/App/ConstraintPyImp.cpp +++ b/src/Mod/Sketcher/App/ConstraintPyImp.cpp @@ -224,14 +224,6 @@ int ConstraintPy::PyInit(PyObject* args, PyObject* /*kwd*/) if (PyNumber_Check(index_or_value)) { // can be float or int SecondIndex = any_index; Value = PyFloat_AsDouble(index_or_value); - //if (strcmp("Distance",ConstraintType) == 0) { - // this->getConstraintPtr()->Type = Distance; - // this->getConstraintPtr()->First = FirstIndex; - // this->getConstraintPtr()->Second = SecondIndex; - // this->getConstraintPtr()->Value = Value; - // return 0; - //} - //else if (strcmp("Angle",ConstraintType) == 0) { if (PyObject_TypeCheck(index_or_value, &(Base::QuantityPy::Type))) { Base::Quantity q = *(static_cast(index_or_value)->getQuantityPtr()); @@ -244,6 +236,13 @@ int ConstraintPy::PyInit(PyObject* args, PyObject* /*kwd*/) this->getConstraintPtr()->setValue(Value); return 0; } + else if (strcmp("Distance",ConstraintType) == 0) { + this->getConstraintPtr()->Type = Distance; + this->getConstraintPtr()->First = FirstIndex; + this->getConstraintPtr()->Second = SecondIndex; + this->getConstraintPtr()->setValue(Value); + return 0; + } else if (strcmp("DistanceX",ConstraintType) == 0) { FirstPos = SecondIndex; SecondIndex = -1; @@ -481,7 +480,7 @@ std::string ConstraintPy::representation() const case Coincident : result << "'Coincident'>";break; case Horizontal : result << "'Horizontal' (" << getConstraintPtr()->First << ")>";break; case Vertical : result << "'Vertical' (" << getConstraintPtr()->First << ")>";break; - case Block : result << "'Block' (" << getConstraintPtr()->First << ")>";break; + case Block : result << "'Block' (" << getConstraintPtr()->First << ")>";break; case Radius : result << "'Radius'>";break; case Diameter : result << "'Diameter'>";break; case Weight : result << "'Weight'>";break; diff --git a/src/Mod/Sketcher/App/PythonConverter.cpp b/src/Mod/Sketcher/App/PythonConverter.cpp index 53196e3bb9..e97d3c0203 100644 --- a/src/Mod/Sketcher/App/PythonConverter.cpp +++ b/src/Mod/Sketcher/App/PythonConverter.cpp @@ -296,6 +296,10 @@ std::string PythonConverter::process(const Sketcher::Constraint * constraint) return boost::str(boost::format("Sketcher.Constraint('Distance', %i, %f)") % constr->First % constr->getValue()); } + else if(constr->FirstPos == Sketcher::PointPos::none){ + return boost::str(boost::format("Sketcher.Constraint('Distance', %i, %i, %f)") % + constr->First % constr->Second % constr->getValue()); + } else if(constr->SecondPos == Sketcher::PointPos::none){ return boost::str(boost::format("Sketcher.Constraint('Distance', %i, %i, %i, %f)") % constr->First % static_cast(constr->FirstPos) % constr->Second % constr->getValue()); diff --git a/src/Mod/Sketcher/App/Sketch.cpp b/src/Mod/Sketcher/App/Sketch.cpp index fab57754e0..3a6b9e448b 100644 --- a/src/Mod/Sketcher/App/Sketch.cpp +++ b/src/Mod/Sketcher/App/Sketch.cpp @@ -1797,6 +1797,20 @@ int Sketch::addConstraint(const Constraint *constraint) constraint->Second,constraint->SecondPos, c.value,c.driving); } + else if (constraint->FirstPos == PointPos::none && + constraint->SecondPos == PointPos::none && + constraint->Second != GeoEnum::GeoUndef && + constraint->Third == GeoEnum::GeoUndef) { // circle to circle, circle to arc, etc. + + c.value = new double(constraint->getValue()); + if(c.driving) + FixParameters.push_back(c.value); + else { + Parameters.push_back(c.value); + DrivenParameters.push_back(c.value); + } + rtn = addDistanceConstraint(constraint->First, constraint->Second,c.value,c.driving); + } else if (constraint->Second != GeoEnum::GeoUndef) { if (constraint->FirstPos != PointPos::none) { // point to line distance c.value = new double(constraint->getValue()); @@ -1806,8 +1820,7 @@ int Sketch::addConstraint(const Constraint *constraint) Parameters.push_back(c.value); DrivenParameters.push_back(c.value); } - rtn = addDistanceConstraint(constraint->First,constraint->FirstPos, - constraint->Second,c.value,c.driving); + rtn = addDistanceConstraint(constraint->First,constraint->FirstPos,constraint->Second,c.value,c.driving); } } else {// line length @@ -2740,6 +2753,19 @@ int Sketch::addDistanceConstraint(int geoId1, PointPos pos1, int geoId2, PointPo return -1; } +// circle-circle offset distance constraint +int Sketch::addDistanceConstraint(int geoId1, int geoId2, double * value, bool driving) +{ + if ((Geoms[geoId1].type == Circle) && (Geoms[geoId2].type == Circle)) { + GCS::Circle &c1 = Circles[Geoms[geoId1].index]; + GCS::Circle &c2 = Circles[Geoms[geoId2].index]; + int tag = ++ConstraintsCounter; + GCSsys.addConstraintC2CDistance(c1, c2, value, tag, driving); + return ConstraintsCounter; + } + return -1; +} + int Sketch::addRadiusConstraint(int geoId, double * value, bool driving) { geoId = checkGeoId(geoId); diff --git a/src/Mod/Sketcher/App/Sketch.h b/src/Mod/Sketcher/App/Sketch.h index 6987e55dd2..69e6743c57 100644 --- a/src/Mod/Sketcher/App/Sketch.h +++ b/src/Mod/Sketcher/App/Sketch.h @@ -276,6 +276,15 @@ public: * Parameters array, as the case may be. */ int addDistanceConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2, double * value, bool driving = true); + /** + * add a length or distance constraint + * + * double * value is a pointer to double allocated in the heap, containing the + * constraint value and already inserted into either the FixParameters or + * Parameters array, as the case may be. + */ + int addDistanceConstraint(int geoId1, int geoId2, double * value, bool driving = true); + /// add a parallel constraint between two lines int addParallelConstraint(int geoId1, int geoId2); /// add a perpendicular constraint between two lines diff --git a/src/Mod/Sketcher/App/planegcs/Constraints.cpp b/src/Mod/Sketcher/App/planegcs/Constraints.cpp index 32c48e147f..c04e54ef01 100644 --- a/src/Mod/Sketcher/App/planegcs/Constraints.cpp +++ b/src/Mod/Sketcher/App/planegcs/Constraints.cpp @@ -2585,5 +2585,109 @@ double ConstraintEqualLineLength::grad(double *param) return deriv*scale; } +// ConstraintC2CDistance +ConstraintC2CDistance::ConstraintC2CDistance(Circle &c1, Circle &c2, double *d) +{ + this->d = d; + pvec.push_back(d); + + this->c1 = c1; + this->c1.PushOwnParams(pvec); + + this->c2 = c2; + this->c2.PushOwnParams(pvec); + + origpvec = pvec; + pvecChangedFlag = true; + rescale(); +} + +void ConstraintC2CDistance::ReconstructGeomPointers() +{ + int i=0; + i++; // skip the first parameter as there is the inline function distance for it + c1.ReconstructOnNewPvec(pvec, i); + c2.ReconstructOnNewPvec(pvec, i); + pvecChangedFlag = false; +} + +ConstraintType ConstraintC2CDistance::getTypeId() +{ + return C2CDistance; +} + +void ConstraintC2CDistance::rescale(double coef) +{ + scale = coef * 1; +} + +void ConstraintC2CDistance::errorgrad(double *err, double *grad, double *param) +{ + if (pvecChangedFlag) ReconstructGeomPointers(); + + DeriVector2 ct1 (c1.center, param); + DeriVector2 ct2 (c2.center, param); + + DeriVector2 vector_ct12 = ct1.subtr(ct2); + + double length_ct12, dlength_ct12; + length_ct12 = vector_ct12.length(dlength_ct12); + + // outer case (defined as the centers of the circles are outside the center of the other circles) + // it may well be that the circles intersect. + if( length_ct12 >= *c1.rad && + length_ct12 >= *c2.rad ) { + if (err) { + *err = length_ct12 - (*c2.rad + *c1.rad + *distance()); + } + else if (grad) { + double drad = (param == c2.rad || param == c1.rad || param == distance())?-1.0:0.0; + *grad = dlength_ct12 + drad; + } + } + else { + double * bigradius = (*c1.rad >= *c2.rad)?c1.rad:c2.rad; + double * smallradius = (*c1.rad >= *c2.rad)?c2.rad:c1.rad; + + double smallspan = *smallradius + length_ct12 + *distance(); + + if (err) { + *err = *bigradius - smallspan; + } + else if (grad) { + double drad = 0.0; + + if(param == bigradius) { + drad = 1.0; + } + else if(param == smallradius) { + drad = -1.0; + } + else if(param == distance()) { + drad = (*distance()<0.)?1.0:-1.0; + } + + *grad = -dlength_ct12 + drad; + } + } +} + +double ConstraintC2CDistance::error() +{ + double err; + errorgrad(&err,nullptr,nullptr); + return scale * err; +} + +double ConstraintC2CDistance::grad(double *param) +{ + if ( findParamInPvec(param) == -1 ) + return 0.0; + + double deriv; + errorgrad(nullptr, &deriv, param); + + return deriv*scale; +} } //namespace GCS diff --git a/src/Mod/Sketcher/App/planegcs/Constraints.h b/src/Mod/Sketcher/App/planegcs/Constraints.h index 0ff4b40349..957e021a0b 100644 --- a/src/Mod/Sketcher/App/planegcs/Constraints.h +++ b/src/Mod/Sketcher/App/planegcs/Constraints.h @@ -72,7 +72,8 @@ namespace GCS CenterOfGravity = 26, WeightedLinearCombination = 27, SlopeAtBSplineKnot = 28, - PointOnBSpline = 29 + PointOnBSpline = 29, + C2CDistance = 30 }; enum InternalAlignmentType { @@ -745,6 +746,22 @@ namespace GCS double grad(double *) override; }; + class ConstraintC2CDistance : public Constraint + { + private: + Circle c1; + Circle c2; + double *d; + inline double* distance() { return pvec[0]; } + void ReconstructGeomPointers(); //writes pointers in pvec to the parameters of c1, c2 + void errorgrad(double* err, double* grad, double *param); //error and gradient combined. Values are returned through pointers. + public: + ConstraintC2CDistance(Circle &c1, Circle &c2, double *d); + ConstraintType getTypeId() override; + void rescale(double coef=1.) override; + double error() override; + double grad(double *) override; + }; } //namespace GCS diff --git a/src/Mod/Sketcher/App/planegcs/GCS.cpp b/src/Mod/Sketcher/App/planegcs/GCS.cpp index f80d5e03bc..0ee8e39366 100644 --- a/src/Mod/Sketcher/App/planegcs/GCS.cpp +++ b/src/Mod/Sketcher/App/planegcs/GCS.cpp @@ -817,6 +817,14 @@ int System::addConstraintTangentAtBSplineKnot(BSpline &b, Line &l, unsigned int return addConstraint(constr); } +int System::addConstraintC2CDistance(Circle &c1, Circle &c2, double *dist, int tagId, bool driving) +{ + Constraint *constr = new ConstraintC2CDistance(c1, c2, dist); + constr->setTag(tagId); + constr->setDriving(driving); + return addConstraint(constr); +} + // derived constraints int System::addConstraintP2PCoincident(Point &p1, Point &p2, int tagId, bool driving) diff --git a/src/Mod/Sketcher/App/planegcs/GCS.h b/src/Mod/Sketcher/App/planegcs/GCS.h index 29e9162f18..fe11547151 100644 --- a/src/Mod/Sketcher/App/planegcs/GCS.h +++ b/src/Mod/Sketcher/App/planegcs/GCS.h @@ -315,6 +315,8 @@ namespace GCS bool flipn1, bool flipn2, int tagId, bool driving = true); + int addConstraintC2CDistance(Circle &c1, Circle &c2, double *dist, int tagId, bool driving = true); + // internal alignment constraints int addConstraintInternalAlignmentPoint2Ellipse(Ellipse &e, Point &p1, InternalAlignmentType alignmentType, int tagId=0, bool driving = true); int addConstraintInternalAlignmentEllipseMajorDiameter(Ellipse &e, Point &p1, Point &p2, int tagId=0, bool driving = true); diff --git a/src/Mod/Sketcher/Gui/CommandConstraints.cpp b/src/Mod/Sketcher/Gui/CommandConstraints.cpp index a1dd198a80..7f878661f8 100644 --- a/src/Mod/Sketcher/Gui/CommandConstraints.cpp +++ b/src/Mod/Sketcher/Gui/CommandConstraints.cpp @@ -2150,7 +2150,7 @@ CmdSketcherConstrainDistance::CmdSketcherConstrainDistance() sAppModule = "Sketcher"; sGroup = "Sketcher"; sMenuText = QT_TR_NOOP("Constrain distance"); - sToolTipText = QT_TR_NOOP("Fix a length of a line or the distance between a line and a vertex"); + sToolTipText = QT_TR_NOOP("Fix a length of a line or the distance between a line and a vertex or between two circles"); sWhatsThis = "Sketcher_ConstrainDistance"; sStatusTip = sToolTipText; sPixmap = "Constraint_Length"; @@ -2160,7 +2160,8 @@ CmdSketcherConstrainDistance::CmdSketcherConstrainDistance() allowedSelSequences = {{SelVertex, SelVertexOrRoot}, {SelRoot, SelVertex}, {SelEdge}, {SelExternalEdge}, {SelVertex, SelEdgeOrAxis}, {SelRoot, SelEdge}, - {SelVertex, SelExternalEdge}, {SelRoot, SelExternalEdge}}; + {SelVertex, SelExternalEdge}, {SelRoot, SelExternalEdge}, + {SelEdge, SelEdge}}; } void CmdSketcherConstrainDistance::activated(int iMsg) @@ -2289,6 +2290,55 @@ void CmdSketcherConstrainDistance::activated(int iMsg) return; } } + else if (isEdge(GeoId1,PosId1) && isEdge(GeoId2,PosId2)) { // circle to circle distance + const Part::Geometry *geom1 = Obj->getGeometry(GeoId1); + const Part::Geometry *geom2 = Obj->getGeometry(GeoId2); + if (geom1->getTypeId() == Part::GeomCircle::getClassTypeId() + && geom2->getTypeId() == Part::GeomCircle::getClassTypeId() ) { + auto circleSeg1 = static_cast(geom1); + double radius1 = circleSeg1->getRadius(); + Base::Vector3d center1 = circleSeg1->getCenter(); + + auto circleSeg2 = static_cast(geom2); + double radius2 = circleSeg2->getRadius(); + Base::Vector3d center2 = circleSeg2->getCenter(); + + double ActDist = 0.; + + Base::Vector3d intercenter = center1 - center2; + double intercenterdistance = intercenter.Length(); + + if( intercenterdistance >= radius1 && + intercenterdistance >= radius2 ) { + + ActDist = intercenterdistance - radius1 - radius2; + } + else { + double bigradius = std::max(radius1,radius2); + double smallradius = std::min(radius1,radius2); + + ActDist = bigradius - smallradius - intercenterdistance; + } + + openCommand(QT_TRANSLATE_NOOP("Command", "Add circle to circle distance constraint")); + Gui::cmdAppObjectArgs(selection[0].getObject(), + "addConstraint(Sketcher.Constraint('Distance',%d,%d,%f)) ", + GeoId1,GeoId2,ActDist); + + if (arebothpointsorsegmentsfixed || constraintCreationMode==Reference) { // it is a constraint on a external line, make it non-driving + const std::vector &ConStr = Obj->Constraints.getValues(); + + Gui::cmdAppObjectArgs(selection[0].getObject(), + "setDriving(%i,%s)", + ConStr.size()-1,"False"); + finishDatumConstraint (this, Obj, false); + } + else + finishDatumConstraint (this, Obj, true); + + return; + } + } else if (isEdge(GeoId1,PosId1)) { // line length if (GeoId1 < 0 && GeoId1 >= Sketcher::GeoEnum::VAxis) { Gui::TranslatedNotification(Obj, @@ -2327,7 +2377,7 @@ void CmdSketcherConstrainDistance::activated(int iMsg) Gui::TranslatedNotification(Obj, QObject::tr("Wrong selection"), - QObject::tr("Select exactly one line or one point and one line or two points from the sketch.")); + QObject::tr("Select exactly one line or one point and one line or two points or two circles from the sketch.")); return; } @@ -2416,6 +2466,9 @@ void CmdSketcherConstrainDistance::applyConstraint(std::vector &selSe else finishDatumConstraint (this, Obj, true); } + else if (geom->getTypeId() == Part::GeomCircle::getClassTypeId()) { + // allow this selection but do nothing as it needs 2 circles + } else { Gui::TranslatedNotification(Obj, QObject::tr("Wrong selection"), @@ -2460,6 +2513,61 @@ void CmdSketcherConstrainDistance::applyConstraint(std::vector &selSe return; } + case 8: // {SelEdge, SelEdge} + { + GeoId1 = selSeq.at(0).GeoId; GeoId2 = selSeq.at(1).GeoId; + const Part::Geometry *geom1 = Obj->getGeometry(GeoId1); + const Part::Geometry *geom2 = Obj->getGeometry(GeoId2); + if (geom1->getTypeId() == Part::GeomCircle::getClassTypeId() + && geom2->getTypeId() == Part::GeomCircle::getClassTypeId() ) { // circle to circle distance + auto circleSeg1 = static_cast(geom1); + double radius1 = circleSeg1->getRadius(); + Base::Vector3d center1 = circleSeg1->getCenter(); + + auto circleSeg2 = static_cast(geom2); + double radius2 = circleSeg2->getRadius(); + Base::Vector3d center2 = circleSeg2->getCenter(); + + double ActDist = 0.; + + Base::Vector3d intercenter = center1 - center2; + double intercenterdistance = intercenter.Length(); + + if( intercenterdistance >= radius1 && + intercenterdistance >= radius2 ) { + + ActDist = intercenterdistance - radius1 - radius2; + } + else { + double bigradius = std::max(radius1,radius2); + double smallradius = std::min(radius1,radius2); + + ActDist = bigradius - smallradius - intercenterdistance; + } + + openCommand(QT_TRANSLATE_NOOP("Command", "Add circle to circle distance constraint")); + Gui::cmdAppObjectArgs(Obj, + "addConstraint(Sketcher.Constraint('Distance',%d,%d,%f)) ", + GeoId1,GeoId2,ActDist); + + if (arebothpointsorsegmentsfixed || constraintCreationMode==Reference) { // it is a constraint on a external line, make it non-driving + const std::vector &ConStr = Obj->Constraints.getValues(); + + Gui::cmdAppObjectArgs(Obj, "setDriving(%i,%s)", + ConStr.size()-1,"False"); + finishDatumConstraint (this, Obj, false); + } + else + finishDatumConstraint (this, Obj, true); + + return; + } else { + Gui::TranslatedNotification(Obj, + QObject::tr("Wrong selection"), + QObject::tr("Select exactly one line or one point and one line or two points or two circles from the sketch.")); + + } + } default: break; } diff --git a/src/Mod/Sketcher/Gui/EditModeConstraintCoinManager.cpp b/src/Mod/Sketcher/Gui/EditModeConstraintCoinManager.cpp index c365b2cede..ffeb8283ee 100644 --- a/src/Mod/Sketcher/Gui/EditModeConstraintCoinManager.cpp +++ b/src/Mod/Sketcher/Gui/EditModeConstraintCoinManager.cpp @@ -62,6 +62,7 @@ #include "SoZoomTranslation.h" #include "ViewProviderSketch.h" #include "ViewProviderSketchCoinAttorney.h" +#include "Utils.h" using namespace SketcherGui; @@ -654,24 +655,33 @@ Restart: if (Constr->SecondPos != Sketcher::PointPos::none) { // point to point distance pnt1 = geolistfacade.getPoint(Constr->First, Constr->FirstPos); pnt2 = geolistfacade.getPoint(Constr->Second, Constr->SecondPos); - } else if (Constr->Second != GeoEnum::GeoUndef) { // point to line distance + } else if (Constr->Second != GeoEnum::GeoUndef) { pnt1 = geolistfacade.getPoint(Constr->First, Constr->FirstPos); const Part::Geometry *geo = geolistfacade.getGeometryFromGeoId(Constr->Second); - if (geo->getTypeId() == Part::GeomLineSegment::getClassTypeId()) { + if (geo->getTypeId() == Part::GeomLineSegment::getClassTypeId()) { // point to line distance const Part::GeomLineSegment *lineSeg = static_cast(geo); Base::Vector3d l2p1 = lineSeg->getStartPoint(); Base::Vector3d l2p2 = lineSeg->getEndPoint(); // calculate the projection of p1 onto line2 pnt2.ProjectToLine(pnt1-l2p1, l2p2-l2p1); pnt2 += pnt1; + + } else if (geo->getTypeId() == Part::GeomCircle::getClassTypeId()) { // circle to circle distance + const Part::Geometry *geo1 = geolistfacade.getGeometryFromGeoId(Constr->First); + if (geo1->getTypeId() == Part::GeomCircle::getClassTypeId()) { + const Part::GeomCircle *circleSeg1 = static_cast(geo1); + auto circleSeg2 = static_cast(geo); + GetCirclesMinimalDistance(circleSeg1, circleSeg2, pnt1, pnt2); + } + } else break; } else if (Constr->FirstPos != Sketcher::PointPos::none) { pnt2 = geolistfacade.getPoint(Constr->First, Constr->FirstPos); } else if (Constr->First != GeoEnum::GeoUndef) { const Part::Geometry *geo = geolistfacade.getGeometryFromGeoId(Constr->First); - if (geo->getTypeId() == Part::GeomLineSegment::getClassTypeId()) { + if (geo->getTypeId() == Part::GeomLineSegment::getClassTypeId()) { // segment distance const Part::GeomLineSegment *lineSeg = static_cast(geo); pnt1 = lineSeg->getStartPoint(); pnt2 = lineSeg->getEndPoint(); diff --git a/src/Mod/Sketcher/Gui/Utils.cpp b/src/Mod/Sketcher/Gui/Utils.cpp index d4d92316da..daf6c19b3f 100644 --- a/src/Mod/Sketcher/Gui/Utils.cpp +++ b/src/Mod/Sketcher/Gui/Utils.cpp @@ -327,6 +327,39 @@ double SketcherGui::GetPointAngle(const Base::Vector2d& p1, const Base::Vector2d return dY >= 0 ? atan2(dY, dX) : atan2(dY, dX) + 2 * M_PI; } +// Set the two points on circles at minimal distance +// in concentric case set points on relative X axis +void SketcherGui::GetCirclesMinimalDistance(const Part::GeomCircle *circle1, const Part::GeomCircle *circle2, Base::Vector3d &point1, Base::Vector3d &point2) +{ + double radius1 = circle1->getRadius(); + double radius2 = circle2->getRadius(); + + point1 = circle1->getCenter(); + point2 = circle2->getCenter(); + + Base::Vector3d v = point2 - point1; + double length = v.Length(); + + if (length == 0) { //concentric case + point1.x += radius1; + point2.x += radius2; + } else { + v = v.Normalize(); + if (length <= std::max(radius1, radius2)){ //inner case + if (radius1 > radius2){ + point1 += v * radius1; + point2 += v * radius2; + } else { + point1 += -v * radius1; + point2 += -v * radius2; + } + } else { //outer case + point1 += v * radius1; + point2 += -v * radius2; + } + } +} + void SketcherGui::ActivateHandler(Gui::Document* doc, DrawSketchHandler* handler) { std::unique_ptr ptr(handler); diff --git a/src/Mod/Sketcher/Gui/Utils.h b/src/Mod/Sketcher/Gui/Utils.h index 547246a6a2..662d9f941f 100644 --- a/src/Mod/Sketcher/Gui/Utils.h +++ b/src/Mod/Sketcher/Gui/Utils.h @@ -119,6 +119,9 @@ inline bool isEdge(int GeoId, Sketcher::PointPos PosId) // Return counter-clockwise angle from horizontal out of p1 to p2 in radians. double GetPointAngle (const Base::Vector2d &p1, const Base::Vector2d &p2); +// Set the two points on circles at minimal distance +void GetCirclesMinimalDistance(const Part::GeomCircle *circle1, const Part::GeomCircle *circle2, Base::Vector3d &point1, Base::Vector3d &point2); + void ActivateHandler(Gui::Document *doc, DrawSketchHandler *handler); /// Returns if a sketch is in edit mode diff --git a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp index 37fda52260..62d81b0f8c 100644 --- a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp +++ b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp @@ -1416,16 +1416,23 @@ void ViewProviderSketch::moveConstraint(int constNum, const Base::Vector2d &toPo if (Constr->SecondPos != Sketcher::PointPos::none) { // point to point distance p1 = getSolvedSketch().getPoint(Constr->First, Constr->FirstPos); p2 = getSolvedSketch().getPoint(Constr->Second, Constr->SecondPos); - } else if (Constr->Second != GeoEnum::GeoUndef) { // point to line distance + } else if (Constr->Second != GeoEnum::GeoUndef) { p1 = getSolvedSketch().getPoint(Constr->First, Constr->FirstPos); const Part::Geometry *geo = GeoList::getGeometryFromGeoId (geomlist, Constr->Second); - if (geo->getTypeId() == Part::GeomLineSegment::getClassTypeId()) { + if (geo->getTypeId() == Part::GeomLineSegment::getClassTypeId()) { // point to line distance const Part::GeomLineSegment *lineSeg = static_cast(geo); Base::Vector3d l2p1 = lineSeg->getStartPoint(); Base::Vector3d l2p2 = lineSeg->getEndPoint(); // calculate the projection of p1 onto line2 p2.ProjectToLine(p1-l2p1, l2p2-l2p1); p2 += p1; + } else if (geo->getTypeId() == Part::GeomCircle::getClassTypeId()) { // circle to circle distance + const Part::Geometry *geo1 = GeoList::getGeometryFromGeoId (geomlist, Constr->First); + if (geo1->getTypeId() == Part::GeomCircle::getClassTypeId()) { + const Part::GeomCircle *circleSeg1 = static_cast(geo1); + const Part::GeomCircle *circleSeg2 = static_cast(geo); + GetCirclesMinimalDistance(circleSeg1, circleSeg2, p1, p2); + } } else return; } else if (Constr->FirstPos != Sketcher::PointPos::none) {