diff --git a/src/srf/ratpoly.cpp b/src/srf/ratpoly.cpp index 8e43367d..05ccd038 100644 --- a/src/srf/ratpoly.cpp +++ b/src/srf/ratpoly.cpp @@ -332,7 +332,7 @@ Vector SSurface::PointAt(double u, double v) const { return num; } -void SSurface::TangentsAt(double u, double v, Vector *tu, Vector *tv) const { +void SSurface::TangentsAt(double u, double v, Vector *tu, Vector *tv, bool retry) const { Vector num = Vector::From(0, 0, 0), num_u = Vector::From(0, 0, 0), num_v = Vector::From(0, 0, 0); @@ -364,6 +364,12 @@ void SSurface::TangentsAt(double u, double v, Vector *tu, Vector *tv) const { *tv = ((num_v.ScaledBy(den)).Minus(num.ScaledBy(den_v))); *tv = tv->ScaledBy(1.0/(den*den)); + + // Tangent is zero at sungularities like the north pole. Move away a bit and retry. + if(tv->Equals(Vector::From(0,0,0)) && retry) + TangentsAt(u+(0.5-u)*0.00001, v, tu, tv, false); + if(tu->Equals(Vector::From(0,0,0)) && retry) + TangentsAt(u, v+(0.5-v)*0.00001, tu, tv, false); } Vector SSurface::NormalAt(Point2d puv) const { diff --git a/src/srf/surface.h b/src/srf/surface.h index 393be4aa..ff8aa0f2 100644 --- a/src/srf/surface.h +++ b/src/srf/surface.h @@ -335,7 +335,7 @@ public: void PointOnCurve(const SBezier *curve, double *up, double *vp); Vector PointAt(double u, double v) const; Vector PointAt(Point2d puv) const; - void TangentsAt(double u, double v, Vector *tu, Vector *tv) const; + void TangentsAt(double u, double v, Vector *tu, Vector *tv, bool retry=true) const; Vector NormalAt(Point2d puv) const; Vector NormalAt(double u, double v) const; bool LineEntirelyOutsideBbox(Vector a, Vector b, bool asSegment) const;