[Sketcher] Expose general tangency with B-splines to Sketcher
The following commits were squashed into this [Sketcher] Handle some corner cases in AngleViaPoint [Sketcher] Avoid redundant constraints with B-splines... When involving tangent, perpendicular and angle constraints. [Sketcher] Add pre-commit changes [Sketcher] Do not allow 2-selection tangent with B-spline Also... [Sketcher] Report error when using direct tangency with B-splines [Sketcher] Fix malformed constraint when B-spline is selected second To clarify, this means the second curve selected. The position of the point in selection order does not matter in angle-via-point. [Sketcher] Fix wrong number for B-Spline tangent on redundancy [Sketcher] Remove existing point-on-object in some redundant cases Particularly when point constrained on a B-spline is being used for tangent, perpendicular or angle via point with the same B-spline. [Sketcher] Fix direction issue with B-spline tangents. Without these changes the solver might try to "twist" the B-spline to make the angle between curves be 0 instead of PI (which may be closer to the initial shape).
This commit is contained in:
@@ -2868,6 +2868,11 @@ int Sketch::addTangentConstraint(int geoId1, int geoId2)
|
||||
GCSsys.addConstraintTangent(l, a, tag);
|
||||
return ConstraintsCounter;
|
||||
}
|
||||
else if (Geoms[geoId2].type == BSpline) {
|
||||
Base::Console().Error("Direct tangency constraint between line and B-spline is not "
|
||||
"supported. Use tangent-via-point instead.");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if (Geoms[geoId1].type == Circle) {
|
||||
GCS::Circle& c = Circles[Geoms[geoId1].index];
|
||||
@@ -2888,6 +2893,11 @@ int Sketch::addTangentConstraint(int geoId1, int geoId2)
|
||||
GCSsys.addConstraintTangent(c, a, tag);
|
||||
return ConstraintsCounter;
|
||||
}
|
||||
else if (Geoms[geoId2].type == BSpline) {
|
||||
Base::Console().Error("Direct tangency constraint between circle and B-spline is not "
|
||||
"supported. Use tangent-via-point instead.");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if (Geoms[geoId1].type == Ellipse) {
|
||||
if (Geoms[geoId2].type == Circle) {
|
||||
@@ -2900,6 +2910,11 @@ int Sketch::addTangentConstraint(int geoId1, int geoId2)
|
||||
"supported. Use tangent-via-point instead.");
|
||||
return -1;
|
||||
}
|
||||
else if (Geoms[geoId2].type == BSpline) {
|
||||
Base::Console().Error("Direct tangency constraint between ellipse and B-spline is not "
|
||||
"supported. Use tangent-via-point instead.");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if (Geoms[geoId1].type == Arc) {
|
||||
GCS::Arc& a = Arcs[Geoms[geoId1].index];
|
||||
@@ -2920,6 +2935,16 @@ int Sketch::addTangentConstraint(int geoId1, int geoId2)
|
||||
GCSsys.addConstraintTangent(a, a2, tag);
|
||||
return ConstraintsCounter;
|
||||
}
|
||||
else if (Geoms[geoId2].type == BSpline) {
|
||||
Base::Console().Error("Direct tangency constraint between arc and B-spline is not "
|
||||
"supported. Use tangent-via-point instead.");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if (Geoms[geoId1].type == BSpline) {
|
||||
Base::Console().Error("Direct tangency constraint including B-splines is not "
|
||||
"supported. Use tangent-via-point instead.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return -1;
|
||||
@@ -3041,7 +3066,6 @@ int Sketch::addAngleAtPointConstraint(int geoId1,
|
||||
ConstraintType cTyp,
|
||||
bool driving)
|
||||
{
|
||||
|
||||
if (!(cTyp == Angle || cTyp == Tangent || cTyp == Perpendicular)) {
|
||||
// assert(0);//none of the three types. Why are we here??
|
||||
return -1;
|
||||
@@ -3146,19 +3170,116 @@ int Sketch::addAngleAtPointConstraint(int geoId1,
|
||||
}
|
||||
|
||||
int tag = -1;
|
||||
// FIXME: Perform construction of any parameters where this method is called instead of here
|
||||
if (e2c) {
|
||||
// increases ConstraintsCounter
|
||||
tag = Sketch::addPointOnObjectConstraint(geoId1, pos1, geoId2, driving);
|
||||
if (Geoms[geoId2].type == BSpline) {
|
||||
GCS::Point& p1 = Points[getPointId(geoId1, pos1)];
|
||||
auto* partBsp = static_cast<GeomBSplineCurve*>(Geoms[geoId2].geo);
|
||||
double uNear;
|
||||
partBsp->closestParameter(Base::Vector3d(*p1.x, *p1.y, 0.0), uNear);
|
||||
double* pointparam = new double(uNear);
|
||||
Parameters.push_back(pointparam);
|
||||
--ConstraintsCounter; // Do this just before point-on-object because ConstraintsCounter
|
||||
// is increased again before being used
|
||||
tag = addPointOnObjectConstraint(geoId1,
|
||||
pos1,
|
||||
geoId2,
|
||||
pointparam,
|
||||
driving); // increases ConstraintsCounter
|
||||
GCSsys.addConstraintAngleViaPointAndParam(*crv2,
|
||||
*crv1,
|
||||
p,
|
||||
pointparam,
|
||||
angle,
|
||||
tag,
|
||||
driving);
|
||||
}
|
||||
else {
|
||||
// increases ConstraintsCounter
|
||||
tag = Sketch::addPointOnObjectConstraint(geoId1,
|
||||
pos1,
|
||||
geoId2,
|
||||
driving); // increases ConstraintsCounter
|
||||
GCSsys.addConstraintAngleViaPoint(*crv1, *crv2, p, angle, tag, driving);
|
||||
}
|
||||
}
|
||||
if (e2e) {
|
||||
tag = ++ConstraintsCounter;
|
||||
GCSsys.addConstraintP2PCoincident(p, *p2, tag, driving);
|
||||
GCSsys.addConstraintAngleViaPoint(*crv1, *crv2, p, angle, tag, driving);
|
||||
}
|
||||
if (avp) {
|
||||
tag = ++ConstraintsCounter;
|
||||
if (Geoms[geoId1].type == BSpline || Geoms[geoId2].type == BSpline) {
|
||||
if (Geoms[geoId1].type == BSpline && Geoms[geoId2].type == BSpline) {
|
||||
GCS::Point& p3 = Points[getPointId(geoId3, pos3)];
|
||||
auto* partBsp = static_cast<GeomBSplineCurve*>(Geoms[geoId1].geo);
|
||||
double uNear;
|
||||
partBsp->closestParameter(Base::Vector3d(*p3.x, *p3.y, 0.0), uNear);
|
||||
double* pointparam1 = new double(uNear);
|
||||
Parameters.push_back(pointparam1);
|
||||
--ConstraintsCounter; // Do this just before point-on-object because
|
||||
// ConstraintsCounter is increased again before being used
|
||||
addPointOnObjectConstraint(geoId3,
|
||||
pos3,
|
||||
geoId1,
|
||||
pointparam1,
|
||||
driving); // increases ConstraintsCounter
|
||||
partBsp = static_cast<GeomBSplineCurve*>(Geoms[geoId2].geo);
|
||||
partBsp->closestParameter(Base::Vector3d(*p3.x, *p3.y, 0.0), uNear);
|
||||
double* pointparam2 = new double(uNear);
|
||||
--ConstraintsCounter; // Do this just before point-on-object because
|
||||
// ConstraintsCounter is increased again before being used
|
||||
addPointOnObjectConstraint(geoId3,
|
||||
pos3,
|
||||
geoId2,
|
||||
pointparam2,
|
||||
driving); // increases ConstraintsCounter
|
||||
Parameters.push_back(pointparam2);
|
||||
GCSsys.addConstraintAngleViaPointAndTwoParams(*crv1,
|
||||
*crv2,
|
||||
p,
|
||||
pointparam1,
|
||||
pointparam2,
|
||||
angle,
|
||||
tag,
|
||||
driving);
|
||||
}
|
||||
else {
|
||||
if (Geoms[geoId1].type != BSpline) {
|
||||
std::swap(geoId1, geoId2);
|
||||
std::swap(crv1, crv2);
|
||||
std::swap(pos1, pos2);
|
||||
// FIXME: Confirm whether or not this is needed
|
||||
// *angle = -*angle;
|
||||
}
|
||||
GCS::Point& p3 = Points[getPointId(geoId3, pos3)];
|
||||
auto* partBsp = static_cast<GeomBSplineCurve*>(Geoms[geoId1].geo);
|
||||
double uNear;
|
||||
partBsp->closestParameter(Base::Vector3d(*p3.x, *p3.y, 0.0), uNear);
|
||||
double* pointparam = new double(uNear);
|
||||
Parameters.push_back(pointparam);
|
||||
--ConstraintsCounter; // Do this just before point-on-object because
|
||||
// ConstraintsCounter is increased again before being used
|
||||
addPointOnObjectConstraint(geoId3,
|
||||
pos3,
|
||||
geoId1,
|
||||
pointparam,
|
||||
driving); // increases ConstraintsCounter
|
||||
GCSsys.addConstraintAngleViaPointAndParam(*crv1,
|
||||
*crv2,
|
||||
p,
|
||||
pointparam,
|
||||
angle,
|
||||
tag,
|
||||
driving);
|
||||
}
|
||||
}
|
||||
else {
|
||||
GCSsys.addConstraintAngleViaPoint(*crv1, *crv2, p, angle, tag, driving);
|
||||
}
|
||||
}
|
||||
|
||||
GCSsys.addConstraintAngleViaPoint(*crv1, *crv2, p, angle, tag, driving);
|
||||
return ConstraintsCounter;
|
||||
}
|
||||
|
||||
@@ -4139,6 +4260,30 @@ double Sketch::calculateAngleViaPoint(int geoId1, int geoId2, double px, double
|
||||
return GCSsys.calculateAngleViaPoint(*crv1, *crv2, p);
|
||||
}
|
||||
|
||||
double Sketch::calculateAngleViaParams(int geoId1, int geoId2, double param1, double param2)
|
||||
{
|
||||
geoId1 = checkGeoId(geoId1);
|
||||
geoId2 = checkGeoId(geoId2);
|
||||
|
||||
// check pointers
|
||||
GCS::Curve* crv1 = getGCSCurveByGeoId(geoId1);
|
||||
GCS::Curve* crv2 = getGCSCurveByGeoId(geoId2);
|
||||
if (!crv1 || !crv2) {
|
||||
throw Base::ValueError("calculateAngleViaPoint: getGCSCurveByGeoId returned NULL!");
|
||||
}
|
||||
// FIXME: This should probably not be needed
|
||||
auto* crv1AsBSpline = dynamic_cast<GCS::BSpline*>(crv1);
|
||||
if (crv1AsBSpline && crv1AsBSpline->flattenedknots.empty()) {
|
||||
crv1AsBSpline->setupFlattenedKnots();
|
||||
}
|
||||
auto* crv2AsBSpline = dynamic_cast<GCS::BSpline*>(crv2);
|
||||
if (crv2AsBSpline && crv2AsBSpline->flattenedknots.empty()) {
|
||||
crv2AsBSpline->setupFlattenedKnots();
|
||||
}
|
||||
|
||||
return GCSsys.calculateAngleViaParams(*crv1, *crv2, ¶m1, ¶m2);
|
||||
}
|
||||
|
||||
Base::Vector3d Sketch::calculateNormalAtPoint(int geoIdCurve, double px, double py) const
|
||||
{
|
||||
geoIdCurve = checkGeoId(geoIdCurve);
|
||||
|
||||
Reference in New Issue
Block a user