Merge pull request #24904 from tetektoza/fix/23459_fix_locked_ovp_allowing_change_geom

Sketcher: Remember cursor angle for OVPs after OVP is set
This commit is contained in:
Kacper Donat
2025-11-03 19:25:56 +01:00
committed by GitHub
3 changed files with 83 additions and 21 deletions

View File

@@ -86,7 +86,10 @@ public:
explicit DrawSketchHandlerLine(
ConstructionMethod constrMethod = ConstructionMethod::OnePointLengthAngle)
: DrawSketchHandlerLineBase(constrMethod)
, length(0.0) {};
, length(0.0)
, lengthSign(0)
, widthSign(0)
, capturedDirection(0.0, 0.0) {};
~DrawSketchHandlerLine() override = default;
private:
@@ -237,10 +240,23 @@ private:
}
}
void onReset() override
{
lengthSign = 0;
widthSign = 0;
capturedDirection = Base::Vector2d(0.0, 0.0);
toolWidgetManager.resetControls();
}
private:
Base::Vector2d startPoint, endPoint;
double length;
// These store the direction sign when OVP is first set to prevent sign flipping
int lengthSign, widthSign;
// Direction tracking to check once OVP is locked
Base::Vector2d capturedDirection;
void createShape(bool onlyeditoutline) override
{
Q_UNUSED(onlyeditoutline);
@@ -427,12 +443,17 @@ void DSHLineControllerBase::doEnforceControlParameters(Base::Vector2d& onSketchP
if (fabs(width) < Precision::Confusion()
&& fourthParam->hasFinishedEditing) {
unsetOnViewParameter(thirdParam.get());
handler->lengthSign = 0;
return;
}
}
}
int sign = (onSketchPos.x - handler->startPoint.x) >= 0 ? 1 : -1;
onSketchPos.x = handler->startPoint.x + sign * length;
// get sign on the first time we set the OVP label, so it won't get flipped
// with mouse next time
if (handler->lengthSign == 0) {
handler->lengthSign = (onSketchPos.x - handler->startPoint.x) >= 0 ? 1 : -1;
}
onSketchPos.x = handler->startPoint.x + handler->lengthSign * length;
}
if (fourthParam->isSet) {
@@ -444,12 +465,15 @@ void DSHLineControllerBase::doEnforceControlParameters(Base::Vector2d& onSketchP
if (fabs(length) < Precision::Confusion()
&& thirdParam->hasFinishedEditing) {
unsetOnViewParameter(fourthParam.get());
handler->widthSign = 0;
return;
}
}
}
int sign = (onSketchPos.y - handler->startPoint.y) >= 0 ? 1 : -1;
onSketchPos.y = handler->startPoint.y + sign * width;
if (handler->widthSign == 0) {
handler->widthSign = (onSketchPos.y - handler->startPoint.y) >= 0 ? 1 : -1;
}
onSketchPos.y = handler->startPoint.y + handler->widthSign * width;
}
}
else if (handler->constructionMethod() == ConstructionMethod::OnePointLengthAngle) {
@@ -460,20 +484,29 @@ void DSHLineControllerBase::doEnforceControlParameters(Base::Vector2d& onSketchP
}
double length = dir.Length();
if (fourthParam->isSet) {
const double angle = Base::toRadians(fourthParam->getValue());
const Base::Vector2d ovpDir(cos(angle), sin(angle));
handler->capturedDirection = ovpDir;
}
else {
handler->capturedDirection = dir.Normalize();
}
if (thirdParam->isSet) {
length = thirdParam->getValue();
if (length < Precision::Confusion() && thirdParam->hasFinishedEditing) {
unsetOnViewParameter(thirdParam.get());
handler->capturedDirection = Base::Vector2d(0.0, 0.0);
return;
}
onSketchPos = handler->startPoint + length * dir.Normalize();
onSketchPos = handler->startPoint + length * handler->capturedDirection;
}
if (fourthParam->isSet) {
double angle = Base::toRadians(fourthParam->getValue());
Base::Vector2d ovpDir(cos(angle), sin(angle));
onSketchPos.ProjectToLine(onSketchPos - handler->startPoint, ovpDir);
else if (fourthParam->isSet) {
// only angle is set, project current position onto that angle
onSketchPos.ProjectToLine(onSketchPos - handler->startPoint,
handler->capturedDirection);
onSketchPos += handler->startPoint;
}
}
@@ -490,6 +523,8 @@ void DSHLineControllerBase::doEnforceControlParameters(Base::Vector2d& onSketchP
&& (onSketchPos - handler->startPoint).Length() < Precision::Confusion()) {
unsetOnViewParameter(thirdParam.get());
unsetOnViewParameter(fourthParam.get());
handler->lengthSign = 0;
handler->widthSign = 0;
}
} break;
default:

View File

@@ -104,6 +104,8 @@ public:
, constructionPointThreeId(Sketcher::GeoEnum::GeoUndef)
, centerPointId(Sketcher::GeoEnum::GeoUndef)
, side(0)
, lengthSign(0)
, widthSign(0)
{}
~DrawSketchHandlerRectangle() override = default;
@@ -815,6 +817,8 @@ private:
void onReset() override
{
thickness = 0.;
lengthSign = 0;
widthSign = 0;
toolWidgetManager.resetControls();
}
@@ -827,6 +831,10 @@ private:
int firstCurve, constructionPointOneId, constructionPointTwoId, constructionPointThreeId,
centerPointId, side;
// Sign tracking for OVP lock fix (issue #23459)
// These store the direction sign when OVP is first set to prevent sign flipping
int lengthSign, widthSign;
void createShape(bool onlyeditoutline) override
{
ShapeGeometry.clear();
@@ -1987,12 +1995,16 @@ void DSHRectangleControllerBase::doEnforceControlParameters(Base::Vector2d& onSk
if (fabs(length) < Precision::Confusion()
&& onViewParameters[OnViewParameter::Third]->hasFinishedEditing) {
unsetOnViewParameter(onViewParameters[OnViewParameter::Third].get());
handler->lengthSign = 0;
return;
}
if (handler->constructionMethod() == ConstructionMethod::Diagonal) {
int sign = (onSketchPos.x - handler->corner1.x) >= 0 ? 1 : -1;
onSketchPos.x = handler->corner1.x + sign * length;
if (handler->lengthSign == 0) {
handler->lengthSign =
(onSketchPos.x - handler->corner1.x) >= 0 ? 1 : -1;
}
onSketchPos.x = handler->corner1.x + handler->lengthSign * length;
}
else {
onSketchPos.x = handler->center.x + length / 2;
@@ -2003,12 +2015,15 @@ void DSHRectangleControllerBase::doEnforceControlParameters(Base::Vector2d& onSk
if (fabs(width) < Precision::Confusion()
&& onViewParameters[OnViewParameter::Fourth]->hasFinishedEditing) {
unsetOnViewParameter(onViewParameters[OnViewParameter::Fourth].get());
handler->widthSign = 0;
return;
}
if (handler->constructionMethod() == ConstructionMethod::Diagonal) {
int sign = (onSketchPos.y - handler->corner1.y) >= 0 ? 1 : -1;
onSketchPos.y = handler->corner1.y + sign * width;
if (handler->widthSign == 0) {
handler->widthSign = (onSketchPos.y - handler->corner1.y) >= 0 ? 1 : -1;
}
onSketchPos.y = handler->corner1.y + handler->widthSign * width;
}
else {
onSketchPos.y = handler->center.y + width / 2;

View File

@@ -74,6 +74,7 @@ public:
, length(0.0)
, angle(0.0)
, firstCurve(0)
, capturedDirection(0.0, 0.0)
{}
~DrawSketchHandlerSlot() override = default;
@@ -339,6 +340,9 @@ private:
Base::Vector2d startPoint, secondPoint;
double radius, length, angle;
int firstCurve;
// Direction tracking to prevent OVP from flipping (issue #23459)
Base::Vector2d capturedDirection;
};
template<>
@@ -403,20 +407,28 @@ void DSHSlotControllerBase::doEnforceControlParameters(Base::Vector2d& onSketchP
}
double length = dir.Length();
if (fourthParam->isSet) {
const double angle = Base::toRadians(fourthParam->getValue());
const Base::Vector2d ovpDir(cos(angle), sin(angle));
handler->capturedDirection = ovpDir;
}
else {
handler->capturedDirection = dir.Normalize();
}
if (thirdParam->isSet) {
length = thirdParam->getValue();
if (length < Precision::Confusion() && thirdParam->hasFinishedEditing) {
unsetOnViewParameter(thirdParam.get());
handler->capturedDirection = Base::Vector2d(0.0, 0.0);
return;
}
onSketchPos = handler->startPoint + length * dir.Normalize();
onSketchPos = handler->startPoint + length * handler->capturedDirection;
}
if (fourthParam->isSet) {
double angle = Base::toRadians(fourthParam->getValue());
Base::Vector2d ovpDir(cos(angle), sin(angle));
onSketchPos.ProjectToLine(onSketchPos - handler->startPoint, ovpDir);
else if (fourthParam->isSet) {
onSketchPos.ProjectToLine(onSketchPos - handler->startPoint,
handler->capturedDirection);
onSketchPos += handler->startPoint;
}
} break;