[Sketcher] Only move one piece of B-spline when dragging

This commit is contained in:
Ajinkya Dahale
2022-06-28 23:58:08 +05:30
committed by abdullahtahiriyo
parent e899c221cc
commit 4db7da7314
4 changed files with 89 additions and 2 deletions

View File

@@ -4021,6 +4021,66 @@ void Sketch::resetInitMove()
isInitMove = false;
}
int Sketch::initBSplinePieceMove(int geoId, PointPos pos, const Base::Vector3d& firstPoint, bool fine)
{
isFine = fine;
geoId = checkGeoId(geoId);
clearTemporaryConstraints();
// don't try to move sketches that contain conflicting constraints
if (hasConflicts()) {
isInitMove = false;
return -1;
}
// this is only meant for B-Splines
if (Geoms[geoId].type != BSpline || pos == PointPos::start || pos == PointPos::end) {
return -1;
}
// Find the closest knot
auto partBsp = static_cast<GeomBSplineCurve*>(Geoms[geoId].geo);
double uNear;
partBsp->closestParameter(firstPoint, uNear);
GCS::BSpline &bsp = BSplines[Geoms[geoId].index];
auto& knots = bsp.knots;
auto upperknot = std::upper_bound(
knots.begin(), knots.end(), uNear,
[](double u, double* element) {
return u < *element;
});
size_t idx = 0;
// skipping the first knot for adjustment
// TODO: ensure this works for periodic as well
for (size_t i=1; i<bsp.mult.size() && knots[i]!=*upperknot; ++i)
idx += bsp.mult[i];
MoveParameters.resize(2*(bsp.degree+1)); // x[idx],y[idx],x[idx+1],y[idx+1],...
size_t mvindex = 0;
auto lastIt = (idx + bsp.degree + 1) % bsp.poles.size();
for (size_t i = idx; i != lastIt; i=(i+1)%bsp.poles.size(), ++mvindex) {
GCS::Point p1;
p1.x = &MoveParameters[mvindex];
++mvindex;
p1.y = &MoveParameters[mvindex];
*p1.x = *bsp.poles[i].x;
*p1.y = *bsp.poles[i].y;
GCSsys.addConstraintP2PCoincident(p1,bsp.poles[i],GCS::DefaultTemporaryConstraint);
}
InitParameters = MoveParameters;
GCSsys.initSolution();
isInitMove = true;
return 0;
}
int Sketch::movePoint(int geoId, PointPos pos, Base::Vector3d toPoint, bool relative)
{
geoId = checkGeoId(geoId);

View File

@@ -133,10 +133,19 @@ public:
*/
int initMove(int geoId, PointPos pos, bool fine=true);
/** Initializes a B-spline piece drag by setting the current
* sketch status as a reference. Only moves piece around `firstPoint`.
*/
int initBSplinePieceMove(int geoId, PointPos pos, const Base::Vector3d& firstPoint, bool fine=true);
/** Resets the initialization of a point or curve drag
*/
void resetInitMove();
/** Limits a b-spline drag to the segment around `firstPoint`.
*/
int limitBSplineMove(int geoId, PointPos pos, const Base::Vector3d& firstPoint);
/** move this point (or curve) to a new location and solve.
* This will introduce some additional weak constraints expressing
* a condition for satisfying the new point location!

View File

@@ -450,6 +450,8 @@ public: /* Solver exposed interface */
{solvedSketch.setRecalculateInitialSolutionWhileMovingPoint(recalculateInitialSolutionWhileMovingPoint);}
/// Forwards a request for a temporary initMove to the solver using the current sketch state as a reference (enables dragging)
inline int initTemporaryMove(int geoId, PointPos pos, bool fine=true);
/// Forwards a request for a temporary initBSplinePieceMove to the solver using the current sketch state as a reference (enables dragging)
inline int initTemporaryBSplinePieceMove(int geoId, PointPos pos, const Base::Vector3d& firstPoint, bool fine=true);
/** Forwards a request for point or curve temporary movement to the solver using the current state as a reference (enables dragging).
* NOTE: A temporary move operation must always be preceded by a initTemporaryMove() operation.
*/
@@ -692,6 +694,17 @@ inline int SketchObject::initTemporaryMove(int geoId, PointPos pos, bool fine/*=
return solvedSketch.initMove(geoId,pos,fine);
}
inline int SketchObject::initTemporaryBSplinePieceMove(int geoId, PointPos pos, const Base::Vector3d& firstPoint, bool fine)
{
// if a previous operation did not update the geometry (including geometry extensions)
// or constraints (including any deleted pointer, as in renameConstraint) of the solver,
// here we update them before starting a temporary operation.
if(solverNeedsUpdate)
solve();
return solvedSketch.initBSplinePieceMove(geoId,pos,firstPoint,fine);
}
inline int SketchObject::moveTemporaryPoint(int geoId, PointPos pos, Base::Vector3d toPoint, bool relative/*=false*/)
{
return solvedSketch.movePoint(geoId, pos, toPoint, relative);

View File

@@ -1234,8 +1234,13 @@ bool ViewProviderSketch::mouseMove(const SbVec2s &cursorPos, Gui::View3DInventor
drag.resetVector();
}
getSketchObject()->initTemporaryMove(drag.DragCurve, Sketcher::PointPos::none, false);
if (geo->getTypeId() == Part::GeomBSplineCurve::getClassTypeId()) {
getSketchObject()->initTemporaryBSplinePieceMove(
drag.DragCurve, Sketcher::PointPos::none,
Base::Vector3d(drag.xInit, drag.yInit, 0.0), false);
} else {
getSketchObject()->initTemporaryMove(drag.DragCurve, Sketcher::PointPos::none, false);
}
} else {
Mode = STATUS_NONE;
}