Merge pull request #11507 from Ondsel-Development/constr_primitives
[Sketcher] Improve angle & radius constraint rendering
This commit is contained in:
@@ -91,6 +91,8 @@ SoDatumLabel::SoDatumLabel()
|
||||
|
||||
SO_NODE_ADD_FIELD(param1, (0.f));
|
||||
SO_NODE_ADD_FIELD(param2, (0.f));
|
||||
SO_NODE_ADD_FIELD(param4, (0.f));
|
||||
SO_NODE_ADD_FIELD(param5, (0.f));
|
||||
|
||||
useAntialiasing = true;
|
||||
|
||||
@@ -994,6 +996,13 @@ void SoDatumLabel::GLRender(SoGLRenderAction * action)
|
||||
SbVec3f p2 = points[1];
|
||||
|
||||
SbVec3f dir = (p2-p1);
|
||||
SbVec3f center = p1;
|
||||
double radius = (p2 - p1).length();
|
||||
if (this->datumtype.getValue() == DIAMETER) {
|
||||
center = (p1 + p2) / 2;
|
||||
radius = radius / 2;
|
||||
}
|
||||
|
||||
dir.normalize();
|
||||
SbVec3f normal (-dir[1],dir[0],0);
|
||||
|
||||
@@ -1053,7 +1062,22 @@ void SoDatumLabel::GLRender(SoGLRenderAction * action)
|
||||
glVertex2f(ar1_1[0], ar1_1[1]);
|
||||
glVertex2f(ar2_1[0], ar2_1[1]);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
// Draw arc helper if needed
|
||||
float startangle = this->param3.getValue();
|
||||
float range = this->param4.getValue();
|
||||
if (range != 0.0) {
|
||||
int countSegments = std::max(6, abs(int(50.0 * range / (2 * M_PI))));
|
||||
double segment = range / (countSegments - 1);
|
||||
|
||||
glBegin(GL_LINE_STRIP);
|
||||
for (int i = 0; i < countSegments; i++) {
|
||||
double theta = startangle + segment * i;
|
||||
SbVec3f v1 = center + SbVec3f(radius * cos(theta), radius * sin(theta), 0);
|
||||
glVertex2f(v1[0], v1[1]);
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1061,11 +1085,17 @@ void SoDatumLabel::GLRender(SoGLRenderAction * action)
|
||||
// Only the angle intersection point is needed
|
||||
SbVec3f p0 = points[0];
|
||||
|
||||
float margin = this->imgHeight / 4.0;
|
||||
|
||||
// Load the Parameters
|
||||
float length = this->param1.getValue();
|
||||
float startangle = this->param2.getValue();
|
||||
float range = this->param3.getValue();
|
||||
float endangle = startangle + range;
|
||||
float endLineLength1 = std::max(this->param4.getValue(), margin);
|
||||
float endLineLength2 = std::max(this->param5.getValue(), margin);
|
||||
float endLineLength12 = std::max(- this->param4.getValue(), margin);
|
||||
float endLineLength22 = std::max(- this->param5.getValue(), margin);
|
||||
|
||||
|
||||
float r = 2*length;
|
||||
@@ -1089,7 +1119,6 @@ void SoDatumLabel::GLRender(SoGLRenderAction * action)
|
||||
|
||||
textOffset = p0 + v0 * r;
|
||||
|
||||
float margin = this->imgHeight / 4.0;
|
||||
|
||||
// Draw
|
||||
glBegin(GL_LINE_STRIP);
|
||||
@@ -1113,10 +1142,10 @@ void SoDatumLabel::GLRender(SoGLRenderAction * action)
|
||||
SbVec3f v1(cos(startangle),sin(startangle),0);
|
||||
SbVec3f v2(cos(endangle),sin(endangle),0);
|
||||
|
||||
SbVec3f pnt1 = p0+(r-margin)*v1;
|
||||
SbVec3f pnt2 = p0+(r+margin)*v1;
|
||||
SbVec3f pnt3 = p0+(r-margin)*v2;
|
||||
SbVec3f pnt4 = p0+(r+margin)*v2;
|
||||
SbVec3f pnt1 = p0 + (r - endLineLength1) * v1;
|
||||
SbVec3f pnt2 = p0 + (r + endLineLength12) * v1;
|
||||
SbVec3f pnt3 = p0 + (r - endLineLength2) * v2;
|
||||
SbVec3f pnt4 = p0 + (r + endLineLength22) * v2;
|
||||
|
||||
glBegin(GL_LINES);
|
||||
glVertex2f(pnt1[0],pnt1[1]);
|
||||
|
||||
@@ -75,6 +75,8 @@ public:
|
||||
SoSFFloat param1;
|
||||
SoSFFloat param2;
|
||||
SoSFFloat param3;
|
||||
SoSFFloat param4;
|
||||
SoSFFloat param5;
|
||||
SoMFVec3f pnts;
|
||||
SoSFVec3f norm;
|
||||
SoSFImage image;
|
||||
|
||||
@@ -664,7 +664,12 @@ void SketchObject::reverseAngleConstraintToSupplementary(Constraint* constr, int
|
||||
{
|
||||
std::swap(constr->First, constr->Second);
|
||||
std::swap(constr->FirstPos, constr->SecondPos);
|
||||
constr->FirstPos = (constr->FirstPos == Sketcher::PointPos::start) ? Sketcher::PointPos::end : Sketcher::PointPos::start;
|
||||
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;
|
||||
}
|
||||
|
||||
// Edit the expression if any, else modify constraint value directly
|
||||
if (constraintHasExpression(constNum)) {
|
||||
@@ -677,6 +682,12 @@ void SketchObject::reverseAngleConstraintToSupplementary(Constraint* constr, int
|
||||
}
|
||||
}
|
||||
|
||||
void SketchObject::inverseAngleConstraint(Constraint* constr)
|
||||
{
|
||||
constr->FirstPos = (constr->FirstPos == Sketcher::PointPos::start) ? Sketcher::PointPos::end : Sketcher::PointPos::start;
|
||||
constr->SecondPos = (constr->SecondPos == Sketcher::PointPos::start) ? Sketcher::PointPos::end : Sketcher::PointPos::start;
|
||||
}
|
||||
|
||||
bool SketchObject::constraintHasExpression(int constNum) const
|
||||
{
|
||||
App::ObjectIdentifier path = Constraints.createPath(constNum);
|
||||
|
||||
@@ -271,6 +271,7 @@ public:
|
||||
|
||||
/// Change an angle constraint to its supplementary angle.
|
||||
void reverseAngleConstraintToSupplementary(Constraint* constr, int constNum);
|
||||
void inverseAngleConstraint(Constraint* constr);
|
||||
/// Modify an angle constraint expression string to its supplementary angle
|
||||
static std::string reverseAngleConstraintExpression(std::string expression);
|
||||
|
||||
|
||||
@@ -1178,7 +1178,10 @@ Restart:
|
||||
|| Constr->Second == GeoEnum::GeoUndef);
|
||||
|
||||
SbVec3f p0;
|
||||
double distance = Constr->LabelDistance;
|
||||
double startangle, range;
|
||||
double endLineLength1 = 0.0;
|
||||
double endLineLength2 = 0.0;
|
||||
if (Constr->Second != GeoEnum::GeoUndef) {
|
||||
Base::Vector3d dir1, dir2;
|
||||
if (Constr->Third == GeoEnum::GeoUndef) { // angle between two lines
|
||||
@@ -1186,46 +1189,48 @@ Restart:
|
||||
geolistfacade.getGeometryFromGeoId(Constr->First);
|
||||
const Part::Geometry* geo2 =
|
||||
geolistfacade.getGeometryFromGeoId(Constr->Second);
|
||||
if (geo1->getTypeId() != Part::GeomLineSegment::getClassTypeId()
|
||||
|| geo2->getTypeId() != Part::GeomLineSegment::getClassTypeId()) {
|
||||
if (!isLineSegment(*geo1) || !isLineSegment(*geo2)) {
|
||||
break;
|
||||
}
|
||||
const Part::GeomLineSegment* lineSeg1 =
|
||||
static_cast<const Part::GeomLineSegment*>(geo1);
|
||||
const Part::GeomLineSegment* lineSeg2 =
|
||||
static_cast<const Part::GeomLineSegment*>(geo2);
|
||||
auto* line1 = static_cast<const Part::GeomLineSegment*>(geo1);
|
||||
auto* line2 = static_cast<const Part::GeomLineSegment*>(geo2);
|
||||
|
||||
bool flip1 = (Constr->FirstPos == PointPos::end);
|
||||
bool flip2 = (Constr->SecondPos == PointPos::end);
|
||||
dir1 = (flip1 ? -1. : 1.)
|
||||
* (lineSeg1->getEndPoint() - lineSeg1->getStartPoint());
|
||||
* (line1->getEndPoint() - line1->getStartPoint()).Normalize();
|
||||
dir2 = (flip2 ? -1. : 1.)
|
||||
* (lineSeg2->getEndPoint() - lineSeg2->getStartPoint());
|
||||
* (line2->getEndPoint() - line2->getStartPoint()).Normalize();
|
||||
Base::Vector3d pnt1 =
|
||||
flip1 ? lineSeg1->getEndPoint() : lineSeg1->getStartPoint();
|
||||
flip1 ? line1->getEndPoint() : line1->getStartPoint();
|
||||
Base::Vector3d pnt2 =
|
||||
flip2 ? lineSeg2->getEndPoint() : lineSeg2->getStartPoint();
|
||||
flip2 ? line2->getEndPoint() : line2->getStartPoint();
|
||||
Base::Vector3d pnt12 =
|
||||
flip1 ? line1->getStartPoint() : line1->getEndPoint();
|
||||
Base::Vector3d pnt22 =
|
||||
flip2 ? line2->getStartPoint() : line2->getEndPoint();
|
||||
|
||||
// line-line intersection
|
||||
Base::Vector3d intersection;
|
||||
{
|
||||
double det = dir1.x * dir2.y - dir1.y * dir2.x;
|
||||
if ((det > 0 ? det : -det) < 1e-10) {
|
||||
// lines are coincident (or parallel) and in this case the
|
||||
// center of the point pairs with the shortest distance is used
|
||||
Base::Vector3d p1[2], p2[2];
|
||||
p1[0] = lineSeg1->getStartPoint();
|
||||
p1[1] = lineSeg1->getEndPoint();
|
||||
p2[0] = lineSeg2->getStartPoint();
|
||||
p2[1] = lineSeg2->getEndPoint();
|
||||
p1[0] = line1->getStartPoint();
|
||||
p1[1] = line1->getEndPoint();
|
||||
p2[0] = line2->getStartPoint();
|
||||
p2[1] = line2->getEndPoint();
|
||||
double length = DBL_MAX;
|
||||
for (int i = 0; i <= 1; i++) {
|
||||
for (int j = 0; j <= 1; j++) {
|
||||
double tmp = (p2[j] - p1[i]).Length();
|
||||
if (tmp < length) {
|
||||
length = tmp;
|
||||
p0.setValue((p2[j].x + p1[i].x) / 2,
|
||||
(p2[j].y + p1[i].y) / 2,
|
||||
0);
|
||||
double x = (p2[j].x + p1[i].x) / 2;
|
||||
double y = (p2[j].y + p1[i].y) / 2;
|
||||
intersection = Base::Vector3d(x, y, 0.);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1235,12 +1240,24 @@ Restart:
|
||||
double c2 = dir2.y * pnt2.x - dir2.x * pnt2.y;
|
||||
double x = (dir1.x * c2 - dir2.x * c1) / det;
|
||||
double y = (dir1.y * c2 - dir2.y * c1) / det;
|
||||
p0 = SbVec3f(x, y, 0);
|
||||
intersection = Base::Vector3d(x, y, 0.);
|
||||
}
|
||||
}
|
||||
p0.setValue(intersection.x, intersection.y, 0.);
|
||||
|
||||
range = Constr->getValue(); // WYSIWYG
|
||||
startangle = atan2(dir1.y, dir1.x);
|
||||
Base::Vector3d vl1 = dir1 * 2 * distance - (pnt1 - intersection);
|
||||
Base::Vector3d vl2 = dir2 * 2 * distance - (pnt2 - intersection);
|
||||
Base::Vector3d vl12 = dir1 * 2 * distance - (pnt12 - intersection);
|
||||
Base::Vector3d vl22 = dir2 * 2 * distance - (pnt22 - intersection);
|
||||
|
||||
endLineLength1 = vl12.Dot(dir1) > 0 ? vl12.Length()
|
||||
: vl1.Dot(dir1) < 0 ? -vl1.Length()
|
||||
: 0.0;
|
||||
endLineLength2 = vl22.Dot(dir2) > 0 ? vl22.Length()
|
||||
: vl2.Dot(dir2) < 0 ? -vl2.Length()
|
||||
: 0.0;
|
||||
}
|
||||
else { // angle-via-point
|
||||
Base::Vector3d p =
|
||||
@@ -1297,9 +1314,11 @@ Restart:
|
||||
asciiText->string =
|
||||
SbString(getPresentationString(Constr).toUtf8().constData());
|
||||
asciiText->datumtype = SoDatumLabel::ANGLE;
|
||||
asciiText->param1 = Constr->LabelDistance;
|
||||
asciiText->param1 = distance;
|
||||
asciiText->param2 = startangle;
|
||||
asciiText->param3 = range;
|
||||
asciiText->param4 = endLineLength1;
|
||||
asciiText->param5 = endLineLength2;
|
||||
|
||||
asciiText->pnts.setNum(2);
|
||||
SbVec3f* verts = asciiText->pnts.startEditing();
|
||||
@@ -1313,27 +1332,42 @@ Restart:
|
||||
assert(Constr->First >= -extGeoCount && Constr->First < intGeoCount);
|
||||
|
||||
Base::Vector3d pnt1(0., 0., 0.), pnt2(0., 0., 0.);
|
||||
double helperStartAngle = 0.;
|
||||
double helperRange = 0.;
|
||||
|
||||
if (Constr->First != GeoEnum::GeoUndef) {
|
||||
const Part::Geometry* geo =
|
||||
geolistfacade.getGeometryFromGeoId(Constr->First);
|
||||
|
||||
if (geo->is<Part::GeomArcOfCircle>()) {
|
||||
const Part::GeomArcOfCircle* arc =
|
||||
static_cast<const Part::GeomArcOfCircle*>(geo);
|
||||
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) {
|
||||
double startangle, endangle;
|
||||
arc->getRange(startangle, endangle, /*emulateCCW=*/true);
|
||||
angle = (startangle + endangle) / 2;
|
||||
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.);
|
||||
}
|
||||
else if (geo->is<Part::GeomCircle>()) {
|
||||
const Part::GeomCircle* circle =
|
||||
static_cast<const Part::GeomCircle*>(geo);
|
||||
auto* circle = static_cast<const Part::GeomCircle*>(geo);
|
||||
double radius = circle->getRadius();
|
||||
double angle = (double)Constr->LabelPosition;
|
||||
if (angle == 10) {
|
||||
@@ -1364,6 +1398,8 @@ Restart:
|
||||
asciiText->datumtype = SoDatumLabel::DIAMETER;
|
||||
asciiText->param1 = Constr->LabelDistance;
|
||||
asciiText->param2 = Constr->LabelPosition;
|
||||
asciiText->param3 = helperStartAngle;
|
||||
asciiText->param4 = helperRange;
|
||||
|
||||
asciiText->pnts.setNum(2);
|
||||
SbVec3f* verts = asciiText->pnts.startEditing();
|
||||
@@ -1378,27 +1414,41 @@ Restart:
|
||||
assert(Constr->First >= -extGeoCount && Constr->First < intGeoCount);
|
||||
|
||||
Base::Vector3d pnt1(0., 0., 0.), pnt2(0., 0., 0.);
|
||||
double helperStartAngle = 0.;
|
||||
double helperRange = 0.;
|
||||
|
||||
if (Constr->First != GeoEnum::GeoUndef) {
|
||||
const Part::Geometry* geo =
|
||||
geolistfacade.getGeometryFromGeoId(Constr->First);
|
||||
|
||||
if (geo->is<Part::GeomArcOfCircle>()) {
|
||||
const Part::GeomArcOfCircle* arc =
|
||||
static_cast<const Part::GeomArcOfCircle*>(geo);
|
||||
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) {
|
||||
double startangle, endangle;
|
||||
arc->getRange(startangle, endangle, /*emulateCCW=*/true);
|
||||
angle = (startangle + endangle) / 2;
|
||||
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.);
|
||||
}
|
||||
else if (geo->is<Part::GeomCircle>()) {
|
||||
const Part::GeomCircle* circle =
|
||||
static_cast<const Part::GeomCircle*>(geo);
|
||||
auto* circle = static_cast<const Part::GeomCircle*>(geo);
|
||||
auto gf = GeometryFacade::getFacade(geo);
|
||||
|
||||
double radius;
|
||||
@@ -1439,6 +1489,8 @@ Restart:
|
||||
asciiText->datumtype = SoDatumLabel::RADIUS;
|
||||
asciiText->param1 = Constr->LabelDistance;
|
||||
asciiText->param2 = Constr->LabelPosition;
|
||||
asciiText->param3 = helperStartAngle;
|
||||
asciiText->param4 = helperRange;
|
||||
|
||||
asciiText->pnts.setNum(2);
|
||||
SbVec3f* verts = asciiText->pnts.startEditing();
|
||||
|
||||
@@ -1918,8 +1918,12 @@ void ViewProviderSketch::moveAngleConstraint(int constNum, const Base::Vector2d&
|
||||
sign2 = isLeftOfLine(p21, p22, ap3);
|
||||
}
|
||||
|
||||
bool inverse = !(sign1 == sign3 && sign2 == sign4);
|
||||
if (inverse) {
|
||||
obj->inverseAngleConstraint(constr);
|
||||
}
|
||||
|
||||
p0 = Base::Vector3d(intersection.x, intersection.y, 0.);
|
||||
factor *= (sign1 == sign3 && sign2 == sign4) ? 1. : -1.;
|
||||
}
|
||||
else {// angle-via-point
|
||||
Base::Vector3d p = getSolvedSketch().getPoint(constr->Third, constr->ThirdPos);
|
||||
|
||||
Reference in New Issue
Block a user