Merge pull request #12012 from Ondsel-Development/radius_render_fix

[Sketcher] Improve rendering of arc-angle, line-angle, arc-distances and fix radius
This commit is contained in:
Chris Hennes
2024-01-22 11:21:53 -06:00
committed by GitHub
4 changed files with 271 additions and 104 deletions

View File

@@ -93,6 +93,9 @@ SoDatumLabel::SoDatumLabel()
SO_NODE_ADD_FIELD(param2, (0.f));
SO_NODE_ADD_FIELD(param4, (0.f));
SO_NODE_ADD_FIELD(param5, (0.f));
SO_NODE_ADD_FIELD(param6, (0.f));
SO_NODE_ADD_FIELD(param7, (0.f));
SO_NODE_ADD_FIELD(param8, (0.f));
useAntialiasing = true;
@@ -989,6 +992,43 @@ void SoDatumLabel::GLRender(SoGLRenderAction * action)
glVertex2f(ar3[0], ar3[1]);
glVertex2f(ar4[0], ar4[1]);
glEnd();
if (this->datumtype.getValue() == DISTANCE) {
// Draw arc helpers if needed
float range1 = this->param4.getValue();
if (range1 != 0.0) {
float startangle1 = this->param3.getValue();
float radius1 = this->param5.getValue();
SbVec3f center = points[2];
int countSegments = std::max(6, abs(int(50.0 * range1 / (2 * M_PI))));
double segment = range1 / (countSegments - 1);
glBegin(GL_LINE_STRIP);
for (int i = 0; i < countSegments; i++) {
double theta = startangle1 + segment * i;
SbVec3f v1 = center + SbVec3f(radius1 * cos(theta), radius1 * sin(theta), 0);
glVertex2f(v1[0], v1[1]);
}
glEnd();
}
float range2 = this->param7.getValue();
if (range2 != 0.0) {
float startangle2 = this->param6.getValue();
float radius2 = this->param8.getValue();
SbVec3f center = points[3];
int countSegments = std::max(6, abs(int(50.0 * range2 / (2 * M_PI))));
double segment = range2 / (countSegments - 1);
glBegin(GL_LINE_STRIP);
for (int i = 0; i < countSegments; i++) {
double theta = startangle2 + segment * i;
SbVec3f v1 = center + SbVec3f(radius2 * cos(theta), radius2 * sin(theta), 0);
glVertex2f(v1[0], v1[1]);
}
glEnd();
}
}
}
else if (this->datumtype.getValue() == RADIUS || this->datumtype.getValue() == DIAMETER) {
// Get the Points

View File

@@ -77,6 +77,9 @@ public:
SoSFFloat param3;
SoSFFloat param4;
SoSFFloat param5;
SoSFFloat param6;
SoSFFloat param7;
SoSFFloat param8;
SoMFVec3f pnts;
SoSFVec3f norm;
SoSFImage image;

View File

@@ -814,6 +814,17 @@ Restart:
case DistanceY: {
assert(Constr->First >= -extGeoCount && Constr->First < intGeoCount);
double helperStartAngle1 = 0.; // for arc helpers
double helperStartAngle2 = 0.;
double helperRange1 = 0.;
double helperRange2 = 0.;
double radius1 = 0.;
double radius2 = 0.;
Base::Vector3d center1(0., 0., 0.);
Base::Vector3d center2(0., 0., 0.);
int numPoints = 2;
// pnt1 will be initialized to (0,0,0) if only one point is given
auto pnt1 = geolistfacade.getPoint(Constr->First, Constr->FirstPos);
@@ -838,17 +849,15 @@ Restart:
pnt2.ProjectToLine(pnt1 - l2p1, l2p2 - l2p1);
pnt2 += pnt1;
}
else {
if (isCircleOrArc(*geo1)) {
// circular to line distance
auto [radius, ct] = getRadiusCenterCircleArc(geo1);
// project the center on the line (translated to origin)
pnt1.ProjectToLine(ct - l2p1, l2p2 - l2p1);
Base::Vector3d dir = pnt1;
dir.Normalize();
pnt1 += ct;
pnt2 = ct + dir * radius;
}
else if (isCircleOrArc(*geo1)) {
// circular to line distance
auto [radius, ct] = getRadiusCenterCircleArc(geo1);
// project the center on the line (translated to origin)
pnt1.ProjectToLine(ct - l2p1, l2p2 - l2p1);
Base::Vector3d dir = pnt1;
dir.Normalize();
pnt1 += ct;
pnt2 = ct + dir * radius;
}
}
else if (isCircleOrArc(*geo2)) {
@@ -890,10 +899,8 @@ Restart:
break;
}
// NOLINTBEGIN
SoDatumLabel* asciiText = static_cast<SoDatumLabel*>(
sep->getChild(static_cast<int>(ConstraintNodePosition::DatumLabelIndex)));
// NOLINTEND
int index = static_cast<int>(ConstraintNodePosition::DatumLabelIndex);
auto* asciiText = static_cast<SoDatumLabel*>(sep->getChild(index)); // NOLINT
// Get presentation string (w/o units if option is set)
asciiText->string =
@@ -909,13 +916,102 @@ Restart:
asciiText->datumtype = SoDatumLabel::DISTANCEY;
}
// Check if arc helpers are needed
if (Constr->Second != GeoEnum::GeoUndef
&& Constr->SecondPos == Sketcher::PointPos::none) {
auto geo1 = geolistfacade.getGeometryFromGeoId(Constr->First);
auto geo2 = geolistfacade.getGeometryFromGeoId(Constr->Second);
if (isArcOfCircle(*geo1)) {
auto arc = static_cast<const Part::GeomArcOfCircle*>(geo1); // NOLINT
radius1 = arc->getRadius();
center1 = arc->getCenter();
double angle =
toVector2d(isLineSegment(*geo2) ? pnt2 - center1 : pnt1 - center1)
.Angle();
double startAngle, endAngle;
arc->getRange(startAngle, endAngle, /*emulateCCW=*/true);
findHelperAngles(helperStartAngle1,
helperRange1,
angle,
startAngle,
endAngle);
if (helperRange1 != 0.) {
// We override to draw the full helper as it does not look good
// otherwise We still use findHelperAngles before to find if helper
// is needed.
helperStartAngle1 = endAngle;
helperRange1 = 2 * M_PI - (endAngle - startAngle);
numPoints++;
}
}
if (isArcOfCircle(*geo2)) {
auto arc = static_cast<const Part::GeomArcOfCircle*>(geo2); // NOLINT
radius2 = arc->getRadius();
center2 = arc->getCenter();
double angle =
toVector2d(pnt2 - center2).Angle(); // between -pi and pi
double startAngle, endAngle; // between 0 and 2*pi
arc->getRange(startAngle, endAngle, /*emulateCCW=*/true);
findHelperAngles(helperStartAngle2,
helperRange2,
angle,
startAngle,
endAngle);
if (helperRange2 != 0.) {
helperStartAngle2 = endAngle;
helperRange2 = 2 * M_PI - (endAngle - startAngle);
numPoints++;
}
}
}
// Assign the Datum Points
asciiText->pnts.setNum(2);
asciiText->pnts.setNum(numPoints);
SbVec3f* verts = asciiText->pnts.startEditing();
verts[0] = SbVec3f(pnt1.x, pnt1.y, zConstrH);
verts[1] = SbVec3f(pnt2.x, pnt2.y, zConstrH);
if (numPoints > 2) {
if (helperRange1 != 0.) {
verts[2] = SbVec3f(center1.x, center1.y, zConstrH);
asciiText->param3 = helperStartAngle1;
asciiText->param4 = helperRange1;
asciiText->param5 = radius1;
}
else {
verts[2] = SbVec3f(center2.x, center2.y, zConstrH);
asciiText->param3 = helperStartAngle2;
asciiText->param4 = helperRange2;
asciiText->param5 = radius2;
}
if (numPoints > 3) {
verts[3] = SbVec3f(center2.x, center2.y, zConstrH);
asciiText->param6 = helperStartAngle2;
asciiText->param7 = helperRange2;
asciiText->param8 = radius2;
}
else {
asciiText->param6 = 0.;
asciiText->param7 = 0.;
asciiText->param8 = 0.;
}
}
else {
asciiText->param3 = 0.;
asciiText->param4 = 0.;
asciiText->param5 = 0.;
}
asciiText->pnts.finishEditing();
// Assign the Label Distance
@@ -1281,20 +1377,25 @@ Restart:
const Part::Geometry* geo =
geolistfacade.getGeometryFromGeoId(Constr->First);
if (geo->is<Part::GeomLineSegment>()) {
const Part::GeomLineSegment* lineSeg =
static_cast<const Part::GeomLineSegment*>(geo);
auto* lineSeg = static_cast<const Part::GeomLineSegment*>(geo);
p0 = Base::convertTo<SbVec3f>(
(lineSeg->getEndPoint() + lineSeg->getStartPoint()) / 2);
double l1 = 2 * distance
- (lineSeg->getEndPoint() - lineSeg->getStartPoint()).Length() / 2;
endLineLength1 = 2 * distance;
endLineLength2 = l1 > 0. ? l1 : 0.;
Base::Vector3d dir = lineSeg->getEndPoint() - lineSeg->getStartPoint();
startangle = 0.;
range = atan2(dir.y, dir.x);
}
else if (geo->is<Part::GeomArcOfCircle>()) {
const Part::GeomArcOfCircle* arc =
static_cast<const Part::GeomArcOfCircle*>(geo);
auto* arc = static_cast<const Part::GeomArcOfCircle*>(geo);
p0 = Base::convertTo<SbVec3f>(arc->getCenter());
endLineLength1 = 2 * distance - arc->getRadius();
endLineLength2 = endLineLength1;
double endangle;
arc->getRange(startangle, endangle, /*emulateCCWXY=*/true);
range = endangle - startangle;
@@ -1333,51 +1434,43 @@ Restart:
double helperStartAngle = 0.;
double helperRange = 0.;
if (Constr->First != GeoEnum::GeoUndef) {
const Part::Geometry* geo =
geolistfacade.getGeometryFromGeoId(Constr->First);
if (Constr->First == GeoEnum::GeoUndef) {
break;
}
if (geo->is<Part::GeomArcOfCircle>()) {
auto* arc = static_cast<const Part::GeomArcOfCircle*>(geo);
double radius = arc->getRadius();
double angle = (double)Constr->LabelPosition;
double startAngle, endAngle;
arc->getRange(startAngle, endAngle, /*emulateCCW=*/true);
if (angle == 10) {
angle = (startAngle + endAngle) / 2;
}
if (!(angle > startAngle && angle < endAngle)) {
if (angle < startAngle
&& startAngle - angle < angle + 2 * M_PI - endAngle) {
helperStartAngle = angle;
helperRange = startAngle - angle;
}
else {
if (angle < endAngle) {
angle += 2 * M_PI;
}
helperStartAngle = endAngle;
helperRange = angle - endAngle;
}
}
Base::Vector3d center = arc->getCenter();
pnt1 = center - radius * Base::Vector3d(cos(angle), sin(angle), 0.);
pnt2 = center + radius * Base::Vector3d(cos(angle), sin(angle), 0.);
const Part::Geometry* geo = geolistfacade.getGeometryFromGeoId(Constr->First);
if (geo->is<Part::GeomArcOfCircle>()) {
auto* arc = static_cast<const Part::GeomArcOfCircle*>(geo);
double radius = arc->getRadius();
double angle = (double)Constr->LabelPosition; // between -pi and pi
double startAngle, endAngle; // between 0 and 2*pi
arc->getRange(startAngle, endAngle, /*emulateCCW=*/true);
if (angle == 10) {
angle = (startAngle + endAngle) / 2;
}
else if (geo->is<Part::GeomCircle>()) {
auto* circle = static_cast<const Part::GeomCircle*>(geo);
double radius = circle->getRadius();
double angle = (double)Constr->LabelPosition;
if (angle == 10) {
angle = 0;
}
Base::Vector3d center = circle->getCenter();
pnt1 = center - radius * Base::Vector3d(cos(angle), sin(angle), 0.);
pnt2 = center + radius * Base::Vector3d(cos(angle), sin(angle), 0.);
}
else {
break;
findHelperAngles(helperStartAngle,
helperRange,
angle,
startAngle,
endAngle);
Base::Vector3d center = arc->getCenter();
pnt1 = center - radius * Base::Vector3d(cos(angle), sin(angle), 0.);
pnt2 = center + radius * Base::Vector3d(cos(angle), sin(angle), 0.);
}
else if (geo->is<Part::GeomCircle>()) {
auto* circle = static_cast<const Part::GeomCircle*>(geo);
double radius = circle->getRadius();
double angle = (double)Constr->LabelPosition;
if (angle == 10) {
angle = 0;
}
Base::Vector3d center = circle->getCenter();
pnt1 = center - radius * Base::Vector3d(cos(angle), sin(angle), 0.);
pnt2 = center + radius * Base::Vector3d(cos(angle), sin(angle), 0.);
}
else {
break;
@@ -1415,54 +1508,45 @@ Restart:
double helperStartAngle = 0.;
double helperRange = 0.;
if (Constr->First != GeoEnum::GeoUndef) {
const Part::Geometry* geo =
geolistfacade.getGeometryFromGeoId(Constr->First);
if (Constr->First == GeoEnum::GeoUndef) {
break;
}
const Part::Geometry* geo = geolistfacade.getGeometryFromGeoId(Constr->First);
if (geo->is<Part::GeomArcOfCircle>()) {
auto* arc = static_cast<const Part::GeomArcOfCircle*>(geo);
double radius = arc->getRadius();
double angle = (double)Constr->LabelPosition;
double startAngle, endAngle;
arc->getRange(startAngle, endAngle, /*emulateCCW=*/true);
if (angle == 10) {
angle = (startAngle + endAngle) / 2;
}
if (!(angle > startAngle && angle < endAngle)) {
if (angle < startAngle
&& startAngle - angle < angle + 2 * M_PI - endAngle) {
helperStartAngle = angle;
helperRange = startAngle - angle;
}
else {
if (angle < endAngle) {
angle += 2 * M_PI;
}
helperStartAngle = endAngle;
helperRange = angle - endAngle;
}
}
pnt1 = arc->getCenter();
pnt2 = pnt1 + radius * Base::Vector3d(cos(angle), sin(angle), 0.);
if (geo->is<Part::GeomArcOfCircle>()) {
auto* arc = static_cast<const Part::GeomArcOfCircle*>(geo);
double radius = arc->getRadius();
double angle = (double)Constr->LabelPosition; // between -pi and pi
double startAngle, endAngle; // between 0 and 2*pi
arc->getRange(startAngle, endAngle, /*emulateCCW=*/true);
if (angle == 10) {
angle = (startAngle + endAngle) / 2;
}
else if (geo->is<Part::GeomCircle>()) {
auto* circle = static_cast<const Part::GeomCircle*>(geo);
auto gf = GeometryFacade::getFacade(geo);
double radius;
findHelperAngles(helperStartAngle,
helperRange,
angle,
startAngle,
endAngle);
radius = circle->getRadius();
pnt1 = arc->getCenter();
pnt2 = pnt1 + radius * Base::Vector3d(cos(angle), sin(angle), 0.);
}
else if (geo->is<Part::GeomCircle>()) {
auto* circle = static_cast<const Part::GeomCircle*>(geo);
auto gf = GeometryFacade::getFacade(geo);
double angle = (double)Constr->LabelPosition;
if (angle == 10) {
angle = 0;
}
pnt1 = circle->getCenter();
pnt2 = pnt1 + radius * Base::Vector3d(cos(angle), sin(angle), 0.);
}
else {
break;
double radius;
radius = circle->getRadius();
double angle = (double)Constr->LabelPosition;
if (angle == 10) {
angle = 0;
}
pnt1 = circle->getCenter();
pnt2 = pnt1 + radius * Base::Vector3d(cos(angle), sin(angle), 0.);
}
else {
break;
@@ -1518,6 +1602,39 @@ Restart:
}
}
void EditModeConstraintCoinManager::findHelperAngles(double& helperStartAngle,
double& helperRange,
double angle,
double startAngle,
double endAngle)
{
double margin = 0.2; // about 10deg
if (angle < 0) {
angle = angle + 2 * M_PI;
}
// endAngle can be more than 2*pi as its startAngle + arcAngle
if (endAngle > 2 * M_PI && angle < endAngle - 2 * M_PI) {
angle = angle + 2 * M_PI;
}
if (!(angle > startAngle && angle < endAngle)) {
if ((angle < startAngle && startAngle - angle < angle + 2 * M_PI - endAngle)
|| (angle > endAngle && startAngle + 2 * M_PI - angle < angle - endAngle)) {
if (angle > startAngle) {
angle -= 2 * M_PI;
}
helperStartAngle = angle - margin;
helperRange = startAngle - angle + margin;
}
else {
if (angle < endAngle) {
angle += 2 * M_PI;
}
helperStartAngle = endAngle;
helperRange = angle - endAngle + margin;
}
}
}
Base::Vector3d EditModeConstraintCoinManager::seekConstraintPosition(const Base::Vector3d& origPos,
const Base::Vector3d& norm,
const Base::Vector3d& dir,

View File

@@ -250,6 +250,13 @@ private:
/// Essentially a version of sendConstraintIconToCoin, with a blank icon
void clearCoinImage(SoImage* soImagePtr);
/// Find helper angle for radius/diameter constraint
void findHelperAngles(double& helperStartAngle,
double& helperAngle,
double angle,
double startAngle,
double endAngle);
//@}
private: