diff --git a/src/Mod/Sketcher/App/SketchObject.cpp b/src/Mod/Sketcher/App/SketchObject.cpp index f803264a2b..9e52eceb30 100644 --- a/src/Mod/Sketcher/App/SketchObject.cpp +++ b/src/Mod/Sketcher/App/SketchObject.cpp @@ -3116,14 +3116,88 @@ int SketchObject::split(int GeoId, const Base::Vector3d &point) } } } + else if (geo->getTypeId() == Part::GeomBSplineCurve::getClassTypeId()) { + const Part::GeomBSplineCurve *bsp = static_cast(geo); + + // find split point + double splitParam; + bsp->closestParameter(point, splitParam); + + // what to do for periodic b-splines? + if (bsp->isPeriodic()) { + Part::GeomBSplineCurve* newBsp; + int newId(GeoEnum::GeoUndef); + newBsp = static_cast(bsp->clone()); + newGeometries.push_back(newBsp); + newBsp->Trim(splitParam, splitParam); + newId = addGeometry(newBsp); + if (newId >= 0) { + newIds.push_back(newId); + setConstruction(newId, GeometryFacade::getConstruction(geo)); + exposeInternalGeometry(newId); + + // no constraints to transfer here, and we assume the split is to "break" the b-spline + ok = true; + } + } + else { + // create new b-splines + Part::GeomBSplineCurve* newBsp; + int newId(GeoEnum::GeoUndef); + newBsp = static_cast(bsp->clone()); + newGeometries.push_back(newBsp); + newBsp->Trim(newBsp->getFirstParameter(), splitParam); + newId = addGeometry(newBsp); + if (newId >= 0) { + newIds.push_back(newId); + setConstruction(newId, GeometryFacade::getConstruction(geo)); + exposeInternalGeometry(newId); + + // the "second" half + newBsp = static_cast(bsp->clone()); + newGeometries.push_back(newBsp); + newBsp->Trim(splitParam, newBsp->getLastParameter()); + newId = addGeometry(newBsp); + if (newId >= 0) { + newIds.push_back(newId); + setConstruction(newId, GeometryFacade::getConstruction(geo)); + exposeInternalGeometry(newId); + + // apply appropriate constraints on the new points at split point + Constraint* joint = new Constraint(); + joint->Type = Coincident; + joint->First = newIds[0]; + joint->FirstPos = PointPos::end; + joint->Second = newIds[1]; + joint->SecondPos = PointPos::start; + newConstraints.push_back(joint); + + // transfer constraints from start and end of original spline + transferConstraints(GeoId, PointPos::start, newIds[0], PointPos::start, true); + transferConstraints(GeoId, PointPos::end, newIds[1], PointPos::end, true); + ok = true; + } + } + } + } if (ok) { std::vector oldConstraints; getConstraintIndices(GeoId, oldConstraints); + const auto& allConstraints = this->Constraints.getValues(); + + // keep constraints on internal geometries so they are deleted + // when the old curve is deleted + oldConstraints.erase( + std::remove_if( + oldConstraints.begin(), oldConstraints.end(), + [=](const auto& i){return allConstraints[i]->Type == InternalAlignment;}), + oldConstraints.end()); + for (unsigned int i = 0; i < oldConstraints.size(); ++i) { - Constraint *con = this->Constraints.getValues()[oldConstraints[i]]; + Constraint *con = allConstraints[oldConstraints[i]]; int conId = con->First; PointPos conPos = con->FirstPos; if (conId == GeoId) { diff --git a/src/Mod/Sketcher/Gui/DrawSketchHandlerSplitting.h b/src/Mod/Sketcher/Gui/DrawSketchHandlerSplitting.h index a251d2eb0e..f1edddba01 100644 --- a/src/Mod/Sketcher/Gui/DrawSketchHandlerSplitting.h +++ b/src/Mod/Sketcher/Gui/DrawSketchHandlerSplitting.h @@ -52,7 +52,8 @@ public: const Part::Geometry *geom = Sketch->getGeometry(GeoId); if (geom->getTypeId() == Part::GeomLineSegment::getClassTypeId() || geom->getTypeId() == Part::GeomCircle::getClassTypeId() - || geom->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) { + || geom->getTypeId() == Part::GeomArcOfCircle::getClassTypeId() + || geom->getTypeId() == Part::GeomBSplineCurve::getClassTypeId()) { return true; } } @@ -88,7 +89,8 @@ public: const Part::Geometry *geom = sketchgui->getSketchObject()->getGeometry(GeoId); if (geom->getTypeId() == Part::GeomLineSegment::getClassTypeId() || geom->getTypeId() == Part::GeomCircle::getClassTypeId() - || geom->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) { + || geom->getTypeId() == Part::GeomArcOfCircle::getClassTypeId() + || geom->getTypeId() == Part::GeomBSplineCurve::getClassTypeId()) { try { Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Split edge")); Gui::cmdAppObjectArgs(sketchgui->getObject(), "split(%d,App.Vector(%f,%f,0))",