From c6f5739763dd657b7bf16c139c6193423abe3658 Mon Sep 17 00:00:00 2001 From: Ajinkya Dahale Date: Sun, 29 Dec 2024 21:26:43 +0530 Subject: [PATCH] [Sketcher] Refactor `SketchObject::split` 1. Now uses `Part::Geometry::createArc`. 2. Removed type-specific codes. It can be generalized now. --- src/Mod/Sketcher/App/SketchObject.cpp | 225 ++++++-------------------- 1 file changed, 48 insertions(+), 177 deletions(-) diff --git a/src/Mod/Sketcher/App/SketchObject.cpp b/src/Mod/Sketcher/App/SketchObject.cpp index ec535c3f416a..f6203dadf838 100644 --- a/src/Mod/Sketcher/App/SketchObject.cpp +++ b/src/Mod/Sketcher/App/SketchObject.cpp @@ -4091,17 +4091,15 @@ int SketchObject::split(int GeoId, const Base::Vector3d& point) return -1; } - bool originalIsPeriodic = false; const Part::Geometry* geo = getGeometry(GeoId); + bool originalIsPeriodic = isClosedCurve(geo); std::vector newIds; std::vector newConstraints; Base::Vector3d startPoint, endPoint, splitPoint; double startParam, endParam, splitParam = 0.0; - auto createGeosFromPeriodic = [&](const Part::GeomCurve* curve, - auto getCurveWithLimitParams, - auto createAndTransferConstraints) { + auto createGeosFromPeriodic = [&](const Part::GeomCurve* curve) { // find split point curve->closestParameter(point, splitParam); double period = curve->getLastParameter() - curve->getFirstParameter(); @@ -4109,7 +4107,7 @@ int SketchObject::split(int GeoId, const Base::Vector3d& point) endParam = splitParam + period; // create new arc and restrict it - auto newCurve = getCurveWithLimitParams(curve, startParam, endParam); + auto newCurve = curve->createArc(startParam, endParam); int newId(GeoEnum::GeoUndef); newId = addGeometry(std::move(newCurve));// after here newCurve is a shell if (newId < 0) { @@ -4120,14 +4118,10 @@ int SketchObject::split(int GeoId, const Base::Vector3d& point) setConstruction(newId, GeometryFacade::getConstruction(curve)); exposeInternalGeometry(newId); - // transfer any constraints - createAndTransferConstraints(GeoId, newId); return true; }; - auto createGeosFromNonPeriodic = [&](const Part::GeomBoundedCurve* curve, - auto getCurveWithLimitParams, - auto createAndTransferConstraints) { + auto createGeosFromNonPeriodic = [&](const Part::GeomBoundedCurve* curve) { startPoint = curve->getStartPoint(); endPoint = curve->getEndPoint(); @@ -4143,7 +4137,7 @@ int SketchObject::split(int GeoId, const Base::Vector3d& point) } // create new curves - auto newCurve = getCurveWithLimitParams(curve, startParam, splitParam); + auto newCurve = curve->createArc(startParam, splitParam); int newId(GeoEnum::GeoUndef); newId = addGeometry(std::move(newCurve)); if (newId < 0) { @@ -4154,7 +4148,7 @@ int SketchObject::split(int GeoId, const Base::Vector3d& point) exposeInternalGeometry(newId); // the "second" half - newCurve = getCurveWithLimitParams(curve, splitParam, endParam); + newCurve = curve->createArc(splitParam, endParam); newId = addGeometry(std::move(newCurve)); if (newId < 0) { return false; @@ -4163,169 +4157,15 @@ int SketchObject::split(int GeoId, const Base::Vector3d& point) setConstruction(newId, GeometryFacade::getConstruction(curve)); exposeInternalGeometry(newId); - // TODO: Certain transfers and new constraint can be directly made here. - // But this may reduce readability. - // apply appropriate constraints on the new points at split point and - // transfer constraints from start and end of original spline - createAndTransferConstraints(GeoId, newIds[0], newIds[1]); return true; }; bool ok = false; - if (geo->is()) { - originalIsPeriodic = false; - ok = createGeosFromNonPeriodic( - static_cast(geo), - [](const Part::GeomCurve* curve, double startParam, double endParam) { - auto newArc = std::unique_ptr( - static_cast(curve->copy())); - newArc->setRange(startParam, endParam); - return newArc; - }, - [this, &newConstraints](int GeoId, int newId0, int newId1) { - Constraint* joint = new Constraint(); - joint->Type = Coincident; - joint->First = newId0; - joint->FirstPos = PointPos::end; - joint->Second = newId1; - joint->SecondPos = PointPos::start; - newConstraints.push_back(joint); - - transferConstraints(GeoId, PointPos::start, newId0, PointPos::start); - transferConstraints(GeoId, PointPos::end, newId1, PointPos::end); - }); + if (originalIsPeriodic) { + ok = createGeosFromPeriodic(static_cast(geo)); } - else if (geo->is()) { - originalIsPeriodic = true; - ok = createGeosFromPeriodic( - static_cast(geo), - [](const Part::GeomCurve* curve, double startParam, double endParam) { - auto newArc = std::make_unique( - Handle(Geom_Circle)::DownCast(curve->handle()->Copy())); - newArc->setRange(startParam, endParam, false); - return newArc; - }, - [this](int GeoId, int newId) { - transferConstraints(GeoId, PointPos::mid, newId, PointPos::mid); - }); - } - else if (geo->is()) { - originalIsPeriodic = true; - ok = createGeosFromPeriodic( - static_cast(geo), - [](const Part::GeomCurve* curve, double startParam, double endParam) { - auto newArc = std::make_unique( - Handle(Geom_Ellipse)::DownCast(curve->handle()->Copy())); - newArc->setRange(startParam, endParam, false); - return newArc; - }, - [this](int GeoId, int newId) { - transferConstraints(GeoId, PointPos::mid, newId, PointPos::mid); - }); - } - else if (geo->is()) { - originalIsPeriodic = false; - ok = createGeosFromNonPeriodic( - static_cast(geo), - [](const Part::GeomCurve* curve, double startParam, double endParam) { - auto newArc = std::unique_ptr( - static_cast(curve->copy())); - newArc->setRange(startParam, endParam, false); - return newArc; - }, - [this, &newConstraints](int GeoId, int newId0, int newId1) { - Constraint* joint = new Constraint(); - joint->Type = Coincident; - joint->First = newId0; - joint->FirstPos = PointPos::end; - joint->Second = newId1; - joint->SecondPos = PointPos::start; - newConstraints.push_back(joint); - - joint = new Constraint(); - joint->Type = Coincident; - joint->First = newId0; - joint->FirstPos = PointPos::mid; - joint->Second = newId1; - joint->SecondPos = PointPos::mid; - newConstraints.push_back(joint); - - transferConstraints(GeoId, PointPos::start, newId0, PointPos::start, true); - transferConstraints(GeoId, PointPos::mid, newId0, PointPos::mid); - transferConstraints(GeoId, PointPos::end, newId1, PointPos::end, true); - }); - } - else if (geo->isDerivedFrom(Part::GeomArcOfConic::getClassTypeId())) { - originalIsPeriodic = false; - ok = createGeosFromNonPeriodic( - static_cast(geo), - [](const Part::GeomCurve* curve, double startParam, double endParam) { - auto newArc = std::unique_ptr( - static_cast(curve->copy())); - newArc->setRange(startParam, endParam); - return newArc; - }, - [this, &newConstraints](int GeoId, int newId0, int newId1) { - // apply appropriate constraints on the new points at split point - Constraint* joint = new Constraint(); - joint->Type = Coincident; - joint->First = newId0; - joint->FirstPos = PointPos::end; - joint->Second = newId1; - joint->SecondPos = PointPos::start; - newConstraints.push_back(joint); - - // TODO: Do we apply constraints on center etc of the conics? - - // transfer constraints from start, mid and end of original - transferConstraints(GeoId, PointPos::start, newId0, PointPos::start, true); - transferConstraints(GeoId, PointPos::mid, newId0, PointPos::mid); - transferConstraints(GeoId, PointPos::end, newId1, PointPos::end, true); - }); - } - else if (geo->is()) { - const auto* bsp = static_cast(geo); - - // what to do for periodic b-splines? - originalIsPeriodic = bsp->isPeriodic(); - if (originalIsPeriodic) { - ok = createGeosFromPeriodic( - static_cast(geo), - [](const Part::GeomCurve* curve, double startParam, double endParam) { - auto newBsp = std::unique_ptr( - static_cast(curve->copy())); - newBsp->Trim(startParam, endParam); - return newBsp; - }, - [](int, int) { - // no constraints to transfer here, and we assume the split is to "break" the - // b-spline - }); - } - else { - ok = createGeosFromNonPeriodic( - static_cast(geo), - [](const Part::GeomCurve* curve, double startParam, double endParam) { - auto newBsp = std::unique_ptr( - static_cast(curve->copy())); - newBsp->Trim(startParam, endParam); - return newBsp; - }, - [this, &newConstraints](int GeoId, int newId0, int newId1) { - // apply appropriate constraints on the new points at split point - Constraint* joint = new Constraint(); - joint->Type = Coincident; - joint->First = newId0; - joint->FirstPos = PointPos::end; - joint->Second = newId1; - joint->SecondPos = PointPos::start; - newConstraints.push_back(joint); - - // transfer constraints from start and end of original spline - transferConstraints(GeoId, PointPos::start, newId0, PointPos::start, true); - transferConstraints(GeoId, PointPos::end, newId1, PointPos::end, true); - }); - } + else { + ok = createGeosFromNonPeriodic(static_cast(geo)); } if (!ok) { @@ -4336,6 +4176,35 @@ int SketchObject::split(int GeoId, const Base::Vector3d& point) return -1; } + if (!originalIsPeriodic) { + Constraint* joint = new Constraint(); + joint->Type = Coincident; + joint->First = newIds.front(); + joint->FirstPos = PointPos::end; + joint->Second = newIds.back(); + joint->SecondPos = PointPos::start; + newConstraints.push_back(joint); + + transferConstraints(GeoId, PointPos::start, newIds.front(), PointPos::start); + transferConstraints(GeoId, PointPos::end, newIds.back(), PointPos::end); + } + + // This additional constraint is there to maintain existing behavior. + // TODO: Decide whether to remove it altogether or also apply to other curves with centers. + if (geo->is()) { + Constraint* joint = new Constraint(); + joint->Type = Coincident; + joint->First = newIds.front(); + joint->FirstPos = PointPos::mid; + joint->Second = newIds.back(); + joint->SecondPos = PointPos::mid; + newConstraints.push_back(joint); + } + + if (geo->isDerivedFrom() || geo->isDerivedFrom()) { + transferConstraints(GeoId, PointPos::mid, newIds.front(), PointPos::mid); + } + std::vector idsOfOldConstraints; getConstraintIndices(GeoId, idsOfOldConstraints); @@ -4343,20 +4212,22 @@ int SketchObject::split(int GeoId, const Base::Vector3d& point) // keep constraints on internal geometries so they are deleted // when the old curve is deleted - idsOfOldConstraints.erase(std::remove_if(idsOfOldConstraints.begin(), - idsOfOldConstraints.end(), - [=](const auto& i) { - return allConstraints[i]->Type == InternalAlignment; - }), - idsOfOldConstraints.end()); + idsOfOldConstraints.erase( + std::remove_if(idsOfOldConstraints.begin(), + idsOfOldConstraints.end(), + [&allConstraints](const auto& i) { + return allConstraints[i]->Type == InternalAlignment; + }), + idsOfOldConstraints.end()); for (const auto& oldConstrId: idsOfOldConstraints) { Constraint* con = allConstraints[oldConstrId]; deriveConstraintsForPieces(GeoId, newIds, con, newConstraints); } - if (noRecomputes) + if (noRecomputes) { solve(); + } delConstraints(idsOfOldConstraints); addConstraints(newConstraints);