- if (aCurve->isCircle()) {
- GeomEdgePtr aEdgePtr(new GeomAPI_Edge(aShape));
- GeomVertexPtr aVertexPtr(new GeomAPI_Vertex(theP.X(), theP.Y(), theP.Z()));
- BRepExtrema_ExtPC aExtrema(aVertexPtr->impl<TopoDS_Vertex>(),
- aEdgePtr->impl<TopoDS_Edge>());
- int aNb = aExtrema.NbExt();
- if (aNb > 0) {
- for (int i = 1; i <= aNb; i++) {
- if (aExtrema.IsMin(i)) {
- double aParam = aExtrema.Parameter(i);
- Handle(Geom_Curve) aCurv = aCurve->impl<Handle_Geom_Curve>();
- gp_Pnt aP;
- aCurv->D1(aParam, aP, aVec);
- break;
- }
- }
+ if (aCurve->isCircle() || aCurve->isEllipse()) {
+ Handle(Geom_Curve) aCurv = aCurve->impl<Handle_Geom_Curve>();
+ GeomAPI_ProjectPointOnCurve anExtr(theP, aCurv);
+ double aParam = anExtr.LowerDistanceParameter();
+ gp_Pnt aP;
+ aCurv->D1(aParam, aP, aVec);
+ // 2458: check correct orientation of the vector
+ if (aVec.SquareMagnitude() > Precision::Confusion()) {
+ std::shared_ptr<GeomAPI_Edge> aCircEdge(new GeomAPI_Edge(aShape));
+ double aFirstParam, aLastParam;
+ aCircEdge->getRange(aFirstParam, aLastParam);
+ // if parameter is near the LastParam, make the vector go inside (reverse)
+ double aDelta = aLastParam - aParam;
+ while (aDelta < -Precision::Confusion())
+ aDelta += 2. * M_PI;
+ while (aDelta > 2. * M_PI - Precision::Confusion())
+ aDelta -= 2. * M_PI;
+ if (fabs(aDelta) < Precision::Confusion())
+ aVec.Reverse();