Skip to content

Commit

Permalink
Merge pull request FreeCAD#11853 from AjinkyaDahale/sketcher-general-…
Browse files Browse the repository at this point in the history
…tangency-splines

[Sketcher] General Tangency with B-splines (re-do)
  • Loading branch information
chennes authored Feb 8, 2024
2 parents 73d214a + 3f1f638 commit 9695bf0
Show file tree
Hide file tree
Showing 12 changed files with 1,336 additions and 279 deletions.
153 changes: 149 additions & 4 deletions src/Mod/Sketcher/App/Sketch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand All @@ -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) {
Expand All @@ -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];
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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, &param1, &param2);
}

Base::Vector3d Sketch::calculateNormalAtPoint(int geoIdCurve, double px, double py) const
{
geoIdCurve = checkGeoId(geoIdCurve);
Expand Down
2 changes: 2 additions & 0 deletions src/Mod/Sketcher/App/Sketch.h
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,8 @@ class SketcherExport Sketch: public Base::Persistence
// value as the point approaches intersection of curves).
double calculateAngleViaPoint(int geoId1, int geoId2, double px, double py);

double calculateAngleViaParams(int geoId1, int geoId2, double param1, double param2);

// This is to be used for rendering of angle-via-point constraint.
Base::Vector3d calculateNormalAtPoint(int geoIdCurve, double px, double py) const;

Expand Down
15 changes: 13 additions & 2 deletions src/Mod/Sketcher/App/SketchObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8578,13 +8578,24 @@ double SketchObject::calculateAngleViaPoint(int GeoId1, int GeoId2, double px, d
// Temporary sketch based calculation. Slow, but guaranteed consistency with constraints.
Sketcher::Sketch sk;

const Part::Geometry* p1 = this->getGeometry(GeoId1);
const Part::Geometry* p2 = this->getGeometry(GeoId2);
const Part::GeomCurve* p1 = dynamic_cast<const Part::GeomCurve*>(this->getGeometry(GeoId1));
const Part::GeomCurve* p2 = dynamic_cast<const Part::GeomCurve*>(this->getGeometry(GeoId2));

if (p1 && p2) {
// TODO: Check if any of these are B-splines
int i1 = sk.addGeometry(this->getGeometry(GeoId1));
int i2 = sk.addGeometry(this->getGeometry(GeoId2));

if (p1->is<Part::GeomBSplineCurve>() ||
p2->is<Part::GeomBSplineCurve>()) {
double p1ClosestParam, p2ClosestParam;
Base::Vector3d pt(px, py, 0);
p1->closestParameter(pt, p1ClosestParam);
p2->closestParameter(pt, p2ClosestParam);

return sk.calculateAngleViaParams(i1, i2, p1ClosestParam, p2ClosestParam);
}

return sk.calculateAngleViaPoint(i1, i2, px, py);
}
else
Expand Down
Loading

0 comments on commit 9695bf0

Please sign in to comment.