Path: blob/devel/ElmerGUI/netgen/libsrc/geom2d/spline.hpp
3206 views
#ifndef FILE_SPLINE_HPP1#define FILE_SPLINE_HPP23/**************************************************************************/4/* File: spline.hpp */5/* Author: Joachim Schoeberl */6/* Date: 24. Jul. 96 */7/**************************************************************************/8910void CalcPartition (double l, double h, double r1, double r2,11double ra, double elto0, ARRAY<double> & points);1213/*14Spline curves for 2D mesh generation15*/161718/// Geometry point19template < int D >20class GeomPoint : public Point<D>21{22public:23/// refinement to point24double refatpoint;25bool hpref;2627GeomPoint ()28{ ; }2930///31GeomPoint (double ax, double ay, double aref = 1, bool ahpref=false)32: Point<D> (ax, ay), refatpoint(aref), hpref(ahpref) { ; }33GeomPoint (double ax, double ay, double az, double aref, bool ahpref=false)34: Point<D> (ax, ay, az), refatpoint(aref), hpref(ahpref) { ; }35GeomPoint (const Point<D> & ap, double aref = 1, bool ahpref=false)36: Point<D>(ap), refatpoint(aref), hpref(ahpref) { ; }37};38394041/// base class for 2d - segment42template < int D >43class SplineSeg44{45public:46/// left domain47int leftdom;48/// right domain49int rightdom;50/// refinement at line51double reffak;52/// boundary condition number53int bc;54/// copy spline mesh from other spline (-1.. do not copy)55int copyfrom;56/// perfrom anisotropic refinement (hp-refinement) to edge57bool hpref_left;58bool hpref_right;59/// calculates length of curve60virtual double Length () const;61/// returns point at curve, 0 <= t <= 162virtual Point<D> GetPoint (double t) const = 0;63/// returns a (not necessarily uniform) tangent vector for 0 <= t <= 164virtual Vec<D> GetTangent (const double t) const65{ cerr << "GetTangent not implemented for spline base-class" << endl; Vec<D> dummy; return dummy;}66virtual void GetDerivatives (const double t,67Point<D> & point,68Vec<D> & first,69Vec<D> & second) const {;}70/// partitionizes curve71void Partition (double h, double elto0,72Mesh & mesh, Point3dTree & searchtree, int segnr) const;73/// returns initial point on curve74virtual const GeomPoint<D> & StartPI () const = 0;75/// returns terminal point on curve76virtual const GeomPoint<D> & EndPI () const = 0;77/** writes curve description for fepp:78for implicitly given quadratic curves, the 6 coefficients of79the polynomial80$$ a x^2 + b y^2 + c x y + d x + e y + f = 0 $$81are written to ost */82void PrintCoeff (ostream & ost) const;8384virtual void GetCoeff (Vector & coeffs) const = 0;8586virtual void GetPoints (int n, ARRAY<Point<D> > & points);8788/** calculates (2D) lineintersections:89for lines $$ a x + b y + c = 0 $$ the interecting points are calculated90and stored in points */91virtual void LineIntersections (const double a, const double b, const double c,92ARRAY < Point<D> > & points, const double eps) const93{points.SetSize(0);}9495virtual double MaxCurvature(void) const = 0;9697virtual string GetType(void) const {return "splinebase";}9899virtual void Project (const Point<D> point, Point<D> & point_on_curve, double & t) const100{ cerr << "Project not implemented for spline base-class" << endl;}101102virtual void GetRawData (ARRAY<double> & data) const103{ cerr << "GetRawData not implemented for spline base-class" << endl;}104105};106107108/// Straight line form p1 to p2109template< int D >110class LineSeg : public SplineSeg<D>111{112///113GeomPoint<D> p1, p2;114//const GeomPoint<D> &p1, &p2;115public:116///117LineSeg (const GeomPoint<D> & ap1, const GeomPoint<D> & ap2);118///119virtual double Length () const;120///121virtual Point<D> GetPoint (double t) const;122///123virtual Vec<D> GetTangent (const double t) const;124125126virtual void GetDerivatives (const double t,127Point<D> & point,128Vec<D> & first,129Vec<D> & second) const;130///131virtual const GeomPoint<D> & StartPI () const { return p1; };132///133virtual const GeomPoint<D> & EndPI () const { return p2; }134///135virtual void GetCoeff (Vector & coeffs) const;136137virtual string GetType(void) const {return "line";}138139virtual void LineIntersections (const double a, const double b, const double c,140ARRAY < Point<D> > & points, const double eps) const;141142virtual double MaxCurvature(void) const {return 0;}143144virtual void Project (const Point<D> point, Point<D> & point_on_curve, double & t) const;145146virtual void GetRawData (ARRAY<double> & data) const;147};148149150/// curve given by a rational, quadratic spline (including ellipses)151template< int D >152class SplineSeg3 : public SplineSeg<D>153{154///155GeomPoint<D> p1, p2, p3;156//const GeomPoint<D> &p1, &p2, &p3;157158mutable double proj_latest_t;159public:160///161SplineSeg3 (const GeomPoint<D> & ap1,162const GeomPoint<D> & ap2,163const GeomPoint<D> & ap3);164///165virtual Point<D> GetPoint (double t) const;166///167virtual Vec<D> GetTangent (const double t) const;168169170virtual void GetDerivatives (const double t,171Point<D> & point,172Vec<D> & first,173Vec<D> & second) const;174///175virtual const GeomPoint<D> & StartPI () const { return p1; };176///177virtual const GeomPoint<D> & EndPI () const { return p3; }178///179virtual void GetCoeff (Vector & coeffs) const;180181virtual string GetType(void) const {return "spline3";}182183const GeomPoint<D> & TangentPoint (void) const { return p2; }184185virtual void LineIntersections (const double a, const double b, const double c,186ARRAY < Point<D> > & points, const double eps) const;187188virtual double MaxCurvature(void) const;189190virtual void Project (const Point<D> point, Point<D> & point_on_curve, double & t) const;191192virtual void GetRawData (ARRAY<double> & data) const;193};194195196// Gundolf Haase 8/26/97197/// A circle198template < int D >199class CircleSeg : public SplineSeg<D>200{201///202private:203GeomPoint<D> p1, p2, p3;204//const GeomPoint<D> &p1, &p2, &p3;205Point<D> pm;206double radius, w1,w3;207public:208///209CircleSeg (const GeomPoint<D> & ap1,210const GeomPoint<D> & ap2,211const GeomPoint<D> & ap3);212///213virtual Point<D> GetPoint (double t) const;214///215virtual const GeomPoint<D> & StartPI () const { return p1; }216///217virtual const GeomPoint<D> & EndPI () const { return p3; }218///219virtual void GetCoeff (Vector & coeffs) const;220///221double Radius() const { return radius; }222///223double StartAngle() const { return w1; }224///225double EndAngle() const { return w3; }226///227const Point<D> & MidPoint(void) const {return pm; }228229virtual string GetType(void) const {return "circle";}230231virtual void LineIntersections (const double a, const double b, const double c,232ARRAY < Point<D> > & points, const double eps) const;233234virtual double MaxCurvature(void) const {return 1./radius;}235};236237238239240241242///243template<int D>244class DiscretePointsSeg : public SplineSeg<D>245{246ARRAY<Point<D> > pts;247GeomPoint<D> p1, p2;248public:249///250DiscretePointsSeg (const ARRAY<Point<D> > & apts);251///252virtual ~DiscretePointsSeg ();253///254virtual Point<D> GetPoint (double t) const;255///256virtual const GeomPoint<D> & StartPI () const { return p1; };257///258virtual const GeomPoint<D> & EndPI () const { return p2; }259///260virtual void GetCoeff (Vector & coeffs) const {;}261262virtual double MaxCurvature(void) const {return 1;}263};264265266267268269270271// calculates length of spline-curve272template<int D>273double SplineSeg<D> :: Length () const274{275Point<D> p, pold;276277int i, n = 100;278double dt = 1.0 / n;279280pold = GetPoint (0);281282double l = 0;283for (i = 1; i <= n; i++)284{285p = GetPoint (i * dt);286l += Dist (p, pold);287pold = p;288}289return l;290}291292293294// partitionizes spline curve295template<int D>296void SplineSeg<D> :: Partition (double h, double elto0,297Mesh & mesh, Point3dTree & searchtree, int segnr) const298{299int i, j;300double l, r1, r2, ra;301double lold, dt, frac;302int n = 100;303Point<D> p, pold, mark, oldmark;304ARRAY<double> curvepoints;305double edgelength, edgelengthold;306l = Length();307308r1 = StartPI().refatpoint;309r2 = EndPI().refatpoint;310ra = reffak;311312// cout << "Partition, l = " << l << ", h = " << h << endl;313CalcPartition (l, h, r1, r2, ra, elto0, curvepoints);314// cout << "curvepoints = " << curvepoints << endl;315316dt = 1.0 / n;317318l = 0;319j = 1;320321pold = GetPoint (0);322lold = 0;323oldmark = pold;324edgelengthold = 0;325ARRAY<int> locsearch;326327for (i = 1; i <= n; i++)328{329p = GetPoint (i*dt);330l = lold + Dist (p, pold);331while (j < curvepoints.Size() && (l >= curvepoints[j] || i == n))332{333frac = (curvepoints[j]-lold) / (l-lold);334mark = pold + frac * (p-pold);335edgelength = i*dt + (frac-1)*dt;336{337PointIndex pi1 = -1, pi2 = -1;338339Point3d mark3(mark(0), mark(1), 0);340Point3d oldmark3(oldmark(0), oldmark(1), 0);341342Vec<3> v (1e-4*h, 1e-4*h, 1e-4*h);343searchtree.GetIntersecting (oldmark3 - v, oldmark3 + v, locsearch);344if (locsearch.Size()) pi1 = locsearch[0];345346searchtree.GetIntersecting (mark3 - v, mark3 + v, locsearch);347if (locsearch.Size()) pi2 = locsearch[0];348/*349for (PointIndex pk = PointIndex::BASE;350pk < mesh.GetNP()+PointIndex::BASE; pk++)351{352if (Dist (mesh[pk], oldmark3) < 1e-4 * h) pi1 = pk;353if (Dist (mesh[pk], mark3) < 1e-4 * h) pi2 = pk;354}355*/356357358// cout << "pi1 = " << pi1 << endl;359// cout << "pi2 = " << pi2 << endl;360361if (pi1 == -1)362{363pi1 = mesh.AddPoint(oldmark3);364searchtree.Insert (oldmark3, pi1);365}366if (pi2 == -1)367{368pi2 = mesh.AddPoint(mark3);369searchtree.Insert (mark3, pi2);370}371372// cout << "pi1 = " << pi1 << endl;373// cout << "pi2 = " << pi2 << endl;374375Segment seg;376seg.edgenr = segnr;377seg.si = bc; // segnr;378seg.p1 = pi1;379seg.p2 = pi2;380seg.domin = leftdom;381seg.domout = rightdom;382seg.epgeominfo[0].edgenr = segnr;383seg.epgeominfo[0].dist = edgelengthold;384seg.epgeominfo[1].edgenr = segnr;385seg.epgeominfo[1].dist = edgelength;386seg.singedge_left = hpref_left;387seg.singedge_right = hpref_right;388mesh.AddSegment (seg);389}390391oldmark = mark;392edgelengthold = edgelength;393j++;394}395396pold = p;397lold = l;398}399}400401402template<int D>403void SplineSeg<D> :: GetPoints (int n, ARRAY<Point<D> > & points)404{405points.SetSize (n);406if (n >= 2)407for (int i = 0; i < n; i++)408points[i] = GetPoint(double(i) / (n-1));409}410411template<int D>412void SplineSeg<D> :: PrintCoeff (ostream & ost) const413{414Vector u(6);415416GetCoeff(u);417418for ( int i=0; i<6; i++)419ost << u[i] << " ";420ost << endl;421}422423424425/*426Implementation of line-segment from p1 to p2427*/428429430template<int D>431LineSeg<D> :: LineSeg (const GeomPoint<D> & ap1,432const GeomPoint<D> & ap2)433: p1(ap1), p2(ap2)434{435;436}437438439template<int D>440Point<D> LineSeg<D> :: GetPoint (double t) const441{442return p1 + t * (p2 - p1);443}444445template<int D>446Vec<D> LineSeg<D> :: GetTangent (const double t) const447{448return p2-p1;449}450451template<int D>452void LineSeg<D> :: GetDerivatives (const double t,453Point<D> & point,454Vec<D> & first,455Vec<D> & second) const456{457first = p2 - p1;458point = p1 + t * first;459second = 0;460}461462463template<int D>464double LineSeg<D> :: Length () const465{466return Dist (p1, p2);467}468469470template<int D>471void LineSeg<D> :: GetCoeff (Vector & coeffs) const472{473coeffs.SetSize(6);474475double dx = p2(0) - p1(0);476double dy = p2(1) - p1(1);477478coeffs[0] = coeffs[1] = coeffs[2] = 0;479coeffs[3] = -dy;480coeffs[4] = dx;481coeffs[5] = -dx * p1(1) + dy * p1(0);482}483484485486template<int D>487void LineSeg<D> :: LineIntersections (const double a, const double b, const double c,488ARRAY < Point<D> > & points, const double eps) const489{490points.SetSize(0);491492double denom = -a*p2(0)+a*p1(0)-b*p2(1)+b*p1(1);493if(fabs(denom) < 1e-20)494return;495496double t = (a*p1(0)+b*p1(1)+c)/denom;497if((t > -eps) && (t < 1.+eps))498points.Append(GetPoint(t));499}500501502503template<int D>504void LineSeg<D> :: Project (const Point<D> point, Point<D> & point_on_curve, double & t) const505{506Vec<D> v = p2-p1;507double l = v.Length();508v *= 1./l;509t = (point-p1)*v;510511if(t<0) t = 0;512if(t>l) t = l;513514point_on_curve = p1+t*v;515516t *= 1./l;517}518519520template<int D>521void LineSeg<D> :: GetRawData (ARRAY<double> & data) const522{523data.Append(2);524for(int i=0; i<D; i++)525data.Append(p1[i]);526for(int i=0; i<D; i++)527data.Append(p2[i]);528}529530531template<int D>532void SplineSeg3<D> :: Project (const Point<D> point, Point<D> & point_on_curve, double & t) const533{534double t_old = -1;535536if(proj_latest_t > 0. && proj_latest_t < 1.)537t = proj_latest_t;538else539t = 0.5;540541Point<D> phi;542Vec<D> phip,phipp,phimp;543544int i=0;545546while(t > -0.5 && t < 1.5 && i<20 && fabs(t-t_old) > 1e-15 )547{548GetDerivatives(t,phi,phip,phipp);549550t_old = t;551552phimp = phi-point;553554//t = min2(max2(t-(phip*phimp)/(phipp*phimp + phip*phip),0.),1.);555t -= (phip*phimp)/(phipp*phimp + phip*phip);556557i++;558}559560//if(i<10 && t > 0. && t < 1.)561if(i<20 && t > -0.4 && t < 1.4)562{563if(t < 0)564{565t = 0.;566}567if(t > 1)568{569t = 1.;570}571572point_on_curve = GetPoint(t);573574double dist = Dist(point,point_on_curve);575576phi = GetPoint(0);577double auxdist = Dist(phi,point);578if(auxdist < dist)579{580t = 0.;581point_on_curve = phi;582dist = auxdist;583}584phi = GetPoint(1);585auxdist = Dist(phi,point);586if(auxdist < dist)587{588t = 1.;589point_on_curve = phi;590dist = auxdist;591}592}593else594{595double t0 = 0;596double t1 = 0.5;597double t2 = 1.;598599double d0,d1,d2;600601602//(*testout) << "newtonersatz" << endl;603while(t2-t0 > 1e-8)604{605606phi = GetPoint(t0); d0 = Dist(phi,point);607phi = GetPoint(t1); d1 = Dist(phi,point);608phi = GetPoint(t2); d2 = Dist(phi,point);609610double a = (2.*d0 - 4.*d1 +2.*d2)/pow(t2-t0,2);611612if(a <= 0)613{614if(d0 < d2)615t2 -= 0.3*(t2-t0);616else617t0 += 0.3*(t2-t0);618619t1 = 0.5*(t2+t0);620}621else622{623double b = (d1-d0-a*(t1*t1-t0*t0))/(t1-t0);624625double auxt1 = -0.5*b/a;626627if(auxt1 < t0)628{629t2 -= 0.4*(t2-t0);630t0 = max2(0.,t0-0.1*(t2-t0));631}632else if (auxt1 > t2)633{634t0 += 0.4*(t2-t0);635t2 = min2(1.,t2+0.1*(t2-t0));636}637else638{639t1 = auxt1;640auxt1 = 0.25*(t2-t0);641t0 = max2(0.,t1-auxt1);642t2 = min2(1.,t1+auxt1);643}644645t1 = 0.5*(t2+t0);646}647648}649650651phi = GetPoint(t0); d0 = Dist(phi,point);652phi = GetPoint(t1); d1 = Dist(phi,point);653phi = GetPoint(t2); d2 = Dist(phi,point);654655double mind = d0;656t = t0;657if(d1 < mind)658{659t = t1;660mind = d1;661}662if(d2 < mind)663{664t = t2;665mind = d2;666}667668point_on_curve = GetPoint(t);669}670//(*testout) << " latest_t " << proj_latest_t << " t " << t << endl;671672proj_latest_t = t;673}674675676677678template<int D>679SplineSeg3<D> :: SplineSeg3 (const GeomPoint<D> & ap1,680const GeomPoint<D> & ap2,681const GeomPoint<D> & ap3)682: p1(ap1), p2(ap2), p3(ap3)683{684proj_latest_t = 0.5;685}686687template<int D>688Point<D> SplineSeg3<D> :: GetPoint (double t) const689{690double x, y, w;691double b1, b2, b3;692693b1 = (1-t)*(1-t);694b2 = sqrt(2.0) * t * (1-t);695b3 = t * t;696697x = p1(0) * b1 + p2(0) * b2 + p3(0) * b3;698y = p1(1) * b1 + p2(1) * b2 + p3(1) * b3;699w = b1 + b2 + b3;700701if(D==3)702{703double z = p1(2) * b1 + p2(2) * b2 + p3(2) * b3;704return Point<D> (x/w, y/w, z/w);705}706else707return Point<D> (x/w, y/w);708}709710711712template<int D>713void SplineSeg3<D> :: GetDerivatives (const double t,714Point<D> & point,715Vec<D> & first,716Vec<D> & second) const717{718Vec<D> v1(p1), v2(p2), v3(p3);719720double b1 = (1.-t)*(1.-t);721double b2 = sqrt(2.)*t*(1.-t);722double b3 = t*t;723double w = b1+b2+b3;724b1 *= 1./w; b2 *= 1./w; b3 *= 1./w;725726double b1p = 2.*(t-1.);727double b2p = sqrt(2.)*(1.-2.*t);728double b3p = 2.*t;729const double wp = b1p+b2p+b3p;730const double fac1 = wp/w;731b1p *= 1./w; b2p *= 1./w; b3p *= 1./w;732733const double b1pp = 2.;734const double b2pp = -2.*sqrt(2.);735const double b3pp = 2.;736const double wpp = b1pp+b2pp+b3pp;737const double fac2 = (wpp*w-2.*wp*wp)/(w*w);738739for(int i=0; i<D; i++)740point(i) = b1*p1(i) + b2*p2(i) + b3*p3(i);741742743first = (b1p - b1*fac1) * v1 +744(b2p - b2*fac1) * v2 +745(b3p - b3*fac1) * v3;746747second = (b1pp/w - b1p*fac1 - b1*fac2) * v1 +748(b2pp/w - b2p*fac1 - b2*fac2) * v2 +749(b3pp/w - b3p*fac1 - b3*fac2) * v3;750}751752753754template<int D>755Vec<D> SplineSeg3<D> :: GetTangent (const double t) const756{757const double b1 = (1.-t)*((sqrt(2.)-2.)*t-sqrt(2.));758const double b2 = sqrt(2.)*(1.-2.*t);759const double b3 = t*((sqrt(2.)-2)*t+2.);760761762Vec<D> retval;763for(int i=0; i<D; i++)764retval(i) = b1*p1(i) + b2*p2(i) + b3*p3(i);765766return retval;767768}769770771template<int D>772void SplineSeg3<D> :: GetCoeff (Vector & u) const773{774double t;775int i;776Point<D> p;777DenseMatrix a(6, 6);778DenseMatrix ata(6, 6);779Vector f(6);780781u.SetSize(6);782783// ata.SetSymmetric(1);784785t = 0;786for (i = 1; i <= 5; i++, t += 0.25)787{788p = GetPoint (t);789a.Elem(i, 1) = p(0) * p(0);790a.Elem(i, 2) = p(1) * p(1);791a.Elem(i, 3) = p(0) * p(1);792a.Elem(i, 4) = p(0);793a.Elem(i, 5) = p(1);794a.Elem(i, 6) = 1;795}796a.Elem(6, 1) = 1;797798CalcAtA (a, ata);799800u = 0;801u.Elem(6) = 1;802a.MultTrans (u, f);803ata.Solve (f, u);804}805806/*807template<int D>808double SplineSeg3<D> :: MaxCurvature(void) const809{810Vec<D> v1 = p1-p2;811Vec<D> v2 = p3-p2;812double l1 = v1.Length();813double l2 = v2.Length();814(*testout) << "v1 " << v1 << " v2 " << v2 << endl;815816double cosalpha = v1*v2/(l1*l2);817818(*testout) << "cosalpha " << cosalpha << endl;819820return sqrt(cosalpha + 1.)/(min2(l1,l2)*(1.-cosalpha));821}822*/823824825template<int D>826void SplineSeg3<D> :: LineIntersections (const double a, const double b, const double c,827ARRAY < Point<D> > & points, const double eps) const828{829points.SetSize(0);830831double t;832833const double c1 = a*p1(0) - sqrt(2.)*a*p2(0) + a*p3(0)834+ b*p1(1) - sqrt(2.)*b*p2(1) + b*p3(1)835+ (2.-sqrt(2.))*c;836const double c2 = -2.*a*p1(0) + sqrt(2.)*a*p2(0) -2.*b*p1(1) + sqrt(2.)*b*p2(1) + (sqrt(2.)-2.)*c;837const double c3 = a*p1(0) + b*p1(1) + c;838839if(fabs(c1) < 1e-20)840{841if(fabs(c2) < 1e-20)842return;843844t = -c3/c2;845if((t > -eps) && (t < 1.+eps))846points.Append(GetPoint(t));847return;848}849850const double discr = c2*c2-4.*c1*c3;851852if(discr < 0)853return;854855if(fabs(discr/(c1*c1)) < 1e-14)856{857t = -0.5*c2/c1;858if((t > -eps) && (t < 1.+eps))859points.Append(GetPoint(t));860return;861}862863t = (-c2 + sqrt(discr))/(2.*c1);864if((t > -eps) && (t < 1.+eps))865points.Append(GetPoint(t));866867t = (-c2 - sqrt(discr))/(2.*c1);868if((t > -eps) && (t < 1.+eps))869points.Append(GetPoint(t));870}871872873template < int D >874void SplineSeg3<D> :: GetRawData (ARRAY<double> & data) const875{876data.Append(3);877for(int i=0; i<D; i++)878data.Append(p1[i]);879for(int i=0; i<D; i++)880data.Append(p2[i]);881for(int i=0; i<D; i++)882data.Append(p3[i]);883}884885886//########################################################################887// circlesegment888889template<int D>890CircleSeg<D> :: CircleSeg (const GeomPoint<D> & ap1,891const GeomPoint<D> & ap2,892const GeomPoint<D> & ap3)893: p1(ap1), p2(ap2), p3(ap3)894{895Vec<D> v1,v2;896897v1 = p1 - p2;898v2 = p3 - p2;899900Point<D> p1t(p1+v1);901Point<D> p2t(p3+v2);902903// works only in 2D!!!!!!!!!904905Line2d g1t,g2t;906907g1t.P1() = Point<2>(p1(0),p1(1));908g1t.P2() = Point<2>(p1t(0),p1t(1));909g2t.P1() = Point<2>(p3(0),p3(1));910g2t.P2() = Point<2>(p2t(0),p2t(1));911912Point<2> mp = CrossPoint (g1t,g2t);913914pm(0) = mp(0); pm(1) = mp(1);915radius = Dist(pm,StartPI());916Vec2d auxv;917auxv.X() = p1(0)-pm(0); auxv.Y() = p1(1)-pm(1);918w1 = Angle(auxv);919auxv.X() = p3(0)-pm(0); auxv.Y() = p3(1)-pm(1);920w3 = Angle(auxv);921if ( fabs(w3-w1) > M_PI )922{923if ( w3>M_PI ) w3 -= 2*M_PI;924if ( w1>M_PI ) w1 -= 2*M_PI;925}926}927928929template<int D>930Point<D> CircleSeg<D> :: GetPoint (double t) const931{932if (t >= 1.0) { return p3; }933934double phi = StartAngle() + t*(EndAngle()-StartAngle());935Vec<D> tmp(cos(phi),sin(phi));936937return pm + Radius()*tmp;938}939940template<int D>941void CircleSeg<D> :: GetCoeff (Vector & coeff) const942{943coeff[0] = coeff[1] = 1.0;944coeff[2] = 0.0;945coeff[3] = -2.0 * pm[0];946coeff[4] = -2.0 * pm[1];947coeff[5] = sqr(pm[0]) + sqr(pm[1]) - sqr(Radius());948}949950951template<int D>952void CircleSeg<D> :: LineIntersections (const double a, const double b, const double c,953ARRAY < Point<D> > & points, const double eps) const954{955points.SetSize(0);956957double px=0,py=0;958959if(fabs(b) > 1e-20)960py = -c/b;961else962px = -c/a;963964const double c1 = a*a + b*b;965const double c2 = 2. * ( a*(py-pm(1)) - b*(px-pm(0)));966const double c3 = pow(px-pm(0),2) + pow(py-pm(1),2) - pow(Radius(),2);967968const double discr = c2*c2 - 4*c1*c3;969970if(discr < 0)971return;972973ARRAY<double> t;974975if(fabs(discr) < 1e-20)976t.Append(-0.5*c2/c1);977else978{979t.Append((-c2+sqrt(discr))/(2.*c1));980t.Append((-c2-sqrt(discr))/(2.*c1));981}982983for(int i=0; i<t.Size(); i++)984{985Point<D> p (px-t[i]*b,py+t[i]*a);986987double angle = atan2(p(1),p(0))+M_PI;988989if(angle > StartAngle()-eps && angle < EndAngle()+eps)990points.Append(p);991}992}993994995996997template<int D>998DiscretePointsSeg<D> :: DiscretePointsSeg (const ARRAY<Point<D> > & apts)999: pts (apts)1000{1001for(int i=0; i<D; i++)1002{1003p1(i) = apts[0](i);1004p2(i) = apts.Last()(i);1005}1006p1.refatpoint = true;1007p2.refatpoint = true;1008}100910101011template<int D>1012DiscretePointsSeg<D> :: ~DiscretePointsSeg ()1013{ ; }10141015template<int D>1016Point<D> DiscretePointsSeg<D> :: GetPoint (double t) const1017{1018double t1 = t * (pts.Size()-1);1019int segnr = int(t1);1020if (segnr < 0) segnr = 0;1021if (segnr >= pts.Size()) segnr = pts.Size()-1;10221023double rest = t1 - segnr;10241025return pts[segnr] + rest*Vec<D>(pts[segnr+1]-pts[segnr]);1026}1027102810291030typedef GeomPoint<2> GeomPoint2d;1031typedef SplineSeg<2> SplineSegment;1032typedef LineSeg<2> LineSegment;1033typedef SplineSeg3<2> SplineSegment3;1034typedef CircleSeg<2> CircleSegment;1035typedef DiscretePointsSeg<2> DiscretePointsSegment;10361037103810391040#endif104110421043