diff --git a/src/Mod/Sketcher/Gui/CommandConstraints.cpp b/src/Mod/Sketcher/Gui/CommandConstraints.cpp index 5915feb7c3..7a4b52bd85 100644 --- a/src/Mod/Sketcher/Gui/CommandConstraints.cpp +++ b/src/Mod/Sketcher/Gui/CommandConstraints.cpp @@ -4364,25 +4364,10 @@ void CmdSketcherConstrainDistance::activated(int iMsg) const Part::Geometry* geom1 = Obj->getGeometry(GeoId1); const Part::Geometry* geom2 = Obj->getGeometry(GeoId2); - auto isCircleOrArc = [](const Part::Geometry & geo) { - return isCircle(geo) || isArcOfCircle(geo); - }; - if(isCircleOrArc(*geom1) && isCircleOrArc(*geom2)) { - auto getRadiusCenter = [](const Part::Geometry * geo) { - if (isArcOfCircle(*geo)) { - auto arc = static_cast(geo); //NOLINT - return std::tuple(arc->getRadius(), arc->getCenter()); - } - else { - auto circ = static_cast(geo); //NOLINT - return std::tuple(circ->getRadius(), circ->getCenter()); - } - }; - - auto [radius1, center1] = getRadiusCenter(geom1); - auto [radius2, center2] = getRadiusCenter(geom2); + auto [radius1, center1] = getRadiusCenterCircleArc(geom1); + auto [radius2, center2] = getRadiusCenterCircleArc(geom2); double ActDist = 0.0; diff --git a/src/Mod/Sketcher/Gui/EditModeConstraintCoinManager.cpp b/src/Mod/Sketcher/Gui/EditModeConstraintCoinManager.cpp index 1e3de86ff3..8051a921f3 100644 --- a/src/Mod/Sketcher/Gui/EditModeConstraintCoinManager.cpp +++ b/src/Mod/Sketcher/Gui/EditModeConstraintCoinManager.cpp @@ -255,9 +255,9 @@ Restart: } else { double ra = 0, rb = 0; - double angle, - angleplus = 0.; // angle = rotation of object as a whole; angleplus - // = arc angle (t parameter for ellipses). + double angle, // rotation of object as a whole + angleplus = 0.; // arc angle (t parameter for ellipses) + if (geo->is()) { const Part::GeomCircle* circle = static_cast(geo); @@ -813,100 +813,88 @@ Restart: case DistanceX: case DistanceY: { assert(Constr->First >= -extGeoCount && Constr->First < intGeoCount); - Base::Vector3d pnt1(0., 0., 0.), pnt2(0., 0., 0.); + + // pnt1 will be initialized to (0,0,0) if First is an edge + auto pnt1 = geolistfacade.getPoint(Constr->First, Constr->FirstPos); + + Base::Vector3d pnt2(0., 0., 0.); + 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) { - const Part::Geometry* geo = - geolistfacade.getGeometryFromGeoId(Constr->Second); - if (geo->is()) { - const Part::GeomLineSegment* lineSeg = - static_cast(geo); - Base::Vector3d l2p1 = lineSeg->getStartPoint(); - Base::Vector3d l2p2 = lineSeg->getEndPoint(); - if (Constr->FirstPos - != Sketcher::PointPos::none) { // point to line distance - pnt1 = geolistfacade.getPoint(Constr->First, Constr->FirstPos); + auto geo = geolistfacade.getGeometryFromGeoId(Constr->Second); + auto geo1 = geolistfacade.getGeometryFromGeoId(Constr->First); + if (isLineSegment(*geo)) { + if (Constr->SecondPos != Sketcher::PointPos::none) { + // point to line distance + // NOLINTNEXTLINE + auto 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 { - const Part::Geometry* geo1 = - geolistfacade.getGeometryFromGeoId(Constr->First); - if (geo1->is()) { // circle to line distance + if (isCircleOrArc(*geo1)) { + // circular to line distance auto lineSeg = static_cast(geo); - auto circleSeg = static_cast(geo1); - Base::Vector3d ct = circleSeg->getCenter(); + + auto [radius, ct] = getRadiusCenterCircleArc(geo1); + Base::Vector3d l2p1 = lineSeg->getStartPoint(); Base::Vector3d l2p2 = lineSeg->getEndPoint(); - double radius = circleSeg->getRadius(); // project on the line translated to origin - pnt2.ProjectToLine(ct - l2p1, l2p2 - l2p1); - Base::Vector3d dir = pnt2; + pnt1.ProjectToLine(ct - l2p1, l2p2 - l2p1); + Base::Vector3d dir = pnt1; dir.Normalize(); - 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); - } + pnt1 += ct; + pnt2 = ct + dir * radius; } } } - 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 if (isCircleOrArc(*geo)) { + if (Constr->FirstPos != Sketcher::PointPos::none) { + // point to circular distance + auto [rad, ct] = getRadiusCenterCircleArc(geo1); + + pnt1 = geolistfacade.getPoint(Constr->First, Constr->FirstPos); + Base::Vector3d v = pnt1 - ct; + v = v.Normalize(); + pnt2 = ct + rad * v; + } + else if (isCircleOrArc(*geo1)) { + // circular to circular distance + GetCirclesMinimalDistance(geo1, geo, pnt1, pnt2); + } } else { - break; + 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->is()) { // segment distance - const Part::GeomLineSegment* lineSeg = - static_cast(geo); - pnt1 = lineSeg->getStartPoint(); - pnt2 = lineSeg->getEndPoint(); + auto geo = geolistfacade.getGeometryFromGeoId(Constr->First); + if (isLineSegment(*geo)) { // segment distance + auto lineSeg = static_cast(geo); + pnt1 = lineSeg->getStartPoint(); + pnt2 = lineSeg->getEndPoint(); } else { - break; + break; } } else { break; } + // NOLINTBEGIN SoDatumLabel* asciiText = static_cast( sep->getChild(static_cast(ConstraintNodePosition::DatumLabelIndex))); + // NOLINTEND // Get presentation string (w/o units if option is set) asciiText->string = @@ -956,22 +944,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); @@ -1006,150 +994,144 @@ 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))); @@ -1194,134 +1176,115 @@ Restart: || Constr->Second == GeoEnum::GeoUndef); SbVec3f p0; - double distance = Constr->LabelDistance; double startangle, range; - double endLineLength1 = 0.0; - double endLineLength2 = 0.0; 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 (geo1->getTypeId() != Part::GeomLineSegment::getClassTypeId() + || geo2->getTypeId() != Part::GeomLineSegment::getClassTypeId()) { + break; + } + const Part::GeomLineSegment* lineSeg1 = + static_cast(geo1); + const Part::GeomLineSegment* lineSeg2 = + 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.) + * (lineSeg1->getEndPoint() - lineSeg1->getStartPoint()); + dir2 = (flip2 ? -1. : 1.) + * (lineSeg2->getEndPoint() - lineSeg2->getStartPoint()); + Base::Vector3d pnt1 = + flip1 ? lineSeg1->getEndPoint() : lineSeg1->getStartPoint(); + Base::Vector3d pnt2 = + flip2 ? lineSeg2->getEndPoint() : lineSeg2->getStartPoint(); - // 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 + { + 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] = lineSeg1->getStartPoint(); + p1[1] = lineSeg1->getEndPoint(); + p2[0] = lineSeg2->getStartPoint(); + p2[1] = lineSeg2->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; + p0.setValue((p2[j].x + p1[i].x) / 2, + (p2[j].y + p1[i].y) / 2, + 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; + p0 = SbVec3f(x, 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); - - 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; + range = Constr->getValue(); // WYSIWYG + startangle = atan2(dir1.y, dir1.x); } 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 { @@ -1333,11 +1296,9 @@ Restart: asciiText->string = SbString(getPresentationString(Constr).toUtf8().constData()); asciiText->datumtype = SoDatumLabel::ANGLE; - asciiText->param1 = distance; + asciiText->param1 = Constr->LabelDistance; asciiText->param2 = startangle; asciiText->param3 = range; - asciiText->param4 = endLineLength1; - asciiText->param5 = endLineLength2; asciiText->pnts.setNum(2); SbVec3f* verts = asciiText->pnts.startEditing(); @@ -1351,57 +1312,38 @@ Restart: assert(Constr->First >= -extGeoCount && Constr->First < intGeoCount); Base::Vector3d pnt1(0., 0., 0.), pnt2(0., 0., 0.); - double helperStartAngle = 0.; - double helperRange = 0.; - if (Constr->First != GeoEnum::GeoUndef) { const Part::Geometry* geo = 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.); + const Part::GeomArcOfCircle* arc = + static_cast(geo); + double radius = arc->getRadius(); + double angle = (double)Constr->LabelPosition; + if (angle == 10) { + double startangle, endangle; + arc->getRange(startangle, endangle, /*emulateCCW=*/true); + angle = (startangle + endangle) / 2; + } + 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.); + const Part::GeomCircle* 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 { @@ -1421,8 +1363,6 @@ Restart: asciiText->datumtype = SoDatumLabel::DIAMETER; asciiText->param1 = Constr->LabelDistance; asciiText->param2 = Constr->LabelPosition; - asciiText->param3 = helperStartAngle; - asciiText->param4 = helperRange; asciiText->pnts.setNum(2); SbVec3f* verts = asciiText->pnts.startEditing(); @@ -1437,56 +1377,42 @@ Restart: assert(Constr->First >= -extGeoCount && Constr->First < intGeoCount); Base::Vector3d pnt1(0., 0., 0.), pnt2(0., 0., 0.); - double helperStartAngle = 0.; - double helperRange = 0.; if (Constr->First != GeoEnum::GeoUndef) { const Part::Geometry* geo = 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.); + const Part::GeomArcOfCircle* arc = + static_cast(geo); + double radius = arc->getRadius(); + double angle = (double)Constr->LabelPosition; + if (angle == 10) { + double startangle, endangle; + arc->getRange(startangle, endangle, /*emulateCCW=*/true); + angle = (startangle + endangle) / 2; + } + 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); + const Part::GeomCircle* 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 { @@ -1512,8 +1438,6 @@ Restart: asciiText->datumtype = SoDatumLabel::RADIUS; asciiText->param1 = Constr->LabelDistance; asciiText->param2 = Constr->LabelPosition; - asciiText->param3 = helperStartAngle; - asciiText->param4 = helperRange; asciiText->pnts.setNum(2); SbVec3f* verts = asciiText->pnts.startEditing(); @@ -2143,18 +2067,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 @@ -2181,32 +2105,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); } } } @@ -2436,24 +2360,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 a2b534f5e2..30853539bf 100644 --- a/src/Mod/Sketcher/Gui/Utils.cpp +++ b/src/Mod/Sketcher/Gui/Utils.cpp @@ -93,6 +93,25 @@ bool Sketcher::isPoint(const Part::Geometry& geom) return geom.is(); } +bool Sketcher::isCircleOrArc(const Part::Geometry& geo) +{ + return isCircle(geo) || isArcOfCircle(geo); +}; + +std::tuple Sketcher::getRadiusCenterCircleArc(const Part::Geometry* geo) +{ + if (isArcOfCircle(*geo)) { + auto arc = static_cast(geo); // NOLINT + return std::tuple(arc->getRadius(), arc->getCenter()); + } + else if (isCircle(*geo)) { + auto circ = static_cast(geo); // NOLINT + return std::tuple(circ->getRadius(), circ->getCenter()); + } + + THROWM(Base::TypeError, "getRadiusCenterCircleArc - Neither an arc nor a circle") +}; + bool SketcherGui::tryAutoRecompute(Sketcher::SketchObject* obj, bool& autoremoveredundants) { ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath( @@ -415,32 +434,12 @@ void SketcherGui::GetCirclesMinimalDistance(const Part::Geometry* geom1, Base::Vector3d& point1, Base::Vector3d& point2) { - double radius1 = 0.0; - double radius2 = 0.0; + // This will throw if geom1 or geom2 are not circles or arcs + auto [radius1, center1] = getRadiusCenterCircleArc(geom1); + auto [radius2, center2] = getRadiusCenterCircleArc(geom2); - 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*/); + point1 = center1; + point2 = center2; 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 c8b87dd763..09f984110a 100644 --- a/src/Mod/Sketcher/Gui/Utils.h +++ b/src/Mod/Sketcher/Gui/Utils.h @@ -63,6 +63,10 @@ bool isArcOfParabola(const Part::Geometry&); bool isBSplineCurve(const Part::Geometry&); bool isPoint(const Part::Geometry&); +bool isCircleOrArc(const Part::Geometry& geo); + +std::tuple getRadiusCenterCircleArc(const Part::Geometry* geo); + } // namespace Sketcher namespace SketcherGui