Merge pull request #15958 from AjinkyaDahale/sk-fix-14736
[Sketcher] Attempt to fix #14736
This commit is contained in:
@@ -1588,10 +1588,10 @@ double ConstraintTangentCircumf::error()
|
||||
double dx = (*c1x() - *c2x());
|
||||
double dy = (*c1y() - *c2y());
|
||||
if (internal) {
|
||||
return scale * (sqrt(dx * dx + dy * dy) - std::abs(*r1() - *r2()));
|
||||
return scale * ((dx * dx + dy * dy) - (*r1() - *r2()) * (*r1() - *r2()));
|
||||
}
|
||||
else {
|
||||
return scale * (sqrt(dx * dx + dy * dy) - (*r1() + *r2()));
|
||||
return scale * ((dx * dx + dy * dy) - (*r1() + *r2()) * (*r1() + *r2()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1602,33 +1602,32 @@ double ConstraintTangentCircumf::grad(double* param)
|
||||
|| param == r2()) {
|
||||
double dx = (*c1x() - *c2x());
|
||||
double dy = (*c1y() - *c2y());
|
||||
double d = sqrt(dx * dx + dy * dy);
|
||||
if (param == c1x()) {
|
||||
deriv += dx / d;
|
||||
deriv += 2 * dx;
|
||||
}
|
||||
if (param == c1y()) {
|
||||
deriv += dy / d;
|
||||
deriv += 2 * dy;
|
||||
}
|
||||
if (param == c2x()) {
|
||||
deriv += -dx / d;
|
||||
deriv += 2 * -dx;
|
||||
}
|
||||
if (param == c2y()) {
|
||||
deriv += -dy / d;
|
||||
deriv += 2 * -dy;
|
||||
}
|
||||
if (internal) {
|
||||
if (param == r1()) {
|
||||
deriv += (*r1() > *r2()) ? -1 : 1;
|
||||
deriv += 2 * (*r2() - *r1());
|
||||
}
|
||||
if (param == r2()) {
|
||||
deriv += (*r1() > *r2()) ? 1 : -1;
|
||||
deriv += 2 * (*r1() - *r2());
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (param == r1()) {
|
||||
deriv += -1;
|
||||
deriv += 2 * (*r1() + *r2());
|
||||
}
|
||||
if (param == r2()) {
|
||||
deriv += -1;
|
||||
deriv += 2 * (*r1() + *r2());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3777,7 +3777,9 @@ bool CmdSketcherConstrainCoincidentUnified::substituteConstraintCombinationsPoin
|
||||
if ((*it)->Type == Sketcher::Tangent && (*it)->FirstPos == Sketcher::PointPos::none
|
||||
&& (*it)->SecondPos == Sketcher::PointPos::none && (*it)->Third == GeoEnum::GeoUndef
|
||||
&& (((*it)->First == GeoId1 && (*it)->Second == GeoId2)
|
||||
|| ((*it)->Second == GeoId1 && (*it)->First == GeoId2))) {
|
||||
|| ((*it)->Second == GeoId1 && (*it)->First == GeoId2))
|
||||
&& (PosId1 == Sketcher::PointPos::start
|
||||
|| PosId1 == Sketcher::PointPos::end)) {
|
||||
|
||||
// NOTE: This function does not either open or commit a command as it is used for group
|
||||
// addition it relies on such infrastructure being provided by the caller.
|
||||
@@ -3813,6 +3815,12 @@ bool CmdSketcherConstrainCoincidentUnified::substituteConstraintCombinationsCoin
|
||||
if ((*it)->Type == Sketcher::Tangent && (*it)->Third == GeoEnum::GeoUndef
|
||||
&& (((*it)->First == GeoId1 && (*it)->Second == GeoId2)
|
||||
|| ((*it)->Second == GeoId1 && (*it)->First == GeoId2))) {
|
||||
if (!(PosId1 == Sketcher::PointPos::start
|
||||
|| PosId1 == Sketcher::PointPos::end)
|
||||
|| !(PosId2 == Sketcher::PointPos::start
|
||||
|| PosId2 == Sketcher::PointPos::end)) {
|
||||
continue;
|
||||
}
|
||||
if ((*it)->FirstPos == Sketcher::PointPos::none
|
||||
&& (*it)->SecondPos == Sketcher::PointPos::none) {
|
||||
|
||||
@@ -6569,8 +6577,11 @@ bool CmdSketcherConstrainTangent::substituteConstraintCombinations(SketchObject*
|
||||
++it, ++cid) {
|
||||
if ((*it)->Type == Sketcher::Coincident
|
||||
&& (((*it)->First == GeoId1 && (*it)->Second == GeoId2)
|
||||
|| ((*it)->Second == GeoId1 && (*it)->First == GeoId2))) {
|
||||
|
||||
|| ((*it)->Second == GeoId1 && (*it)->First == GeoId2))
|
||||
&& ((*it)->FirstPos == Sketcher::PointPos::start
|
||||
|| (*it)->FirstPos == Sketcher::PointPos::end)
|
||||
&& ((*it)->SecondPos == Sketcher::PointPos::start
|
||||
|| (*it)->SecondPos == Sketcher::PointPos::end)) {
|
||||
// save values because 'doEndpointTangency' changes the
|
||||
// constraint property and thus invalidates this iterator
|
||||
int first = (*it)->First;
|
||||
@@ -6596,8 +6607,9 @@ bool CmdSketcherConstrainTangent::substituteConstraintCombinations(SketchObject*
|
||||
}
|
||||
else if ((*it)->Type == Sketcher::PointOnObject
|
||||
&& (((*it)->First == GeoId1 && (*it)->Second == GeoId2)
|
||||
|| ((*it)->Second == GeoId1 && (*it)->First == GeoId2))) {
|
||||
|
||||
|| ((*it)->Second == GeoId1 && (*it)->First == GeoId2))
|
||||
&& ((*it)->FirstPos == Sketcher::PointPos::start
|
||||
|| (*it)->FirstPos == Sketcher::PointPos::end)) {
|
||||
Gui::Command::openCommand(
|
||||
QT_TRANSLATE_NOOP("Command",
|
||||
"Swap point on object and tangency with point to curve tangency"));
|
||||
|
||||
@@ -1387,7 +1387,7 @@ void SketcherCopy::activate(SketcherCopy::Op op)
|
||||
int GeoId;
|
||||
Sketcher::PointPos PosId;
|
||||
Obj->getGeoVertexIndex(VtId, GeoId, PosId);
|
||||
if (Obj->getGeometry(GeoId)->getTypeId() != Part::GeomPoint::getClassTypeId()) {
|
||||
if (!Obj->getGeometry(GeoId)->is<Part::GeomPoint>()) {
|
||||
LastGeoId = GeoId;
|
||||
LastPointPos = PosId;
|
||||
}
|
||||
@@ -1990,7 +1990,7 @@ void CmdSketcherRectangularArray::activated(int iMsg)
|
||||
int GeoId;
|
||||
Sketcher::PointPos PosId;
|
||||
Obj->getGeoVertexIndex(VtId, GeoId, PosId);
|
||||
if (Obj->getGeometry(GeoId)->getTypeId() != Part::GeomPoint::getClassTypeId()) {
|
||||
if (!Obj->getGeometry(GeoId)->is<Part::GeomPoint>()) {
|
||||
LastGeoId = GeoId;
|
||||
LastPointPos = PosId;
|
||||
}
|
||||
|
||||
@@ -497,8 +497,6 @@ protected:
|
||||
|
||||
createAutoConstraints();
|
||||
}
|
||||
|
||||
tryAutoRecomputeIfNotSolve(sketchgui->getSketchObject());
|
||||
}
|
||||
catch (const Base::RuntimeError& e) {
|
||||
// RuntimeError exceptions inside of the block above must provide a translatable
|
||||
@@ -507,6 +505,17 @@ protected:
|
||||
Base::Console().Error(e.what());
|
||||
}
|
||||
|
||||
// Keep the recompute separate so that everything is drawn even if execution fails
|
||||
// partially
|
||||
try {
|
||||
tryAutoRecomputeIfNotSolve(sketchgui->getSketchObject());
|
||||
}
|
||||
catch (const Base::RuntimeError& e) {
|
||||
// RuntimeError exceptions inside of the block above must provide a translatable
|
||||
// message. It is reported both to developer (report view) and user (notifications
|
||||
// area).
|
||||
Base::Console().Error(e.what());
|
||||
}
|
||||
return handleContinuousMode();
|
||||
}
|
||||
return false;
|
||||
@@ -666,19 +675,26 @@ protected:
|
||||
}
|
||||
|
||||
// find if there is already a matching tangency
|
||||
auto result = std::find_if(AutoConstraints.begin(),
|
||||
AutoConstraints.end(),
|
||||
[&](const auto& ace) {
|
||||
return ace->Type == Sketcher::Tangent
|
||||
&& ace->First == geoId1
|
||||
&& ace->Second == ac.GeoId;
|
||||
});
|
||||
auto itOfTangentConstraint = AutoConstraints.end();
|
||||
if ((posId1 == Sketcher::PointPos::start
|
||||
|| posId1 == Sketcher::PointPos::end)
|
||||
&& (ac.PosId == Sketcher::PointPos::start
|
||||
|| ac.PosId == Sketcher::PointPos::end)) {
|
||||
itOfTangentConstraint =
|
||||
std::find_if(AutoConstraints.begin(),
|
||||
AutoConstraints.end(),
|
||||
[&](const auto& ace) {
|
||||
return ace->Type == Sketcher::Tangent
|
||||
&& ace->First == geoId1
|
||||
&& ace->Second == ac.GeoId;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
if (result
|
||||
!= AutoConstraints.end()) { // modify tangency to endpoint-to-endpoint
|
||||
(*result)->FirstPos = posId1;
|
||||
(*result)->SecondPos = ac.PosId;
|
||||
if (itOfTangentConstraint != AutoConstraints.end()) {
|
||||
// modify tangency to endpoint-to-endpoint
|
||||
(*itOfTangentConstraint)->FirstPos = posId1;
|
||||
(*itOfTangentConstraint)->SecondPos = ac.PosId;
|
||||
}
|
||||
else {
|
||||
auto c = std::make_unique<Sketcher::Constraint>();
|
||||
@@ -699,21 +715,27 @@ protected:
|
||||
std::swap(posId1, posId2);
|
||||
}
|
||||
|
||||
auto result = std::find_if(AutoConstraints.begin(),
|
||||
AutoConstraints.end(),
|
||||
[&](const auto& ace) {
|
||||
return ace->Type == Sketcher::Tangent
|
||||
&& ace->First == geoId1
|
||||
&& ace->Second == ac.GeoId;
|
||||
});
|
||||
auto itOfTangentConstraint = AutoConstraints.end();
|
||||
if (posId1 == Sketcher::PointPos::start
|
||||
|| posId1 == Sketcher::PointPos::end) {
|
||||
itOfTangentConstraint =
|
||||
std::find_if(AutoConstraints.begin(),
|
||||
AutoConstraints.end(),
|
||||
[&](const auto& ace) {
|
||||
return ace->Type == Sketcher::Tangent
|
||||
&& ace->First == geoId1
|
||||
&& ace->Second == ac.GeoId;
|
||||
});
|
||||
}
|
||||
|
||||
// if tangency, convert to point-to-edge tangency
|
||||
if (result != AutoConstraints.end()) {
|
||||
(*result)->FirstPos = posId1;
|
||||
|
||||
if ((*result)->First != geoId1) {
|
||||
std::swap((*result)->Second, (*result)->First);
|
||||
if (itOfTangentConstraint != AutoConstraints.end()) {
|
||||
if ((*itOfTangentConstraint)->First != geoId1) {
|
||||
std::swap((*itOfTangentConstraint)->Second,
|
||||
(*itOfTangentConstraint)->First);
|
||||
}
|
||||
|
||||
(*itOfTangentConstraint)->FirstPos = posId1;
|
||||
}
|
||||
else {
|
||||
auto c = std::make_unique<Sketcher::Constraint>();
|
||||
@@ -735,11 +757,11 @@ protected:
|
||||
c->ThirdPos = posId1;
|
||||
AutoConstraints.push_back(std::move(c));
|
||||
} break;
|
||||
// In special case of Horizontal/Vertical constraint, geoId2 is normally unused
|
||||
// and should be 'Constraint::GeoUndef' However it can be used as a way to
|
||||
// require the function to apply these constraints on another geometry In this
|
||||
// case the caller as to set geoId2, then it will be used as target instead of
|
||||
// geoId2
|
||||
// In special case of Horizontal/Vertical constraint, geoId2 is normally
|
||||
// unused and should be 'Constraint::GeoUndef' However it can be used as a
|
||||
// way to require the function to apply these constraints on another
|
||||
// geometry In this case the caller as to set geoId2, then it will be used
|
||||
// as target instead of geoId2
|
||||
case Sketcher::Horizontal: {
|
||||
auto c = std::make_unique<Sketcher::Constraint>();
|
||||
c->Type = Sketcher::Horizontal;
|
||||
@@ -761,10 +783,8 @@ protected:
|
||||
|
||||
// ellipse tangency support using construction elements (lines)
|
||||
if (geom1 && geom2
|
||||
&& (geom1->getTypeId() == Part::GeomEllipse::getClassTypeId()
|
||||
|| geom2->getTypeId() == Part::GeomEllipse::getClassTypeId())) {
|
||||
|
||||
if (geom1->getTypeId() != Part::GeomEllipse::getClassTypeId()) {
|
||||
&& (geom1->is<Part::GeomEllipse>() || geom2->is<Part::GeomEllipse>())) {
|
||||
if (!geom1->is<Part::GeomEllipse>()) {
|
||||
std::swap(geoId1, geoId2);
|
||||
}
|
||||
|
||||
@@ -772,14 +792,15 @@ protected:
|
||||
geom1 = Obj->getGeometry(geoId1);
|
||||
geom2 = Obj->getGeometry(geoId2);
|
||||
|
||||
if (geom2->getTypeId() == Part::GeomEllipse::getClassTypeId()
|
||||
|| geom2->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId()
|
||||
|| geom2->getTypeId() == Part::GeomCircle::getClassTypeId()
|
||||
|| geom2->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) {
|
||||
if (geom2->is<Part::GeomEllipse>()
|
||||
|| geom2->is<Part::GeomArcOfEllipse>()
|
||||
|| geom2->is<Part::GeomCircle>()
|
||||
|| geom2->is<Part::GeomArcOfCircle>()) {
|
||||
// in all these cases an intermediate element is needed
|
||||
/*makeTangentToEllipseviaNewPoint(Obj,
|
||||
static_cast<const Part::GeomEllipse
|
||||
*>(geom1), geom2, geoId1, geoId2);*/
|
||||
// makeTangentToEllipseviaNewPoint(
|
||||
// Obj,
|
||||
// static_cast<const Part::GeomEllipse *>(geom1),
|
||||
// geom2, geoId1, geoId2);
|
||||
// NOTE: Temporarily deactivated
|
||||
return;
|
||||
}
|
||||
@@ -787,11 +808,10 @@ protected:
|
||||
|
||||
// arc of ellipse tangency support using external elements
|
||||
if (geom1 && geom2
|
||||
&& (geom1->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId()
|
||||
|| geom2->getTypeId()
|
||||
== Part::GeomArcOfEllipse::getClassTypeId())) {
|
||||
&& (geom1->is<Part::GeomArcOfEllipse>()
|
||||
|| geom2->is<Part::GeomArcOfEllipse>())) {
|
||||
|
||||
if (geom1->getTypeId() != Part::GeomArcOfEllipse::getClassTypeId()) {
|
||||
if (!geom1->is<Part::GeomArcOfEllipse>()) {
|
||||
std::swap(geoId1, geoId2);
|
||||
}
|
||||
|
||||
@@ -799,15 +819,13 @@ protected:
|
||||
geom1 = Obj->getGeometry(geoId1);
|
||||
geom2 = Obj->getGeometry(geoId2);
|
||||
|
||||
if (geom2->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId()
|
||||
|| geom2->getTypeId() == Part::GeomCircle::getClassTypeId()
|
||||
|| geom2->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) {
|
||||
if (geom2->is<Part::GeomArcOfEllipse>() || geom2->is<Part::GeomCircle>()
|
||||
|| geom2->is<Part::GeomArcOfCircle>()) {
|
||||
// in all these cases an intermediate element is needed
|
||||
// makeTangentToArcOfEllipseviaNewPoint(Obj,
|
||||
// static_cast<const
|
||||
// Part::GeomArcOfEllipse
|
||||
// *>(geom1), geom2, geoId1,
|
||||
// geoId2);
|
||||
// makeTangentToArcOfEllipseviaNewPoint(
|
||||
// Obj,
|
||||
// static_cast<const Part::GeomArcOfEllipse*>(geom1), geom2,
|
||||
// geoId1, geoId2);
|
||||
// NOTE: Temporarily deactivated
|
||||
return;
|
||||
}
|
||||
@@ -830,12 +848,18 @@ protected:
|
||||
|| (ace->First == ac.GeoId && ace->Second == geoId1));
|
||||
});
|
||||
|
||||
if (resultcoincident
|
||||
!= AutoConstraints.end()) { // endpoint-to-endpoint tangency
|
||||
if (resultcoincident != AutoConstraints.end()
|
||||
&& ((*resultcoincident)->FirstPos == Sketcher::PointPos::start
|
||||
|| (*resultcoincident)->FirstPos == Sketcher::PointPos::end)
|
||||
&& ((*resultcoincident)->SecondPos == Sketcher::PointPos::start
|
||||
|| (*resultcoincident)->SecondPos == Sketcher::PointPos::end)) {
|
||||
// endpoint-to-endpoint tangency
|
||||
(*resultcoincident)->Type = Sketcher::Tangent;
|
||||
}
|
||||
else if (resultpointonobject
|
||||
!= AutoConstraints.end()) { // endpoint-to-edge tangency
|
||||
else if (resultpointonobject != AutoConstraints.end()
|
||||
&& ((*resultcoincident)->FirstPos == Sketcher::PointPos::start
|
||||
|| (*resultcoincident)->FirstPos == Sketcher::PointPos::end)) {
|
||||
// endpoint-to-edge tangency
|
||||
(*resultpointonobject)->Type = Sketcher::Tangent;
|
||||
}
|
||||
else { // regular edge to edge tangency
|
||||
|
||||
@@ -440,8 +440,8 @@ int DrawSketchHandler::seekAutoConstraint(std::vector<AutoConstraint>& suggested
|
||||
int preSelPnt = getPreselectPoint();
|
||||
int preSelCrv = getPreselectCurve();
|
||||
int preSelCrs = getPreselectCross();
|
||||
int GeoId = GeoEnum::GeoUndef;
|
||||
|
||||
int GeoId = GeoEnum::GeoUndef;
|
||||
PointPos PosId = PointPos::none;
|
||||
|
||||
if (preSelPnt != -1) {
|
||||
@@ -459,15 +459,18 @@ int DrawSketchHandler::seekAutoConstraint(std::vector<AutoConstraint>& suggested
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (preSelCrs == 0) { // root point
|
||||
else if (preSelCrs == 0) {
|
||||
// root point
|
||||
GeoId = Sketcher::GeoEnum::RtPnt;
|
||||
PosId = PointPos::start;
|
||||
}
|
||||
else if (preSelCrs == 1) { // x axis
|
||||
else if (preSelCrs == 1) {
|
||||
// x axis
|
||||
GeoId = Sketcher::GeoEnum::HAxis;
|
||||
hitShapeDir = Base::Vector3d(1, 0, 0);
|
||||
}
|
||||
else if (preSelCrs == 2) { // y axis
|
||||
else if (preSelCrs == 2) {
|
||||
// y axis
|
||||
GeoId = Sketcher::GeoEnum::VAxis;
|
||||
hitShapeDir = Base::Vector3d(0, 1, 0);
|
||||
}
|
||||
@@ -819,7 +822,7 @@ void DrawSketchHandler::createAutoConstraints(const std::vector<AutoConstraint>&
|
||||
if (geom1 && geom2
|
||||
&& (geom1->is<Part::GeomEllipse>() || geom2->is<Part::GeomEllipse>())) {
|
||||
|
||||
if (geom1->getTypeId() != Part::GeomEllipse::getClassTypeId()) {
|
||||
if (!geom1->is<Part::GeomEllipse>()) {
|
||||
std::swap(geoId1, geoId2);
|
||||
}
|
||||
|
||||
@@ -846,7 +849,7 @@ void DrawSketchHandler::createAutoConstraints(const std::vector<AutoConstraint>&
|
||||
&& (geom1->is<Part::GeomArcOfEllipse>()
|
||||
|| geom2->is<Part::GeomArcOfEllipse>())) {
|
||||
|
||||
if (geom1->getTypeId() != Part::GeomArcOfEllipse::getClassTypeId()) {
|
||||
if (!geom1->is<Part::GeomArcOfEllipse>()) {
|
||||
std::swap(geoId1, geoId2);
|
||||
}
|
||||
|
||||
|
||||
@@ -162,8 +162,7 @@ private:
|
||||
|
||||
// in the exceptional event that this may lead to a circle, do not
|
||||
// exposeInternalGeometry
|
||||
if (!ShapeGeometry.empty()
|
||||
&& ShapeGeometry[0]->getTypeId() == Part::GeomEllipse::getClassTypeId()) {
|
||||
if (!ShapeGeometry.empty() && ShapeGeometry[0]->is<Part::GeomEllipse>()) {
|
||||
Gui::cmdAppObjectArgs(sketchgui->getObject(),
|
||||
"exposeInternalGeometry(%d)",
|
||||
ellipseGeoId);
|
||||
@@ -713,8 +712,7 @@ void DSHEllipseController::addConstraints()
|
||||
|
||||
using namespace Sketcher;
|
||||
|
||||
if (!handler->ShapeGeometry.empty()
|
||||
&& handler->ShapeGeometry[0]->getTypeId() == Part::GeomEllipse::getClassTypeId()) {
|
||||
if (!handler->ShapeGeometry.empty() && handler->ShapeGeometry[0]->is<Part::GeomEllipse>()) {
|
||||
|
||||
int firstLine = firstCurve + 1; // this is always the major axis
|
||||
int secondLine = firstCurve + 2; // this is always the minor axis
|
||||
|
||||
@@ -564,8 +564,7 @@ Restart:
|
||||
|
||||
Base::Vector3d midpos1, dir1, norm1;
|
||||
Base::Vector3d midpos2, dir2, norm2;
|
||||
if (geo1->getTypeId() != Part::GeomLineSegment::getClassTypeId()
|
||||
|| geo2->getTypeId() != Part::GeomLineSegment::getClassTypeId()) {
|
||||
if (!geo1->is<Part::GeomLineSegment>() || !geo2->is<Part::GeomLineSegment>()) {
|
||||
if (Constr->Type == Equal) {
|
||||
double r1a = 0, r1b = 0, r2a = 0, r2b = 0;
|
||||
double angle1,
|
||||
@@ -731,8 +730,7 @@ Restart:
|
||||
|
||||
|
||||
if (geo2->is<Part::GeomEllipse>() || geo2->is<Part::GeomArcOfEllipse>()
|
||||
|| geo2->getTypeId()
|
||||
== Part::GeomArcOfHyperbola::getClassTypeId()) {
|
||||
|| geo2->is<Part::GeomArcOfHyperbola>()) {
|
||||
|
||||
Base::Vector3d majDir, minDir, rvec;
|
||||
majDir = Base::Vector3d(cos(angle2),
|
||||
|
||||
Reference in New Issue
Block a user