From 1bbc764e9efef3fe61a307fc4f1990bf027db891 Mon Sep 17 00:00:00 2001 From: DeepSOIC Date: Sun, 25 Jan 2015 00:24:06 +0300 Subject: [PATCH] Sketcher: fix reversed geometry and rotated arcs Fixes a bug where an arc, ellipse, or arc-of-ellipse, being reversed in XY plane, behaved badly in sketcher (see forum thread "Sketch: how to handle reversed external arcs?" http://forum.freecadweb.org/viewtopic.php?f=10&t=9130 ). Also fixes a problem with rotated arcs (see forum thread "Rotating Arc in Sketcher" http://forum.freecadweb.org/viewtopic.php?f=22&t=9145#p74262 ). This is done by adding an emulation flag to a few methods in Part::GeomXXX, which makes the shape to pretend being non-reversed (CCW). This causes endpoints of reversed arcs of circles lineked as external geometry to swap, causing broken sketches sometimes. --- src/Mod/Part/App/Geometry.cpp | 320 ++++++++++++++++-- src/Mod/Part/App/Geometry.h | 27 +- src/Mod/Sketcher/App/Sketch.cpp | 32 +- src/Mod/Sketcher/App/SketchObject.cpp | 90 ++--- src/Mod/Sketcher/App/planegcs/GCS.h | 1 - src/Mod/Sketcher/Gui/CommandConstraints.cpp | 10 +- src/Mod/Sketcher/Gui/CommandCreateGeo.cpp | 8 +- src/Mod/Sketcher/Gui/CommandSketcherTools.cpp | 19 +- src/Mod/Sketcher/Gui/DrawSketchHandler.cpp | 20 +- .../Sketcher/Gui/TaskSketcherValidation.cpp | 8 +- src/Mod/Sketcher/Gui/ViewProviderSketch.cpp | 88 ++--- 11 files changed, 451 insertions(+), 172 deletions(-) diff --git a/src/Mod/Part/App/Geometry.cpp b/src/Mod/Part/App/Geometry.cpp index 6678de8645..c8115748a1 100644 --- a/src/Mod/Part/App/Geometry.cpp +++ b/src/Mod/Part/App/Geometry.cpp @@ -641,6 +641,13 @@ void GeomCircle::setRadius(double Radius) } } +bool GeomCircle::isReversed() const +{ + Handle_Geom_Circle c = myCurve; + assert(!c.IsNull()); + return c->Axis().Direction().Z() < 0; +} + // Persistence implementer unsigned int GeomCircle::getMemSize (void) const { @@ -746,15 +753,33 @@ Geometry *GeomArcOfCircle::clone(void) const return copy; } -Base::Vector3d GeomArcOfCircle::getStartPoint() const +/*! + * \brief GeomArcOfCircle::getStartPoint + * \param emulateCCWXY: if true, the arc will pretent to be a CCW arc in XY plane. + * For this to work, the arc must lie in XY plane (i.e. Axis is either +Z or -Z). + * \return XYZ of the arc's starting point. + */ +Base::Vector3d GeomArcOfCircle::getStartPoint(bool emulateCCWXY) const { gp_Pnt pnt = this->myCurve->StartPoint(); + if(emulateCCWXY) + if(isReversedInXY()) + pnt = this->myCurve->EndPoint(); return Base::Vector3d(pnt.X(), pnt.Y(), pnt.Z()); } -Base::Vector3d GeomArcOfCircle::getEndPoint() const +/*! + * \brief GeomArcOfCircle::getEndPoint + * \param emulateCCWXY: if true, the arc will pretent to be a CCW arc in XY plane. + * For this to work, the arc must lie in XY plane (i.e. Axis is either +Z or -Z). + * \return + */ +Base::Vector3d GeomArcOfCircle::getEndPoint(bool emulateCCWXY) const { gp_Pnt pnt = this->myCurve->EndPoint(); + if(emulateCCWXY) + if(isReversedInXY()) + pnt = this->myCurve->StartPoint(); return Base::Vector3d(pnt.X(), pnt.Y(), pnt.Z()); } @@ -801,15 +826,70 @@ void GeomArcOfCircle::setRadius(double Radius) } } -void GeomArcOfCircle::getRange(double& u, double& v) const +/*! + * \brief GeomArcOfCircle::getRange + * \param u [out] start angle of the arc, in radians. + * \param v [out] end angle of the arc, in radians. + * \param emulateCCWXY: if true, the arc will pretent to be a CCW arc in XY plane. + * For this to work, the arc must lie in XY plane (i.e. Axis is either +Z or -Z). + * Additionally, arc's rotation as a whole will be included in the returned u,v + * (ArcOfCircle specific). + */ +void GeomArcOfCircle::getRange(double& u, double& v, bool emulateCCWXY) const { u = myCurve->FirstParameter(); v = myCurve->LastParameter(); + if(emulateCCWXY){ + Handle_Geom_Circle cir = Handle_Geom_Circle::DownCast(myCurve->BasisCurve()); + double angleXU = -cir->Position().XDirection().AngleWithRef(gp_Dir(1.0,0.0,0.0), gp_Dir(0.0,0.0,1.0)); + double u1 = u, v1 = v;//the true arc curve parameters, cached. u,v will contain the rotation-corrected and swapped angles. + if(cir->Axis().Direction().Z() > 0.0){ + //normal CCW arc + u = u1 + angleXU; + v = v1 + angleXU; + } else { + //reversed (CW) arc + u = angleXU - v1; + v = angleXU - u1; + } + + if (v < u) + v += 2*M_PI; + if (v-u > 2*M_PI) + v -= 2*M_PI; + + } + } -void GeomArcOfCircle::setRange(double u, double v) +/*! + * \brief GeomArcOfCircle::setRange + * \param u [in] start angle of the arc, in radians. + * \param v [in] end angle of the arc, in radians. + * \param emulateCCWXY: if true, the arc will pretent to be a CCW arc in XY plane. + * For this to work, the arc must lie in XY plane (i.e. Axis is either +Z or -Z). + * Additionally, arc's rotation as a whole will be subtracted from u,v + * (ArcOfCircle specific). + */ +void GeomArcOfCircle::setRange(double u, double v, bool emulateCCWXY) { + try { + if(emulateCCWXY){ + Handle_Geom_Circle cir = Handle_Geom_Circle::DownCast(myCurve->BasisCurve()); + double angleXU = -cir->Position().XDirection().AngleWithRef(gp_Dir(1.0,0.0,0.0), gp_Dir(0.0,0.0,1.0)); + double u1 = u, v1 = v;//the values that were passed, ccw angles from X axis. u,v will contain the rotation-corrected and swapped angles. + if(cir->Axis().Direction().Z() > 0.0){ + //normal CCW arc + u = u1 - angleXU; + v = v1 - angleXU; + } else { + //reversed (CW) arc + u = angleXU - v1; + v = angleXU - u1; + } + } + myCurve->SetTrim(u, v); } catch (Standard_Failure) { @@ -818,6 +898,19 @@ void GeomArcOfCircle::setRange(double u, double v) } } +/*! + * \brief GeomArcOfCircle::isReversedInXY + * \return tests if an arc that lies in XY plane is reversed (i.e. drawn from + * startpoint to endpoint in CW direction instead of CCW.). Returns True if the + * arc is CW and false if CCW. + */ +bool GeomArcOfCircle::isReversedInXY() const +{ + Handle_Geom_Circle c = Handle_Geom_Circle::DownCast( myCurve->BasisCurve() ); + assert(!c.IsNull()); + return c->Axis().Direction().Z() < 0; +} + // Persistence implementer unsigned int GeomArcOfCircle::getMemSize (void) const { @@ -988,21 +1081,35 @@ void GeomEllipse::setMinorRadius(double Radius) } } +/*! + * \brief GeomEllipse::getAngleXU + * \return The angle between ellipse's major axis (in direction to focus1) and + * X axis of a default axis system in the plane of ellipse. The angle is + * counted CCW as seen when looking at the ellipse so that ellipse's axis is + * pointing at you. Note that this function may give unexpected results when + * the ellipse is in XY, but reversed, because the X axis of the default axis + * system is reversed compared to the global X axis. This angle, in conjunction + * with ellipse's axis, fully defines the orientation of the ellipse. + */ double GeomEllipse::getAngleXU(void) const { Handle_Geom_Ellipse ellipse = Handle_Geom_Ellipse::DownCast(handle()); - + gp_Pnt center = this->myCurve->Axis().Location(); gp_Dir normal = this->myCurve->Axis().Direction(); gp_Dir xdir = this->myCurve->XAxis().Direction(); - - + + gp_Ax2 xdirref(center, normal); // this is a reference system, might be CCW or CW depending on the creation method - + return -xdir.AngleWithRef(xdirref.XDirection(),normal); } +/*! + * \brief GeomEllipse::setAngleXU complements getAngleXU. + * \param angle + */ void GeomEllipse::setAngleXU(double angle) { Handle_Geom_Ellipse ellipse = Handle_Geom_Ellipse::DownCast(handle()); @@ -1010,13 +1117,13 @@ void GeomEllipse::setAngleXU(double angle) try { gp_Pnt center = this->myCurve->Axis().Location(); gp_Dir normal = this->myCurve->Axis().Direction(); - + gp_Ax1 normaxis(center, normal); - + gp_Ax2 xdirref(center, normal); - + xdirref.Rotate(normaxis,angle); - + this->myCurve->SetPosition(xdirref); } @@ -1026,6 +1133,54 @@ void GeomEllipse::setAngleXU(double angle) } } +/*! + * \brief GeomEllipse::getMajorAxisDir + * \return the direction vector (unit-length) of major axis of the ellipse. The + * direction also points to the first focus. + */ +Base::Vector3d GeomEllipse::getMajorAxisDir() const +{ + gp_Dir xdir = myCurve->XAxis().Direction(); + return Base::Vector3d(xdir.X(), xdir.Y(), xdir.Z()); +} + +/*! + * \brief GeomEllipse::setMajorAxisDir Rotates the ellipse in its plane, so + * that its major axis is as close as possible to the provided direction. + * \param newdir [in] is the new direction. If the vector is small, the + * orientation of the ellipse will be preserved. If the vector is not small, + * but its projection onto plane of the ellipse is small, an exception will be + * thrown. + */ +void GeomEllipse::setMajorAxisDir(Base::Vector3d newdir) +{ + if (newdir.Sqr() < Precision::SquareConfusion()) + return;//zero vector was passed. Keep the old orientation. + try { + gp_Ax2 pos = myCurve->Position(); + pos.SetXDirection(gp_Dir(newdir.x, newdir.y, newdir.z));//OCC should keep the old main Direction (Z), and change YDirection to accomodate the new XDirection. + myCurve->SetPosition(pos); + } + catch (Standard_Failure) { + Handle_Standard_Failure e = Standard_Failure::Caught(); + throw Base::Exception(e->GetMessageString()); + } +} + + +/*! + * \brief GeomEllipse::isReversedInXY tests if an ellipse that lies in XY plane + * is reversed (i.e. drawn from startpoint to endpoint in CW direction instead + * of CCW.) + * \return Returns True if the arc is CW and false if CCW. + */ +bool GeomEllipse::isReversedInXY() const +{ + Handle_Geom_Ellipse c = myCurve; + assert(!c.IsNull()); + return c->Axis().Direction().Z() < 0; +} + // Persistence implementer unsigned int GeomEllipse::getMemSize (void) const { @@ -1113,6 +1268,11 @@ PyObject *GeomEllipse::getPyObject(void) return new EllipsePy((GeomEllipse*)this->clone()); } +void GeomEllipse::setHandle(const Handle_Geom_Ellipse &e) +{ + this->myCurve = Handle_Geom_Ellipse::DownCast(e->Copy()); +} + // ------------------------------------------------- TYPESYSTEM_SOURCE(Part::GeomArcOfEllipse,Part::GeomCurve); @@ -1153,15 +1313,34 @@ Geometry *GeomArcOfEllipse::clone(void) const return copy; } -Base::Vector3d GeomArcOfEllipse::getStartPoint() const +/*! + * \brief GeomArcOfEllipse::getStartPoint + * \param emulateCCWXY: if true, the arc will pretent to be a CCW arc in XY plane. + * For this to work, the arc must lie in XY plane (i.e. Axis is either +Z or -Z). + * \return XYZ of the arc's starting point. + */ +Base::Vector3d GeomArcOfEllipse::getStartPoint(bool emulateCCWXY) const { gp_Pnt pnt = this->myCurve->StartPoint(); + if(emulateCCWXY) + if(isReversedInXY()) + pnt = this->myCurve->EndPoint(); return Base::Vector3d(pnt.X(), pnt.Y(), pnt.Z()); } -Base::Vector3d GeomArcOfEllipse::getEndPoint() const +/*! + * \brief GeomArcOfEllipse::getEndPoint + * \param emulateCCWXY: if true, the arc will pretent to be a CCW arc in XY plane. + * For this to work, the arc must lie in XY plane (i.e. Axis is either +Z or -Z). + * \return XYZ of the arc's starting point. + */ +Base::Vector3d GeomArcOfEllipse::getEndPoint(bool emulateCCWXY) const { gp_Pnt pnt = this->myCurve->EndPoint(); + if(emulateCCWXY) + if(isReversedInXY()) + pnt = this->myCurve->StartPoint(); + return Base::Vector3d(pnt.X(), pnt.Y(), pnt.Z()); } @@ -1225,20 +1404,33 @@ void GeomArcOfEllipse::setMinorRadius(double Radius) } } +/*! + * \brief GeomArcOfEllipse::getAngleXU + * \return The angle between ellipse's major axis (in direction to focus1) and + * X axis of a default axis system in the plane of ellipse. The angle is + * counted CCW as seen when looking at the ellipse so that ellipse's axis is + * pointing at you. Note that this function may give unexpected results when + * the ellipse is in XY, but reversed, because the X axis of the default axis + * system is reversed compared to the global X axis. This angle, in conjunction + * with ellipse's axis, fully defines the orientation of the ellipse. + */ double GeomArcOfEllipse::getAngleXU(void) const { Handle_Geom_Ellipse ellipse = Handle_Geom_Ellipse::DownCast(myCurve->BasisCurve()); - + gp_Pnt center = ellipse->Axis().Location(); gp_Dir normal = ellipse->Axis().Direction(); gp_Dir xdir = ellipse->XAxis().Direction(); - + gp_Ax2 xdirref(center, normal); // this is a reference system, might be CCW or CW depending on the creation method - + return -xdir.AngleWithRef(xdirref.XDirection(),normal); } +/*! + * \brief GeomArcOfEllipse::setAngleXU complements getAngleXU. + */ void GeomArcOfEllipse::setAngleXU(double angle) { Handle_Geom_Ellipse ellipse = Handle_Geom_Ellipse::DownCast(myCurve->BasisCurve()); @@ -1246,13 +1438,13 @@ void GeomArcOfEllipse::setAngleXU(double angle) try { gp_Pnt center = ellipse->Axis().Location(); gp_Dir normal = ellipse->Axis().Direction(); - + gp_Ax1 normaxis(center, normal); - + gp_Ax2 xdirref(center, normal); - + xdirref.Rotate(normaxis,angle); - + ellipse->SetPosition(xdirref); } @@ -1262,15 +1454,95 @@ void GeomArcOfEllipse::setAngleXU(double angle) } } -void GeomArcOfEllipse::getRange(double& u, double& v) const +/*! + * \brief GeomArcOfEllipse::getMajorAxisDir + * \return the direction vector (unit-length) of major axis of the ellipse. The + * direction also points to the first focus. + */ +Base::Vector3d GeomArcOfEllipse::getMajorAxisDir() const +{ + Handle_Geom_Ellipse c = Handle_Geom_Ellipse::DownCast( myCurve->BasisCurve() ); + assert(!c.IsNull()); + gp_Dir xdir = c->XAxis().Direction(); + return Base::Vector3d(xdir.X(), xdir.Y(), xdir.Z()); +} + +/*! + * \brief GeomArcOfEllipse::setMajorAxisDir Rotates the ellipse in its plane, so + * that its major axis is as close as possible to the provided direction. + * \param newdir [in] is the new direction. If the vector is small, the + * orientation of the ellipse will be preserved. If the vector is not small, + * but its projection onto plane of the ellipse is small, an exception will be + * thrown. + */ +void GeomArcOfEllipse::setMajorAxisDir(Base::Vector3d newdir) +{ + Handle_Geom_Ellipse c = Handle_Geom_Ellipse::DownCast( myCurve->BasisCurve() ); + assert(!c.IsNull()); + if (newdir.Sqr() < Precision::SquareConfusion()) + return;//zero vector was passed. Keep the old orientation. + try { + gp_Ax2 pos = c->Position(); + pos.SetXDirection(gp_Dir(newdir.x, newdir.y, newdir.z));//OCC should keep the old main Direction (Z), and change YDirection to accomodate the new XDirection. + c->SetPosition(pos); + } + catch (Standard_Failure) { + Handle_Standard_Failure e = Standard_Failure::Caught(); + throw Base::Exception(e->GetMessageString()); + } +} + +/*! + * \brief GeomArcOfEllipse::isReversedInXY tests if an arc that lies in XY plane is reversed + * (i.e. drawn from startpoint to endpoint in CW direction instead of CCW.) + * \return Returns True if the arc is CW and false if CCW. + */ +bool GeomArcOfEllipse::isReversedInXY() const +{ + Handle_Geom_Ellipse c = Handle_Geom_Ellipse::DownCast( myCurve->BasisCurve() ); + assert(!c.IsNull()); + return c->Axis().Direction().Z() < 0; +} + +/*! + * \brief GeomArcOfEllipse::getRange + * \param u [out] start angle of the arc, in radians. + * \param v [out] end angle of the arc, in radians. + * \param emulateCCWXY: if true, the arc will pretent to be a CCW arc in XY plane. + * For this to work, the arc must lie in XY plane (i.e. Axis is either +Z or -Z). + */ +void GeomArcOfEllipse::getRange(double& u, double& v, bool emulateCCWXY) const { u = myCurve->FirstParameter(); v = myCurve->LastParameter(); + if(emulateCCWXY){ + if(isReversedInXY()){ + std::swap(u,v); + u = -u; v = -v; + if (v < u) + v += 2*M_PI; + if (v-u > 2*M_PI) + v -= 2*M_PI; + } + } } -void GeomArcOfEllipse::setRange(double u, double v) +/*! + * \brief GeomArcOfEllipse::setRange + * \param u [in] start angle of the arc, in radians. + * \param v [in] end angle of the arc, in radians. + * \param emulateCCWXY: if true, the arc will pretent to be a CCW arc in XY plane. + * For this to work, the arc must lie in XY plane (i.e. Axis is either +Z or -Z). + */ +void GeomArcOfEllipse::setRange(double u, double v, bool emulateCCWXY) { try { + if(emulateCCWXY){ + if(isReversedInXY()){ + std::swap(u,v); + u = -u; v = -v; + } + } myCurve->SetTrim(u, v); } catch (Standard_Failure) { @@ -3291,7 +3563,7 @@ GeomArcOfCircle *createFilletGeometry(const GeomLineSegment *lineSeg1, const Geo GeomArcOfCircle *arc = new GeomArcOfCircle(); arc->setRadius(radius); arc->setCenter(center); - arc->setRange(startAngle, endAngle); + arc->setRange(startAngle, endAngle, /*emulateCCWXY=*/true); return arc; } diff --git a/src/Mod/Part/App/Geometry.h b/src/Mod/Part/App/Geometry.h index d6eab2dd61..1073721bfc 100644 --- a/src/Mod/Part/App/Geometry.h +++ b/src/Mod/Part/App/Geometry.h @@ -188,6 +188,7 @@ public: double getRadius(void) const; void setCenter(const Base::Vector3d& Center); void setRadius(double Radius); + bool isReversed() const; // Persistence implementer --------------------- virtual unsigned int getMemSize(void) const; @@ -211,15 +212,16 @@ public: virtual ~GeomArcOfCircle(); virtual Geometry *clone(void) const; - Base::Vector3d getStartPoint() const; - Base::Vector3d getEndPoint() const; + Base::Vector3d getStartPoint(bool emulateCCWXY) const; + Base::Vector3d getEndPoint(bool emulateCCWXY) const; Base::Vector3d getCenter(void) const; double getRadius(void) const; void setCenter(const Base::Vector3d& Center); void setRadius(double Radius); - void getRange(double& u, double& v) const; - void setRange(double u, double v); + void getRange(double& u, double& v, bool emulateCCWXY) const; + void setRange(double u, double v, bool emulateCCWXY); + bool isReversedInXY() const; // Persistence implementer --------------------- virtual unsigned int getMemSize(void) const; @@ -252,6 +254,9 @@ public: void setMinorRadius(double Radius); double getAngleXU(void) const; void setAngleXU(double angle); + Base::Vector3d getMajorAxisDir() const; + void setMajorAxisDir(Base::Vector3d newdir); + bool isReversedInXY() const; // Persistence implementer --------------------- virtual unsigned int getMemSize(void) const; @@ -260,6 +265,7 @@ public: // Base implementer ---------------------------- virtual PyObject *getPyObject(void); + void setHandle(const Handle_Geom_Ellipse &e); const Handle_Geom_Geometry& handle() const; private: @@ -275,8 +281,8 @@ public: virtual ~GeomArcOfEllipse(); virtual Geometry *clone(void) const; - Base::Vector3d getStartPoint() const; - Base::Vector3d getEndPoint() const; + Base::Vector3d getStartPoint(bool emulateCCWXY) const; + Base::Vector3d getEndPoint(bool emulateCCWXY) const; Base::Vector3d getCenter(void) const; void setCenter(const Base::Vector3d& Center); @@ -286,9 +292,12 @@ public: void setMinorRadius(double Radius); double getAngleXU(void) const; void setAngleXU(double angle); - - void getRange(double& u, double& v) const; - void setRange(double u, double v); + Base::Vector3d getMajorAxisDir() const; + void setMajorAxisDir(Base::Vector3d newdir); + bool isReversedInXY() const; + + void getRange(double& u, double& v, bool emulateCCWXY) const; + void setRange(double u, double v, bool emulateCCWXY); // Persistence implementer --------------------- virtual unsigned int getMemSize(void) const; diff --git a/src/Mod/Sketcher/App/Sketch.cpp b/src/Mod/Sketcher/App/Sketch.cpp index 6a3e0c4751..abbe2fa280 100644 --- a/src/Mod/Sketcher/App/Sketch.cpp +++ b/src/Mod/Sketcher/App/Sketch.cpp @@ -295,11 +295,11 @@ int Sketch::addArc(const Part::GeomArcOfCircle &circleSegment, bool fixed) def.type = Arc; Base::Vector3d center = aoc->getCenter(); - Base::Vector3d startPnt = aoc->getStartPoint(); - Base::Vector3d endPnt = aoc->getEndPoint(); + Base::Vector3d startPnt = aoc->getStartPoint(/*emulateCCW=*/true); + Base::Vector3d endPnt = aoc->getEndPoint(/*emulateCCW=*/true); double radius = aoc->getRadius(); double startAngle, endAngle; - aoc->getRange(startAngle, endAngle); + aoc->getRange(startAngle, endAngle, /*emulateCCW=*/true); GCS::Point p1, p2, p3; @@ -368,18 +368,18 @@ int Sketch::addArcOfEllipse(const Part::GeomArcOfEllipse &ellipseSegment, bool f def.type = ArcOfEllipse; Base::Vector3d center = aoe->getCenter(); - Base::Vector3d startPnt = aoe->getStartPoint(); - Base::Vector3d endPnt = aoe->getEndPoint(); + Base::Vector3d startPnt = aoe->getStartPoint(/*emulateCCW=*/true); + Base::Vector3d endPnt = aoe->getEndPoint(/*emulateCCW=*/true); double radmaj = aoe->getMajorRadius(); double radmin = aoe->getMinorRadius(); - double phi = aoe->getAngleXU(); + Base::Vector3d radmajdir = aoe->getMajorAxisDir(); double dist_C_F = sqrt(radmaj*radmaj-radmin*radmin); // solver parameters - Base::Vector3d focus1 = center+dist_C_F*Vector3d(cos(phi), sin(phi),0); //+x + Base::Vector3d focus1 = center + dist_C_F*radmajdir; double startAngle, endAngle; - aoe->getRange(startAngle, endAngle); + aoe->getRange(startAngle, endAngle, /*emulateCCW=*/true); GCS::Point p1, p2, p3; @@ -505,11 +505,11 @@ int Sketch::addEllipse(const Part::GeomEllipse &elip, bool fixed) Base::Vector3d center = elips->getCenter(); double radmaj = elips->getMajorRadius(); double radmin = elips->getMinorRadius(); - double phi = elips->getAngleXU(); + Base::Vector3d radmajdir = elips->getMajorAxisDir(); double dist_C_F = sqrt(radmaj*radmaj-radmin*radmin); // solver parameters - Base::Vector3d focus1 = center+dist_C_F*Vector3d(cos(phi), sin(phi),0); //+x + Base::Vector3d focus1 = center + dist_C_F*radmajdir; //+x //double *radmin; GCS::Point c; @@ -1929,7 +1929,7 @@ bool Sketch::updateGeometry() 0.0) ); aoc->setRadius(*myArc.rad); - aoc->setRange(*myArc.startAngle, *myArc.endAngle); + aoc->setRange(*myArc.startAngle, *myArc.endAngle, /*emulateCCW=*/true); } else if (it->type == ArcOfEllipse) { GCS::ArcOfEllipse &myArc = ArcsOfEllipse[it->index]; @@ -1942,8 +1942,6 @@ bool Sketch::updateGeometry() Base::Vector3d fd=f1-center; double radmaj = sqrt(fd*fd+radmin*radmin); - double phi = atan2(fd.y,fd.x); - aoe->setCenter(center); if ( radmaj >= aoe->getMinorRadius() ){//ensure that ellipse's major radius is always larger than minor raduis... may still cause problems with degenerates. aoe->setMajorRadius(radmaj); @@ -1952,8 +1950,8 @@ bool Sketch::updateGeometry() aoe->setMinorRadius(radmin); aoe->setMajorRadius(radmaj); } - aoe->setAngleXU(phi); - aoe->setRange(*myArc.startAngle, *myArc.endAngle); + aoe->setMajorAxisDir(fd); + aoe->setRange(*myArc.startAngle, *myArc.endAngle, /*emulateCCW=*/true); } else if (it->type == Circle) { GeomCircle *circ = dynamic_cast(it->geo); circ->setCenter(Vector3d(*Points[it->midPointId].x, @@ -1972,8 +1970,6 @@ bool Sketch::updateGeometry() Base::Vector3d fd=f1-center; double radmaj = sqrt(fd*fd+radmin*radmin); - double phi = atan2(fd.y,fd.x); - ellipse->setCenter(center); if ( radmaj >= ellipse->getMinorRadius() ){//ensure that ellipse's major radius is always larger than minor raduis... may still cause problems with degenerates. ellipse->setMajorRadius(radmaj); @@ -1982,7 +1978,7 @@ bool Sketch::updateGeometry() ellipse->setMinorRadius(radmin); ellipse->setMajorRadius(radmaj); } - ellipse->setAngleXU(phi); + ellipse->setMajorAxisDir(fd); } } catch (Base::Exception e) { Base::Console().Error("Updating geometry: Error build geometry(%d): %s\n", diff --git a/src/Mod/Sketcher/App/SketchObject.cpp b/src/Mod/Sketcher/App/SketchObject.cpp index 17eeb9737a..9c4d792824 100644 --- a/src/Mod/Sketcher/App/SketchObject.cpp +++ b/src/Mod/Sketcher/App/SketchObject.cpp @@ -269,17 +269,17 @@ Base::Vector3d SketchObject::getPoint(int GeoId, PointPos PosId) const } else if (geo->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) { const Part::GeomArcOfCircle *aoc = dynamic_cast(geo); if (PosId == start) - return aoc->getStartPoint(); + return aoc->getStartPoint(/*emulateCCW=*/true); else if (PosId == end) - return aoc->getEndPoint(); + return aoc->getEndPoint(/*emulateCCW=*/true); else if (PosId == mid) return aoc->getCenter(); } else if (geo->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId()) { const Part::GeomArcOfEllipse *aoc = dynamic_cast(geo); if (PosId == start) - return aoc->getStartPoint(); + return aoc->getStartPoint(/*emulateCCW=*/true); else if (PosId == end) - return aoc->getEndPoint(); + return aoc->getEndPoint(/*emulateCCW=*/true); else if (PosId == mid) return aoc->getCenter(); } @@ -699,8 +699,8 @@ int SketchObject::fillet(int GeoId1, int GeoId2, delete arc; return -1; } - dist1.ProjToLine(arc->getStartPoint()-intersection, dir1); - dist2.ProjToLine(arc->getStartPoint()-intersection, dir2); + dist1.ProjToLine(arc->getStartPoint(/*emulateCCW=*/true)-intersection, dir1); + dist2.ProjToLine(arc->getStartPoint(/*emulateCCW=*/true)-intersection, dir2); Part::Geometry *newgeo = dynamic_cast(arc); filletId = addGeometry(newgeo); if (filletId < 0) { @@ -733,14 +733,14 @@ int SketchObject::fillet(int GeoId1, int GeoId2, if (dist1.Length() < dist2.Length()) { tangent1->SecondPos = start; tangent2->SecondPos = end; - movePoint(GeoId1, PosId1, arc->getStartPoint()); - movePoint(GeoId2, PosId2, arc->getEndPoint()); + movePoint(GeoId1, PosId1, arc->getStartPoint(/*emulateCCW=*/true)); + movePoint(GeoId2, PosId2, arc->getEndPoint(/*emulateCCW=*/true)); } else { tangent1->SecondPos = end; tangent2->SecondPos = start; - movePoint(GeoId1, PosId1, arc->getEndPoint()); - movePoint(GeoId2, PosId2, arc->getStartPoint()); + movePoint(GeoId1, PosId1, arc->getEndPoint(/*emulateCCW=*/true)); + movePoint(GeoId2, PosId2, arc->getStartPoint(/*emulateCCW=*/true)); } addConstraint(tangent1); @@ -936,7 +936,7 @@ int SketchObject::trim(int GeoId, const Base::Vector3d& point) Part::GeomArcOfCircle *geoNew = new Part::GeomArcOfCircle(); geoNew->setCenter(center); geoNew->setRadius(circle->getRadius()); - geoNew->setRange(theta1, theta2); + geoNew->setRange(theta1, theta2,/*emulateCCW=*/true); std::vector< Part::Geometry * > newVals(geomlist); newVals[GeoId] = geoNew; @@ -1022,8 +1022,8 @@ int SketchObject::trim(int GeoId, const Base::Vector3d& point) geoNew->setCenter(center); geoNew->setMajorRadius(ellipse->getMajorRadius()); geoNew->setMinorRadius(ellipse->getMinorRadius()); - geoNew->setAngleXU(ellipse->getAngleXU()); - geoNew->setRange(theta1, theta2); + geoNew->setMajorAxisDir(ellipse->getMajorAxisDir()); + geoNew->setRange(theta1, theta2, /*emulateCCW=*/true); std::vector< Part::Geometry * > newVals(geomlist); newVals[GeoId] = geoNew; @@ -1083,7 +1083,7 @@ int SketchObject::trim(int GeoId, const Base::Vector3d& point) const Part::GeomArcOfCircle *aoc = dynamic_cast(geo); Base::Vector3d center = aoc->getCenter(); double startAngle, endAngle; - aoc->getRange(startAngle, endAngle); + aoc->getRange(startAngle, endAngle, /*emulateCCW=*/true); double dir = (startAngle < endAngle) ? 1 : -1; // this is always == 1 double arcLength = (endAngle - startAngle)*dir; double theta0 = Base::fmod(atan2(point.y - center.y, point.x - center.x) - startAngle, 2.f*M_PI); // x0 @@ -1104,8 +1104,8 @@ int SketchObject::trim(int GeoId, const Base::Vector3d& point) Part::GeomArcOfCircle *aoc1 = dynamic_cast(geomlist[GeoId]); Part::GeomArcOfCircle *aoc2 = dynamic_cast(geomlist[newGeoId]); - aoc1->setRange(startAngle, startAngle + theta1); - aoc2->setRange(startAngle + theta2, endAngle); + aoc1->setRange(startAngle, startAngle + theta1, /*emulateCCW=*/true); + aoc2->setRange(startAngle + theta2, endAngle, /*emulateCCW=*/true); // constrain the trimming points on the corresponding geometries Sketcher::Constraint *newConstr = new Sketcher::Constraint(); @@ -1201,7 +1201,7 @@ int SketchObject::trim(int GeoId, const Base::Vector3d& point) if (theta1 > theta0) { // trim arc start delConstraintOnPoint(GeoId, start, false); Part::GeomArcOfCircle *aoc1 = dynamic_cast(geomlist[GeoId]); - aoc1->setRange(startAngle + theta1, endAngle); + aoc1->setRange(startAngle + theta1, endAngle, /*emulateCCW=*/true); // constrain the trimming point on the corresponding geometry Sketcher::Constraint *newConstr = new Sketcher::Constraint(); newConstr->Type = constrType; @@ -1219,7 +1219,7 @@ int SketchObject::trim(int GeoId, const Base::Vector3d& point) else { // trim arc end delConstraintOnPoint(GeoId, end, false); Part::GeomArcOfCircle *aoc1 = dynamic_cast(geomlist[GeoId]); - aoc1->setRange(startAngle, startAngle + theta1); + aoc1->setRange(startAngle, startAngle + theta1, /*emulateCCW=*/true); Sketcher::Constraint *newConstr = new Sketcher::Constraint(); newConstr->Type = constrType; newConstr->First = GeoId; @@ -1239,21 +1239,21 @@ int SketchObject::trim(int GeoId, const Base::Vector3d& point) const Part::GeomArcOfEllipse *aoe = dynamic_cast(geo); Base::Vector3d center = aoe->getCenter(); double startAngle, endAngle; - aoe->getRange(startAngle, endAngle); + aoe->getRange(startAngle, endAngle,/*emulateCCW=*/true); double dir = (startAngle < endAngle) ? 1 : -1; // this is always == 1 double arcLength = (endAngle - startAngle)*dir; double theta0 = Base::fmod( - atan2(-aoe->getMajorRadius()*((point.x-center.x)*sin(aoe->getAngleXU())-(point.y-center.y)*cos(aoe->getAngleXU())), - aoe->getMinorRadius()*((point.x-center.x)*cos(aoe->getAngleXU())+(point.y-center.y)*sin(aoe->getAngleXU())) + atan2(-aoe->getMajorRadius()*((point.x-center.x)*aoe->getMajorAxisDir().y-(point.y-center.y)*aoe->getMajorAxisDir().x), + aoe->getMinorRadius()*((point.x-center.x)*aoe->getMajorAxisDir().x+(point.y-center.y)*aoe->getMajorAxisDir().y) )- startAngle, 2.f*M_PI); // x0 if (GeoId1 >= 0 && GeoId2 >= 0) { double theta1 = Base::fmod( - atan2(-aoe->getMajorRadius()*((point1.x-center.x)*sin(aoe->getAngleXU())-(point1.y-center.y)*cos(aoe->getAngleXU())), - aoe->getMinorRadius()*((point1.x-center.x)*cos(aoe->getAngleXU())+(point1.y-center.y)*sin(aoe->getAngleXU())) + atan2(-aoe->getMajorRadius()*((point1.x-center.x)*aoe->getMajorAxisDir().y-(point1.y-center.y)*aoe->getMajorAxisDir().x), + aoe->getMinorRadius()*((point1.x-center.x)*aoe->getMajorAxisDir().x+(point1.y-center.y)*aoe->getMajorAxisDir().y) )- startAngle, 2.f*M_PI) * dir; // x1 double theta2 = Base::fmod( - atan2(-aoe->getMajorRadius()*((point2.x-center.x)*sin(aoe->getAngleXU())-(point2.y-center.y)*cos(aoe->getAngleXU())), - aoe->getMinorRadius()*((point2.x-center.x)*cos(aoe->getAngleXU())+(point2.y-center.y)*sin(aoe->getAngleXU())) + atan2(-aoe->getMajorRadius()*((point2.x-center.x)*aoe->getMajorAxisDir().y-(point2.y-center.y)*aoe->getMajorAxisDir().x), + aoe->getMinorRadius()*((point2.x-center.x)*aoe->getMajorAxisDir().x+(point2.y-center.y)*aoe->getMajorAxisDir().y) )- startAngle, 2.f*M_PI) * dir; // x2 if (theta1 > theta2) { @@ -1270,8 +1270,8 @@ int SketchObject::trim(int GeoId, const Base::Vector3d& point) Part::GeomArcOfEllipse *aoe1 = dynamic_cast(geomlist[GeoId]); Part::GeomArcOfEllipse *aoe2 = dynamic_cast(geomlist[newGeoId]); - aoe1->setRange(startAngle, startAngle + theta1); - aoe2->setRange(startAngle + theta2, endAngle); + aoe1->setRange(startAngle, startAngle + theta1, /*emulateCCW=*/true); + aoe2->setRange(startAngle + theta2, endAngle, /*emulateCCW=*/true); // constrain the trimming points on the corresponding geometries Sketcher::Constraint *newConstr = new Sketcher::Constraint(); @@ -1362,15 +1362,15 @@ int SketchObject::trim(int GeoId, const Base::Vector3d& point) } double theta1 = Base::fmod( - atan2(-aoe->getMajorRadius()*((point1.x-center.x)*sin(aoe->getAngleXU())-(point1.y-center.y)*cos(aoe->getAngleXU())), - aoe->getMinorRadius()*((point1.x-center.x)*cos(aoe->getAngleXU())+(point1.y-center.y)*sin(aoe->getAngleXU())) + atan2(-aoe->getMajorRadius()*((point1.x-center.x)*aoe->getMajorAxisDir().y-(point1.y-center.y)*aoe->getMajorAxisDir().x), + aoe->getMinorRadius()*((point1.x-center.x)*aoe->getMajorAxisDir().x+(point1.y-center.y)*aoe->getMajorAxisDir().y) )- startAngle, 2.f*M_PI) * dir; // x1 if (theta1 >= 0.001*arcLength && theta1 <= 0.999*arcLength) { if (theta1 > theta0) { // trim arc start delConstraintOnPoint(GeoId, start, false); Part::GeomArcOfEllipse *aoe1 = dynamic_cast(geomlist[GeoId]); - aoe1->setRange(startAngle + theta1, endAngle); + aoe1->setRange(startAngle + theta1, endAngle, /*emulateCCW=*/true); // constrain the trimming point on the corresponding geometry Sketcher::Constraint *newConstr = new Sketcher::Constraint(); newConstr->Type = constrType; @@ -1388,7 +1388,7 @@ int SketchObject::trim(int GeoId, const Base::Vector3d& point) else { // trim arc end delConstraintOnPoint(GeoId, end, false); Part::GeomArcOfEllipse *aoe1 = dynamic_cast(geomlist[GeoId]); - aoe1->setRange(startAngle, startAngle + theta1); + aoe1->setRange(startAngle, startAngle + theta1, /*emulateCCW=*/true); return 0; } @@ -1451,7 +1451,7 @@ int SketchObject::ExposeInternalGeometry(int GeoId) Base::Vector3d center; double majord; double minord; - double phi; + Base::Vector3d majdir; if(geo->getTypeId() == Part::GeomEllipse::getClassTypeId()){ const Part::GeomEllipse *ellipse = static_cast(geo); @@ -1459,7 +1459,7 @@ int SketchObject::ExposeInternalGeometry(int GeoId) center=ellipse->getCenter(); majord=ellipse->getMajorRadius(); minord=ellipse->getMinorRadius(); - phi=ellipse->getAngleXU(); + majdir=ellipse->getMajorAxisDir(); } else { const Part::GeomArcOfEllipse *aoe = static_cast(geo); @@ -1467,18 +1467,20 @@ int SketchObject::ExposeInternalGeometry(int GeoId) center=aoe->getCenter(); majord=aoe->getMajorRadius(); minord=aoe->getMinorRadius(); - phi=aoe->getAngleXU(); + majdir=aoe->getMajorAxisDir(); } + + Base::Vector3d mindir = Vector3d(-majdir.y, majdir.x); - Base::Vector3d majorpositiveend = center + majord * Base::Vector3d(cos(phi),sin(phi),0); - Base::Vector3d majornegativeend = center - majord * Base::Vector3d(cos(phi),sin(phi),0); - Base::Vector3d minorpositiveend = center + minord * Base::Vector3d(-sin(phi),cos(phi),0); - Base::Vector3d minornegativeend = center - minord * Base::Vector3d(-sin(phi),cos(phi),0); + Base::Vector3d majorpositiveend = center + majord * majdir; + Base::Vector3d majornegativeend = center - majord * majdir; + Base::Vector3d minorpositiveend = center + minord * mindir; + Base::Vector3d minornegativeend = center - minord * mindir; double df= sqrt(majord*majord-minord*minord); - Base::Vector3d focus1P = center + df * Base::Vector3d(cos(phi),sin(phi),0); - Base::Vector3d focus2P = center - df * Base::Vector3d(cos(phi),sin(phi),0); + Base::Vector3d focus1P = center + df * majdir; + Base::Vector3d focus2P = center - df * majdir; if(!major) { @@ -1982,16 +1984,14 @@ void SketchObject::rebuildExternalGeometry(void) gp_Pnt P2 = projCurve.Value(projCurve.LastParameter()); //gp_Dir normal = e.Axis().Direction(); - gp_Dir normal = gp_Dir(0,0,1); + gp_Dir normal = gp_Dir(0,0,1); gp_Dir xdir = e.XAxis().Direction(); gp_Ax2 xdirref(p, normal); if (P1.SquareDistance(P2) < Precision::Confusion()) { Part::GeomEllipse* ellipse = new Part::GeomEllipse(); - ellipse->setMajorRadius(e.MajorRadius()); - ellipse->setMinorRadius(e.MinorRadius()); - ellipse->setCenter(Base::Vector3d(p.X(),p.Y(),p.Z())); - ellipse->setAngleXU(-xdir.AngleWithRef(xdirref.XDirection(),normal)); + Handle_Geom_Ellipse curve = new Geom_Ellipse(e); + ellipse->setHandle(curve); ellipse->Construction = true; ExternalGeo.push_back(ellipse); } diff --git a/src/Mod/Sketcher/App/planegcs/GCS.h b/src/Mod/Sketcher/App/planegcs/GCS.h index d8d675535f..4baa40309f 100644 --- a/src/Mod/Sketcher/App/planegcs/GCS.h +++ b/src/Mod/Sketcher/App/planegcs/GCS.h @@ -157,7 +157,6 @@ namespace GCS int addConstraintTangent(Circle &c, Arc &a, int tagId=0); int addConstraintCircleRadius(Circle &c, double *radius, int tagId=0); - int addConstraintEllipseAngleXU(Ellipse &e, double *angle, int tagId=0); int addConstraintArcRadius(Arc &a, double *radius, int tagId=0); int addConstraintEqualLength(Line &l1, Line &l2, double *length, int tagId=0); int addConstraintEqualRadius(Circle &c1, Circle &c2, int tagId=0); diff --git a/src/Mod/Sketcher/Gui/CommandConstraints.cpp b/src/Mod/Sketcher/Gui/CommandConstraints.cpp index 25517244eb..4fc1f9ac0d 100644 --- a/src/Mod/Sketcher/Gui/CommandConstraints.cpp +++ b/src/Mod/Sketcher/Gui/CommandConstraints.cpp @@ -285,7 +285,7 @@ void SketcherGui::makeTangentToEllipseviaNewPoint(const Sketcher::SketchObject* Base::Vector3d center=ellipse->getCenter(); double majord=ellipse->getMajorRadius(); double minord=ellipse->getMinorRadius(); - double phi=ellipse->getAngleXU(); + double phi=atan2(ellipse->getMajorAxisDir().y, ellipse->getMajorAxisDir().x); Base::Vector3d center2; @@ -349,7 +349,7 @@ void SketcherGui::makeTangentToArcOfEllipseviaNewPoint(const Sketcher::SketchObj Base::Vector3d center=aoe->getCenter(); double majord=aoe->getMajorRadius(); double minord=aoe->getMinorRadius(); - double phi=aoe->getAngleXU(); + double phi=atan2(aoe->getMajorAxisDir().y, aoe->getMajorAxisDir().x); Base::Vector3d center2; @@ -1599,7 +1599,7 @@ void CmdSketcherConstrainPerpendicular::activated(int iMsg) center=ellipse->getCenter(); majord=ellipse->getMajorRadius(); minord=ellipse->getMinorRadius(); - phi=ellipse->getAngleXU(); + phi=atan2(ellipse->getMajorAxisDir().y, ellipse->getMajorAxisDir().x); } else if( geo1->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId() ){ const Part::GeomArcOfEllipse *aoe = static_cast(geo1); @@ -1607,7 +1607,7 @@ void CmdSketcherConstrainPerpendicular::activated(int iMsg) center=aoe->getCenter(); majord=aoe->getMajorRadius(); minord=aoe->getMinorRadius(); - phi=aoe->getAngleXU(); + phi=atan2(aoe->getMajorAxisDir().y, aoe->getMajorAxisDir().x); } const Part::GeomLineSegment *line = static_cast(geo2); @@ -2285,7 +2285,7 @@ void CmdSketcherConstrainAngle::activated(int iMsg) const Part::GeomArcOfCircle *arc; arc = dynamic_cast(geom); double startangle, endangle; - arc->getRange(startangle, endangle); + arc->getRange(startangle, endangle, /*EmulateCCWXY=*/true); double angle = endangle - startangle; openCommand("Add angle constraint"); diff --git a/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp b/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp index 16161d8959..0cb7f3bac2 100644 --- a/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp +++ b/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp @@ -994,12 +994,12 @@ protected: else if (geom->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) { const Part::GeomArcOfCircle *arcSeg = dynamic_cast(geom); if (PosId == Sketcher::start) { - EditCurve[0] = Base::Vector2D(arcSeg->getStartPoint().x,arcSeg->getStartPoint().y); - dirVec = Base::Vector3d(0.f,0.f,-1.0) % (arcSeg->getStartPoint()-arcSeg->getCenter()); + EditCurve[0] = Base::Vector2D(arcSeg->getStartPoint(/*emulateCCW=*/true).x,arcSeg->getStartPoint(/*emulateCCW=*/true).y); + dirVec = Base::Vector3d(0.f,0.f,-1.0) % (arcSeg->getStartPoint(/*emulateCCW=*/true)-arcSeg->getCenter()); } else { - EditCurve[0] = Base::Vector2D(arcSeg->getEndPoint().x,arcSeg->getEndPoint().y); - dirVec = Base::Vector3d(0.f,0.f,1.0) % (arcSeg->getEndPoint()-arcSeg->getCenter()); + EditCurve[0] = Base::Vector2D(arcSeg->getEndPoint(/*emulateCCW=*/true).x,arcSeg->getEndPoint(/*emulateCCW=*/true).y); + dirVec = Base::Vector3d(0.f,0.f,1.0) % (arcSeg->getEndPoint(/*emulateCCW=*/true)-arcSeg->getCenter()); } } dirVec.Normalize(); diff --git a/src/Mod/Sketcher/Gui/CommandSketcherTools.cpp b/src/Mod/Sketcher/Gui/CommandSketcherTools.cpp index ad443172c0..8509328cb4 100644 --- a/src/Mod/Sketcher/Gui/CommandSketcherTools.cpp +++ b/src/Mod/Sketcher/Gui/CommandSketcherTools.cpp @@ -853,7 +853,7 @@ void CmdSketcherRestoreInternalAlignmentGeometry::activated(int iMsg) Base::Vector3d center; double majord; double minord; - double phi; + Base::Vector3d majdir; if(geo->getTypeId() == Part::GeomEllipse::getClassTypeId()){ const Part::GeomEllipse *ellipse = static_cast(geo); @@ -861,7 +861,7 @@ void CmdSketcherRestoreInternalAlignmentGeometry::activated(int iMsg) center=ellipse->getCenter(); majord=ellipse->getMajorRadius(); minord=ellipse->getMinorRadius(); - phi=ellipse->getAngleXU(); + majdir=ellipse->getMajorAxisDir(); } else { const Part::GeomArcOfEllipse *aoe = static_cast(geo); @@ -869,19 +869,20 @@ void CmdSketcherRestoreInternalAlignmentGeometry::activated(int iMsg) center=aoe->getCenter(); majord=aoe->getMajorRadius(); minord=aoe->getMinorRadius(); - phi=aoe->getAngleXU(); + majdir=aoe->getMajorAxisDir(); } + Base::Vector3d mindir = Base::Vector3d(-majdir.y, majdir.x, 0.0); - Base::Vector3d majorpositiveend = center + majord * Base::Vector3d(cos(phi),sin(phi),0); - Base::Vector3d majornegativeend = center - majord * Base::Vector3d(cos(phi),sin(phi),0); - Base::Vector3d minorpositiveend = center + minord * Base::Vector3d(-sin(phi),cos(phi),0); - Base::Vector3d minornegativeend = center - minord * Base::Vector3d(-sin(phi),cos(phi),0); + Base::Vector3d majorpositiveend = center + majord * majdir; + Base::Vector3d majornegativeend = center - majord * majdir; + Base::Vector3d minorpositiveend = center + minord * mindir; + Base::Vector3d minornegativeend = center - minord * mindir; double df= sqrt(majord*majord-minord*minord); - Base::Vector3d focus1P = center + df * Base::Vector3d(cos(phi),sin(phi),0); - Base::Vector3d focus2P = center - df * Base::Vector3d(cos(phi),sin(phi),0); + Base::Vector3d focus1P = center + df * majdir; + Base::Vector3d focus2P = center - df * majdir; try{ if(!major) diff --git a/src/Mod/Sketcher/Gui/DrawSketchHandler.cpp b/src/Mod/Sketcher/Gui/DrawSketchHandler.cpp index 9aa1a02f4c..8507dee722 100644 --- a/src/Mod/Sketcher/Gui/DrawSketchHandler.cpp +++ b/src/Mod/Sketcher/Gui/DrawSketchHandler.cpp @@ -279,12 +279,12 @@ int DrawSketchHandler::seekAutoConstraint(std::vector &suggested double a = ellipse->getMajorRadius(); double b = ellipse->getMinorRadius(); - double phi = ellipse->getAngleXU(); + Base::Vector3d majdir = ellipse->getMajorAxisDir(); double cf = sqrt(a*a - b*b); - Base::Vector3d focus1P = center + cf * Base::Vector3d(cos(phi),sin(phi),0); - Base::Vector3d focus2P = center - cf * Base::Vector3d(cos(phi),sin(phi),0); + Base::Vector3d focus1P = center + cf * majdir; + Base::Vector3d focus2P = center - cf * majdir; Base::Vector3d norm = Base::Vector3d(Dir.fY,-Dir.fX).Normalize(); @@ -315,7 +315,7 @@ int DrawSketchHandler::seekAutoConstraint(std::vector &suggested if (projDist < tangDeviation) { double startAngle, endAngle; - arc->getRange(startAngle, endAngle); + arc->getRange(startAngle, endAngle, /*emulateCCW=*/true); double angle = atan2(projPnt.y, projPnt.x); while(angle < startAngle) @@ -334,12 +334,12 @@ int DrawSketchHandler::seekAutoConstraint(std::vector &suggested double a = aoe->getMajorRadius(); double b = aoe->getMinorRadius(); - double phi = aoe->getAngleXU(); + Base::Vector3d majdir = aoe->getMajorAxisDir(); double cf = sqrt(a*a - b*b); - Base::Vector3d focus1P = center + cf * Base::Vector3d(cos(phi),sin(phi),0); - Base::Vector3d focus2P = center - cf * Base::Vector3d(cos(phi),sin(phi),0); + Base::Vector3d focus1P = center + cf * majdir; + Base::Vector3d focus2P = center - cf * majdir; Base::Vector3d norm = Base::Vector3d(Dir.fY,-Dir.fX).Normalize(); @@ -356,11 +356,11 @@ int DrawSketchHandler::seekAutoConstraint(std::vector &suggested if (error < tangDeviation) { double startAngle, endAngle; - aoe->getRange(startAngle, endAngle); + aoe->getRange(startAngle, endAngle, /*emulateCCW=*/true); double angle = Base::fmod( - atan2(-aoe->getMajorRadius()*((tmpPos.x-center.x)*sin(aoe->getAngleXU())-(tmpPos.y-center.y)*cos(aoe->getAngleXU())), - aoe->getMinorRadius()*((tmpPos.x-center.x)*cos(aoe->getAngleXU())+(tmpPos.y-center.y)*sin(aoe->getAngleXU())) + atan2(-aoe->getMajorRadius()*((tmpPos.x-center.x)*majdir.y-(tmpPos.y-center.y)*majdir.x), + aoe->getMinorRadius()*((tmpPos.x-center.x)*majdir.x+(tmpPos.y-center.y)*majdir.y) )- startAngle, 2.f*M_PI); while(angle < startAngle) diff --git a/src/Mod/Sketcher/Gui/TaskSketcherValidation.cpp b/src/Mod/Sketcher/Gui/TaskSketcherValidation.cpp index 296c8b25ab..6122dc5e8b 100644 --- a/src/Mod/Sketcher/Gui/TaskSketcherValidation.cpp +++ b/src/Mod/Sketcher/Gui/TaskSketcherValidation.cpp @@ -194,11 +194,11 @@ void SketcherValidation::on_findButton_clicked() VertexIds id; id.GeoId = (int)i; id.PosId = Sketcher::start; - id.v = segm->getStartPoint(); + id.v = segm->getStartPoint(/*emulateCCW=*/true); vertexIds.push_back(id); id.GeoId = (int)i; id.PosId = Sketcher::end; - id.v = segm->getEndPoint(); + id.v = segm->getEndPoint(/*emulateCCW=*/true); vertexIds.push_back(id); } else if (g->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId()) { @@ -206,11 +206,11 @@ void SketcherValidation::on_findButton_clicked() VertexIds id; id.GeoId = (int)i; id.PosId = Sketcher::start; - id.v = segm->getStartPoint(); + id.v = segm->getStartPoint(/*emulateCCW=*/true); vertexIds.push_back(id); id.GeoId = (int)i; id.PosId = Sketcher::end; - id.v = segm->getEndPoint(); + id.v = segm->getEndPoint(/*emulateCCW=*/true); vertexIds.push_back(id); } } diff --git a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp index 9358db36e4..556780367a 100644 --- a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp +++ b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp @@ -1179,7 +1179,7 @@ void ViewProviderSketch::moveConstraint(int constNum, const Base::Vector2D &toPo double angle = Constr->LabelPosition; if (angle == 10) { double startangle, endangle; - arc->getRange(startangle, endangle); + arc->getRange(startangle, endangle, /*emulateCCW=*/true); angle = (startangle + endangle)/2; } else { @@ -1919,20 +1919,19 @@ void ViewProviderSketch::doBoxSelection(const SbVec2s &startPos, const SbVec2s & Gui::Selection().addSelection(doc->getName(), sketchObject->getNameInDocument(), ss.str().c_str()); int countSegments = 12; - float segment = float(2 * M_PI) / countSegments; + double segment = (2 * M_PI) / countSegments; // circumscribed polygon radius - float a = float(ellipse->getMajorRadius()) / cos(segment/2); - float b = float(ellipse->getMinorRadius()) / cos(segment/2); - float phi = float(ellipse->getAngleXU()); + double a = (ellipse->getMajorRadius()) / cos(segment/2); + double b = (ellipse->getMinorRadius()) / cos(segment/2); + Base::Vector3d majdir = ellipse->getMajorAxisDir(); + Base::Vector3d mindir = Base::Vector3d(-majdir.y, majdir.x, 0.0); bool bpolyInside = true; pnt0 = ellipse->getCenter(); - float angle = 0.f; + double angle = 0.; for (int i = 0; i < countSegments; ++i, angle += segment) { - pnt = Base::Vector3d(pnt0.x + a * cos(angle) * cos(phi) - b * sin(angle) * sin(phi), - pnt0.y + a * cos(angle) * sin(phi) + b * sin(angle) * cos(phi), - 0.f); + pnt = pnt0 + (cos(angle)*a)*majdir + sin(angle)*b*mindir; Plm.multVec(pnt, pnt); pnt = proj(pnt); if (!polygon.Contains(Base::Vector2D(pnt.x, pnt.y))) { @@ -1953,8 +1952,8 @@ void ViewProviderSketch::doBoxSelection(const SbVec2s &startPos, const SbVec2s & // Check if arc lies inside box selection const Part::GeomArcOfCircle *aoc = dynamic_cast(*it); - pnt0 = aoc->getStartPoint(); - pnt1 = aoc->getEndPoint(); + pnt0 = aoc->getStartPoint(/*emulateCCW=*/true); + pnt1 = aoc->getEndPoint(/*emulateCCW=*/true); pnt2 = aoc->getCenter(); VertexId += 3; @@ -1987,7 +1986,7 @@ void ViewProviderSketch::doBoxSelection(const SbVec2s &startPos, const SbVec2s & if (pnt0Inside && pnt1Inside) { double startangle, endangle; - aoc->getRange(startangle, endangle); + aoc->getRange(startangle, endangle, /*emulateCCW=*/true); if (startangle > endangle) // if arc is reversed std::swap(startangle, endangle); @@ -2024,8 +2023,8 @@ void ViewProviderSketch::doBoxSelection(const SbVec2s &startPos, const SbVec2s & // Check if arc lies inside box selection const Part::GeomArcOfEllipse *aoe = dynamic_cast(*it); - pnt0 = aoe->getStartPoint(); - pnt1 = aoe->getEndPoint(); + pnt0 = aoe->getStartPoint(/*emulateCCW=*/true); + pnt1 = aoe->getEndPoint(/*emulateCCW=*/true); pnt2 = aoe->getCenter(); VertexId += 3; @@ -2058,26 +2057,25 @@ void ViewProviderSketch::doBoxSelection(const SbVec2s &startPos, const SbVec2s & if (pnt0Inside && pnt1Inside) { double startangle, endangle; - aoe->getRange(startangle, endangle); + aoe->getRange(startangle, endangle, /*emulateCCW=*/true); if (startangle > endangle) // if arc is reversed std::swap(startangle, endangle); double range = endangle-startangle; int countSegments = std::max(2, int(12.0 * range / (2 * M_PI))); - float segment = float(range) / countSegments; + double segment = (range) / countSegments; // circumscribed polygon radius - float a = float(aoe->getMajorRadius()) / cos(segment/2); - float b = float(aoe->getMinorRadius()) / cos(segment/2); - float phi = float(aoe->getAngleXU()); - + double a = (aoe->getMajorRadius()) / cos(segment/2); + double b = (aoe->getMinorRadius()) / cos(segment/2); + Base::Vector3d majdir = aoe->getMajorAxisDir(); + Base::Vector3d mindir = Base::Vector3d(-majdir.y, majdir.x, 0.0); + bool bpolyInside = true; pnt0 = aoe->getCenter(); - float angle = float(startangle) + segment/2; + double angle = (startangle) + segment/2; for (int i = 0; i < countSegments; ++i, angle += segment) { - pnt = Base::Vector3d(pnt0.x + a * cos(angle) * cos(phi) - b * sin(angle) * sin(phi), - pnt0.y + a * cos(angle) * sin(phi) + b * sin(angle) * cos(phi), - 0.f); + pnt = pnt0 + cos(angle)*a*majdir + sin(angle)*b*mindir; Plm.multVec(pnt, pnt); pnt = proj(pnt); if (!polygon.Contains(Base::Vector2D(pnt.x, pnt.y))) { @@ -2953,7 +2951,7 @@ void ViewProviderSketch::draw(bool temp) Handle_Geom_TrimmedCurve curve = Handle_Geom_TrimmedCurve::DownCast(arc->handle()); double startangle, endangle; - arc->getRange(startangle, endangle); + arc->getRange(startangle, endangle, /*emulateCCW=*/false); if (startangle > endangle) // if arc is reversed std::swap(startangle, endangle); @@ -2962,8 +2960,8 @@ void ViewProviderSketch::draw(bool temp) double segment = range / countSegments; Base::Vector3d center = arc->getCenter(); - Base::Vector3d start = arc->getStartPoint(); - Base::Vector3d end = arc->getEndPoint(); + Base::Vector3d start = arc->getStartPoint(/*emulateCCW=*/true); + Base::Vector3d end = arc->getEndPoint(/*emulateCCW=*/true); for (int i=0; i < countSegments; i++) { gp_Pnt pnt = curve->Value(startangle); @@ -2986,7 +2984,7 @@ void ViewProviderSketch::draw(bool temp) Handle_Geom_TrimmedCurve curve = Handle_Geom_TrimmedCurve::DownCast(arc->handle()); double startangle, endangle; - arc->getRange(startangle, endangle); + arc->getRange(startangle, endangle, /*emulateCCW=*/false); if (startangle > endangle) // if arc is reversed std::swap(startangle, endangle); @@ -2995,8 +2993,8 @@ void ViewProviderSketch::draw(bool temp) double segment = range / countSegments; Base::Vector3d center = arc->getCenter(); - Base::Vector3d start = arc->getStartPoint(); - Base::Vector3d end = arc->getEndPoint(); + Base::Vector3d start = arc->getStartPoint(/*emulateCCW=*/true); + Base::Vector3d end = arc->getEndPoint(/*emulateCCW=*/true); for (int i=0; i < countSegments; i++) { gp_Pnt pnt = curve->Value(startangle); @@ -3200,7 +3198,7 @@ Restart: } else if (geo1->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) { const Part::GeomArcOfCircle *arc = dynamic_cast(geo1); double startangle, endangle, midangle; - arc->getRange(startangle, endangle); + arc->getRange(startangle, endangle, /*emulateCCW=*/true); midangle = (startangle + endangle)/2; norm1 = Base::Vector3d(cos(midangle),sin(midangle),0); dir1 = Base::Vector3d(-norm1.y,norm1.x,0); @@ -3221,7 +3219,7 @@ Restart: } else if (geo2->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) { const Part::GeomArcOfCircle *arc = dynamic_cast(geo2); double startangle, endangle, midangle; - arc->getRange(startangle, endangle); + arc->getRange(startangle, endangle, /*emulateCCW=*/true); midangle = (startangle + endangle)/2; norm2 = Base::Vector3d(cos(midangle),sin(midangle),0); dir2 = Base::Vector3d(-norm2.y,norm2.x,0); @@ -3276,14 +3274,15 @@ Restart: const Part::GeomArcOfCircle *arc = dynamic_cast(geo1); r1a = arc->getRadius(); double startangle, endangle; - arc->getRange(startangle, endangle); + arc->getRange(startangle, endangle, /*emulateCCW=*/true); angle1 = (startangle + endangle)/2; midpos1 = arc->getCenter(); } else if (geo1->getTypeId() == Part::GeomEllipse::getClassTypeId()) { const Part::GeomEllipse *ellipse = dynamic_cast(geo1); r1a = ellipse->getMajorRadius(); r1b = ellipse->getMinorRadius(); - angle1 = ellipse->getAngleXU(); + Base::Vector3d majdir = ellipse->getMajorAxisDir(); + angle1 = atan2(majdir.y, majdir.x); angle1plus = M_PI/4; midpos1 = ellipse->getCenter(); } else if (geo1->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId()) { @@ -3291,8 +3290,9 @@ Restart: r1a = aoe->getMajorRadius(); r1b = aoe->getMinorRadius(); double startangle, endangle; - aoe->getRange(startangle, endangle); - angle1 = aoe->getAngleXU(); + aoe->getRange(startangle, endangle, /*emulateCCW=*/true); + Base::Vector3d majdir = aoe->getMajorAxisDir(); + angle1 = atan2(majdir.y, majdir.x); angle1plus = (startangle + endangle)/2; midpos1 = aoe->getCenter(); } else @@ -3307,14 +3307,15 @@ Restart: const Part::GeomArcOfCircle *arc = dynamic_cast(geo2); r2a = arc->getRadius(); double startangle, endangle; - arc->getRange(startangle, endangle); + arc->getRange(startangle, endangle, /*emulateCCW=*/true); angle2 = (startangle + endangle)/2; midpos2 = arc->getCenter(); } else if (geo2->getTypeId() == Part::GeomEllipse::getClassTypeId()) { const Part::GeomEllipse *ellipse = dynamic_cast(geo2); r2a = ellipse->getMajorRadius(); r2b = ellipse->getMinorRadius(); - angle2 = ellipse->getAngleXU(); + Base::Vector3d majdir = ellipse->getMajorAxisDir(); + angle2 = atan2(majdir.y, majdir.x); angle2plus = M_PI/4; midpos2 = ellipse->getCenter(); } else if (geo2->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId()) { @@ -3322,8 +3323,9 @@ Restart: r2a = aoe->getMajorRadius(); r2b = aoe->getMinorRadius(); double startangle, endangle; - aoe->getRange(startangle, endangle); - angle2 = aoe->getAngleXU(); + aoe->getRange(startangle, endangle, /*emulateCCW=*/true); + Base::Vector3d majdir = aoe->getMajorAxisDir(); + angle2 = atan2(majdir.y, majdir.x); angle2plus = (startangle + endangle)/2; midpos2 = aoe->getCenter(); } else @@ -3741,8 +3743,8 @@ Restart: const Part::GeomArcOfCircle *arc = dynamic_cast(geo); p0 = Base::convertTo(arc->getCenter()); - Base::Vector3d dir = arc->getEndPoint()-arc->getStartPoint(); - arc->getRange(startangle, endangle); + Base::Vector3d dir = arc->getEndPoint(/*emulateCCWXY=*/true)-arc->getStartPoint(/*emulateCCWXY=*/true); + arc->getRange(startangle, endangle,/*emulateCCWXY=*/true); range = endangle - startangle; } else { @@ -3781,7 +3783,7 @@ Restart: double angle = (double) Constr->LabelPosition; if (angle == 10) { double startangle, endangle; - arc->getRange(startangle, endangle); + arc->getRange(startangle, endangle, /*emulateCCW=*/true); angle = (startangle + endangle)/2; } pnt1 = arc->getCenter();