Sketcher: Fix Angle Constraint jumping to opposite side on movement (#24150)
* Sketcher: Fix Angle Constraint jumping to opposite side on movement * implement way to dynamically disable snapping where not needed --------- Co-authored-by: Matthias Danner <28687794+matthiasdanner@users.noreply.github.com>
This commit is contained in:
@@ -1153,12 +1153,7 @@ void SketchObject::reverseAngleConstraintToSupplementary(Constraint* constr, int
|
||||
{
|
||||
std::swap(constr->First, constr->Second);
|
||||
std::swap(constr->FirstPos, constr->SecondPos);
|
||||
if (constr->FirstPos == constr->SecondPos) {
|
||||
constr->FirstPos = (constr->FirstPos == Sketcher::PointPos::start) ? Sketcher::PointPos::end : Sketcher::PointPos::start;
|
||||
}
|
||||
else {
|
||||
constr->SecondPos = (constr->SecondPos == Sketcher::PointPos::start) ? Sketcher::PointPos::end : Sketcher::PointPos::start;
|
||||
}
|
||||
constr->FirstPos = (constr->FirstPos == Sketcher::PointPos::start) ? Sketcher::PointPos::end : Sketcher::PointPos::start;
|
||||
|
||||
// Edit the expression if any, else modify constraint value directly
|
||||
if (constraintHasExpression(constNum)) {
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
#include "ViewProviderSketch.h"
|
||||
#include "ui_InsertDatum.h"
|
||||
#include <Inventor/events/SoKeyboardEvent.h>
|
||||
#include "SnapManager.h"
|
||||
|
||||
// Remove this after pre-commit hook is activated
|
||||
// clang-format off
|
||||
@@ -1033,7 +1034,7 @@ public:
|
||||
Gui::Selection().rmvSelectionGate();
|
||||
}
|
||||
|
||||
void mouseMove(Base::Vector2d /*onSketchPos*/) override
|
||||
void mouseMove(SnapManager::SnapHandle snapHandle) override
|
||||
{}
|
||||
|
||||
bool pressButton(Base::Vector2d /*onSketchPos*/) override
|
||||
@@ -1835,13 +1836,16 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void mouseMove(Base::Vector2d onSketchPos) override
|
||||
void mouseMove(SnapManager::SnapHandle snapHandle) override
|
||||
{
|
||||
if (hasBeenAborted()) {
|
||||
resetTool();
|
||||
return;
|
||||
}
|
||||
|
||||
//All snap Positions except of edges, because it results in jumps on angle constraints
|
||||
SnapType mask = static_cast<SnapType>(static_cast<int>(SnapType::All) & ~static_cast<int>(SnapType::Edge));
|
||||
Base::Vector2d onSketchPos = snapHandle.compute(mask);
|
||||
previousOnSketchPos = onSketchPos;
|
||||
|
||||
//Change distance constraint based on position of mouse.
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
#include "DrawSketchHandler.h"
|
||||
#include "Utils.h"
|
||||
#include "ViewProviderSketch.h"
|
||||
#include "SnapManager.h"
|
||||
|
||||
|
||||
using namespace std;
|
||||
@@ -765,9 +766,10 @@ public:
|
||||
~DrawSketchHandlerBSplineInsertKnot() override
|
||||
{}
|
||||
|
||||
void mouseMove(Base::Vector2d onSketchPos) override
|
||||
void mouseMove(SnapManager::SnapHandle snapHandle) override
|
||||
{
|
||||
auto bsp = static_cast<const Part::GeomBSplineCurve*>(Obj->getGeometry(GeoId));
|
||||
Base::Vector2d onSketchPos = snapHandle.compute();
|
||||
|
||||
// get closest parameter using OCC
|
||||
// TODO: This is called every time we move the cursor. Can get overwhelming.
|
||||
|
||||
@@ -64,6 +64,7 @@
|
||||
#include "DrawSketchHandlerRotate.h"
|
||||
#include "DrawSketchHandlerScale.h"
|
||||
#include "DrawSketchHandlerSymmetry.h"
|
||||
#include "SnapManager.h"
|
||||
|
||||
// Hint: this is to prevent to re-format big parts of the file. Remove it later again.
|
||||
// clang-format off
|
||||
@@ -1211,9 +1212,10 @@ public:
|
||||
Snap5Degree
|
||||
};
|
||||
|
||||
void mouseMove(Base::Vector2d onSketchPos) override
|
||||
void mouseMove(SnapManager::SnapHandle snapHandle) override
|
||||
{
|
||||
using std::numbers::pi;
|
||||
Base::Vector2d onSketchPos = snapHandle.compute();
|
||||
|
||||
if (Mode == STATUS_SEEK_First) {
|
||||
|
||||
@@ -1789,9 +1791,10 @@ public:
|
||||
Snap5Degree
|
||||
};
|
||||
|
||||
void mouseMove(Base::Vector2d onSketchPos) override
|
||||
void mouseMove(SnapManager::SnapHandle snapHandle) override
|
||||
{
|
||||
using std::numbers::pi;
|
||||
Base::Vector2d onSketchPos = snapHandle.compute();
|
||||
|
||||
if (Mode == STATUS_SEEK_First) {
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <type_traits>
|
||||
|
||||
#include "DrawSketchDefaultHandler.h"
|
||||
#include "SnapManager.h"
|
||||
|
||||
namespace SketcherGui
|
||||
{
|
||||
@@ -79,8 +80,9 @@ public:
|
||||
|
||||
/** @name functions NOT intended for specialisation or further overriding */
|
||||
//@{
|
||||
void mouseMove(Base::Vector2d onSketchPos) override
|
||||
void mouseMove(SnapManager::SnapHandle snapHandle) override
|
||||
{
|
||||
Base::Vector2d onSketchPos = snapHandle.compute();
|
||||
toolWidgetManager.mouseMoved(onSketchPos);
|
||||
|
||||
toolWidgetManager.enforceControlParameters(onSketchPos);
|
||||
|
||||
@@ -333,7 +333,8 @@ public:
|
||||
handler->reset(); // reset of handler to restart.
|
||||
}
|
||||
|
||||
handler->mouseMove(prevCursorPosition);
|
||||
auto snapHandle = std::make_unique<SnapManager::SnapHandle>(nullptr, prevCursorPosition);
|
||||
handler->mouseMove(*snapHandle);
|
||||
}
|
||||
//@}
|
||||
|
||||
@@ -534,7 +535,9 @@ public:
|
||||
virtual void afterHandlerModeChanged()
|
||||
{
|
||||
if (handler && (!handler->isState(SelectModeT::End) || handler->continuousMode)) {
|
||||
handler->mouseMove(prevCursorPosition);
|
||||
auto snapHandle =
|
||||
std::make_unique<SnapManager::SnapHandle>(nullptr, prevCursorPosition);
|
||||
handler->mouseMove(*snapHandle);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -624,7 +627,8 @@ protected:
|
||||
/// change
|
||||
void finishControlsChanged()
|
||||
{
|
||||
handler->mouseMove(prevCursorPosition);
|
||||
auto snapHandle = std::make_unique<SnapManager::SnapHandle>(nullptr, prevCursorPosition);
|
||||
handler->mouseMove(*snapHandle);
|
||||
|
||||
auto currentstate = handler->state();
|
||||
// ensure that object at point is preselected, so that autoconstraints are generated
|
||||
@@ -645,7 +649,9 @@ protected:
|
||||
// reset)
|
||||
if (shouldProcessLastPosWithNextState) {
|
||||
// mode has changed, so reprocess the previous position to the new widget state
|
||||
handler->mouseMove(prevCursorPosition);
|
||||
auto snapHandle =
|
||||
std::make_unique<SnapManager::SnapHandle>(nullptr, prevCursorPosition);
|
||||
handler->mouseMove(*snapHandle);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
#include "AutoConstraint.h"
|
||||
#include "DrawSketchHandler.h"
|
||||
#include "ViewProviderSketch.h"
|
||||
#include "SnapManager.h"
|
||||
|
||||
#include "Utils.h"
|
||||
|
||||
@@ -425,9 +426,9 @@ public:
|
||||
* overridden/specialised instead.
|
||||
*/
|
||||
//@{
|
||||
void mouseMove(Base::Vector2d onSketchPos) override
|
||||
void mouseMove(SnapManager::SnapHandle snapHandle) override
|
||||
{
|
||||
updateDataAndDrawToPosition(onSketchPos);
|
||||
updateDataAndDrawToPosition(snapHandle.compute());
|
||||
}
|
||||
|
||||
bool pressButton(Base::Vector2d onSketchPos) override
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
|
||||
#include "AutoConstraint.h"
|
||||
#include "Utils.h"
|
||||
#include "SnapManager.h"
|
||||
|
||||
class QWidget;
|
||||
|
||||
@@ -154,7 +155,7 @@ public:
|
||||
void setSketchGui(ViewProviderSketch* vp);
|
||||
void deactivate() override;
|
||||
|
||||
virtual void mouseMove(Base::Vector2d pos) = 0;
|
||||
virtual void mouseMove(SnapManager::SnapHandle snapHandle) = 0;
|
||||
virtual bool pressButton(Base::Vector2d pos) = 0;
|
||||
virtual bool releaseButton(Base::Vector2d pos) = 0;
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "GeometryCreationMode.h"
|
||||
#include "Utils.h"
|
||||
#include "ViewProviderSketch.h"
|
||||
#include "SnapManager.h"
|
||||
|
||||
|
||||
namespace SketcherGui
|
||||
@@ -67,9 +68,10 @@ public:
|
||||
STATUS_Close
|
||||
};
|
||||
|
||||
void mouseMove(Base::Vector2d onSketchPos) override
|
||||
void mouseMove(SnapManager::SnapHandle snapHandle) override
|
||||
{
|
||||
using std::numbers::pi;
|
||||
Base::Vector2d onSketchPos = snapHandle.compute();
|
||||
|
||||
if (Mode == STATUS_SEEK_First) {
|
||||
setPositionText(onSketchPos);
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include "GeometryCreationMode.h"
|
||||
#include "Utils.h"
|
||||
#include "ViewProviderSketch.h"
|
||||
#include "SnapManager.h"
|
||||
|
||||
|
||||
namespace SketcherGui
|
||||
@@ -64,8 +65,9 @@ public:
|
||||
STATUS_Close
|
||||
};
|
||||
|
||||
void mouseMove(Base::Vector2d onSketchPos) override
|
||||
void mouseMove(SnapManager::SnapHandle snapHandle) override
|
||||
{
|
||||
Base::Vector2d onSketchPos = snapHandle.compute();
|
||||
if (Mode == STATUS_SEEK_First) {
|
||||
setPositionText(onSketchPos);
|
||||
seekAndRenderAutoConstraint(sugConstr1, onSketchPos, Base::Vector2d(0.f, 0.f));
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include "GeometryCreationMode.h"
|
||||
#include "Utils.h"
|
||||
#include "ViewProviderSketch.h"
|
||||
#include "SnapManager.h"
|
||||
|
||||
namespace SketcherGui
|
||||
{
|
||||
@@ -67,8 +68,9 @@ public:
|
||||
STATUS_Close
|
||||
};
|
||||
|
||||
void mouseMove(Base::Vector2d onSketchPos) override
|
||||
void mouseMove(SnapManager::SnapHandle snapHandle) override
|
||||
{
|
||||
Base::Vector2d onSketchPos = snapHandle.compute();
|
||||
if (Mode == STATUS_SEEK_First) {
|
||||
setPositionText(onSketchPos);
|
||||
seekAndRenderAutoConstraint(sugConstr1, onSketchPos, Base::Vector2d(0.f, 0.f));
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
#include "GeometryCreationMode.h"
|
||||
#include "Utils.h"
|
||||
#include "ViewProviderSketch.h"
|
||||
#include "SnapManager.h"
|
||||
|
||||
|
||||
namespace SketcherGui
|
||||
@@ -127,9 +128,9 @@ public:
|
||||
Gui::Selection().rmvSelectionGate();
|
||||
}
|
||||
|
||||
void mouseMove(Base::Vector2d onSketchPos) override
|
||||
void mouseMove(SnapManager::SnapHandle snapHandle) override
|
||||
{
|
||||
Q_UNUSED(onSketchPos);
|
||||
Q_UNUSED(snapHandle);
|
||||
if (Gui::Selection().getPreselection().pObjectName) {
|
||||
applyCursor();
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "GeometryCreationMode.h"
|
||||
#include "Utils.h"
|
||||
#include "ViewProviderSketch.h"
|
||||
#include "SnapManager.h"
|
||||
|
||||
|
||||
namespace SketcherGui
|
||||
@@ -107,9 +108,9 @@ public:
|
||||
STATUS_SEEK_Second,
|
||||
};
|
||||
|
||||
void mouseMove(Base::Vector2d onSketchPos) override
|
||||
void mouseMove(SnapManager::SnapHandle snapHandle) override
|
||||
{
|
||||
Q_UNUSED(onSketchPos);
|
||||
Base::Vector2d onSketchPos = snapHandle.compute();
|
||||
|
||||
using std::numbers::pi;
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
#include "Utils.h"
|
||||
#include "ViewProviderSketch.h"
|
||||
#include <Mod/Part/App/Datums.h>
|
||||
#include "SnapManager.h"
|
||||
|
||||
|
||||
namespace SketcherGui
|
||||
@@ -133,9 +134,9 @@ public:
|
||||
Gui::Selection().rmvSelectionGate();
|
||||
}
|
||||
|
||||
void mouseMove(Base::Vector2d onSketchPos) override
|
||||
void mouseMove(SnapManager::SnapHandle snapHandle) override
|
||||
{
|
||||
Q_UNUSED(onSketchPos);
|
||||
Q_UNUSED(snapHandle);
|
||||
if (Gui::Selection().getPreselection().pObjectName) {
|
||||
applyCursor();
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
#include "GeometryCreationMode.h"
|
||||
#include "Utils.h"
|
||||
#include "ViewProviderSketch.h"
|
||||
#include "SnapManager.h"
|
||||
|
||||
|
||||
namespace SketcherGui
|
||||
@@ -181,16 +182,18 @@ public:
|
||||
else {
|
||||
EditCurve.resize(32);
|
||||
}
|
||||
mouseMove(onSketchPos); // trigger an update of EditCurve
|
||||
auto snapHandle = std::make_unique<SnapManager::SnapHandle>(nullptr, onSketchPos);
|
||||
mouseMove(*snapHandle); // trigger an update of EditCurve
|
||||
}
|
||||
else {
|
||||
DrawSketchHandler::registerPressedKey(pressed, key);
|
||||
}
|
||||
}
|
||||
|
||||
void mouseMove(Base::Vector2d onSketchPos) override
|
||||
void mouseMove(SnapManager::SnapHandle snapHandle) override
|
||||
{
|
||||
using std::numbers::pi;
|
||||
Base::Vector2d onSketchPos = snapHandle.compute();
|
||||
|
||||
suppressTransition = false;
|
||||
if (Mode == STATUS_SEEK_First) {
|
||||
@@ -711,7 +714,8 @@ public:
|
||||
SegmentMode = SEGMENT_MODE_Line;
|
||||
SnapMode = SNAP_MODE_Free;
|
||||
EditCurve[1] = EditCurve[0];
|
||||
mouseMove(onSketchPos); // trigger an update of EditCurve
|
||||
auto snapHandle = std::make_unique<SnapManager::SnapHandle>(nullptr, onSketchPos);
|
||||
mouseMove(*snapHandle); // trigger an update of EditCurve
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "GeometryCreationMode.h"
|
||||
#include "Utils.h"
|
||||
#include "ViewProviderSketch.h"
|
||||
#include "SnapManager.h"
|
||||
|
||||
|
||||
namespace SketcherGui
|
||||
@@ -100,9 +101,9 @@ public:
|
||||
Gui::Selection().rmvSelectionGate();
|
||||
}
|
||||
|
||||
void mouseMove(Base::Vector2d onSketchPos) override
|
||||
void mouseMove(SnapManager::SnapHandle snapHandle) override
|
||||
{
|
||||
Q_UNUSED(onSketchPos);
|
||||
Q_UNUSED(snapHandle);
|
||||
}
|
||||
|
||||
bool pressButton(Base::Vector2d onSketchPos) override
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include "GeometryCreationMode.h"
|
||||
#include "Utils.h"
|
||||
#include "ViewProviderSketch.h"
|
||||
#include "SnapManager.h"
|
||||
|
||||
|
||||
namespace SketcherGui
|
||||
@@ -88,9 +89,9 @@ public:
|
||||
Gui::Selection().rmvSelectionGate();
|
||||
}
|
||||
|
||||
void mouseMove(Base::Vector2d onSketchPos) override
|
||||
void mouseMove(SnapManager::SnapHandle snapHandle) override
|
||||
{
|
||||
Q_UNUSED(onSketchPos);
|
||||
Base::Vector2d onSketchPos = snapHandle.compute();
|
||||
if (mousePressed) {
|
||||
executeCommands(onSketchPos);
|
||||
return;
|
||||
|
||||
@@ -184,55 +184,62 @@ SnapManager::SnapManager(ViewProviderSketch& vp)
|
||||
SnapManager::~SnapManager()
|
||||
{}
|
||||
|
||||
bool SnapManager::snap(double& x, double& y)
|
||||
Base::Vector2d SnapManager::snap(Base::Vector2d inputPos, SnapType mask)
|
||||
{
|
||||
if (!snapRequested) {
|
||||
return false;
|
||||
return inputPos;
|
||||
}
|
||||
|
||||
// In order of priority :
|
||||
Base::Vector2d snapPos;
|
||||
|
||||
// In order of priority:
|
||||
|
||||
// 1 - Snap at an angle
|
||||
if (angleSnapRequested && QApplication::keyboardModifiers() == Qt::ControlModifier) {
|
||||
return snapAtAngle(x, y);
|
||||
if ((static_cast<int>(mask) & static_cast<int>(SnapType::Angle)) && angleSnapRequested
|
||||
&& QApplication::keyboardModifiers() == Qt::ControlModifier
|
||||
&& snapAtAngle(inputPos, snapPos)) {
|
||||
return snapPos;
|
||||
}
|
||||
else {
|
||||
lastMouseAngle = 0.0;
|
||||
}
|
||||
|
||||
// 2 - Snap to objects
|
||||
if (snapToObjectsRequested && snapToObject(x, y)) {
|
||||
return true;
|
||||
if ((static_cast<int>(mask)
|
||||
& (static_cast<int>(SnapType::Point) | static_cast<int>(SnapType::Edge)))
|
||||
&& snapToObjectsRequested && snapToObject(inputPos, snapPos, mask)) {
|
||||
return snapPos;
|
||||
}
|
||||
|
||||
// 3 - Snap to grid
|
||||
if (snapToGridRequested /*&& viewProvider.ShowGrid.getValue() */) { // Snap to grid is enabled
|
||||
// even if the grid is not
|
||||
// visible.
|
||||
return snapToGrid(x, y);
|
||||
if ((static_cast<int>(mask) & static_cast<int>(SnapType::Grid)) && snapToGridRequested
|
||||
&& snapToGrid(inputPos, snapPos)
|
||||
/*&& viewProvider.ShowGrid.getValue() */) { // Snap to grid is
|
||||
// enabled
|
||||
// even if the grid is not
|
||||
// visible.
|
||||
|
||||
return snapPos;
|
||||
}
|
||||
|
||||
return false;
|
||||
return inputPos;
|
||||
}
|
||||
|
||||
bool SnapManager::snapAtAngle(double& x, double& y)
|
||||
bool SnapManager::snapAtAngle(Base::Vector2d inputPos, Base::Vector2d& snapPos)
|
||||
{
|
||||
Base::Vector2d pointToOverride(x, y);
|
||||
double length = (pointToOverride - referencePoint).Length();
|
||||
double length = (inputPos - referencePoint).Length();
|
||||
|
||||
double angle1 = (pointToOverride - referencePoint).Angle();
|
||||
double angle1 = (inputPos - referencePoint).Angle();
|
||||
double angle2 = angle1 + (angle1 < 0. ? 2 : -2) * std::numbers::pi;
|
||||
lastMouseAngle = abs(angle1 - lastMouseAngle) < abs(angle2 - lastMouseAngle) ? angle1 : angle2;
|
||||
|
||||
double angle = round(lastMouseAngle / snapAngle) * snapAngle;
|
||||
pointToOverride = referencePoint + length * Base::Vector2d(cos(angle), sin(angle));
|
||||
x = pointToOverride.x;
|
||||
y = pointToOverride.y;
|
||||
snapPos = referencePoint + length * Base::Vector2d(cos(angle), sin(angle));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SnapManager::snapToObject(double& x, double& y)
|
||||
bool SnapManager::snapToObject(Base::Vector2d inputPos, Base::Vector2d& snapPos, SnapType mask)
|
||||
{
|
||||
Sketcher::SketchObject* Obj = viewProvider.getSketchObject();
|
||||
int geoId = GeoEnum::GeoUndef;
|
||||
@@ -242,7 +249,7 @@ bool SnapManager::snapToObject(double& x, double& y)
|
||||
int CrsId = ViewProviderSketchSnapAttorney::getPreselectCross(viewProvider);
|
||||
int CrvId = ViewProviderSketchSnapAttorney::getPreselectCurve(viewProvider);
|
||||
|
||||
if (CrsId == 0 || VtId >= 0) {
|
||||
if ((static_cast<int>(mask) & static_cast<int>(SnapType::Point)) && (CrsId == 0 || VtId >= 0)) {
|
||||
if (CrsId == 0) {
|
||||
geoId = Sketcher::GeoEnum::RtPnt;
|
||||
posId = Sketcher::PointPos::start;
|
||||
@@ -251,78 +258,81 @@ bool SnapManager::snapToObject(double& x, double& y)
|
||||
Obj->getGeoVertexIndex(VtId, geoId, posId);
|
||||
}
|
||||
|
||||
x = Obj->getPoint(geoId, posId).x;
|
||||
y = Obj->getPoint(geoId, posId).y;
|
||||
snapPos.x = Obj->getPoint(geoId, posId).x;
|
||||
snapPos.y = Obj->getPoint(geoId, posId).y;
|
||||
return true;
|
||||
}
|
||||
else if (CrsId == 1) { // H_Axis
|
||||
y = 0;
|
||||
return true;
|
||||
}
|
||||
else if (CrsId == 2) { // V_Axis
|
||||
x = 0;
|
||||
return true;
|
||||
}
|
||||
else if (CrvId >= 0 || CrvId <= Sketcher::GeoEnum::RefExt) { // Curves
|
||||
|
||||
const Part::Geometry* geo = Obj->getGeometry(CrvId);
|
||||
|
||||
Base::Vector3d pointToOverride(x, y, 0.);
|
||||
|
||||
double pointParam = 0.0;
|
||||
auto curve = dynamic_cast<const Part::GeomCurve*>(geo);
|
||||
if (curve) {
|
||||
try {
|
||||
curve->closestParameter(pointToOverride, pointParam);
|
||||
pointToOverride = curve->pointAtParameter(pointParam);
|
||||
}
|
||||
catch (Base::CADKernelError& e) {
|
||||
e.reportException();
|
||||
return false;
|
||||
}
|
||||
|
||||
// If it is a line, then we check if we need to snap to the middle.
|
||||
if (geo->is<Part::GeomLineSegment>()) {
|
||||
const Part::GeomLineSegment* line = static_cast<const Part::GeomLineSegment*>(geo);
|
||||
snapToLineMiddle(pointToOverride, line);
|
||||
}
|
||||
|
||||
// If it is an arc, then we check if we need to snap to the middle (not the center).
|
||||
if (geo->is<Part::GeomArcOfCircle>()) {
|
||||
const Part::GeomArcOfCircle* arc = static_cast<const Part::GeomArcOfCircle*>(geo);
|
||||
snapToArcMiddle(pointToOverride, arc);
|
||||
}
|
||||
|
||||
x = pointToOverride.x;
|
||||
y = pointToOverride.y;
|
||||
|
||||
else if (static_cast<int>(mask) & static_cast<int>(SnapType::Edge)) {
|
||||
if (CrsId == 1) { // H_Axis
|
||||
snapPos.y = 0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (CrsId == 2) { // V_Axis
|
||||
snapPos.x = 0;
|
||||
return true;
|
||||
}
|
||||
else if (CrvId >= 0 || CrvId <= Sketcher::GeoEnum::RefExt) { // Curves
|
||||
|
||||
const Part::Geometry* geo = Obj->getGeometry(CrvId);
|
||||
|
||||
Base::Vector3d pointToOverride(inputPos.x, inputPos.y, 0.);
|
||||
|
||||
double pointParam = 0.0;
|
||||
auto curve = dynamic_cast<const Part::GeomCurve*>(geo);
|
||||
if (curve) {
|
||||
try {
|
||||
curve->closestParameter(pointToOverride, pointParam);
|
||||
pointToOverride = curve->pointAtParameter(pointParam);
|
||||
}
|
||||
catch (Base::CADKernelError& e) {
|
||||
e.reportException();
|
||||
return false;
|
||||
}
|
||||
|
||||
// If it is a line, then we check if we need to snap to the middle.
|
||||
if (geo->is<Part::GeomLineSegment>()) {
|
||||
const Part::GeomLineSegment* line =
|
||||
static_cast<const Part::GeomLineSegment*>(geo);
|
||||
snapToLineMiddle(pointToOverride, line);
|
||||
}
|
||||
|
||||
// If it is an arc, then we check if we need to snap to the middle (not the center).
|
||||
if (geo->is<Part::GeomArcOfCircle>()) {
|
||||
const Part::GeomArcOfCircle* arc =
|
||||
static_cast<const Part::GeomArcOfCircle*>(geo);
|
||||
snapToArcMiddle(pointToOverride, arc);
|
||||
}
|
||||
|
||||
snapPos.x = pointToOverride.x;
|
||||
snapPos.y = pointToOverride.y;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SnapManager::snapToGrid(double& x, double& y)
|
||||
bool SnapManager::snapToGrid(Base::Vector2d inputPos, Base::Vector2d& snapPos)
|
||||
{
|
||||
// Snap Tolerance in pixels
|
||||
const double snapTol = viewProvider.getGridSize() / 5;
|
||||
|
||||
double tmpX = x, tmpY = y;
|
||||
double tmpX = inputPos.x, tmpY = inputPos.y;
|
||||
|
||||
viewProvider.getClosestGridPoint(tmpX, tmpY);
|
||||
|
||||
bool snapped = false;
|
||||
|
||||
// Check if x within snap tolerance
|
||||
if (x < tmpX + snapTol && x > tmpX - snapTol) {
|
||||
x = tmpX; // Snap X Mouse Position
|
||||
if (inputPos.x < tmpX + snapTol && inputPos.x > tmpX - snapTol) {
|
||||
snapPos.x = tmpX; // Snap X Mouse Position
|
||||
snapped = true;
|
||||
}
|
||||
|
||||
// Check if y within snap tolerance
|
||||
if (y < tmpY + snapTol && y > tmpY - snapTol) {
|
||||
y = tmpY; // Snap Y Mouse Position
|
||||
if (inputPos.y < tmpY + snapTol && inputPos.y > tmpY - snapTol) {
|
||||
snapPos.y = tmpY; // Snap Y Mouse Position
|
||||
snapped = true;
|
||||
}
|
||||
|
||||
@@ -389,3 +399,11 @@ void SnapManager::setAngleSnapping(bool enable, Base::Vector2d referencepoint)
|
||||
angleSnapRequested = enable;
|
||||
referencePoint = referencepoint;
|
||||
}
|
||||
|
||||
Base::Vector2d SketcherGui::SnapManager::SnapHandle::compute(SnapType mask)
|
||||
{
|
||||
if (!mgr) {
|
||||
return cursorPos;
|
||||
}
|
||||
return mgr->snap(cursorPos, mask);
|
||||
}
|
||||
|
||||
@@ -51,6 +51,17 @@ private:
|
||||
friend class SnapManager;
|
||||
};
|
||||
|
||||
enum class SnapType
|
||||
{
|
||||
None = 0x0,
|
||||
Angle = 0x1,
|
||||
Point = 0x2,
|
||||
Edge = 0x4,
|
||||
Grid = 0x8,
|
||||
|
||||
All = Angle | Point | Edge | Grid
|
||||
};
|
||||
|
||||
/* This class is used to manage the overriding of mouse pointer coordinates in Sketcher
|
||||
* (in Edit-Mode) depending on the situation. Those situations are in priority order :
|
||||
* 1 - Snap at angle: For tools like Slot, Arc, Line, Ellipse, this enables to constrain the angle
|
||||
@@ -99,16 +110,29 @@ public:
|
||||
explicit SnapManager(ViewProviderSketch& vp);
|
||||
~SnapManager();
|
||||
|
||||
bool snap(double& x, double& y);
|
||||
bool snapAtAngle(double& x, double& y);
|
||||
bool snapToObject(double& x, double& y);
|
||||
bool snapToGrid(double& x, double& y);
|
||||
Base::Vector2d snap(Base::Vector2d inputPos, SnapType mask);
|
||||
bool snapAtAngle(Base::Vector2d inputPos, Base::Vector2d& snapPos);
|
||||
bool snapToObject(Base::Vector2d inputPos, Base::Vector2d& snapPos, SnapType mask);
|
||||
bool snapToGrid(Base::Vector2d inputPos, Base::Vector2d& snapPos);
|
||||
|
||||
bool snapToLineMiddle(Base::Vector3d& pointToOverride, const Part::GeomLineSegment* line);
|
||||
bool snapToArcMiddle(Base::Vector3d& pointToOverride, const Part::GeomArcOfCircle* arc);
|
||||
|
||||
void setAngleSnapping(bool enable, Base::Vector2d referencepoint);
|
||||
|
||||
struct SnapHandle
|
||||
{
|
||||
SnapManager* mgr = nullptr;
|
||||
Base::Vector2d cursorPos;
|
||||
|
||||
SnapHandle(SnapManager* m, const Base::Vector2d& cursorPos)
|
||||
: mgr(m)
|
||||
, cursorPos(cursorPos)
|
||||
{}
|
||||
|
||||
Base::Vector2d compute(SnapType mask = SnapType::All);
|
||||
};
|
||||
|
||||
private:
|
||||
/// Reference to ViewProviderSketch in order to access the public and the Attorney Interface
|
||||
ViewProviderSketch& viewProvider;
|
||||
|
||||
@@ -963,9 +963,10 @@ bool ViewProviderSketch::mouseButtonPressed(int Button, bool pressed, const SbVe
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<SnapManager::SnapHandle> snapHandle;
|
||||
try {
|
||||
getCoordsOnSketchPlane(pos, normal, x, y);
|
||||
snapManager->snap(x, y);
|
||||
snapHandle = std::make_unique<SnapManager::SnapHandle>(snapManager.get(), Base::Vector2d(x, y));
|
||||
}
|
||||
catch (const Base::ZeroDivisionError&) {
|
||||
return false;
|
||||
@@ -1436,10 +1437,11 @@ bool ViewProviderSketch::mouseMove(const SbVec2s& cursorPos, Gui::View3DInventor
|
||||
SbLine line;
|
||||
getProjectingLine(cursorPos, viewer, line);
|
||||
|
||||
double x, y;
|
||||
std::unique_ptr<SnapManager::SnapHandle> snapHandle;
|
||||
try {
|
||||
double x, y;
|
||||
getCoordsOnSketchPlane(line.getPosition(), line.getDirection(), x, y);
|
||||
snapManager->snap(x, y);
|
||||
snapHandle = std::make_unique<SnapManager::SnapHandle>(snapManager.get(), Base::Vector2d(x, y));
|
||||
}
|
||||
catch (const Base::ZeroDivisionError&) {
|
||||
return false;
|
||||
@@ -1488,27 +1490,31 @@ bool ViewProviderSketch::mouseMove(const SbVec2s& cursorPos, Gui::View3DInventor
|
||||
}
|
||||
resetPreselectPoint();
|
||||
return true;
|
||||
case STATUS_SELECT_Constraint:
|
||||
case STATUS_SELECT_Constraint: {
|
||||
setSketchMode(STATUS_SKETCH_DragConstraint);
|
||||
drag.DragConstraintSet = preselection.PreselectConstraintSet;
|
||||
drag.xInit = x;
|
||||
drag.yInit = y;
|
||||
Base::Vector2d selectionPos = snapHandle->compute();
|
||||
drag.xInit = selectionPos.x;
|
||||
drag.yInit = selectionPos.y;
|
||||
resetPreselectPoint();
|
||||
return true;
|
||||
}
|
||||
case STATUS_SKETCH_Drag: {
|
||||
doDragStep(x, y);
|
||||
Base::Vector2d dragPos = snapHandle->compute();
|
||||
doDragStep(dragPos.x, dragPos.y);
|
||||
return true;
|
||||
}
|
||||
case STATUS_SKETCH_DragConstraint:
|
||||
if (!drag.DragConstraintSet.empty()) {
|
||||
Base::Vector2d dragPos = snapHandle->compute();
|
||||
auto idset = drag.DragConstraintSet;
|
||||
for (int id : idset) {
|
||||
moveConstraint(id, Base::Vector2d(x, y));
|
||||
moveConstraint(id, Base::Vector2d(dragPos.x, dragPos.y));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
case STATUS_SKETCH_UseHandler:
|
||||
sketchHandler->mouseMove(Base::Vector2d(x, y));
|
||||
sketchHandler->mouseMove(*snapHandle);
|
||||
if (preselectChanged) {
|
||||
editCoinManager->drawConstraintIcons();
|
||||
sketchHandler->applyCursor();
|
||||
@@ -1617,7 +1623,7 @@ void ViewProviderSketch::initDragging(int geoId, Sketcher::PointPos pos, Gui::Vi
|
||||
getProjectingLine(DoubleClick::prvCursorPos, viewer, line2);
|
||||
getCoordsOnSketchPlane(
|
||||
line2.getPosition(), line2.getDirection(), drag.xInit, drag.yInit);
|
||||
snapManager->snap(drag.xInit, drag.yInit);
|
||||
snapManager->snap(Base::Vector2d(drag.xInit, drag.yInit), SnapType::All);
|
||||
};
|
||||
|
||||
if (drag.Dragged.size() == 1 && pos == Sketcher::PointPos::none) {
|
||||
|
||||
Reference in New Issue
Block a user