Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/ElmerGUI/netgen/libsrc/gprim/geom2d.hpp
3206 views
1
#ifndef FILE_GEOM2D
2
#define FILE_GEOM2D
3
4
/* *************************************************************************/
5
/* File: geom2d.hh */
6
/* Author: Joachim Schoeberl */
7
/* Date: 5. Aug. 95 */
8
/* *************************************************************************/
9
10
11
12
/* Geometric Algorithms */
13
14
#define EPSGEOM 1E-5
15
16
17
// extern void MyError (const char * ch);
18
19
class Point2d;
20
class Vec2d;
21
22
class LINE2D;
23
class Line2d;
24
class PLine2d;
25
class TRIANGLE2D;
26
class PTRIANGLE2D;
27
28
29
inline Vec2d operator- (const Point2d & p1, const Point2d & p2);
30
inline Point2d operator- (const Point2d & p1, const Vec2d & v);
31
inline Point2d operator+ (const Point2d & p1, const Vec2d & v);
32
inline Point2d Center (const Point2d & p1, const Point2d & p2);
33
34
inline void PpSmV (const Point2d & p1, double s, const Vec2d & v, Point2d & p2);
35
inline void PmP (const Point2d & p1, const Point2d & p2, Vec2d & v);
36
ostream & operator<<(ostream & s, const Point2d & p);
37
inline Vec2d operator- (const Point2d & p1, const Point2d & p2);
38
inline Point2d operator- (const Point2d & p1, const Vec2d & v);
39
inline Point2d operator+ (const Point2d & p1, const Vec2d & v);
40
inline Vec2d operator- (const Vec2d & p1, const Vec2d & v);
41
inline Vec2d operator+ (const Vec2d & p1, const Vec2d & v);
42
inline Vec2d operator* (double scal, const Vec2d & v);
43
double Angle (const Vec2d & v);
44
double FastAngle (const Vec2d & v);
45
double Angle (const Vec2d & v1, const Vec2d & v2);
46
double FastAngle (const Vec2d & v1, const Vec2d & v2);
47
ostream & operator<<(ostream & s, const Vec2d & v);
48
double Dist2(const Line2d & g, const Line2d & h ); // GH
49
int Near (const Point2d & p1, const Point2d & p2, const double eps);
50
51
int Parallel (const Line2d & l1, const Line2d & l2, double peps = EPSGEOM);
52
int IsOnLine (const Line2d & l, const Point2d & p, double heps = EPSGEOM);
53
int IsOnLongLine (const Line2d & l, const Point2d & p);
54
int Hit (const Line2d & l1, const Line2d & l2, double heps = EPSGEOM);
55
ostream & operator<<(ostream & s, const Line2d & l);
56
Point2d CrossPoint (const PLine2d & l1, const PLine2d & l2);
57
int Parallel (const PLine2d & l1, const PLine2d & l2, double peps = EPSGEOM);
58
int IsOnLine (const PLine2d & l, const Point2d & p, double heps = EPSGEOM);
59
int IsOnLongLine (const PLine2d & l, const Point2d & p);
60
int Hit (const PLine2d & l1, const Line2d & l2, double heps = EPSGEOM);
61
ostream & operator<<(ostream & s, const Line2d & l);
62
ostream & operator<<(ostream & s, const TRIANGLE2D & t);
63
ostream & operator<<(ostream & s, const PTRIANGLE2D & t);
64
65
///
66
class Point2d
67
{
68
///
69
friend class Vec2d;
70
71
protected:
72
///
73
double px, py;
74
75
public:
76
///
77
Point2d() { /* px = py = 0; */ }
78
///
79
Point2d(double ax, double ay) { px = ax; py = ay; }
80
///
81
Point2d(const Point2d & p2) { px = p2.px; py = p2.py; }
82
83
Point2d (const Point<2> & p2)
84
{
85
px = p2(0);
86
py = p2(1);
87
}
88
///
89
Point2d & operator= (const Point2d & p2)
90
{ px = p2.px; py = p2.py; return *this; }
91
92
///
93
int operator== (const Point2d & p2) const // GH
94
{ return (px == p2.px && py == p2.py) ; }
95
96
///
97
double & X() { return px; }
98
///
99
double & Y() { return py; }
100
///
101
double X() const { return px; }
102
///
103
double Y() const { return py; }
104
105
operator Point<2> () const
106
{
107
return Point<2> (px, py);
108
}
109
110
111
///
112
friend inline Vec2d operator- (const Point2d & p1, const Point2d & p2);
113
///
114
friend inline Point2d operator- (const Point2d & p1, const Vec2d & v);
115
///
116
friend inline Point2d operator+ (const Point2d & p1, const Vec2d & v);
117
118
///
119
friend inline Point2d Center (const Point2d & p1, const Point2d & p2);
120
121
const Point2d & SetToMin (const Point2d & p2)
122
{
123
if (p2.px < px) px = p2.px;
124
if (p2.py < py) py = p2.py;
125
return *this;
126
}
127
128
129
///
130
const Point2d & SetToMax (const Point2d & p2)
131
{
132
if (p2.px > px) px = p2.px;
133
if (p2.py > py) py = p2.py;
134
return *this;
135
}
136
137
///
138
friend double Dist (const Point2d & p1, const Point2d & p2)
139
{ return sqrt ( (p1.px - p2.px) * (p1.px - p2.px) +
140
(p1.py - p2.py) * (p1.py - p2.py) ); }
141
// { return sqrt ( sqr (p1.X()-p2.X()) + sqr (p1.Y()-p2.Y()) ); }
142
143
///
144
friend double Dist2 (const Point2d & p1, const Point2d & p2)
145
{ return ( (p1.px - p2.px) * (p1.px - p2.px) +
146
(p1.py - p2.py) * (p1.py - p2.py) ); }
147
// { return sqr (p1.X()-p2.X()) + sqr (p1.Y()-p2.Y()) ; }
148
149
150
/**
151
Points clock-wise ?
152
Are the points (p1, p2, p3) clock-wise ?
153
*/
154
friend inline int CW (const Point2d & p1, const Point2d & p2, const Point2d & p3)
155
{
156
// return Cross (p2 - p1, p3 - p2) < 0;
157
return
158
(p2.px - p1.px) * (p3.py - p2.py) -
159
(p2.py - p1.py) * (p3.px - p2.px) < 0;
160
}
161
/**
162
Points counter-clock-wise ?
163
Are the points (p1, p2, p3) counter-clock-wise ?
164
*/
165
friend inline bool CCW (const Point2d & p1, const Point2d & p2, const Point2d & p3)
166
{
167
// return Cross (p2 - p1, p3 - p2) > 0;
168
return
169
(p2.px - p1.px) * (p3.py - p2.py) -
170
(p2.py - p1.py) * (p3.px - p2.px) > 0;
171
} /**
172
Points counter-clock-wise ?
173
Are the points (p1, p2, p3) counter-clock-wise ?
174
*/
175
friend inline bool CCW (const Point2d & p1, const Point2d & p2, const Point2d & p3, double eps)
176
{
177
// return Cross (p2 - p1, p3 - p2) > 0;
178
double ax = p2.px - p1.px;
179
double ay = p2.py - p1.py;
180
double bx = p3.px - p2.px;
181
double by = p3.py - p2.py;
182
183
return ax*by - ay*bx > eps*eps*max2(ax*ax+ay*ay,bx*bx+by*by);
184
}
185
186
///
187
friend inline void PpSmV (const Point2d & p1, double s, const Vec2d & v, Point2d & p2);
188
///
189
friend inline void PmP (const Point2d & p1, const Point2d & p2, Vec2d & v);
190
191
///
192
friend ostream & operator<<(ostream & s, const Point2d & p);
193
};
194
195
196
inline int Near (const Point2d & p1, const Point2d & p2,
197
const double eps = 1e-4 )
198
{
199
return Dist2(p1,p2) <= eps*eps;
200
}
201
202
203
204
205
206
207
///
208
class Vec2d
209
{
210
protected:
211
///
212
double vx, vy;
213
214
public:
215
///
216
Vec2d() { /* vx = vy = 0; */ }
217
///
218
Vec2d(double ax, double ay)
219
{ vx = ax; vy = ay; }
220
///
221
Vec2d(const Vec2d & v2) { vx = v2.vx; vy = v2.vy; }
222
223
///
224
explicit Vec2d(const Vec<2> & v2) { vx = v2(0); vy = v2(1); }
225
226
///
227
Vec2d(const Point2d & p1, const Point2d & p2)
228
{ vx = p2.px - p1.px; vy = p2.py - p1.py; }
229
230
///
231
Vec2d & operator= (const Vec2d & p2)
232
{ vx = p2.vx; vy = p2.vy; return *this; }
233
234
///
235
double & X() { return vx; }
236
///
237
double & Y() { return vy; }
238
///
239
double X() const { return vx; }
240
///
241
double Y() const { return vy; }
242
243
///
244
double Length() const { return sqrt (vx * vx + vy * vy); }
245
///
246
double Length2() const { return vx * vx + vy * vy; }
247
248
void GetNormal (Vec2d & n) const { n.vx=-vy; n.vy=vx; } // GH
249
250
///
251
inline Vec2d & operator+= (const Vec2d & v2);
252
///
253
inline Vec2d & operator-= (const Vec2d & v2);
254
///
255
inline Vec2d & operator*= (double s);
256
///
257
inline Vec2d & operator/= (double s);
258
259
///
260
friend inline Vec2d operator- (const Point2d & p1, const Point2d & p2);
261
///
262
friend inline Point2d operator- (const Point2d & p1, const Vec2d & v);
263
///
264
friend inline Point2d operator+ (const Point2d & p1, const Vec2d & v);
265
///
266
friend inline Vec2d operator- (const Vec2d & p1, const Vec2d & v);
267
///
268
friend inline Vec2d operator+ (const Vec2d & p1, const Vec2d & v);
269
///
270
friend inline Vec2d operator* (double scal, const Vec2d & v);
271
272
///
273
friend double operator* (const Vec2d & v1, const Vec2d & v2)
274
{ return v1.X() * v2.X() + v1.Y() * v2.Y(); }
275
276
277
///
278
friend double Cross (const Vec2d & v1, const Vec2d & v2)
279
{ return double(v1.X()) * double(v2.Y()) -
280
double(v1.Y()) * double(v2.X()); }
281
282
///
283
friend inline void PpSmV (const Point2d & p1, double s, const Vec2d & v, Point2d & p2);
284
///
285
friend inline void PmP (const Point2d & p1, const Point2d & p2, Vec2d & v);
286
287
/// Angle in [0,2*PI)
288
289
///
290
friend double Angle (const Vec2d & v);
291
///
292
friend double FastAngle (const Vec2d & v);
293
///
294
friend double Angle (const Vec2d & v1, const Vec2d & v2);
295
///
296
friend double FastAngle (const Vec2d & v1, const Vec2d & v2);
297
298
///
299
friend ostream & operator<<(ostream & s, const Vec2d & v);
300
};
301
302
303
304
///
305
class Line2d
306
{
307
protected:
308
///
309
Point2d p1, p2;
310
311
public:
312
///
313
Line2d() : p1(), p2() { };
314
///
315
Line2d(const Point2d & ap1, const Point2d & ap2)
316
{ p1 = ap1; p2 = ap2; }
317
318
///
319
Line2d & operator= (const Line2d & l2)
320
{ p1 = l2.p1; p2 = l2.p2; return *this;}
321
322
///
323
Point2d & P1() { return p1; }
324
///
325
Point2d & P2() { return p2; }
326
///
327
const Point2d & P1() const { return p1; }
328
///
329
const Point2d & P2() const { return p2; }
330
331
///
332
double XMax() const { return max2 (p1.X(), p2.X()); }
333
///
334
double YMax() const { return max2 (p1.Y(), p2.Y()); }
335
///
336
double XMin() const { return min2 (p1.X(), p2.X()); }
337
///
338
double YMin() const { return min2 (p1.Y(), p2.Y()); }
339
340
///
341
Vec2d Delta () const { return Vec2d (p2.X()-p1.X(), p2.Y()-p1.Y()); }
342
///
343
double Length () const { return Delta().Length(); }
344
///
345
double Length2 () const
346
{ return sqr (p1.X() - p2.X()) +
347
sqr (p1.Y() - p2.Y()); }
348
349
void GetNormal (Line2d & n) const; // GH
350
Vec2d NormalDelta () const; // GH
351
352
/// square of the distance between two 2d-lines.
353
friend double Dist2(const Line2d & g, const Line2d & h ); // GH
354
355
///
356
friend Point2d CrossPoint (const Line2d & l1, const Line2d & l2);
357
/// returns 1 iff parallel
358
friend int CrossPointBarycentric (const Line2d & l1, const Line2d & l2,
359
double & lam1, double & lam2);
360
361
///
362
friend int Parallel (const Line2d & l1, const Line2d & l2, double peps);
363
///
364
friend int IsOnLine (const Line2d & l, const Point2d & p, double heps);
365
///
366
friend int IsOnLongLine (const Line2d & l, const Point2d & p);
367
///
368
friend int Hit (const Line2d & l1, const Line2d & l2, double heps);
369
370
///
371
friend ostream & operator<<(ostream & s, const Line2d & l);
372
};
373
374
375
#ifdef NONE
376
///
377
class PLine2d
378
{
379
protected:
380
///
381
Point2d const * p1, *p2;
382
383
public:
384
///
385
PLine2d() { };
386
///
387
PLine2d(Point2d const * ap1, Point2d const * ap2)
388
{ p1 = ap1; p2 = ap2; }
389
390
///
391
PLine2d & operator= (const PLine2d & l2)
392
{ p1 = l2.p1; p2 = l2.p2; return *this;}
393
394
///
395
const Point2d *& P1() { return p1; }
396
///
397
const Point2d *& P2() { return p2; }
398
///
399
const Point2d & P1() const { return *p1; }
400
///
401
const Point2d & P2() const { return *p2; }
402
403
///
404
double XMax() const { return max2 (p1->X(), p2->X()); }
405
///
406
double YMax() const { return max2 (p1->Y(), p2->Y()); }
407
///
408
double XMin() const { return min2 (p1->X(), p2->X()); }
409
///
410
double YMin() const { return min2 (p1->Y(), p2->Y()); }
411
412
413
///
414
Vec2d Delta () const { return Vec2d (p2->X()-p1->X(), p2->Y()-p1->Y()); }
415
///
416
double Length () const { return Delta().Length(); }
417
///
418
double Length2 () const
419
{ return sqr (p1->X() - p2->X()) +
420
sqr (p1->Y() - p2->Y()); }
421
422
423
424
///
425
friend Point2d CrossPoint (const PLine2d & l1, const PLine2d & l2);
426
///
427
friend int Parallel (const PLine2d & l1, const PLine2d & l2, double peps);
428
///
429
friend int IsOnLine (const PLine2d & l, const Point2d & p, double heps);
430
///
431
friend int IsOnLongLine (const PLine2d & l, const Point2d & p);
432
///
433
friend int Hit (const PLine2d & l1, const Line2d & l2, double heps);
434
435
///
436
friend ostream & operator<<(ostream & s, const Line2d & l);
437
};
438
439
440
441
///
442
class ILINE
443
{
444
///
445
INDEX i[2];
446
447
public:
448
///
449
ILINE() {};
450
///
451
ILINE(INDEX i1, INDEX i2) { i[0] = i1; i[1] = i2; }
452
///
453
ILINE(const ILINE & l) { i[0] = l.i[0]; i[1] = l.i[1]; }
454
455
///
456
ILINE & operator= (const ILINE & l)
457
{ i[0] = l.i[0]; i[1] = l.i[1]; return *this; }
458
459
///
460
const INDEX & I(int ai) const { return i[ai-1]; }
461
///
462
const INDEX & X() const { return i[0]; }
463
///
464
const INDEX & Y() const { return i[1]; }
465
///
466
const INDEX & I1() const { return i[0]; }
467
///
468
const INDEX & I2() const { return i[1]; }
469
470
///
471
INDEX & I(int ai) { return i[ai-1]; }
472
///
473
INDEX & X() { return i[0]; }
474
///
475
INDEX & Y() { return i[1]; }
476
///
477
INDEX & I1() { return i[0]; }
478
///
479
INDEX & I2() { return i[1]; }
480
};
481
482
483
484
485
///
486
class TRIANGLE2D
487
{
488
private:
489
///
490
Point2d p1, p2, p3;
491
492
public:
493
///
494
TRIANGLE2D() { };
495
///
496
TRIANGLE2D (const Point2d & ap1, const Point2d & ap2,
497
const Point2d & ap3)
498
{ p1 = ap1; p2 = ap2; p3 = ap3;}
499
500
///
501
TRIANGLE2D & operator= (const TRIANGLE2D & t2)
502
{ p1 = t2.p1; p2 = t2.p2; p3 = t2.p3; return *this; }
503
504
///
505
Point2d & P1() { return p1; }
506
///
507
Point2d & P2() { return p2; }
508
///
509
Point2d & P3() { return p3; }
510
///
511
const Point2d & P1() const { return p1; }
512
///
513
const Point2d & P2() const { return p2; }
514
///
515
const Point2d & P3() const { return p3; }
516
517
///
518
double XMax() const { return max3 (p1.X(), p2.X(), p3.X()); }
519
///
520
double YMax() const { return max3 (p1.Y(), p2.Y(), p3.Y()); }
521
///
522
double XMin() const { return min3 (p1.X(), p2.X(), p3.X()); }
523
///
524
double YMin() const { return min3 (p1.Y(), p2.Y(), p3.Y()); }
525
526
///
527
inline Point2d Center () const
528
{ return Point2d( (p1.X()+p2.X()+p3.X())/3, (p1.Y()+p2.Y()+p3.Y())/3); }
529
530
///
531
int Regular() const;
532
///
533
int CW () const;
534
///
535
int CCW () const;
536
537
///
538
int IsOn (const Point2d & p) const;
539
///
540
int IsIn (const Point2d & p) const;
541
///
542
friend ostream & operator<<(ostream & s, const TRIANGLE2D & t);
543
};
544
545
546
///
547
class PTRIANGLE2D
548
{
549
private:
550
///
551
Point2d const *p1, *p2, *p3;
552
553
public:
554
///
555
PTRIANGLE2D() { };
556
///
557
PTRIANGLE2D (const Point2d * ap1, const Point2d * ap2,
558
const Point2d * ap3)
559
{ p1 = ap1; p2 = ap2; p3 = ap3;}
560
561
///
562
PTRIANGLE2D & operator= (const PTRIANGLE2D & t2)
563
{ p1 = t2.p1; p2 = t2.p2; p3 = t2.p3; return *this; }
564
565
///
566
const Point2d *& P1() { return p1; }
567
///
568
const Point2d *& P2() { return p2; }
569
///
570
const Point2d *& P3() { return p3; }
571
///
572
const Point2d * P1() const { return p1; }
573
///
574
const Point2d * P2() const { return p2; }
575
///
576
const Point2d * P3() const { return p3; }
577
578
///
579
double XMax() const { return max3 (p1->X(), p2->X(), p3->X()); }
580
///
581
double YMax() const { return max3 (p1->Y(), p2->Y(), p3->Y()); }
582
///
583
double XMin() const { return min3 (p1->X(), p2->X(), p3->X()); }
584
///
585
double YMin() const { return min3 (p1->Y(), p2->Y(), p3->Y()); }
586
587
///
588
Point2d Center () const
589
{ return Point2d( (p1->X()+p2->X()+p3->X())/3, (p1->Y()+p2->Y()+p3->Y())/3); }
590
591
592
///
593
int Regular() const;
594
///
595
int CW () const;
596
///
597
int CCW () const;
598
599
///
600
int IsOn (const Point2d & p) const;
601
///
602
int IsIn (const Point2d & p) const;
603
///
604
friend ostream & operator<<(ostream & s, const PTRIANGLE2D & t);
605
};
606
#endif
607
608
609
610
class Polygon2d
611
{
612
protected:
613
ARRAY<Point2d> points;
614
615
public:
616
Polygon2d ();
617
~Polygon2d ();
618
619
void AddPoint (const Point2d & p);
620
int GetNP() const { return points.Size(); }
621
void GetPoint (int i, Point2d & p) const
622
{ p = points.Get(i); }
623
void GetLine (int i, Point2d & p1, Point2d & p2) const
624
{ p1 = points.Get(i); p2 = points.Get(i%points.Size()+1); }
625
626
double Area () const { return fabs (HArea()); }
627
int CW () const { return HArea() > 0; }
628
int CCW () const { return HArea() < 0; }
629
630
int IsOn (const Point2d & p) const;
631
int IsIn (const Point2d & p) const;
632
633
int IsConvex () const;
634
635
int IsStarPoint (const Point2d & p) const;
636
Point2d Center() const;
637
Point2d EqualAreaPoint () const;
638
private:
639
double HArea () const;
640
};
641
642
643
/** Cheap approximation to atan2.
644
A monotone function of atan2(x,y) is computed.
645
*/
646
extern double Fastatan2 (double x, double y);
647
648
649
inline Vec2d & Vec2d :: operator+= (const Vec2d & v2)
650
{
651
vx += v2.vx;
652
vy += v2.vy;
653
return *this;
654
}
655
656
inline Vec2d & Vec2d :: operator-= (const Vec2d & v2)
657
{
658
vx -= v2.vx;
659
vy -= v2.vy;
660
return *this;
661
}
662
663
inline Vec2d & Vec2d :: operator*= (double s)
664
{
665
vx *= s;
666
vy *= s;
667
return *this;
668
}
669
670
671
inline Vec2d & Vec2d :: operator/= (double s)
672
{
673
if (s != 0)
674
{
675
vx /= s;
676
vy /= s;
677
}
678
else
679
{
680
MyError ("Vec2d::operator /=: Division by zero");
681
}
682
return *this;
683
}
684
685
686
687
inline Vec2d operator- (const Point2d & p1, const Point2d & p2)
688
{
689
return Vec2d (p1.X() - p2.X(), p1.Y() - p2.Y());
690
}
691
692
693
inline Point2d operator- (const Point2d & p1, const Vec2d & v)
694
{
695
return Point2d (p1.X() - v.X(), p1.Y() - v.Y());
696
}
697
698
699
inline Point2d operator+ (const Point2d & p1, const Vec2d & v)
700
{
701
return Point2d (p1.X() + v.X(), p1.Y() + v.Y());
702
}
703
704
705
inline Point2d Center (const Point2d & p1, const Point2d & p2)
706
{
707
return Point2d ((p1.X() + p2.X()) / 2, (p1.Y() + p2.Y()) / 2);
708
}
709
710
711
inline Vec2d operator- (const Vec2d & v1, const Vec2d & v2)
712
{
713
return Vec2d (v1.X() - v2.X(), v1.Y() - v2.Y());
714
}
715
716
717
inline Vec2d operator+ (const Vec2d & v1, const Vec2d & v2)
718
{
719
return Vec2d (v1.X() + v2.X(), v1.Y() + v2.Y());
720
}
721
722
723
inline Vec2d operator* (double scal, const Vec2d & v)
724
{
725
return Vec2d (scal * v.X(), scal * v.Y());
726
}
727
728
729
inline void PpSmV (const Point2d & p1, double s,
730
const Vec2d & v, Point2d & p2)
731
{
732
p2.X() = p1.X() + s * v.X();
733
p2.Y() = p1.Y() + s * v.Y();
734
}
735
736
737
inline void PmP (const Point2d & p1, const Point2d & p2, Vec2d & v)
738
{
739
v.X() = p1.X() - p2.X();
740
v.Y() = p1.Y() - p2.Y();
741
}
742
743
744
745
746
747
#ifdef none
748
inline int TRIANGLE2D :: Regular() const
749
{
750
return fabs(Cross ( p2 - p1, p3 - p2)) > EPSGEOM;
751
}
752
753
754
inline int TRIANGLE2D :: CW () const
755
{
756
return Cross ( p2 - p1, p3 - p2) < 0;
757
}
758
759
760
inline int TRIANGLE2D :: CCW () const
761
{
762
return Cross ( p2 - p1, p3 - p2) > 0;
763
}
764
765
766
767
768
inline int PTRIANGLE2D :: Regular() const
769
{
770
return fabs(Cross ( *p2 - *p1, *p3 - *p2)) > EPSGEOM;
771
}
772
773
774
inline int PTRIANGLE2D :: CW () const
775
{
776
return Cross ( *p2 - *p1, *p3 - *p2) < 0;
777
}
778
779
780
inline int PTRIANGLE2D :: CCW () const
781
{
782
return Cross ( *p2 - *p1, *p3 - *p2) > 0;
783
}
784
785
786
#endif
787
788
789
///
790
class Mat2d
791
{
792
protected:
793
///
794
double coeff[4];
795
796
public:
797
///
798
Mat2d() { coeff[0] = coeff[1] = coeff[2] = coeff[3] = 0; }
799
///
800
Mat2d(double a11, double a12, double a21, double a22)
801
{ coeff[0] = a11; coeff[1] = a12; coeff[2] = a21; coeff[3] = a22; }
802
///
803
Mat2d(const Mat2d & m2)
804
{ for (int i = 0; i < 4; i++) coeff[i] = m2.Get(i); }
805
806
///
807
double & Elem (INDEX i, INDEX j) { return coeff[2*(i-1)+j-1]; }
808
///
809
double & Elem (INDEX i) {return coeff[i]; }
810
///
811
double Get (INDEX i, INDEX j) const { return coeff[2*(i-1)+j-1]; }
812
///
813
double Get (INDEX i) const {return coeff[i]; }
814
815
///
816
double Det () const { return coeff[0] * coeff[3] - coeff[1] * coeff[2]; }
817
818
///
819
void Mult (const Vec2d & v, Vec2d & prod) const;
820
///
821
void MultTrans (const Vec2d & v , Vec2d & prod) const;
822
///
823
void Solve (const Vec2d & rhs, Vec2d & x) const;
824
/// Solves mat * x = rhs, but using a positive definite matrix instead of mat
825
void SolvePositiveDefinite (const Vec2d & rhs, Vec2d & x) const;
826
/// add a term \alpha * v * v^T
827
void AddDiadicProduct (double alpha, Vec2d & v);
828
};
829
830
831
832
inline void Mat2d :: Mult (const Vec2d & v, Vec2d & prod) const
833
{
834
prod.X() = coeff[0] * v.X() + coeff[1] * v.Y();
835
prod.Y() = coeff[2] * v.X() + coeff[3] * v.Y();
836
}
837
838
839
inline void Mat2d :: MultTrans (const Vec2d & v, Vec2d & prod) const
840
{
841
prod.X() = coeff[0] * v.X() + coeff[2] * v.Y();
842
prod.Y() = coeff[1] * v.X() + coeff[3] * v.Y();
843
}
844
845
846
847
inline void Mat2d :: Solve (const Vec2d & rhs, Vec2d & x) const
848
{
849
double det = Det();
850
851
if (det == 0)
852
MyError ("Mat2d::Solve: zero determinant");
853
else
854
{
855
x.X() = (coeff[3] * rhs.X() - coeff[1] * rhs.Y()) / det;
856
x.Y() = (-coeff[2] * rhs.X() + coeff[0] * rhs.Y()) / det;
857
}
858
}
859
860
861
inline void Mat2d :: SolvePositiveDefinite (const Vec2d & rhs, Vec2d & x) const
862
{
863
double a = max2(coeff[0], 1e-8);
864
double b = coeff[1] / a;
865
double c = coeff[2] / a;
866
double d = max2(coeff[3] - a *b * c, 1e-8);
867
868
x.X() = (rhs.X() - b * rhs.Y()) / a;
869
x.Y() = rhs.Y() / d - c * x.X();
870
}
871
872
873
inline void Mat2d :: AddDiadicProduct (double alpha, Vec2d & v)
874
{
875
coeff[0] += alpha * v.X() * v.X();
876
coeff[1] += alpha * v.X() * v.Y();
877
coeff[2] += alpha * v.Y() * v.X();
878
coeff[3] += alpha * v.Y() * v.Y();
879
}
880
881
882
883
#endif
884
885