Path: blob/devel/ElmerGUI/netgen/libsrc/gprim/geom2d.hpp
3206 views
#ifndef FILE_GEOM2D1#define FILE_GEOM2D23/* *************************************************************************/4/* File: geom2d.hh */5/* Author: Joachim Schoeberl */6/* Date: 5. Aug. 95 */7/* *************************************************************************/891011/* Geometric Algorithms */1213#define EPSGEOM 1E-5141516// extern void MyError (const char * ch);1718class Point2d;19class Vec2d;2021class LINE2D;22class Line2d;23class PLine2d;24class TRIANGLE2D;25class PTRIANGLE2D;262728inline Vec2d operator- (const Point2d & p1, const Point2d & p2);29inline Point2d operator- (const Point2d & p1, const Vec2d & v);30inline Point2d operator+ (const Point2d & p1, const Vec2d & v);31inline Point2d Center (const Point2d & p1, const Point2d & p2);3233inline void PpSmV (const Point2d & p1, double s, const Vec2d & v, Point2d & p2);34inline void PmP (const Point2d & p1, const Point2d & p2, Vec2d & v);35ostream & operator<<(ostream & s, const Point2d & p);36inline Vec2d operator- (const Point2d & p1, const Point2d & p2);37inline Point2d operator- (const Point2d & p1, const Vec2d & v);38inline Point2d operator+ (const Point2d & p1, const Vec2d & v);39inline Vec2d operator- (const Vec2d & p1, const Vec2d & v);40inline Vec2d operator+ (const Vec2d & p1, const Vec2d & v);41inline Vec2d operator* (double scal, const Vec2d & v);42double Angle (const Vec2d & v);43double FastAngle (const Vec2d & v);44double Angle (const Vec2d & v1, const Vec2d & v2);45double FastAngle (const Vec2d & v1, const Vec2d & v2);46ostream & operator<<(ostream & s, const Vec2d & v);47double Dist2(const Line2d & g, const Line2d & h ); // GH48int Near (const Point2d & p1, const Point2d & p2, const double eps);4950int Parallel (const Line2d & l1, const Line2d & l2, double peps = EPSGEOM);51int IsOnLine (const Line2d & l, const Point2d & p, double heps = EPSGEOM);52int IsOnLongLine (const Line2d & l, const Point2d & p);53int Hit (const Line2d & l1, const Line2d & l2, double heps = EPSGEOM);54ostream & operator<<(ostream & s, const Line2d & l);55Point2d CrossPoint (const PLine2d & l1, const PLine2d & l2);56int Parallel (const PLine2d & l1, const PLine2d & l2, double peps = EPSGEOM);57int IsOnLine (const PLine2d & l, const Point2d & p, double heps = EPSGEOM);58int IsOnLongLine (const PLine2d & l, const Point2d & p);59int Hit (const PLine2d & l1, const Line2d & l2, double heps = EPSGEOM);60ostream & operator<<(ostream & s, const Line2d & l);61ostream & operator<<(ostream & s, const TRIANGLE2D & t);62ostream & operator<<(ostream & s, const PTRIANGLE2D & t);6364///65class Point2d66{67///68friend class Vec2d;6970protected:71///72double px, py;7374public:75///76Point2d() { /* px = py = 0; */ }77///78Point2d(double ax, double ay) { px = ax; py = ay; }79///80Point2d(const Point2d & p2) { px = p2.px; py = p2.py; }8182Point2d (const Point<2> & p2)83{84px = p2(0);85py = p2(1);86}87///88Point2d & operator= (const Point2d & p2)89{ px = p2.px; py = p2.py; return *this; }9091///92int operator== (const Point2d & p2) const // GH93{ return (px == p2.px && py == p2.py) ; }9495///96double & X() { return px; }97///98double & Y() { return py; }99///100double X() const { return px; }101///102double Y() const { return py; }103104operator Point<2> () const105{106return Point<2> (px, py);107}108109110///111friend inline Vec2d operator- (const Point2d & p1, const Point2d & p2);112///113friend inline Point2d operator- (const Point2d & p1, const Vec2d & v);114///115friend inline Point2d operator+ (const Point2d & p1, const Vec2d & v);116117///118friend inline Point2d Center (const Point2d & p1, const Point2d & p2);119120const Point2d & SetToMin (const Point2d & p2)121{122if (p2.px < px) px = p2.px;123if (p2.py < py) py = p2.py;124return *this;125}126127128///129const Point2d & SetToMax (const Point2d & p2)130{131if (p2.px > px) px = p2.px;132if (p2.py > py) py = p2.py;133return *this;134}135136///137friend double Dist (const Point2d & p1, const Point2d & p2)138{ return sqrt ( (p1.px - p2.px) * (p1.px - p2.px) +139(p1.py - p2.py) * (p1.py - p2.py) ); }140// { return sqrt ( sqr (p1.X()-p2.X()) + sqr (p1.Y()-p2.Y()) ); }141142///143friend double Dist2 (const Point2d & p1, const Point2d & p2)144{ return ( (p1.px - p2.px) * (p1.px - p2.px) +145(p1.py - p2.py) * (p1.py - p2.py) ); }146// { return sqr (p1.X()-p2.X()) + sqr (p1.Y()-p2.Y()) ; }147148149/**150Points clock-wise ?151Are the points (p1, p2, p3) clock-wise ?152*/153friend inline int CW (const Point2d & p1, const Point2d & p2, const Point2d & p3)154{155// return Cross (p2 - p1, p3 - p2) < 0;156return157(p2.px - p1.px) * (p3.py - p2.py) -158(p2.py - p1.py) * (p3.px - p2.px) < 0;159}160/**161Points counter-clock-wise ?162Are the points (p1, p2, p3) counter-clock-wise ?163*/164friend inline bool CCW (const Point2d & p1, const Point2d & p2, const Point2d & p3)165{166// return Cross (p2 - p1, p3 - p2) > 0;167return168(p2.px - p1.px) * (p3.py - p2.py) -169(p2.py - p1.py) * (p3.px - p2.px) > 0;170} /**171Points counter-clock-wise ?172Are the points (p1, p2, p3) counter-clock-wise ?173*/174friend inline bool CCW (const Point2d & p1, const Point2d & p2, const Point2d & p3, double eps)175{176// return Cross (p2 - p1, p3 - p2) > 0;177double ax = p2.px - p1.px;178double ay = p2.py - p1.py;179double bx = p3.px - p2.px;180double by = p3.py - p2.py;181182return ax*by - ay*bx > eps*eps*max2(ax*ax+ay*ay,bx*bx+by*by);183}184185///186friend inline void PpSmV (const Point2d & p1, double s, const Vec2d & v, Point2d & p2);187///188friend inline void PmP (const Point2d & p1, const Point2d & p2, Vec2d & v);189190///191friend ostream & operator<<(ostream & s, const Point2d & p);192};193194195inline int Near (const Point2d & p1, const Point2d & p2,196const double eps = 1e-4 )197{198return Dist2(p1,p2) <= eps*eps;199}200201202203204205206///207class Vec2d208{209protected:210///211double vx, vy;212213public:214///215Vec2d() { /* vx = vy = 0; */ }216///217Vec2d(double ax, double ay)218{ vx = ax; vy = ay; }219///220Vec2d(const Vec2d & v2) { vx = v2.vx; vy = v2.vy; }221222///223explicit Vec2d(const Vec<2> & v2) { vx = v2(0); vy = v2(1); }224225///226Vec2d(const Point2d & p1, const Point2d & p2)227{ vx = p2.px - p1.px; vy = p2.py - p1.py; }228229///230Vec2d & operator= (const Vec2d & p2)231{ vx = p2.vx; vy = p2.vy; return *this; }232233///234double & X() { return vx; }235///236double & Y() { return vy; }237///238double X() const { return vx; }239///240double Y() const { return vy; }241242///243double Length() const { return sqrt (vx * vx + vy * vy); }244///245double Length2() const { return vx * vx + vy * vy; }246247void GetNormal (Vec2d & n) const { n.vx=-vy; n.vy=vx; } // GH248249///250inline Vec2d & operator+= (const Vec2d & v2);251///252inline Vec2d & operator-= (const Vec2d & v2);253///254inline Vec2d & operator*= (double s);255///256inline Vec2d & operator/= (double s);257258///259friend inline Vec2d operator- (const Point2d & p1, const Point2d & p2);260///261friend inline Point2d operator- (const Point2d & p1, const Vec2d & v);262///263friend inline Point2d operator+ (const Point2d & p1, const Vec2d & v);264///265friend inline Vec2d operator- (const Vec2d & p1, const Vec2d & v);266///267friend inline Vec2d operator+ (const Vec2d & p1, const Vec2d & v);268///269friend inline Vec2d operator* (double scal, const Vec2d & v);270271///272friend double operator* (const Vec2d & v1, const Vec2d & v2)273{ return v1.X() * v2.X() + v1.Y() * v2.Y(); }274275276///277friend double Cross (const Vec2d & v1, const Vec2d & v2)278{ return double(v1.X()) * double(v2.Y()) -279double(v1.Y()) * double(v2.X()); }280281///282friend inline void PpSmV (const Point2d & p1, double s, const Vec2d & v, Point2d & p2);283///284friend inline void PmP (const Point2d & p1, const Point2d & p2, Vec2d & v);285286/// Angle in [0,2*PI)287288///289friend double Angle (const Vec2d & v);290///291friend double FastAngle (const Vec2d & v);292///293friend double Angle (const Vec2d & v1, const Vec2d & v2);294///295friend double FastAngle (const Vec2d & v1, const Vec2d & v2);296297///298friend ostream & operator<<(ostream & s, const Vec2d & v);299};300301302303///304class Line2d305{306protected:307///308Point2d p1, p2;309310public:311///312Line2d() : p1(), p2() { };313///314Line2d(const Point2d & ap1, const Point2d & ap2)315{ p1 = ap1; p2 = ap2; }316317///318Line2d & operator= (const Line2d & l2)319{ p1 = l2.p1; p2 = l2.p2; return *this;}320321///322Point2d & P1() { return p1; }323///324Point2d & P2() { return p2; }325///326const Point2d & P1() const { return p1; }327///328const Point2d & P2() const { return p2; }329330///331double XMax() const { return max2 (p1.X(), p2.X()); }332///333double YMax() const { return max2 (p1.Y(), p2.Y()); }334///335double XMin() const { return min2 (p1.X(), p2.X()); }336///337double YMin() const { return min2 (p1.Y(), p2.Y()); }338339///340Vec2d Delta () const { return Vec2d (p2.X()-p1.X(), p2.Y()-p1.Y()); }341///342double Length () const { return Delta().Length(); }343///344double Length2 () const345{ return sqr (p1.X() - p2.X()) +346sqr (p1.Y() - p2.Y()); }347348void GetNormal (Line2d & n) const; // GH349Vec2d NormalDelta () const; // GH350351/// square of the distance between two 2d-lines.352friend double Dist2(const Line2d & g, const Line2d & h ); // GH353354///355friend Point2d CrossPoint (const Line2d & l1, const Line2d & l2);356/// returns 1 iff parallel357friend int CrossPointBarycentric (const Line2d & l1, const Line2d & l2,358double & lam1, double & lam2);359360///361friend int Parallel (const Line2d & l1, const Line2d & l2, double peps);362///363friend int IsOnLine (const Line2d & l, const Point2d & p, double heps);364///365friend int IsOnLongLine (const Line2d & l, const Point2d & p);366///367friend int Hit (const Line2d & l1, const Line2d & l2, double heps);368369///370friend ostream & operator<<(ostream & s, const Line2d & l);371};372373374#ifdef NONE375///376class PLine2d377{378protected:379///380Point2d const * p1, *p2;381382public:383///384PLine2d() { };385///386PLine2d(Point2d const * ap1, Point2d const * ap2)387{ p1 = ap1; p2 = ap2; }388389///390PLine2d & operator= (const PLine2d & l2)391{ p1 = l2.p1; p2 = l2.p2; return *this;}392393///394const Point2d *& P1() { return p1; }395///396const Point2d *& P2() { return p2; }397///398const Point2d & P1() const { return *p1; }399///400const Point2d & P2() const { return *p2; }401402///403double XMax() const { return max2 (p1->X(), p2->X()); }404///405double YMax() const { return max2 (p1->Y(), p2->Y()); }406///407double XMin() const { return min2 (p1->X(), p2->X()); }408///409double YMin() const { return min2 (p1->Y(), p2->Y()); }410411412///413Vec2d Delta () const { return Vec2d (p2->X()-p1->X(), p2->Y()-p1->Y()); }414///415double Length () const { return Delta().Length(); }416///417double Length2 () const418{ return sqr (p1->X() - p2->X()) +419sqr (p1->Y() - p2->Y()); }420421422423///424friend Point2d CrossPoint (const PLine2d & l1, const PLine2d & l2);425///426friend int Parallel (const PLine2d & l1, const PLine2d & l2, double peps);427///428friend int IsOnLine (const PLine2d & l, const Point2d & p, double heps);429///430friend int IsOnLongLine (const PLine2d & l, const Point2d & p);431///432friend int Hit (const PLine2d & l1, const Line2d & l2, double heps);433434///435friend ostream & operator<<(ostream & s, const Line2d & l);436};437438439440///441class ILINE442{443///444INDEX i[2];445446public:447///448ILINE() {};449///450ILINE(INDEX i1, INDEX i2) { i[0] = i1; i[1] = i2; }451///452ILINE(const ILINE & l) { i[0] = l.i[0]; i[1] = l.i[1]; }453454///455ILINE & operator= (const ILINE & l)456{ i[0] = l.i[0]; i[1] = l.i[1]; return *this; }457458///459const INDEX & I(int ai) const { return i[ai-1]; }460///461const INDEX & X() const { return i[0]; }462///463const INDEX & Y() const { return i[1]; }464///465const INDEX & I1() const { return i[0]; }466///467const INDEX & I2() const { return i[1]; }468469///470INDEX & I(int ai) { return i[ai-1]; }471///472INDEX & X() { return i[0]; }473///474INDEX & Y() { return i[1]; }475///476INDEX & I1() { return i[0]; }477///478INDEX & I2() { return i[1]; }479};480481482483484///485class TRIANGLE2D486{487private:488///489Point2d p1, p2, p3;490491public:492///493TRIANGLE2D() { };494///495TRIANGLE2D (const Point2d & ap1, const Point2d & ap2,496const Point2d & ap3)497{ p1 = ap1; p2 = ap2; p3 = ap3;}498499///500TRIANGLE2D & operator= (const TRIANGLE2D & t2)501{ p1 = t2.p1; p2 = t2.p2; p3 = t2.p3; return *this; }502503///504Point2d & P1() { return p1; }505///506Point2d & P2() { return p2; }507///508Point2d & P3() { return p3; }509///510const Point2d & P1() const { return p1; }511///512const Point2d & P2() const { return p2; }513///514const Point2d & P3() const { return p3; }515516///517double XMax() const { return max3 (p1.X(), p2.X(), p3.X()); }518///519double YMax() const { return max3 (p1.Y(), p2.Y(), p3.Y()); }520///521double XMin() const { return min3 (p1.X(), p2.X(), p3.X()); }522///523double YMin() const { return min3 (p1.Y(), p2.Y(), p3.Y()); }524525///526inline Point2d Center () const527{ return Point2d( (p1.X()+p2.X()+p3.X())/3, (p1.Y()+p2.Y()+p3.Y())/3); }528529///530int Regular() const;531///532int CW () const;533///534int CCW () const;535536///537int IsOn (const Point2d & p) const;538///539int IsIn (const Point2d & p) const;540///541friend ostream & operator<<(ostream & s, const TRIANGLE2D & t);542};543544545///546class PTRIANGLE2D547{548private:549///550Point2d const *p1, *p2, *p3;551552public:553///554PTRIANGLE2D() { };555///556PTRIANGLE2D (const Point2d * ap1, const Point2d * ap2,557const Point2d * ap3)558{ p1 = ap1; p2 = ap2; p3 = ap3;}559560///561PTRIANGLE2D & operator= (const PTRIANGLE2D & t2)562{ p1 = t2.p1; p2 = t2.p2; p3 = t2.p3; return *this; }563564///565const Point2d *& P1() { return p1; }566///567const Point2d *& P2() { return p2; }568///569const Point2d *& P3() { return p3; }570///571const Point2d * P1() const { return p1; }572///573const Point2d * P2() const { return p2; }574///575const Point2d * P3() const { return p3; }576577///578double XMax() const { return max3 (p1->X(), p2->X(), p3->X()); }579///580double YMax() const { return max3 (p1->Y(), p2->Y(), p3->Y()); }581///582double XMin() const { return min3 (p1->X(), p2->X(), p3->X()); }583///584double YMin() const { return min3 (p1->Y(), p2->Y(), p3->Y()); }585586///587Point2d Center () const588{ return Point2d( (p1->X()+p2->X()+p3->X())/3, (p1->Y()+p2->Y()+p3->Y())/3); }589590591///592int Regular() const;593///594int CW () const;595///596int CCW () const;597598///599int IsOn (const Point2d & p) const;600///601int IsIn (const Point2d & p) const;602///603friend ostream & operator<<(ostream & s, const PTRIANGLE2D & t);604};605#endif606607608609class Polygon2d610{611protected:612ARRAY<Point2d> points;613614public:615Polygon2d ();616~Polygon2d ();617618void AddPoint (const Point2d & p);619int GetNP() const { return points.Size(); }620void GetPoint (int i, Point2d & p) const621{ p = points.Get(i); }622void GetLine (int i, Point2d & p1, Point2d & p2) const623{ p1 = points.Get(i); p2 = points.Get(i%points.Size()+1); }624625double Area () const { return fabs (HArea()); }626int CW () const { return HArea() > 0; }627int CCW () const { return HArea() < 0; }628629int IsOn (const Point2d & p) const;630int IsIn (const Point2d & p) const;631632int IsConvex () const;633634int IsStarPoint (const Point2d & p) const;635Point2d Center() const;636Point2d EqualAreaPoint () const;637private:638double HArea () const;639};640641642/** Cheap approximation to atan2.643A monotone function of atan2(x,y) is computed.644*/645extern double Fastatan2 (double x, double y);646647648inline Vec2d & Vec2d :: operator+= (const Vec2d & v2)649{650vx += v2.vx;651vy += v2.vy;652return *this;653}654655inline Vec2d & Vec2d :: operator-= (const Vec2d & v2)656{657vx -= v2.vx;658vy -= v2.vy;659return *this;660}661662inline Vec2d & Vec2d :: operator*= (double s)663{664vx *= s;665vy *= s;666return *this;667}668669670inline Vec2d & Vec2d :: operator/= (double s)671{672if (s != 0)673{674vx /= s;675vy /= s;676}677else678{679MyError ("Vec2d::operator /=: Division by zero");680}681return *this;682}683684685686inline Vec2d operator- (const Point2d & p1, const Point2d & p2)687{688return Vec2d (p1.X() - p2.X(), p1.Y() - p2.Y());689}690691692inline Point2d operator- (const Point2d & p1, const Vec2d & v)693{694return Point2d (p1.X() - v.X(), p1.Y() - v.Y());695}696697698inline Point2d operator+ (const Point2d & p1, const Vec2d & v)699{700return Point2d (p1.X() + v.X(), p1.Y() + v.Y());701}702703704inline Point2d Center (const Point2d & p1, const Point2d & p2)705{706return Point2d ((p1.X() + p2.X()) / 2, (p1.Y() + p2.Y()) / 2);707}708709710inline Vec2d operator- (const Vec2d & v1, const Vec2d & v2)711{712return Vec2d (v1.X() - v2.X(), v1.Y() - v2.Y());713}714715716inline Vec2d operator+ (const Vec2d & v1, const Vec2d & v2)717{718return Vec2d (v1.X() + v2.X(), v1.Y() + v2.Y());719}720721722inline Vec2d operator* (double scal, const Vec2d & v)723{724return Vec2d (scal * v.X(), scal * v.Y());725}726727728inline void PpSmV (const Point2d & p1, double s,729const Vec2d & v, Point2d & p2)730{731p2.X() = p1.X() + s * v.X();732p2.Y() = p1.Y() + s * v.Y();733}734735736inline void PmP (const Point2d & p1, const Point2d & p2, Vec2d & v)737{738v.X() = p1.X() - p2.X();739v.Y() = p1.Y() - p2.Y();740}741742743744745746#ifdef none747inline int TRIANGLE2D :: Regular() const748{749return fabs(Cross ( p2 - p1, p3 - p2)) > EPSGEOM;750}751752753inline int TRIANGLE2D :: CW () const754{755return Cross ( p2 - p1, p3 - p2) < 0;756}757758759inline int TRIANGLE2D :: CCW () const760{761return Cross ( p2 - p1, p3 - p2) > 0;762}763764765766767inline int PTRIANGLE2D :: Regular() const768{769return fabs(Cross ( *p2 - *p1, *p3 - *p2)) > EPSGEOM;770}771772773inline int PTRIANGLE2D :: CW () const774{775return Cross ( *p2 - *p1, *p3 - *p2) < 0;776}777778779inline int PTRIANGLE2D :: CCW () const780{781return Cross ( *p2 - *p1, *p3 - *p2) > 0;782}783784785#endif786787788///789class Mat2d790{791protected:792///793double coeff[4];794795public:796///797Mat2d() { coeff[0] = coeff[1] = coeff[2] = coeff[3] = 0; }798///799Mat2d(double a11, double a12, double a21, double a22)800{ coeff[0] = a11; coeff[1] = a12; coeff[2] = a21; coeff[3] = a22; }801///802Mat2d(const Mat2d & m2)803{ for (int i = 0; i < 4; i++) coeff[i] = m2.Get(i); }804805///806double & Elem (INDEX i, INDEX j) { return coeff[2*(i-1)+j-1]; }807///808double & Elem (INDEX i) {return coeff[i]; }809///810double Get (INDEX i, INDEX j) const { return coeff[2*(i-1)+j-1]; }811///812double Get (INDEX i) const {return coeff[i]; }813814///815double Det () const { return coeff[0] * coeff[3] - coeff[1] * coeff[2]; }816817///818void Mult (const Vec2d & v, Vec2d & prod) const;819///820void MultTrans (const Vec2d & v , Vec2d & prod) const;821///822void Solve (const Vec2d & rhs, Vec2d & x) const;823/// Solves mat * x = rhs, but using a positive definite matrix instead of mat824void SolvePositiveDefinite (const Vec2d & rhs, Vec2d & x) const;825/// add a term \alpha * v * v^T826void AddDiadicProduct (double alpha, Vec2d & v);827};828829830831inline void Mat2d :: Mult (const Vec2d & v, Vec2d & prod) const832{833prod.X() = coeff[0] * v.X() + coeff[1] * v.Y();834prod.Y() = coeff[2] * v.X() + coeff[3] * v.Y();835}836837838inline void Mat2d :: MultTrans (const Vec2d & v, Vec2d & prod) const839{840prod.X() = coeff[0] * v.X() + coeff[2] * v.Y();841prod.Y() = coeff[1] * v.X() + coeff[3] * v.Y();842}843844845846inline void Mat2d :: Solve (const Vec2d & rhs, Vec2d & x) const847{848double det = Det();849850if (det == 0)851MyError ("Mat2d::Solve: zero determinant");852else853{854x.X() = (coeff[3] * rhs.X() - coeff[1] * rhs.Y()) / det;855x.Y() = (-coeff[2] * rhs.X() + coeff[0] * rhs.Y()) / det;856}857}858859860inline void Mat2d :: SolvePositiveDefinite (const Vec2d & rhs, Vec2d & x) const861{862double a = max2(coeff[0], 1e-8);863double b = coeff[1] / a;864double c = coeff[2] / a;865double d = max2(coeff[3] - a *b * c, 1e-8);866867x.X() = (rhs.X() - b * rhs.Y()) / a;868x.Y() = rhs.Y() / d - c * x.X();869}870871872inline void Mat2d :: AddDiadicProduct (double alpha, Vec2d & v)873{874coeff[0] += alpha * v.X() * v.X();875coeff[1] += alpha * v.X() * v.Y();876coeff[2] += alpha * v.Y() * v.X();877coeff[3] += alpha * v.Y() * v.Y();878}879880881882#endif883884885