[Sketcher] Add line tangent at knot through endpoint

This commit is contained in:
Ajinkya Dahale
2023-01-16 22:51:20 +05:30
committed by abdullahtahiriyo
parent 199ef42f62
commit 982152c332
3 changed files with 89 additions and 10 deletions

View File

@@ -1715,15 +1715,18 @@ int Sketch::addConstraint(const Constraint *constraint)
c.value, constraint->Type, c.driving);
}
break;
case Tangent:
case Tangent: {
bool isSpecialCase = false;
if (constraint->FirstPos == PointPos::none &&
constraint->SecondPos == PointPos::none &&
constraint->Third == GeoEnum::GeoUndef){
//simple tangency
rtn = addTangentConstraint(constraint->First,constraint->Second);
isSpecialCase = true;
}
else if (constraint->FirstPos == PointPos::start &&
constraint->SecondPos == PointPos::none &&
constraint->Third == GeoEnum::GeoUndef) {
// check for B-Spline Knot to curve tangency
auto knotgeoId = checkGeoId(constraint->First);
@@ -1737,13 +1740,25 @@ int Sketch::addConstraint(const Constraint *constraint)
auto linegeoid = checkGeoId(constraint->Second);
if (Geoms[linegeoid].type == Line)
rtn = addTangentLineAtBSplineKnotConstraint(
linegeoid, bsplinegeoid, knotgeoId);
if (Geoms[linegeoid].type == Line) {
if (constraint->SecondPos == PointPos::none) {
rtn = addTangentLineAtBSplineKnotConstraint(
linegeoid, bsplinegeoid, knotgeoId);
isSpecialCase = true;
}
else if (constraint->SecondPos == PointPos::start ||
constraint->SecondPos == PointPos::end) {
rtn = addTangentLineEndpointAtBSplineKnotConstraint(
linegeoid, constraint->SecondPos, bsplinegeoid, knotgeoId);
isSpecialCase = true;
}
}
}
}
}
else {
if (!isSpecialCase) {
//any other point-wise tangency (endpoint-to-curve, endpoint-to-endpoint, tangent-via-point)
c.value = new double(constraint->getValue());
if(c.driving)
@@ -1760,6 +1775,7 @@ int Sketch::addConstraint(const Constraint *constraint)
c.value, constraint->Type, c.driving);
}
break;
}
case Distance:
if (constraint->SecondPos != PointPos::none){ // point to point distance
c.value = new double(constraint->getValue());
@@ -2497,6 +2513,53 @@ int Sketch::addTangentLineAtBSplineKnotConstraint(int checkedlinegeoId, int chec
}
}
int Sketch::addTangentLineEndpointAtBSplineKnotConstraint(int checkedlinegeoId, PointPos endpointPos, int checkedbsplinegeoId, int checkedknotgeoid)
{
GCS::BSpline &b = BSplines[Geoms[checkedbsplinegeoId].index];
GCS::Line &l = Lines[Geoms[checkedlinegeoId].index];
auto pointId = getPointId(checkedlinegeoId, endpointPos);
auto pointIdKnot = getPointId(checkedknotgeoid, PointPos::start);
GCS::Point &p = Points[pointId];
GCS::Point &pk = Points[pointIdKnot];
size_t knotindex = b.knots.size();
auto knotIt = std::find(b.knotpointGeoids.begin(),
b.knotpointGeoids.end(), checkedknotgeoid);
knotindex = std::distance(b.knotpointGeoids.begin(), knotIt);
if (knotindex >= b.knots.size()){
Base::Console().Error("addConstraint: Knot index out-of-range!\n");
return -1;
}
if (b.mult[knotindex] >= b.degree) {
if (b.periodic || (knotindex > 0 && knotindex < (b.knots.size()-1))) {
Base::Console().Error("addTangentLineEndpointAtBSplineKnotConstraint: cannot set constraint when B-spline slope is discontinuous at knot!\n");
return -1;
}
else {
// TODO: Let angle-at-point do the work. Requires a `double * value`
// return addAngleAtPointConstraint(
// linegeoid, endpointPos,
// bsplinegeoid, PointPos::none,
// knotgeoId, PointPos::start,
// nullptr, Tangent, true);
// For now we just throw an error.
Base::Console().Error("addTangentLineEndpointAtBSplineKnotConstraint: This method cannot set tangent constraint at end knots of a B-spline. Please constrain the start/end points instead.\n");
return -1;
}
}
else {
int tag = ++ConstraintsCounter;
GCSsys.addConstraintP2PCoincident(p, pk, tag);
GCSsys.addConstraintTangentAtBSplineKnot(b, l, knotindex, tag);
return ConstraintsCounter;
}
}
//This function handles any type of tangent, perpendicular and angle
// constraint that involves a point.
// i.e. endpoint-to-curve, endpoint-to-endpoint and tangent-via-point
@@ -3032,7 +3095,7 @@ int Sketch::addSnellsLawConstraint(int geoIdRay1, PointPos posRay1,
GCS::Point &p1 = Points[pointId1];
// add the parameters (refractive indexes)
// n1 uses the place hold by n2divn1, so that is retrivable in updateNonDrivingConstraints
// n1 uses the place hold by n2divn1, so that is retrievable in updateNonDrivingConstraints
double *n1 = value;
double *n2 = secondvalue;

View File

@@ -283,6 +283,7 @@ public:
/// add a tangency constraint between two geometries
int addTangentConstraint(int geoId1, int geoId2);
int addTangentLineAtBSplineKnotConstraint(int checkedlinegeoId, int checkedbsplinegeoId, int checkedknotgeoid);
int addTangentLineEndpointAtBSplineKnotConstraint(int checkedlinegeoId, PointPos endpointPos, int checkedbsplinegeoId, int checkedknotgeoid);
int addAngleAtPointConstraint(
int geoId1, PointPos pos1,
int geoId2, PointPos pos2,

View File

@@ -4203,11 +4203,26 @@ void CmdSketcherConstrainTangent::activated(int iMsg)
if (isVertex(GeoId1,PosId1) && isVertex(GeoId2,PosId2)) { // endpoint-to-endpoint tangency
if (isBsplineKnot(Obj, GeoId2)) {
std::swap(GeoId1,GeoId2);
std::swap(PosId1,PosId2);
}
if (isSimpleVertex(Obj, GeoId1, PosId1) ||
isSimpleVertex(Obj, GeoId2, PosId2)) {
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
QObject::tr("Cannot add a tangency constraint at an unconnected point!"));
return;
if (isBsplineKnot(Obj, GeoId1)) {
const Part::Geometry *geom2 = Obj->getGeometry(GeoId2);
if (!geom2 || geom2->getTypeId() !=Part::GeomLineSegment::getClassTypeId()) {
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
QObject::tr("Tangent constraint at B-spline knot is only supported with lines!"));
return;
}
}
else {
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
QObject::tr("Cannot add a tangency constraint at an unconnected point!"));
return;
}
}
openCommand(QT_TRANSLATE_NOOP("Command", "Add tangent constraint"));