From ef35ec195d0c00469b16ddeae74016b53645084d Mon Sep 17 00:00:00 2001 From: Florian Foinant-Willig Date: Sat, 24 Feb 2024 22:52:37 +0100 Subject: [PATCH 1/3] Sketcher : ArcLength Constraint --- src/Mod/Sketcher/App/Sketch.cpp | 20 +++-- src/Mod/Sketcher/App/planegcs/Constraints.cpp | 88 +++++++++++++++++++ src/Mod/Sketcher/App/planegcs/Constraints.h | 25 +++++- src/Mod/Sketcher/App/planegcs/GCS.cpp | 9 ++ src/Mod/Sketcher/App/planegcs/GCS.h | 1 + src/Mod/Sketcher/App/planegcs/Geo.h | 1 + src/Mod/Sketcher/Gui/CommandConstraints.cpp | 27 ++++++ 7 files changed, 162 insertions(+), 9 deletions(-) diff --git a/src/Mod/Sketcher/App/Sketch.cpp b/src/Mod/Sketcher/App/Sketch.cpp index bf68f40fae..fd29941145 100644 --- a/src/Mod/Sketcher/App/Sketch.cpp +++ b/src/Mod/Sketcher/App/Sketch.cpp @@ -2162,7 +2162,7 @@ int Sketch::addConstraint(const Constraint* constraint) c.driving); } } - else { // line length + else { // line length, arc length c.value = new double(constraint->getValue()); if (c.driving) { FixParameters.push_back(c.value); @@ -3288,19 +3288,23 @@ int Sketch::addAngleAtPointConstraint(int geoId1, return ConstraintsCounter; } -// line length constraint +// line length and arc length constraint int Sketch::addDistanceConstraint(int geoId, double* value, bool driving) { geoId = checkGeoId(geoId); - if (Geoms[geoId].type != Line) { + int tag = ++ConstraintsCounter; + if (Geoms[geoId].type == Line) { + GCS::Line& l = Lines[Geoms[geoId].index]; + GCSsys.addConstraintP2PDistance(l.p1, l.p2, value, tag, driving); + } + else if (Geoms[geoId].type == Arc) { + GCS::Arc& a = Arcs[Geoms[geoId].index]; + GCSsys.addConstraintArcLength(a, value, tag, driving); + } + else { return -1; } - - GCS::Line& l = Lines[Geoms[geoId].index]; - - int tag = ++ConstraintsCounter; - GCSsys.addConstraintP2PDistance(l.p1, l.p2, value, tag, driving); return ConstraintsCounter; } diff --git a/src/Mod/Sketcher/App/planegcs/Constraints.cpp b/src/Mod/Sketcher/App/planegcs/Constraints.cpp index 5a66be5bee..4fe4e64a58 100644 --- a/src/Mod/Sketcher/App/planegcs/Constraints.cpp +++ b/src/Mod/Sketcher/App/planegcs/Constraints.cpp @@ -24,6 +24,8 @@ #pragma warning(disable : 4251) #endif +#include + #include #define DEBUG_DERIVS 0 #if DEBUG_DERIVS @@ -3491,4 +3493,90 @@ double ConstraintP2CDistance::grad(double* param) return deriv * scale; } +// -------------------------------------------------------- +// ConstraintArcLength +ConstraintArcLength::ConstraintArcLength(Arc& a, double* d) +{ + this->d = d; + pvec.push_back(d); + + this->arc = a; + this->arc.PushOwnParams(pvec); + + origpvec = pvec; + pvecChangedFlag = true; + rescale(); +} + +void ConstraintArcLength::ReconstructGeomPointers() +{ + int i = 0; + i++; // skip the first parameter as there is the inline function distance for it + arc.ReconstructOnNewPvec(pvec, i); + pvecChangedFlag = false; +} + +ConstraintType ConstraintArcLength::getTypeId() +{ + return ArcLength; +} + +void ConstraintArcLength::rescale(double coef) +{ + scale = coef; +} + +void ConstraintArcLength::errorgrad(double* err, double* grad, double* param) +{ + if (pvecChangedFlag) { + ReconstructGeomPointers(); + } + + double rad = *arc.rad; + double endA = *arc.endAngle; + double startA = *arc.startAngle; + // Assume positive angles and CCW arc + while (startA < 0.) { + startA += 2. * M_PI; + } + while (endA < startA) { + endA += 2. * M_PI; + } + if (err) { + *err = rad * (endA - startA) - *distance(); + } + else if (grad) { + if (param == distance()) { + // if constraint is not driving it varies on distance(). + *grad = -1.; + } + else { + double dRad = param == arc.rad ? 1. : 0.; + double dStartA = param == arc.startAngle ? 1. : 0.; + double dEndA = param == arc.endAngle ? 1. : 0.; + *grad = rad * (dEndA - dStartA) + dRad * (endA - startA); + } + } +} + +double ConstraintArcLength::error() +{ + double err; + errorgrad(&err, nullptr, nullptr); + return scale * err; +} + +double ConstraintArcLength::grad(double* param) +{ + if (findParamInPvec(param) == -1) { + return 0.0; + } + + double deriv; + errorgrad(nullptr, &deriv, param); + + return deriv * scale; +} + + } // namespace GCS diff --git a/src/Mod/Sketcher/App/planegcs/Constraints.h b/src/Mod/Sketcher/App/planegcs/Constraints.h index 017165ca6f..04c2003d5e 100644 --- a/src/Mod/Sketcher/App/planegcs/Constraints.h +++ b/src/Mod/Sketcher/App/planegcs/Constraints.h @@ -81,7 +81,8 @@ enum ConstraintType P2CDistance = 32, AngleViaPointAndParam = 33, AngleViaPointAndTwoParams = 34, - AngleViaTwoPoints = 35 + AngleViaTwoPoints = 35, + ArcLength = 36, }; enum InternalAlignmentType @@ -1385,6 +1386,28 @@ public: double grad(double*) override; }; +// ArcLength +class ConstraintArcLength: public Constraint +{ +private: + Arc arc; + double* d; + inline double* distance() + { + return pvec[0]; + } + void ReconstructGeomPointers(); // writes pointers in pvec to the parameters of a + void + errorgrad(double* err, + double* grad, + double* param); // error and gradient combined. Values are returned through pointers. +public: + ConstraintArcLength(Arc& a, double* d); + ConstraintType getTypeId() override; + void rescale(double coef = 1.) override; + double error() override; + double grad(double*) override; +}; } // namespace GCS diff --git a/src/Mod/Sketcher/App/planegcs/GCS.cpp b/src/Mod/Sketcher/App/planegcs/GCS.cpp index cb87fc5892..036894b8be 100644 --- a/src/Mod/Sketcher/App/planegcs/GCS.cpp +++ b/src/Mod/Sketcher/App/planegcs/GCS.cpp @@ -889,6 +889,15 @@ int System::addConstraintP2CDistance(Point& p, Circle& c, double* distance, int return addConstraint(constr); } +int System::addConstraintArcLength(Arc& a, double* distance, int tagId, bool driving) +{ + Constraint* constr = new ConstraintArcLength(a, distance); + constr->setTag(tagId); + constr->setDriving(driving); + return addConstraint(constr); +} + + // derived constraints int System::addConstraintP2PCoincident(Point& p1, Point& p2, int tagId, bool driving) diff --git a/src/Mod/Sketcher/App/planegcs/GCS.h b/src/Mod/Sketcher/App/planegcs/GCS.h index 5d941a9f91..6b0b12da05 100644 --- a/src/Mod/Sketcher/App/planegcs/GCS.h +++ b/src/Mod/Sketcher/App/planegcs/GCS.h @@ -462,6 +462,7 @@ public: double* distance, int tagId = 0, bool driving = true); + int addConstraintArcLength(Arc& a, double* dist, int tagId, bool driving = true); // internal alignment constraints int addConstraintInternalAlignmentPoint2Ellipse(Ellipse& e, diff --git a/src/Mod/Sketcher/App/planegcs/Geo.h b/src/Mod/Sketcher/App/planegcs/Geo.h index b021ef2e84..4604c55b26 100644 --- a/src/Mod/Sketcher/App/planegcs/Geo.h +++ b/src/Mod/Sketcher/App/planegcs/Geo.h @@ -243,6 +243,7 @@ public: double* startAngle; double* endAngle; // double *rad; //inherited + // start and end points are computed by an ArcRules constraint Point start; Point end; // Point center; //inherited diff --git a/src/Mod/Sketcher/Gui/CommandConstraints.cpp b/src/Mod/Sketcher/Gui/CommandConstraints.cpp index 8371a57744..eb42689663 100644 --- a/src/Mod/Sketcher/Gui/CommandConstraints.cpp +++ b/src/Mod/Sketcher/Gui/CommandConstraints.cpp @@ -4615,6 +4615,33 @@ void CmdSketcherConstrainDistance::activated(int iMsg) finishDatumConstraint(this, Obj, true); } + return; + } + else if (isArcOfCircle(*geom)) { + auto arc = static_cast(geom); + double ActLength = arc->getAngle(false) * arc->getRadius(); + + openCommand(QT_TRANSLATE_NOOP("Command", "Add length constraint")); + Gui::cmdAppObjectArgs(selection[0].getObject(), + "addConstraint(Sketcher.Constraint('Distance',%d,%f))", + GeoId1, + ActLength); + + // it is a constraint on a external line, make it non-driving + if (arebothpointsorsegmentsfixed || GeoId1 <= Sketcher::GeoEnum::RefExt + || constraintCreationMode == Reference) { + const std::vector& ConStr = Obj->Constraints.getValues(); + + Gui::cmdAppObjectArgs(selection[0].getObject(), + "setDriving(%d,%s)", + ConStr.size() - 1, + "False"); + finishDatumConstraint(this, Obj, false); + } + else { + finishDatumConstraint(this, Obj, true); + } + return; } } From e2086ce1c7996a3264b51691f936ae15a5fa0981 Mon Sep 17 00:00:00 2001 From: Florian Foinant-Willig Date: Sun, 25 Feb 2024 18:00:06 +0100 Subject: [PATCH 2/3] Sketcher: ArcLength GUI --- src/Gui/SoDatumLabel.cpp | 240 ++++++++++++++++++ src/Gui/SoDatumLabel.h | 5 +- .../Gui/EditModeConstraintCoinManager.cpp | 27 ++ src/Mod/Sketcher/Gui/ViewProviderSketch.cpp | 58 +++-- 4 files changed, 307 insertions(+), 23 deletions(-) diff --git a/src/Gui/SoDatumLabel.cpp b/src/Gui/SoDatumLabel.cpp index 20ac698084..1839e52b24 100644 --- a/src/Gui/SoDatumLabel.cpp +++ b/src/Gui/SoDatumLabel.cpp @@ -87,6 +87,7 @@ SoDatumLabel::SoDatumLabel() SO_NODE_DEFINE_ENUM_VALUE(Type, ANGLE); SO_NODE_DEFINE_ENUM_VALUE(Type, RADIUS); SO_NODE_DEFINE_ENUM_VALUE(Type, DIAMETER); + SO_NODE_DEFINE_ENUM_VALUE(Type, ARCLENGTH); SO_NODE_SET_SF_ENUM_TYPE(datumtype, Type); SO_NODE_ADD_FIELD(param1, (0.f)); @@ -174,6 +175,9 @@ public: else if (label->datumtype.getValue() == SoDatumLabel::SYMMETRIC) { corners = computeSymmetricBBox(); } + else if (label->datumtype.getValue() == SoDatumLabel::ARCLENGTH) { + corners = computeArcLengthBBox(); + } getBBox(corners, box, center); } @@ -430,6 +434,73 @@ private: return corners; } + std::vector computeArcLengthBBox() const + { SbVec2s imgsize; + int nc; + int srcw = 1; + int srch = 1; + + const unsigned char * dataptr = label->image.getValue(imgsize, nc); + if (dataptr) { + srcw = imgsize[0]; + srch = imgsize[1]; + } + + float aspectRatio = (float) srcw / (float) srch; + float imgHeight = scale * (float) (srch); + float imgWidth = aspectRatio * imgHeight; + + // Get the points stored in the pnt field + const SbVec3f *points = label->pnts.getValues(0); + if (label->pnts.getNum() < 3) { + return {}; + } + + SbVec3f ctr = points[0]; + SbVec3f p1 = points[1]; + SbVec3f p2 = points[2]; + + SbVec3f img1 = SbVec3f(-imgWidth / 2, -imgHeight / 2, 0.f); + SbVec3f img2 = SbVec3f(-imgWidth / 2, imgHeight / 2, 0.f); + SbVec3f img3 = SbVec3f( imgWidth / 2, -imgHeight / 2, 0.f); + SbVec3f img4 = SbVec3f( imgWidth / 2, imgHeight / 2, 0.f); + + //Text orientation + SbVec3f dir = (p2 - p1); + dir.normalize(); + SbVec3f normal = SbVec3f (-dir[1], dir[0], 0); + float angle = atan2f(dir[1],dir[0]); + + // Rotate through an angle + float s = sin(angle); + float c = cos(angle); + img1 = SbVec3f((img1[0] * c) - (img1[1] * s), (img1[0] * s) + (img1[1] * c), 0.f); + img2 = SbVec3f((img2[0] * c) - (img2[1] * s), (img2[0] * s) + (img2[1] * c), 0.f); + img3 = SbVec3f((img3[0] * c) - (img3[1] * s), (img3[0] * s) + (img3[1] * c), 0.f); + img4 = SbVec3f((img4[0] * c) - (img4[1] * s), (img4[0] * s) + (img4[1] * c), 0.f); + + float length = label->param1.getValue(); + + // Text location + SbVec3f vm = (p1+p2)/2 - ctr; + vm.normalize(); + SbVec3f textCenter = ctr + vm * (length + imgHeight); + img1 += textCenter; + img2 += textCenter; + img3 += textCenter; + img4 += textCenter; + + // Finds the mins and maxes + std::vector corners; + float margin = imgHeight / 4.0F; + corners.push_back(textCenter + dir * (imgWidth / 2.0F + margin) - normal * (imgHeight / 2.0F + margin)); + corners.push_back(textCenter - dir * (imgWidth / 2.0F + margin) - normal * (imgHeight / 2.0F + margin)); + corners.push_back(textCenter + dir * (imgWidth / 2.0F + margin) + normal * (imgHeight / 2.0F + margin)); + corners.push_back(textCenter - dir * (imgWidth / 2.0F + margin) + normal * (imgHeight / 2.0F + margin)); + + return corners; + } + private: float scale; SoDatumLabel* label; @@ -451,6 +522,7 @@ SbVec3f SoDatumLabel::getLabelTextCenter() const SbVec3f* points = this->pnts.getValues(0); SbVec3f p1 = points[0]; SbVec3f p2 = points[1]; + SbVec3f p3 = points[2]; if (datumtype.getValue() == SoDatumLabel::DISTANCE || datumtype.getValue() == SoDatumLabel::DISTANCEX || @@ -465,6 +537,9 @@ SbVec3f SoDatumLabel::getLabelTextCenter() else if (datumtype.getValue() == SoDatumLabel::ANGLE) { return getLabelTextCenterAngle(p1); } + else if (datumtype.getValue() == SoDatumLabel::ARCLENGTH) { + return getLabelTextCenterArcLength(p1, p2, p3); + } return p1; } @@ -525,6 +600,18 @@ SbVec3f SoDatumLabel::getLabelTextCenterAngle(const SbVec3f& p0) return textCenter; } +SbVec3f SoDatumLabel::getLabelTextCenterArcLength(const SbVec3f& ctr, const SbVec3f& p1, const SbVec3f& p2) +{ + float length = this->param1.getValue(); + + // Text location + SbVec3f vm = (p1+p2)/2 - ctr; + vm.normalize(); + SbVec3f textCenter = ctr + vm * (length + this->imgHeight); + return textCenter; +} + + void SoDatumLabel::generateDistancePrimitives(SoAction * action, const SbVec3f& p1, const SbVec3f& p2) { SbVec3f dir; @@ -725,6 +812,56 @@ void SoDatumLabel::generateSymmetricPrimitives(SoAction * action, const SbVec3f& this->endShape(); } +void SoDatumLabel::generateArcLengthPrimitives(SoAction * action, const SbVec3f& ctr, const SbVec3f& p1, const SbVec3f& p2) +{ + SbVec3f img1 = SbVec3f(-this->imgWidth / 2, -this->imgHeight / 2, 0.f); + SbVec3f img2 = SbVec3f(-this->imgWidth / 2, this->imgHeight / 2, 0.f); + SbVec3f img3 = SbVec3f( this->imgWidth / 2, -this->imgHeight / 2, 0.f); + SbVec3f img4 = SbVec3f( this->imgWidth / 2, this->imgHeight / 2, 0.f); + + //Text orientation + SbVec3f dir = (p2 - p1); + dir.normalize(); + float angle = atan2f(dir[1],dir[0]); + + // Rotate through an angle + float s = sin(angle); + float c = cos(angle); + img1 = SbVec3f((img1[0] * c) - (img1[1] * s), (img1[0] * s) + (img1[1] * c), 0.f); + img2 = SbVec3f((img2[0] * c) - (img2[1] * s), (img2[0] * s) + (img2[1] * c), 0.f); + img3 = SbVec3f((img3[0] * c) - (img3[1] * s), (img3[0] * s) + (img3[1] * c), 0.f); + img4 = SbVec3f((img4[0] * c) - (img4[1] * s), (img4[0] * s) + (img4[1] * c), 0.f); + + //Text location + SbVec3f textOffset = getLabelTextCenterArcLength(ctr, p1, p2); + img1 += textOffset; + img2 += textOffset; + img3 += textOffset; + img4 += textOffset; + + // Primitive Shape is only for text as this should only be selectable + SoPrimitiveVertex pv; + + this->beginShape(action, TRIANGLE_STRIP); + + pv.setNormal( SbVec3f(0.f, 0.f, 1.f) ); + + // Set coordinates + pv.setPoint( img1 ); + shapeVertex(&pv); + + pv.setPoint( img2 ); + shapeVertex(&pv); + + pv.setPoint( img3 ); + shapeVertex(&pv); + + pv.setPoint( img4 ); + shapeVertex(&pv); + + this->endShape(); +} + void SoDatumLabel::generatePrimitives(SoAction * action) { // Initialisation check (needs something more sensible) prevents an infinite loop bug @@ -735,6 +872,7 @@ void SoDatumLabel::generatePrimitives(SoAction * action) const SbVec3f *points = this->pnts.getValues(0); SbVec3f p1 = points[0]; SbVec3f p2 = points[1]; + SbVec3f p3 = points[2]; // Change the offset and bounding box parameters depending on Datum Type if (this->datumtype.getValue() == DISTANCE || @@ -756,6 +894,10 @@ void SoDatumLabel::generatePrimitives(SoAction * action) generateSymmetricPrimitives(action, p1, p2); } + else if (this->datumtype.getValue() == ARCLENGTH) { + + generateArcLengthPrimitives(action, p1, p2, p3); + } } void SoDatumLabel::notify(SoNotList * l) @@ -1272,6 +1414,104 @@ void SoDatumLabel::GLRender(SoGLRenderAction * action) glVertex3f(ar5[0], ar5[1], ZCONSTR); glEnd(); } + else if (this->datumtype.getValue() == ARCLENGTH) { + SbVec3f ctr = points[0]; + SbVec3f p1 = points[1]; + SbVec3f p2 = points[2]; + float length = this->param1.getValue(); + + float margin = this->imgHeight / 3.0; + + // Angles calculations + SbVec3f vc1 = (p1 - ctr); + SbVec3f vc2 = (p2 - ctr); + + float startangle = atan2f(vc1[1], vc1[0]); + float endangle = atan2f(vc2[1], vc2[0]); + if (endangle < startangle) + endangle += 2. * M_PI; + + float radius = vc1.length(); + + float range = endangle - startangle; + + //Text orientation + SbVec3f dir = (p2 - p1); + dir.normalize(); + // Get magnitude of angle between horizontal + angle = atan2f(dir[1],dir[0]); + if (angle > M_PI_2+M_PI/12) { + angle -= (float)M_PI; + } else if (angle <= -M_PI_2+M_PI/12) { + angle += (float)M_PI; + } + + // Text location + SbVec3f vm = (p1+p2)/2 - ctr; + vm.normalize(); + textOffset = ctr + vm * (length + this->imgHeight); + + int countSegments = std::max(6, abs(int(50.0 * range / (2 * M_PI)))); + double segment = range / (countSegments - 1); + + // Draw arc + glBegin(GL_LINE_STRIP); + + for (int i=0; i < countSegments; i++) { + double theta = startangle + segment*i; + SbVec3f v1 = ctr + radius * SbVec3f(cos(theta),sin(theta),0) + (length-radius) * vm; + glVertex2f(v1[0],v1[1]); + } + glEnd(); + + //Draw lines + SbVec3f pnt1 = p1; + SbVec3f pnt2 = p1 + (length-radius) * vm; + SbVec3f pnt3 = p2; + SbVec3f pnt4 = p2 + (length-radius) * vm; + + glBegin(GL_LINES); + glVertex2f(pnt1[0],pnt1[1]); + glVertex2f(pnt2[0],pnt2[1]); + + glVertex2f(pnt3[0],pnt3[1]); + glVertex2f(pnt4[0],pnt4[1]); + glEnd(); + + // Create the arrowheads + // Direction vectors at arc start and end + SbVec3f v1(cos(startangle),sin(startangle),0); + SbVec3f v2(cos(endangle),sin(endangle),0); + float arrowLength = margin * 2; + float arrowWidth = margin * 0.5; + + // Normals for the arrowheads + SbVec3f dirStart(v1[1], -v1[0], 0); + SbVec3f dirEnd(-v2[1], v2[0], 0); + + // Calculate arrowhead points for start angle + SbVec3f startArrowBase = pnt2; + SbVec3f startArrowLeft = startArrowBase - arrowLength * dirStart + arrowWidth * v1; + SbVec3f startArrowRight = startArrowBase - arrowLength * dirStart - arrowWidth * v1; + + // Calculate arrowhead points for end angle + SbVec3f endArrowBase = pnt4; + SbVec3f endArrowLeft = endArrowBase - arrowLength * dirEnd + arrowWidth * v2; + SbVec3f endArrowRight = endArrowBase - arrowLength * dirEnd - arrowWidth * v2; + + // Draw arrowheads + glBegin(GL_TRIANGLES); + // Start angle arrowhead + glVertex2f(startArrowBase[0], startArrowBase[1]); + glVertex2f(startArrowLeft[0], startArrowLeft[1]); + glVertex2f(startArrowRight[0], startArrowRight[1]); + + // End angle arrowhead + glVertex2f(endArrowBase[0], endArrowBase[1]); + glVertex2f(endArrowLeft[0], endArrowLeft[1]); + glVertex2f(endArrowRight[0], endArrowRight[1]); + glEnd(); + } if (hasText) { const unsigned char * dataptr = this->image.getValue(imgsize, nc); diff --git a/src/Gui/SoDatumLabel.h b/src/Gui/SoDatumLabel.h index 2e55ffeb8e..d2b75844ed 100644 --- a/src/Gui/SoDatumLabel.h +++ b/src/Gui/SoDatumLabel.h @@ -54,7 +54,8 @@ public: DISTANCEY, RADIUS, DIAMETER, - SYMMETRIC + SYMMETRIC, + ARCLENGTH }; static void initClass(); @@ -99,9 +100,11 @@ private: void generateDiameterPrimitives(SoAction * action, const SbVec3f&, const SbVec3f&); void generateAnglePrimitives(SoAction * action, const SbVec3f&); void generateSymmetricPrimitives(SoAction * action, const SbVec3f&, const SbVec3f&); + void generateArcLengthPrimitives(SoAction * action, const SbVec3f&, const SbVec3f&, const SbVec3f&); SbVec3f getLabelTextCenterDistance(const SbVec3f&, const SbVec3f&); SbVec3f getLabelTextCenterDiameter(const SbVec3f&, const SbVec3f&); SbVec3f getLabelTextCenterAngle(const SbVec3f&); + SbVec3f getLabelTextCenterArcLength(const SbVec3f&, const SbVec3f&, const SbVec3f&); private: void drawImage(); diff --git a/src/Mod/Sketcher/Gui/EditModeConstraintCoinManager.cpp b/src/Mod/Sketcher/Gui/EditModeConstraintCoinManager.cpp index 04fc7cdaa8..ab3ec908f0 100644 --- a/src/Mod/Sketcher/Gui/EditModeConstraintCoinManager.cpp +++ b/src/Mod/Sketcher/Gui/EditModeConstraintCoinManager.cpp @@ -891,6 +891,33 @@ Restart: pnt1 = lineSeg->getStartPoint(); pnt2 = lineSeg->getEndPoint(); } + else if (isArcOfCircle(*geo)) { + // arc length + auto arc = static_cast(geo); + int index = static_cast(ConstraintNodePosition::DatumLabelIndex); + auto* asciiText = static_cast(sep->getChild(index)); + center1 = arc->getCenter(); + pnt1 = arc->getStartPoint(); + pnt2 = arc->getEndPoint(); + + double startAngle, endAngle; + arc->getRange(startAngle, endAngle, /*emulateCCW=*/false); + + asciiText->datumtype = SoDatumLabel::ARCLENGTH; + asciiText->param1 = Constr->LabelDistance; + asciiText->string = + SbString(std::string("◠ ") + .append(getPresentationString(Constr).toUtf8()) + .c_str()); + + asciiText->pnts.setNum(3); + SbVec3f* verts = asciiText->pnts.startEditing(); + verts[0] = SbVec3f(center1.x, center1.y, center1.z); + verts[1] = SbVec3f(pnt1.x, pnt1.y, pnt1.z); + verts[2] = SbVec3f(pnt2.x, pnt2.y, pnt2.z); + asciiText->pnts.finishEditing(); + break; + } else { break; } diff --git a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp index 95ae557362..84357b9a42 100644 --- a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp +++ b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp @@ -1731,6 +1731,18 @@ void ViewProviderSketch::moveConstraint(Sketcher::Constraint* Constr, int constN // with memory allocation const std::vector geomlist = getSolvedSketch().extractGeometry(true, true); + // lambda to finalize the move + auto cleanAndDraw = [this, geomlist](){ + // delete the cloned objects + for (Part::Geometry* geomPtr : geomlist) { + if (geomPtr) { + delete geomPtr; + } + } + + draw(true, false); + }; + #ifdef FC_DEBUG assert(int(geomlist.size()) == extGeoCount + intGeoCount); assert((Constr->First >= -extGeoCount && Constr->First < intGeoCount) @@ -1806,23 +1818,33 @@ void ViewProviderSketch::moveConstraint(Sketcher::Constraint* Constr, int constN const Part::GeomArcOfCircle* arc = static_cast(geo); double radius = arc->getRadius(); Base::Vector3d center = arc->getCenter(); - p1 = center; + double startangle, endangle; + arc->getRange(startangle, endangle, /*emulateCCW=*/true); - double angle = Constr->LabelPosition; - if (angle == 10) { - double startangle, endangle; - arc->getRange(startangle, endangle, /*emulateCCW=*/true); - angle = (startangle + endangle) / 2; + if (Constr->Type == Distance && Constr->Second == GeoEnum::GeoUndef){ + //arc length + Base::Vector3d dir = Base::Vector3d(toPos.x, toPos.y, 0.) - arc->getCenter(); + Constr->LabelDistance = dir.Length(); + + cleanAndDraw(); + return; } else { - Base::Vector3d tmpDir = Base::Vector3d(toPos.x, toPos.y, 0) - p1; - angle = atan2(tmpDir.y, tmpDir.x); + // radius and diameter + p1 = center; + double angle = Constr->LabelPosition; + if (angle == 10) { + angle = (startangle + endangle) / 2; + } + else { + Base::Vector3d tmpDir = Base::Vector3d(toPos.x, toPos.y, 0) - p1; + angle = atan2(tmpDir.y, tmpDir.x); + } + if (Constr->Type == Sketcher::Diameter) + p1 = center - radius * Base::Vector3d(cos(angle), sin(angle), 0.); + + p2 = center + radius * Base::Vector3d(cos(angle), sin(angle), 0.); } - - if (Constr->Type == Sketcher::Diameter) - p1 = center - radius * Base::Vector3d(cos(angle), sin(angle), 0.); - - p2 = center + radius * Base::Vector3d(cos(angle), sin(angle), 0.); } else if (geo->is()) { const Part::GeomCircle* circle = static_cast(geo); @@ -1863,7 +1885,6 @@ void ViewProviderSketch::moveConstraint(Sketcher::Constraint* Constr, int constN } else return; - Base::Vector3d vec = Base::Vector3d(toPos.x, toPos.y, 0) - p2; Base::Vector3d dir; @@ -1893,14 +1914,7 @@ void ViewProviderSketch::moveConstraint(Sketcher::Constraint* Constr, int constN moveAngleConstraint(Constr, constNum, toPos); } - // delete the cloned objects - for (Part::Geometry* geomPtr : geomlist) { - if (geomPtr) { - delete geomPtr; - } - } - - draw(true, false); + cleanAndDraw(); } void ViewProviderSketch::moveAngleConstraint(Sketcher::Constraint* constr, int constNum, const Base::Vector2d& toPos) From 311137c9580eb35c23ac35b696fafca478334b5e Mon Sep 17 00:00:00 2001 From: Florian Foinant-Willig Date: Mon, 11 Mar 2024 14:12:48 +0100 Subject: [PATCH 3/3] fix undeclared M_PI --- src/Mod/Sketcher/App/planegcs/Constraints.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Mod/Sketcher/App/planegcs/Constraints.cpp b/src/Mod/Sketcher/App/planegcs/Constraints.cpp index 4fe4e64a58..c56e652721 100644 --- a/src/Mod/Sketcher/App/planegcs/Constraints.cpp +++ b/src/Mod/Sketcher/App/planegcs/Constraints.cpp @@ -24,14 +24,14 @@ #pragma warning(disable : 4251) #endif -#include +#define _USE_MATH_DEFINES +#include #include #define DEBUG_DERIVS 0 #if DEBUG_DERIVS #include #endif -#include #include