Merge pull request #25914 from AjinkyaDahale/sk-fix-25281
Sketcher: Handle angle constraint on sketchobject changes
This commit is contained in:
@@ -3417,7 +3417,7 @@ void createNewConstraintsForTrim(
|
||||
}
|
||||
// We have already transferred all constraints on endpoints to the new pieces.
|
||||
// If there is still any left, this means one of the remaining pieces was degenerate.
|
||||
if (!con->involvesGeoIdAndPosId(GeoId, PointPos::none)) {
|
||||
if (!(con->Type == Angle || con->involvesGeoIdAndPosId(GeoId, PointPos::none))) {
|
||||
continue;
|
||||
}
|
||||
// constraint has not yet been changed
|
||||
@@ -3444,6 +3444,34 @@ void createNewConstraintsForTrim(
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<size_t> findPieceContainingPoint(
|
||||
const SketchObject* obj,
|
||||
const Part::Geometry* geo,
|
||||
const Base::Vector3d& point,
|
||||
const std::vector<int>& newIds,
|
||||
const std::vector<const Part::Geometry*>& newGeos
|
||||
)
|
||||
{
|
||||
double conParam;
|
||||
auto* geoAsCurve = static_cast<const Part::GeomCurve*>(geo);
|
||||
geoAsCurve->closestParameter(point, conParam);
|
||||
// Choose based on where the closest point lies
|
||||
// If it's not there, just leave this constraint out
|
||||
for (size_t i = 0; i < newIds.size(); ++i) {
|
||||
double newGeoFirstParam = static_cast<const Part::GeomCurve*>(newGeos[i])->getFirstParameter();
|
||||
double newGeoLastParam = static_cast<const Part::GeomCurve*>(newGeos[i])->getLastParameter();
|
||||
// For periodic curves the point may need a full revolution
|
||||
if ((newGeoFirstParam - conParam) > Precision::PApproximation() && obj->isClosedCurve(geo)) {
|
||||
conParam += (geoAsCurve->getLastParameter() - geoAsCurve->getFirstParameter());
|
||||
}
|
||||
if ((newGeoFirstParam - conParam) <= Precision::PApproximation()
|
||||
&& (conParam - newGeoLastParam) <= Precision::PApproximation()) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
int SketchObject::trim(int GeoId, const Base::Vector3d& point)
|
||||
{
|
||||
if (!isGeoIdAllowedForTrim(this, GeoId)) {
|
||||
@@ -3693,8 +3721,7 @@ bool SketchObject::deriveConstraintsForPieces(
|
||||
case Vertical:
|
||||
case Parallel: {
|
||||
transferToAll = geo->is<Part::GeomLineSegment>();
|
||||
break;
|
||||
}
|
||||
} break;
|
||||
case Tangent:
|
||||
case Perpendicular: {
|
||||
if (geo->is<Part::GeomLineSegment>()) {
|
||||
@@ -3728,9 +3755,63 @@ bool SketchObject::deriveConstraintsForPieces(
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case Angle: {
|
||||
const auto [thirdGeo, thirdPos] = con->getElement(2);
|
||||
if (thirdGeo == oldId) {
|
||||
// TODO: transfer to a coincident point,
|
||||
// is it possible to do it somewhere else and avoid?
|
||||
std::vector<int> GeoIdList;
|
||||
std::vector<PointPos> PosIdList;
|
||||
getDirectlyCoincidentPoints(thirdGeo, thirdPos, GeoIdList, PosIdList);
|
||||
if (GeoIdList.size() <= 1) {
|
||||
// TODO: Even in this case we can add a point
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
// transfer only to the curve that actually intersects
|
||||
Base::Vector3d point(getPoint(thirdGeo, thirdPos));
|
||||
std::optional<size_t> idx = findPieceContainingPoint(this, geo, point, newIds, newGeos);
|
||||
|
||||
if (idx.has_value()) {
|
||||
Constraint* trans = con->copy();
|
||||
trans->substituteIndexAndPos(GeoIdList[0], PosIdList[0], GeoIdList[1], PosIdList[1]);
|
||||
trans->substituteIndex(oldId, newIds[idx.value()]);
|
||||
newConstraints.push_back(trans);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (thirdGeo != GeoEnum::GeoUndef) {
|
||||
// Angle via point but the point won't change, can transfer to all or first
|
||||
// transfer only to the curve that actually intersects
|
||||
Base::Vector3d point(getPoint(thirdGeo, thirdPos));
|
||||
std::optional<size_t> idx = findPieceContainingPoint(this, geo, point, newIds, newGeos);
|
||||
|
||||
if (idx.has_value()) {
|
||||
Constraint* trans = con->copy();
|
||||
trans->substituteIndex(oldId, newIds[idx.value()]);
|
||||
newConstraints.push_back(trans);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if (std::ranges::any_of(newGeos, [](const Part::Geometry* geo) {
|
||||
return !geo->is<Part::GeomLineSegment>();
|
||||
})) {
|
||||
// Angle without a specific point is only supported when _all_ geometries are lines.
|
||||
// If the original was a line, we may reach this point, for example, when converting
|
||||
// it to NURBS.
|
||||
|
||||
// NOTE: We may decide to change this logic in the future. Follows
|
||||
// `Sketch::addConstraint`.
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
// Straight up angle, can transfer to all or first
|
||||
transferToAll = true;
|
||||
break;
|
||||
}
|
||||
} break;
|
||||
case Distance:
|
||||
case DistanceX:
|
||||
case DistanceY:
|
||||
@@ -3778,9 +3859,7 @@ bool SketchObject::deriveConstraintsForPieces(
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
} break;
|
||||
case Radius:
|
||||
case Diameter:
|
||||
case Equal: {
|
||||
@@ -3794,7 +3873,7 @@ bool SketchObject::deriveConstraintsForPieces(
|
||||
newConstraints.push_back(trans);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
// Release other constraints
|
||||
break;
|
||||
@@ -9493,7 +9572,7 @@ const std::map<int, Sketcher::PointPos> SketchObject::getAllCoincidentPoints(int
|
||||
|
||||
void SketchObject::getDirectlyCoincidentPoints(int GeoId, PointPos PosId,
|
||||
std::vector<int>& GeoIdList,
|
||||
std::vector<PointPos>& PosIdList)
|
||||
std::vector<PointPos>& PosIdList) const
|
||||
{
|
||||
const std::vector<Constraint*>& constraints = this->Constraints.getValues();
|
||||
|
||||
@@ -9535,7 +9614,7 @@ void SketchObject::getDirectlyCoincidentPoints(int GeoId, PointPos PosId,
|
||||
}
|
||||
|
||||
void SketchObject::getDirectlyCoincidentPoints(int VertexId, std::vector<int>& GeoIdList,
|
||||
std::vector<PointPos>& PosIdList)
|
||||
std::vector<PointPos>& PosIdList) const
|
||||
{
|
||||
int GeoId;
|
||||
PointPos PosId;
|
||||
|
||||
@@ -640,12 +640,12 @@ public:
|
||||
PointPos PosId,
|
||||
std::vector<int>& GeoIdList,
|
||||
std::vector<PointPos>& PosIdList
|
||||
);
|
||||
) const;
|
||||
void getDirectlyCoincidentPoints(
|
||||
int VertexId,
|
||||
std::vector<int>& GeoIdList,
|
||||
std::vector<PointPos>& PosIdList
|
||||
);
|
||||
) const;
|
||||
bool arePointsCoincident(int GeoId1, PointPos PosId1, int GeoId2, PointPos PosId2);
|
||||
|
||||
// Returns true if the sketch has 1 or more block constraint
|
||||
|
||||
Reference in New Issue
Block a user