diff --git a/src/Mod/Sketcher/App/Sketch.cpp b/src/Mod/Sketcher/App/Sketch.cpp index 64614c3d1a..a42bbdbcb4 100644 --- a/src/Mod/Sketcher/App/Sketch.cpp +++ b/src/Mod/Sketcher/App/Sketch.cpp @@ -3178,7 +3178,7 @@ int Sketch::addDistanceConstraint(int geoId, double* value, bool driving) return ConstraintsCounter; } -// point to line distance constraint +// point to line or circle distance constraint int Sketch::addDistanceConstraint(int geoId1, PointPos pos1, int geoId2, @@ -3245,23 +3245,44 @@ int Sketch::addDistanceConstraint(int geoId1, int geoId2, double* value, bool dr geoId1 = checkGeoId(geoId1); geoId2 = checkGeoId(geoId2); - if (Geoms[geoId1].type == Circle) { - if (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; + GCS::Circle *c1, *c2; + if (Geoms[geoId2].type == Line) { + if (Geoms[geoId1].type == Circle) { + c1 = &Circles[Geoms[geoId1].index]; } - else if (Geoms[geoId2].type == Line) { - GCS::Circle& c = Circles[Geoms[geoId1].index]; - GCS::Line& l = Lines[Geoms[geoId2].index]; - int tag = ++ConstraintsCounter; - GCSsys.addConstraintC2LDistance(c, l, value, tag, driving); - return ConstraintsCounter; + else if (Geoms[geoId1].type == Arc) { + c1 = &Arcs[Geoms[geoId1].index]; } + GCS::Line* l = &Lines[Geoms[geoId2].index]; + int tag = ++ConstraintsCounter; + GCSsys.addConstraintC2LDistance(*c1, *l, value, tag, driving); + return ConstraintsCounter; + } + else { + if ((Geoms[geoId1].type == Circle) && (Geoms[geoId2].type == Circle)) { + c1 = &Circles[Geoms[geoId1].index]; + c2 = &Circles[Geoms[geoId2].index]; + } + else if ((Geoms[geoId1].type == Arc) && (Geoms[geoId2].type == Circle)) { + c1 = &Arcs[Geoms[geoId1].index]; + c2 = &Circles[Geoms[geoId2].index]; + } + else if ((Geoms[geoId1].type == Circle) && (Geoms[geoId2].type == Arc)) { + c1 = &Circles[Geoms[geoId1].index]; + c2 = &Arcs[Geoms[geoId2].index]; + } + else if ((Geoms[geoId1].type == Arc) && (Geoms[geoId2].type == Arc)) { + c1 = &Arcs[Geoms[geoId1].index]; + c2 = &Arcs[Geoms[geoId2].index]; + } + else { + return -1; + } + + int tag = ++ConstraintsCounter; + GCSsys.addConstraintC2CDistance(*c1, *c2, value, tag, driving); + return ConstraintsCounter; } - return -1; } diff --git a/src/Mod/Sketcher/Gui/CommandConstraints.cpp b/src/Mod/Sketcher/Gui/CommandConstraints.cpp index 34759f62ae..f792900fd1 100644 --- a/src/Mod/Sketcher/Gui/CommandConstraints.cpp +++ b/src/Mod/Sketcher/Gui/CommandConstraints.cpp @@ -4363,54 +4363,33 @@ void CmdSketcherConstrainDistance::activated(int iMsg) else if (isEdge(GeoId1, PosId1) && isEdge(GeoId2, PosId2)) { const Part::Geometry* geom1 = Obj->getGeometry(GeoId1); const Part::Geometry* geom2 = Obj->getGeometry(GeoId2); - - if (isCircle(*geom1) && isCircle(*geom2)) {// circle to circle distance + double radius1 = 0.0, radius2 = 0.0; + Base::Vector3d center1, center2; + if (isArcOfCircle(*geom1)) { + auto arcSeg1 = static_cast(geom1); + radius1 = arcSeg1->getRadius(); + center1 = arcSeg1->getCenter(); + } + if (isArcOfCircle(*geom2))) { + auto arcSeg2 = static_cast(geom2); + radius2 = arcSeg2->getRadius(); + center2 = arcSeg2->getCenter(); + } + if (isCircle(*geom1)) { auto circleSeg1 = static_cast(geom1); - double radius1 = circleSeg1->getRadius(); - Base::Vector3d center1 = circleSeg1->getCenter(); - + radius1 = circleSeg1->getRadius(); + center1 = circleSeg1->getCenter(); + } + if (isCircle(*geom2)) { 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(%d,%s)", - ConStr.size() - 1, - "False"); - finishDatumConstraint(this, Obj, false); - } - else { - finishDatumConstraint(this, Obj, true); - } - + radius2 = circleSeg2->getRadius(); + center2 = circleSeg2->getCenter(); + } + if (radius1 == 0.0 || radius2 == 0.0) { + Gui::TranslatedNotification( + Obj, + QObject::tr("Wrong selection"), + QObject::tr("Cannot add a length constraint on this selection!")); return; } else if ((isCircle(*geom1) && isLineSegment(*geom2)) @@ -4458,6 +4437,45 @@ void CmdSketcherConstrainDistance::activated(int iMsg) return; } + double ActDist = 0.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(%d,%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) { diff --git a/src/Mod/Sketcher/Gui/EditModeConstraintCoinManager.cpp b/src/Mod/Sketcher/Gui/EditModeConstraintCoinManager.cpp index c8eb0a17d5..1e3de86ff3 100644 --- a/src/Mod/Sketcher/Gui/EditModeConstraintCoinManager.cpp +++ b/src/Mod/Sketcher/Gui/EditModeConstraintCoinManager.cpp @@ -704,8 +704,7 @@ Restart: } if (geo1->is() || geo1->is() - || geo1->getTypeId() - == Part::GeomArcOfHyperbola::getClassTypeId()) { + || geo1->is()) { Base::Vector3d majDir, minDir, rvec; majDir = Base::Vector3d(cos(angle1), @@ -837,43 +836,53 @@ Restart: else { const Part::Geometry* geo1 = geolistfacade.getGeometryFromGeoId(Constr->First); - if (geo1->is()) { // circle to line - // distance - const Part::GeomCircle* circleSeg = - static_cast(geo1); + if (geo1->is()) { // circle to line distance + auto lineSeg = static_cast(geo); + auto circleSeg = static_cast(geo1); Base::Vector3d ct = circleSeg->getCenter(); + Base::Vector3d l2p1 = lineSeg->getStartPoint(); + Base::Vector3d l2p2 = lineSeg->getEndPoint(); double radius = circleSeg->getRadius(); - pnt1.ProjectToLine( - ct - l2p1, - l2p2 - l2p1); // project on the line translated to origin - Base::Vector3d dir = pnt1; + // project on the line translated to origin + pnt2.ProjectToLine(ct - l2p1, l2p2 - l2p1); + Base::Vector3d dir = pnt2; dir.Normalize(); - pnt1 += ct; - pnt2 = ct + dir * radius; + pnt1 = ct + dir * radius; + pnt2 += ct; + Base::Vector3d d = l2p2 - l2p1; + double ActDist = std::abs(-ct.x * d.y + ct.y * d.x + + l2p1.x * l2p2.y - l2p2.x * l2p1.y) + / d.Length() + - radius; + if (ActDist < 0) { + std::swap(pnt1, pnt2); + } } } } - else if (geo->is()) { - const Part::Geometry* geo1 = - geolistfacade.getGeometryFromGeoId(Constr->First); - if (geo1->is()) { // circle to circle - // distance - const Part::GeomCircle* circleSeg1 = - static_cast(geo1); - auto circleSeg2 = static_cast(geo); - GetCirclesMinimalDistance(circleSeg1, circleSeg2, pnt1, pnt2); - } - else if (Constr->FirstPos - != Sketcher::PointPos::none) { // point to circle distance - auto circleSeg2 = static_cast(geo); - pnt1 = geolistfacade.getPoint(Constr->First, Constr->FirstPos); - Base::Vector3d v = pnt1 - circleSeg2->getCenter(); - v = v.Normalize(); - pnt2 = circleSeg2->getCenter() + circleSeg2->getRadius() * v; - } + else if (geo->is()) { // circle to circle distance + || geo->is()) + { + if (geo1->is() + || geo1->is()) { + GetCirclesMinimalDistance(geo1, geo, pnt1, pnt2); + } + else if (Constr->FirstPos + != Sketcher::PointPos::none) { // point to circle + // distance + auto circleSeg2 = + static_cast(geo); + pnt1 = geolistfacade.getPoint(Constr->First, + Constr->FirstPos); + Base::Vector3d v = pnt1 - circleSeg2->getCenter(); + v = v.Normalize(); + pnt2 = + circleSeg2->getCenter() + circleSeg2->getRadius() * v; + } + } } else { - break; + break; } } else if (Constr->FirstPos != Sketcher::PointPos::none) { @@ -883,13 +892,13 @@ Restart: const Part::Geometry* geo = geolistfacade.getGeometryFromGeoId(Constr->First); if (geo->is()) { // segment distance - const Part::GeomLineSegment* lineSeg = - static_cast(geo); - pnt1 = lineSeg->getStartPoint(); - pnt2 = lineSeg->getEndPoint(); + const Part::GeomLineSegment* lineSeg = + static_cast(geo); + pnt1 = lineSeg->getStartPoint(); + pnt2 = lineSeg->getEndPoint(); } else { - break; + break; } } else { @@ -947,22 +956,22 @@ Restart: int ptGeoId; Sketcher::PointPos ptPosId; do { // dummy loop to use break =) Maybe goto? - ptGeoId = Constr->First; - ptPosId = Constr->FirstPos; - if (ptPosId != Sketcher::PointPos::none) { - break; - } - ptGeoId = Constr->Second; - ptPosId = Constr->SecondPos; - if (ptPosId != Sketcher::PointPos::none) { - break; - } - ptGeoId = Constr->Third; - ptPosId = Constr->ThirdPos; - if (ptPosId != Sketcher::PointPos::none) { - break; - } - assert(0); // no point found! + ptGeoId = Constr->First; + ptPosId = Constr->FirstPos; + if (ptPosId != Sketcher::PointPos::none) { + break; + } + ptGeoId = Constr->Second; + ptPosId = Constr->SecondPos; + if (ptPosId != Sketcher::PointPos::none) { + break; + } + ptGeoId = Constr->Third; + ptPosId = Constr->ThirdPos; + if (ptPosId != Sketcher::PointPos::none) { + break; + } + assert(0); // no point found! } while (false); pos = geolistfacade.getPoint(ptGeoId, ptPosId); @@ -997,143 +1006,150 @@ Restart: if (geo1->is() && geo2->is()) { - const Part::GeomLineSegment* lineSeg1 = - static_cast(geo1); - const Part::GeomLineSegment* lineSeg2 = - static_cast(geo2); - // tangency between two lines - Base::Vector3d midpos1 = - ((lineSeg1->getEndPoint() + lineSeg1->getStartPoint()) / 2); - Base::Vector3d midpos2 = - ((lineSeg2->getEndPoint() + lineSeg2->getStartPoint()) / 2); - Base::Vector3d dir1 = - (lineSeg1->getEndPoint() - lineSeg1->getStartPoint()).Normalize(); - Base::Vector3d dir2 = - (lineSeg2->getEndPoint() - lineSeg2->getStartPoint()).Normalize(); - Base::Vector3d norm1 = Base::Vector3d(-dir1.y, dir1.x, 0.f); - Base::Vector3d norm2 = Base::Vector3d(-dir2.y, dir2.x, 0.f); + const Part::GeomLineSegment* lineSeg1 = + static_cast(geo1); + const Part::GeomLineSegment* lineSeg2 = + static_cast(geo2); + // tangency between two lines + Base::Vector3d midpos1 = + ((lineSeg1->getEndPoint() + lineSeg1->getStartPoint()) / 2); + Base::Vector3d midpos2 = + ((lineSeg2->getEndPoint() + lineSeg2->getStartPoint()) / 2); + Base::Vector3d dir1 = + (lineSeg1->getEndPoint() - lineSeg1->getStartPoint()) + .Normalize(); + Base::Vector3d dir2 = + (lineSeg2->getEndPoint() - lineSeg2->getStartPoint()) + .Normalize(); + Base::Vector3d norm1 = Base::Vector3d(-dir1.y, dir1.x, 0.f); + Base::Vector3d norm2 = Base::Vector3d(-dir2.y, dir2.x, 0.f); - Base::Vector3d relpos1 = seekConstraintPosition( - midpos1, - norm1, - dir1, - 4.0, - editModeScenegraphNodes.constrGroup->getChild(i)); - Base::Vector3d relpos2 = seekConstraintPosition( - midpos2, - norm2, - dir2, - 4.0, - editModeScenegraphNodes.constrGroup->getChild(i)); + Base::Vector3d relpos1 = seekConstraintPosition( + midpos1, + norm1, + dir1, + 4.0, + editModeScenegraphNodes.constrGroup->getChild(i)); + Base::Vector3d relpos2 = seekConstraintPosition( + midpos2, + norm2, + dir2, + 4.0, + editModeScenegraphNodes.constrGroup->getChild(i)); - auto translation = static_cast(sep->getChild( - static_cast(ConstraintNodePosition::FirstTranslationIndex))); + auto translation = + static_cast(sep->getChild(static_cast( + ConstraintNodePosition::FirstTranslationIndex))); - translation->abPos = - SbVec3f(midpos1.x, midpos1.y, zConstrH); // Absolute Reference - translation->translation = SbVec3f(relpos1.x, relpos1.y, 0); + translation->abPos = + SbVec3f(midpos1.x, midpos1.y, zConstrH); // Absolute Reference + translation->translation = SbVec3f(relpos1.x, relpos1.y, 0); - Base::Vector3d secondPos = midpos2 - midpos1; + Base::Vector3d secondPos = midpos2 - midpos1; - translation = static_cast(sep->getChild( - static_cast(ConstraintNodePosition::SecondTranslationIndex))); + translation = + static_cast(sep->getChild(static_cast( + ConstraintNodePosition::SecondTranslationIndex))); - translation->abPos = - SbVec3f(secondPos.x, secondPos.y, zConstrH); // Absolute Reference - translation->translation = - SbVec3f(relpos2.x - relpos1.x, relpos2.y - relpos1.y, 0); + translation->abPos = SbVec3f(secondPos.x, + secondPos.y, + zConstrH); // Absolute Reference + translation->translation = + SbVec3f(relpos2.x - relpos1.x, relpos2.y - relpos1.y, 0); - break; + break; } else if (geo2->is()) { - std::swap(geo1, geo2); + std::swap(geo1, geo2); } if (geo1->is()) { - const Part::GeomLineSegment* lineSeg = - static_cast(geo1); - Base::Vector3d dir = - (lineSeg->getEndPoint() - lineSeg->getStartPoint()).Normalize(); - Base::Vector3d norm(-dir.y, dir.x, 0); - if (geo2->is()) { - const Part::GeomCircle* circle = - static_cast(geo2); - // tangency between a line and a circle - float length = - (circle->getCenter() - lineSeg->getStartPoint()) * dir; + const Part::GeomLineSegment* lineSeg = + static_cast(geo1); + Base::Vector3d dir = + (lineSeg->getEndPoint() - lineSeg->getStartPoint()) + .Normalize(); + Base::Vector3d norm(-dir.y, dir.x, 0); + if (geo2->is()) { + const Part::GeomCircle* circle = + static_cast(geo2); + // tangency between a line and a circle + float length = + (circle->getCenter() - lineSeg->getStartPoint()) * dir; - pos = lineSeg->getStartPoint() + dir * length; - relPos = norm * 1; // TODO Huh? - } - else if (geo2->is() - || geo2->is()) { + pos = lineSeg->getStartPoint() + dir * length; + relPos = norm * 1; // TODO Huh? + } + else if (geo2->is() + || geo2->is()) { - Base::Vector3d center; - if (geo2->is()) { - const Part::GeomEllipse* ellipse = - static_cast(geo2); - center = ellipse->getCenter(); - } - else { - const Part::GeomArcOfEllipse* aoc = - static_cast(geo2); - center = aoc->getCenter(); - } + Base::Vector3d center; + if (geo2->is()) { + const Part::GeomEllipse* ellipse = + static_cast(geo2); + center = ellipse->getCenter(); + } + else { + const Part::GeomArcOfEllipse* aoc = + static_cast(geo2); + center = aoc->getCenter(); + } - // tangency between a line and an ellipse - float length = (center - lineSeg->getStartPoint()) * dir; + // tangency between a line and an ellipse + float length = (center - lineSeg->getStartPoint()) * dir; - pos = lineSeg->getStartPoint() + dir * length; - relPos = norm * 1; - } - else if (geo2->is()) { - const Part::GeomArcOfCircle* arc = - static_cast(geo2); - // tangency between a line and an arc - float length = (arc->getCenter() - lineSeg->getStartPoint()) * dir; + pos = lineSeg->getStartPoint() + dir * length; + relPos = norm * 1; + } + else if (geo2->is()) { + const Part::GeomArcOfCircle* arc = + static_cast(geo2); + // tangency between a line and an arc + float length = + (arc->getCenter() - lineSeg->getStartPoint()) * dir; - pos = lineSeg->getStartPoint() + dir * length; - relPos = norm * 1; // TODO Huh? - } + pos = lineSeg->getStartPoint() + dir * length; + relPos = norm * 1; // TODO Huh? + } } if (geo1->is() && geo2->is()) { - const Part::GeomCircle* circle1 = - static_cast(geo1); - const Part::GeomCircle* circle2 = - static_cast(geo2); - // tangency between two circles - Base::Vector3d dir = - (circle2->getCenter() - circle1->getCenter()).Normalize(); - pos = circle1->getCenter() + dir * circle1->getRadius(); - relPos = dir * 1; + const Part::GeomCircle* circle1 = + static_cast(geo1); + const Part::GeomCircle* circle2 = + static_cast(geo2); + // tangency between two circles + Base::Vector3d dir = + (circle2->getCenter() - circle1->getCenter()).Normalize(); + pos = circle1->getCenter() + dir * circle1->getRadius(); + relPos = dir * 1; } else if (geo2->is()) { - std::swap(geo1, geo2); + std::swap(geo1, geo2); } if (geo1->is() && geo2->is()) { - const Part::GeomCircle* circle = - static_cast(geo1); - const Part::GeomArcOfCircle* arc = - static_cast(geo2); - // tangency between a circle and an arc - Base::Vector3d dir = - (arc->getCenter() - circle->getCenter()).Normalize(); - pos = circle->getCenter() + dir * circle->getRadius(); - relPos = dir * 1; + const Part::GeomCircle* circle = + static_cast(geo1); + const Part::GeomArcOfCircle* arc = + static_cast(geo2); + // tangency between a circle and an arc + Base::Vector3d dir = + (arc->getCenter() - circle->getCenter()).Normalize(); + pos = circle->getCenter() + dir * circle->getRadius(); + relPos = dir * 1; } else if (geo1->is() && geo2->is()) { - const Part::GeomArcOfCircle* arc1 = - static_cast(geo1); - const Part::GeomArcOfCircle* arc2 = - static_cast(geo2); - // tangency between two arcs - Base::Vector3d dir = - (arc2->getCenter() - arc1->getCenter()).Normalize(); - pos = arc1->getCenter() + dir * arc1->getRadius(); - relPos = dir * 1; + const Part::GeomArcOfCircle* arc1 = + static_cast(geo1); + const Part::GeomArcOfCircle* arc2 = + static_cast(geo2); + // tangency between two arcs + Base::Vector3d dir = + (arc2->getCenter() - arc1->getCenter()).Normalize(); + pos = arc1->getCenter() + dir * arc1->getRadius(); + relPos = dir * 1; } auto translation = static_cast(sep->getChild( static_cast(ConstraintNodePosition::FirstTranslationIndex))); @@ -1185,124 +1201,127 @@ Restart: if (Constr->Second != GeoEnum::GeoUndef) { Base::Vector3d dir1, dir2; if (Constr->Third == GeoEnum::GeoUndef) { // angle between two lines - const Part::Geometry* geo1 = - geolistfacade.getGeometryFromGeoId(Constr->First); - const Part::Geometry* geo2 = - geolistfacade.getGeometryFromGeoId(Constr->Second); - if (!isLineSegment(*geo1) || !isLineSegment(*geo2)) { - break; - } - auto* line1 = static_cast(geo1); - auto* line2 = static_cast(geo2); + const Part::Geometry* geo1 = + geolistfacade.getGeometryFromGeoId(Constr->First); + const Part::Geometry* geo2 = + geolistfacade.getGeometryFromGeoId(Constr->Second); + if (!isLineSegment(*geo1) || !isLineSegment(*geo2)) { + break; + } + auto* line1 = static_cast(geo1); + auto* line2 = static_cast(geo2); - bool flip1 = (Constr->FirstPos == PointPos::end); - bool flip2 = (Constr->SecondPos == PointPos::end); - dir1 = (flip1 ? -1. : 1.) - * (line1->getEndPoint() - line1->getStartPoint()).Normalize(); - dir2 = (flip2 ? -1. : 1.) - * (line2->getEndPoint() - line2->getStartPoint()).Normalize(); - Base::Vector3d pnt1 = - flip1 ? line1->getEndPoint() : line1->getStartPoint(); - Base::Vector3d pnt2 = - flip2 ? line2->getEndPoint() : line2->getStartPoint(); - Base::Vector3d pnt12 = - flip1 ? line1->getStartPoint() : line1->getEndPoint(); - Base::Vector3d pnt22 = - flip2 ? line2->getStartPoint() : line2->getEndPoint(); + bool flip1 = (Constr->FirstPos == PointPos::end); + bool flip2 = (Constr->SecondPos == PointPos::end); + dir1 = (flip1 ? -1. : 1.) + * (line1->getEndPoint() - line1->getStartPoint()).Normalize(); + dir2 = (flip2 ? -1. : 1.) + * (line2->getEndPoint() - line2->getStartPoint()).Normalize(); + Base::Vector3d pnt1 = + flip1 ? line1->getEndPoint() : line1->getStartPoint(); + Base::Vector3d pnt2 = + flip2 ? line2->getEndPoint() : line2->getStartPoint(); + Base::Vector3d pnt12 = + flip1 ? line1->getStartPoint() : line1->getEndPoint(); + Base::Vector3d pnt22 = + flip2 ? line2->getStartPoint() : line2->getEndPoint(); - // line-line intersection - Base::Vector3d intersection; - { - double det = dir1.x * dir2.y - dir1.y * dir2.x; - if ((det > 0 ? det : -det) < 1e-10) { - // lines are coincident (or parallel) and in this case the - // center of the point pairs with the shortest distance is used - Base::Vector3d p1[2], p2[2]; - p1[0] = line1->getStartPoint(); - p1[1] = line1->getEndPoint(); - p2[0] = line2->getStartPoint(); - p2[1] = line2->getEndPoint(); - double length = DBL_MAX; - for (int i = 0; i <= 1; i++) { - for (int j = 0; j <= 1; j++) { - double tmp = (p2[j] - p1[i]).Length(); - if (tmp < length) { - length = tmp; - double x = (p2[j].x + p1[i].x) / 2; - double y = (p2[j].y + p1[i].y) / 2; - intersection = Base::Vector3d(x, y, 0.); - } - } - } - } - else { - double c1 = dir1.y * pnt1.x - dir1.x * pnt1.y; - double c2 = dir2.y * pnt2.x - dir2.x * pnt2.y; - double x = (dir1.x * c2 - dir2.x * c1) / det; - double y = (dir1.y * c2 - dir2.y * c1) / det; - intersection = Base::Vector3d(x, y, 0.); - } - } - p0.setValue(intersection.x, intersection.y, 0.); + // line-line intersection + Base::Vector3d intersection; + { + double det = dir1.x * dir2.y - dir1.y * dir2.x; + if ((det > 0 ? det : -det) < 1e-10) { + // lines are coincident (or parallel) and in this case the + // center of the point pairs with the shortest distance is + // used + Base::Vector3d p1[2], p2[2]; + p1[0] = line1->getStartPoint(); + p1[1] = line1->getEndPoint(); + p2[0] = line2->getStartPoint(); + p2[1] = line2->getEndPoint(); + double length = DBL_MAX; + for (int i = 0; i <= 1; i++) { + for (int j = 0; j <= 1; j++) { + double tmp = (p2[j] - p1[i]).Length(); + if (tmp < length) { + length = tmp; + double x = (p2[j].x + p1[i].x) / 2; + double y = (p2[j].y + p1[i].y) / 2; + intersection = Base::Vector3d(x, y, 0.); + } + } + } + } + else { + double c1 = dir1.y * pnt1.x - dir1.x * pnt1.y; + double c2 = dir2.y * pnt2.x - dir2.x * pnt2.y; + double x = (dir1.x * c2 - dir2.x * c1) / det; + double y = (dir1.y * c2 - dir2.y * c1) / det; + intersection = Base::Vector3d(x, y, 0.); + } + } + p0.setValue(intersection.x, intersection.y, 0.); - range = Constr->getValue(); // WYSIWYG - startangle = atan2(dir1.y, dir1.x); - Base::Vector3d vl1 = dir1 * 2 * distance - (pnt1 - intersection); - Base::Vector3d vl2 = dir2 * 2 * distance - (pnt2 - intersection); - Base::Vector3d vl12 = dir1 * 2 * distance - (pnt12 - intersection); - Base::Vector3d vl22 = dir2 * 2 * distance - (pnt22 - intersection); + range = Constr->getValue(); // WYSIWYG + startangle = atan2(dir1.y, dir1.x); + Base::Vector3d vl1 = dir1 * 2 * distance - (pnt1 - intersection); + Base::Vector3d vl2 = dir2 * 2 * distance - (pnt2 - intersection); + Base::Vector3d vl12 = dir1 * 2 * distance - (pnt12 - intersection); + Base::Vector3d vl22 = dir2 * 2 * distance - (pnt22 - intersection); - endLineLength1 = vl12.Dot(dir1) > 0 ? vl12.Length() - : vl1.Dot(dir1) < 0 ? -vl1.Length() - : 0.0; - endLineLength2 = vl22.Dot(dir2) > 0 ? vl22.Length() - : vl2.Dot(dir2) < 0 ? -vl2.Length() - : 0.0; + endLineLength1 = vl12.Dot(dir1) > 0 ? vl12.Length() + : vl1.Dot(dir1) < 0 ? -vl1.Length() + : 0.0; + endLineLength2 = vl22.Dot(dir2) > 0 ? vl22.Length() + : vl2.Dot(dir2) < 0 ? -vl2.Length() + : 0.0; } else { // angle-via-point - Base::Vector3d p = - geolistfacade.getPoint(Constr->Third, Constr->ThirdPos); - p0 = SbVec3f(p.x, p.y, 0); - dir1 = getNormal(geolistfacade, Constr->First, p); - // TODO: Check - // dir1 = getSolvedSketch().calculateNormalAtPoint(Constr->First, p.x, - // p.y); - dir1.RotateZ(-M_PI / 2); // convert to vector of tangency by rotating - dir2 = getNormal(geolistfacade, Constr->Second, p); - // TODO: Check - // dir2 = getSolvedSketch().calculateNormalAtPoint(Constr->Second, p.x, - // p.y); - dir2.RotateZ(-M_PI / 2); + Base::Vector3d p = + geolistfacade.getPoint(Constr->Third, Constr->ThirdPos); + p0 = SbVec3f(p.x, p.y, 0); + dir1 = getNormal(geolistfacade, Constr->First, p); + // TODO: Check + // dir1 = getSolvedSketch().calculateNormalAtPoint(Constr->First, + // p.x, p.y); + dir1.RotateZ(-M_PI + / 2); // convert to vector of tangency by rotating + dir2 = getNormal(geolistfacade, Constr->Second, p); + // TODO: Check + // dir2 = getSolvedSketch().calculateNormalAtPoint(Constr->Second, + // p.x, p.y); + dir2.RotateZ(-M_PI / 2); - startangle = atan2(dir1.y, dir1.x); - range = atan2(dir1.x * dir2.y - dir1.y * dir2.x, - dir1.x * dir2.x + dir1.y * dir2.y); + startangle = atan2(dir1.y, dir1.x); + range = atan2(dir1.x * dir2.y - dir1.y * dir2.x, + dir1.x * dir2.x + dir1.y * dir2.y); } } else if (Constr->First != GeoEnum::GeoUndef) { const Part::Geometry* geo = geolistfacade.getGeometryFromGeoId(Constr->First); if (geo->is()) { - const Part::GeomLineSegment* lineSeg = - static_cast(geo); - p0 = Base::convertTo( - (lineSeg->getEndPoint() + lineSeg->getStartPoint()) / 2); + const Part::GeomLineSegment* lineSeg = + static_cast(geo); + p0 = Base::convertTo( + (lineSeg->getEndPoint() + lineSeg->getStartPoint()) / 2); - Base::Vector3d dir = lineSeg->getEndPoint() - lineSeg->getStartPoint(); - startangle = 0.; - range = atan2(dir.y, dir.x); + Base::Vector3d dir = + lineSeg->getEndPoint() - lineSeg->getStartPoint(); + startangle = 0.; + range = atan2(dir.y, dir.x); } else if (geo->is()) { - const Part::GeomArcOfCircle* arc = - static_cast(geo); - p0 = Base::convertTo(arc->getCenter()); + const Part::GeomArcOfCircle* arc = + static_cast(geo); + p0 = Base::convertTo(arc->getCenter()); - double endangle; - arc->getRange(startangle, endangle, /*emulateCCWXY=*/true); - range = endangle - startangle; + double endangle; + arc->getRange(startangle, endangle, /*emulateCCWXY=*/true); + range = endangle - startangle; } else { - break; + break; } } else { @@ -1340,45 +1359,49 @@ Restart: geolistfacade.getGeometryFromGeoId(Constr->First); if (geo->is()) { - auto* arc = static_cast(geo); - double radius = arc->getRadius(); - double angle = (double)Constr->LabelPosition; - double startAngle, endAngle; - arc->getRange(startAngle, endAngle, /*emulateCCW=*/true); - if (angle == 10) { - angle = (startAngle + endAngle) / 2; - } - if (!(angle > startAngle && angle < endAngle)) { - if (angle < startAngle - && startAngle - angle < angle + 2 * M_PI - endAngle) { - helperStartAngle = angle; - helperRange = startAngle - angle; - } - else { - if (angle < endAngle) { - angle += 2 * M_PI; - } - helperStartAngle = endAngle; - helperRange = angle - endAngle; - } - } - Base::Vector3d center = arc->getCenter(); - pnt1 = center - radius * Base::Vector3d(cos(angle), sin(angle), 0.); - pnt2 = center + radius * Base::Vector3d(cos(angle), sin(angle), 0.); + auto* arc = static_cast(geo); + double radius = arc->getRadius(); + double angle = (double)Constr->LabelPosition; + double startAngle, endAngle; + arc->getRange(startAngle, endAngle, /*emulateCCW=*/true); + if (angle == 10) { + angle = (startAngle + endAngle) / 2; + } + if (!(angle > startAngle && angle < endAngle)) { + if (angle < startAngle + && startAngle - angle < angle + 2 * M_PI - endAngle) { + helperStartAngle = angle; + helperRange = startAngle - angle; + } + else { + if (angle < endAngle) { + angle += 2 * M_PI; + } + helperStartAngle = endAngle; + helperRange = angle - endAngle; + } + } + Base::Vector3d center = arc->getCenter(); + pnt1 = + center - radius * Base::Vector3d(cos(angle), sin(angle), 0.); + pnt2 = + center + radius * Base::Vector3d(cos(angle), sin(angle), 0.); } else if (geo->is()) { - auto* circle = static_cast(geo); - double radius = circle->getRadius(); - double angle = (double)Constr->LabelPosition; - if (angle == 10) { - angle = 0; - } - Base::Vector3d center = circle->getCenter(); - pnt1 = center - radius * Base::Vector3d(cos(angle), sin(angle), 0.); - pnt2 = center + radius * Base::Vector3d(cos(angle), sin(angle), 0.); + auto* circle = static_cast(geo); + double radius = circle->getRadius(); + double angle = (double)Constr->LabelPosition; + if (angle == 10) { + angle = 0; + } + Base::Vector3d center = circle->getCenter(); + pnt1 = + center - radius * Base::Vector3d(cos(angle), sin(angle), 0.); + pnt2 = + center + radius * Base::Vector3d(cos(angle), sin(angle), 0.); } else { - break; + break; } } else { @@ -1422,48 +1445,48 @@ Restart: geolistfacade.getGeometryFromGeoId(Constr->First); if (geo->is()) { - auto* arc = static_cast(geo); - double radius = arc->getRadius(); - double angle = (double)Constr->LabelPosition; - double startAngle, endAngle; - arc->getRange(startAngle, endAngle, /*emulateCCW=*/true); - if (angle == 10) { - angle = (startAngle + endAngle) / 2; - } - if (!(angle > startAngle && angle < endAngle)) { - if (angle < startAngle - && startAngle - angle < angle + 2 * M_PI - endAngle) { - helperStartAngle = angle; - helperRange = startAngle - angle; - } - else { - if (angle < endAngle) { - angle += 2 * M_PI; - } - helperStartAngle = endAngle; - helperRange = angle - endAngle; - } - } - pnt1 = arc->getCenter(); - pnt2 = pnt1 + radius * Base::Vector3d(cos(angle), sin(angle), 0.); + auto* arc = static_cast(geo); + double radius = arc->getRadius(); + double angle = (double)Constr->LabelPosition; + double startAngle, endAngle; + arc->getRange(startAngle, endAngle, /*emulateCCW=*/true); + if (angle == 10) { + angle = (startAngle + endAngle) / 2; + } + if (!(angle > startAngle && angle < endAngle)) { + if (angle < startAngle + && startAngle - angle < angle + 2 * M_PI - endAngle) { + helperStartAngle = angle; + helperRange = startAngle - angle; + } + else { + if (angle < endAngle) { + angle += 2 * M_PI; + } + helperStartAngle = endAngle; + helperRange = angle - endAngle; + } + } + pnt1 = arc->getCenter(); + pnt2 = pnt1 + radius * Base::Vector3d(cos(angle), sin(angle), 0.); } else if (geo->is()) { - auto* circle = static_cast(geo); - auto gf = GeometryFacade::getFacade(geo); + auto* circle = static_cast(geo); + auto gf = GeometryFacade::getFacade(geo); - double radius; + double radius; - radius = circle->getRadius(); + radius = circle->getRadius(); - double angle = (double)Constr->LabelPosition; - if (angle == 10) { - angle = 0; - } - pnt1 = circle->getCenter(); - pnt2 = pnt1 + radius * Base::Vector3d(cos(angle), sin(angle), 0.); + double angle = (double)Constr->LabelPosition; + if (angle == 10) { + angle = 0; + } + pnt1 = circle->getCenter(); + pnt2 = pnt1 + radius * Base::Vector3d(cos(angle), sin(angle), 0.); } else { - break; + break; } } else { @@ -2120,18 +2143,18 @@ std::set EditModeConstraintCoinManager::detectPreselectionConstr(const SoPi if (tail != sep->getChild( static_cast(ConstraintNodePosition::FirstIconIndex))) { - Base::Console().Log("SecondIcon\n"); + Base::Console().Log("SecondIcon\n"); - auto translation2 = static_cast( - static_cast(tailFather) - ->getChild(static_cast( - ConstraintNodePosition::SecondTranslationIndex))); + auto translation2 = static_cast( + static_cast(tailFather) + ->getChild(static_cast( + ConstraintNodePosition::SecondTranslationIndex))); - absPos += translation2->abPos.getValue(); + absPos += translation2->abPos.getValue(); - trans += translation2->translation.getValue(); + trans += translation2->translation.getValue(); - scaleFactor = translation2->getScaleFactor(); + scaleFactor = translation2->getScaleFactor(); } // Only the translation is scaled because this is how SoZoomTranslation @@ -2158,31 +2181,32 @@ std::set EditModeConstraintCoinManager::detectPreselectionConstr(const SoPi ++b) { #ifdef FC_DEBUG - // Useful code to debug coordinates and bounding boxes that does not - // need to be compiled in for any debug operations. + // Useful code to debug coordinates and bounding boxes that does + // not need to be compiled in for any debug operations. - /*Base::Console().Log("Abs(%f,%f),Trans(%f,%f),Coords(%d,%d),iCoords(%f,%f),icon(%d,%d),isize(%d,%d),boundingbox([%d,%d],[%d,%d])\n", - * absPos[0],absPos[1],trans[0], trans[1], cursorPos[0], cursorPos[1], - * iconCoords[0], iconCoords[1], iconX, iconY, iconSize[0], iconSize[1], - * b->first.topLeft().x(),b->first.topLeft().y(),b->first.bottomRight().x(),b->first.bottomRight().y());*/ + /*Base::Console().Log("Abs(%f,%f),Trans(%f,%f),Coords(%d,%d),iCoords(%f,%f),icon(%d,%d),isize(%d,%d),boundingbox([%d,%d],[%d,%d])\n", + * absPos[0],absPos[1],trans[0], trans[1], cursorPos[0], + * cursorPos[1], iconCoords[0], iconCoords[1], iconX, iconY, + * iconSize[0], iconSize[1], + * b->first.topLeft().x(),b->first.topLeft().y(),b->first.bottomRight().x(),b->first.bottomRight().y());*/ #endif - if (b->first.contains(iconX, iconY)) { - // We've found a bounding box that contains the mouse pointer! - for (std::set::iterator k = b->second.begin(); - k != b->second.end(); - ++k) { - constrIndices.insert(*k); - } - } + if (b->first.contains(iconX, iconY)) { + // We've found a bounding box that contains the mouse pointer! + for (std::set::iterator k = b->second.begin(); + k != b->second.end(); + ++k) { + constrIndices.insert(*k); + } + } } } else { // It's a constraint icon, not a combined one QStringList constrIdStrings = constrIdsStr.split(QString::fromLatin1(",")); while (!constrIdStrings.empty()) { - auto constraintid = constrIdStrings.takeAt(0).toInt(); - constrIndices.insert(constraintid); + auto constraintid = constrIdStrings.takeAt(0).toInt(); + constrIndices.insert(constraintid); } } } @@ -2412,24 +2436,24 @@ void EditModeConstraintCoinManager::combineConstraintIcons(IconQueue iconQueue) + pow(i->position[1] - j->position[1], 2); if (distSquared <= maxDistSquared && (*i).type != QString::fromLatin1("Constraint_Symmetric")) { - // Found an icon in iconQueue that's close enough to - // a member of thisGroup, so move it into thisGroup - thisGroup.push_back(*i); - i = iconQueue.erase(i); - addedToGroup = true; - break; + // Found an icon in iconQueue that's close enough to + // a member of thisGroup, so move it into thisGroup + thisGroup.push_back(*i); + i = iconQueue.erase(i); + addedToGroup = true; + break; } } if (addedToGroup) { if (i == iconQueue.end()) { - // We just got the last icon out of iconQueue - break; + // We just got the last icon out of iconQueue + break; } else { - // Start looking through the iconQueue again, in case - // we have an icon that's now close enough to thisGroup - i = iconQueue.begin(); + // Start looking through the iconQueue again, in case + // we have an icon that's now close enough to thisGroup + i = iconQueue.begin(); } } else { diff --git a/src/Mod/Sketcher/Gui/Utils.cpp b/src/Mod/Sketcher/Gui/Utils.cpp index 0db4a47d12..a2b534f5e2 100644 --- a/src/Mod/Sketcher/Gui/Utils.cpp +++ b/src/Mod/Sketcher/Gui/Utils.cpp @@ -410,16 +410,37 @@ double SketcherGui::GetPointAngle(const Base::Vector2d& p1, const Base::Vector2d // 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, +void SketcherGui::GetCirclesMinimalDistance(const Part::Geometry* geom1, + const Part::Geometry* geom2, Base::Vector3d& point1, Base::Vector3d& point2) { - double radius1 = circle1->getRadius(); - double radius2 = circle2->getRadius(); + double radius1 = 0.0; + double radius2 = 0.0; - point1 = circle1->getCenter(); - point2 = circle2->getCenter(); + if (geom1->is()) { + auto circle = static_cast(geom1); + radius1 = circle->getRadius(); + point1 = circle->getCenter(); + } + else if (geom1->is()) { + auto arc = static_cast(geom1); + radius1 = arc->getRadius(); + point1 = arc->getCenter(); + } + + if (geom2->is()) { + auto circle = static_cast(geom2); + radius2 = circle->getRadius(); + point2 = circle->getCenter(); + } + else if (geom2->is()) { + auto arc = static_cast(geom2); + radius2 = arc->getRadius(); + point2 = arc->getCenter(); + } + + assert(radius1 == 0 || radius2 == 0 /*Circles characteristics not available*/); Base::Vector3d v = point2 - point1; double length = v.Length(); diff --git a/src/Mod/Sketcher/Gui/Utils.h b/src/Mod/Sketcher/Gui/Utils.h index d1f3454fb2..c8b87dd763 100644 --- a/src/Mod/Sketcher/Gui/Utils.h +++ b/src/Mod/Sketcher/Gui/Utils.h @@ -165,8 +165,8 @@ inline const char* constructionModeAsBooleanText() 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, +void GetCirclesMinimalDistance(const Part::Geometry* geom1, + const Part::Geometry* geom2, Base::Vector3d& point1, Base::Vector3d& point2); diff --git a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp index abb44f2ec2..e4f6715ee3 100644 --- a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp +++ b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp @@ -1698,43 +1698,20 @@ void ViewProviderSketch::moveConstraint(int constNum, const Base::Vector2d& toPo } else if (Constr->Second != GeoEnum::GeoUndef) { p1 = getSolvedSketch().getPoint(Constr->First, Constr->FirstPos); - const Part::Geometry* geo = GeoList::getGeometryFromGeoId(geomlist, Constr->Second); - if (geo->is()) { - const Part::GeomLineSegment* lineSeg = - static_cast(geo); + const Part::Geometry *geo = GeoList::getGeometryFromGeoId (geomlist, Constr->Second); + const Part::Geometry *geo1 = GeoList::getGeometryFromGeoId (geomlist, Constr->First); + if (geo->is()) { // point to line distance + auto *lineSeg = static_cast(geo); Base::Vector3d l2p1 = lineSeg->getStartPoint(); Base::Vector3d l2p2 = lineSeg->getEndPoint(); - if (Constr->FirstPos != Sketcher::PointPos::none) {// point to line distance - // calculate the projection of p1 onto line2 - p2.ProjectToLine(p1 - l2p1, l2p2 - l2p1); - p2 += p1; - } - else { - const Part::Geometry* geo1 = - GeoList::getGeometryFromGeoId(geomlist, Constr->First); - const Part::GeomCircle* circleSeg = static_cast(geo1); - Base::Vector3d ct = circleSeg->getCenter(); - double radius = circleSeg->getRadius(); - p1.ProjectToLine(ct - l2p1, - l2p2 - l2p1);// project on the line translated to origin - Base::Vector3d dir = p1; - dir.Normalize(); - p1 += ct; - p2 = ct + dir * radius; - } - } - else if (geo->is()) {// circle to circle distance - const Part::Geometry* geo1 = GeoList::getGeometryFromGeoId(geomlist, Constr->First); - if (geo1->is()) { - const Part::GeomCircle* circleSeg1 = static_cast(geo1); - const Part::GeomCircle* circleSeg2 = static_cast(geo); - GetCirclesMinimalDistance(circleSeg1, circleSeg2, p1, p2); - } else if (Constr->FirstPos != Sketcher::PointPos::none) { //point to circle distance - auto circleSeg2 = static_cast(geo); - p1 = getSolvedSketch().getPoint(Constr->First, Constr->FirstPos); - Base::Vector3d v = p1 - circleSeg2->getCenter(); - v = v.Normalize(); - p2 = circleSeg2->getCenter() + circleSeg2->getRadius() * v; + // calculate the projection of p1 onto line2 + p2.ProjectToLine(p1-l2p1, l2p2-l2p1); + p2 += p1; + } else if (geo->is() // circle to circle distance + || geo->is()) { + if (geo1->is() + || geo1->is()) { + GetCirclesMinimalDistance(geo1, geo, p1, p2); } } else