Skip to content

Commit

Permalink
[Sketcher] Refactor SketchObject::split
Browse files Browse the repository at this point in the history
1. Now uses `Part::Geometry::createArc`.
2. Removed type-specific codes. It can be generalized now.
  • Loading branch information
AjinkyaDahale committed Jan 16, 2025
1 parent e6becd0 commit c6f5739
Showing 1 changed file with 48 additions and 177 deletions.
225 changes: 48 additions & 177 deletions src/Mod/Sketcher/App/SketchObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4091,25 +4091,23 @@ 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<int> newIds;
std::vector<Constraint*> 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();
startParam = splitParam;
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) {
Expand All @@ -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();

Expand All @@ -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) {
Expand All @@ -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;
Expand All @@ -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<Part::GeomLineSegment>()) {
originalIsPeriodic = false;
ok = createGeosFromNonPeriodic(
static_cast<const Part::GeomBoundedCurve*>(geo),
[](const Part::GeomCurve* curve, double startParam, double endParam) {
auto newArc = std::unique_ptr<Part::GeomLineSegment>(
static_cast<Part::GeomLineSegment*>(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<const Part::GeomBoundedCurve*>(geo));
}
else if (geo->is<Part::GeomCircle>()) {
originalIsPeriodic = true;
ok = createGeosFromPeriodic(
static_cast<const Part::GeomCurve*>(geo),
[](const Part::GeomCurve* curve, double startParam, double endParam) {
auto newArc = std::make_unique<Part::GeomArcOfCircle>(
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<Part::GeomEllipse>()) {
originalIsPeriodic = true;
ok = createGeosFromPeriodic(
static_cast<const Part::GeomCurve*>(geo),
[](const Part::GeomCurve* curve, double startParam, double endParam) {
auto newArc = std::make_unique<Part::GeomArcOfEllipse>(
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<Part::GeomArcOfCircle>()) {
originalIsPeriodic = false;
ok = createGeosFromNonPeriodic(
static_cast<const Part::GeomBoundedCurve*>(geo),
[](const Part::GeomCurve* curve, double startParam, double endParam) {
auto newArc = std::unique_ptr<Part::GeomArcOfCircle>(
static_cast<Part::GeomArcOfCircle*>(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<const Part::GeomBoundedCurve*>(geo),
[](const Part::GeomCurve* curve, double startParam, double endParam) {
auto newArc = std::unique_ptr<Part::GeomArcOfConic>(
static_cast<Part::GeomArcOfConic*>(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<Part::GeomBSplineCurve>()) {
const auto* bsp = static_cast<const Part::GeomBSplineCurve*>(geo);

// what to do for periodic b-splines?
originalIsPeriodic = bsp->isPeriodic();
if (originalIsPeriodic) {
ok = createGeosFromPeriodic(
static_cast<const Part::GeomCurve*>(geo),
[](const Part::GeomCurve* curve, double startParam, double endParam) {
auto newBsp = std::unique_ptr<Part::GeomBSplineCurve>(
static_cast<Part::GeomBSplineCurve*>(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<const Part::GeomBoundedCurve*>(geo),
[](const Part::GeomCurve* curve, double startParam, double endParam) {
auto newBsp = std::unique_ptr<Part::GeomBSplineCurve>(
static_cast<Part::GeomBSplineCurve*>(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<const Part::GeomBoundedCurve*>(geo));
}

if (!ok) {
Expand All @@ -4336,27 +4176,58 @@ 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<Part::GeomArcOfCircle>()) {
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<Part::GeomConic>() || geo->isDerivedFrom<Part::GeomArcOfConic>()) {
transferConstraints(GeoId, PointPos::mid, newIds.front(), PointPos::mid);
}

std::vector<int> idsOfOldConstraints;
getConstraintIndices(GeoId, idsOfOldConstraints);

const auto& allConstraints = this->Constraints.getValues();

// 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);
Expand Down

0 comments on commit c6f5739

Please sign in to comment.