Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/ElmerGUI/netgen/libsrc/geom2d/spline.hpp
3206 views
1
#ifndef FILE_SPLINE_HPP
2
#define FILE_SPLINE_HPP
3
4
/**************************************************************************/
5
/* File: spline.hpp */
6
/* Author: Joachim Schoeberl */
7
/* Date: 24. Jul. 96 */
8
/**************************************************************************/
9
10
11
void CalcPartition (double l, double h, double r1, double r2,
12
double ra, double elto0, ARRAY<double> & points);
13
14
/*
15
Spline curves for 2D mesh generation
16
*/
17
18
19
/// Geometry point
20
template < int D >
21
class GeomPoint : public Point<D>
22
{
23
public:
24
/// refinement to point
25
double refatpoint;
26
bool hpref;
27
28
GeomPoint ()
29
{ ; }
30
31
///
32
GeomPoint (double ax, double ay, double aref = 1, bool ahpref=false)
33
: Point<D> (ax, ay), refatpoint(aref), hpref(ahpref) { ; }
34
GeomPoint (double ax, double ay, double az, double aref, bool ahpref=false)
35
: Point<D> (ax, ay, az), refatpoint(aref), hpref(ahpref) { ; }
36
GeomPoint (const Point<D> & ap, double aref = 1, bool ahpref=false)
37
: Point<D>(ap), refatpoint(aref), hpref(ahpref) { ; }
38
};
39
40
41
42
/// base class for 2d - segment
43
template < int D >
44
class SplineSeg
45
{
46
public:
47
/// left domain
48
int leftdom;
49
/// right domain
50
int rightdom;
51
/// refinement at line
52
double reffak;
53
/// boundary condition number
54
int bc;
55
/// copy spline mesh from other spline (-1.. do not copy)
56
int copyfrom;
57
/// perfrom anisotropic refinement (hp-refinement) to edge
58
bool hpref_left;
59
bool hpref_right;
60
/// calculates length of curve
61
virtual double Length () const;
62
/// returns point at curve, 0 <= t <= 1
63
virtual Point<D> GetPoint (double t) const = 0;
64
/// returns a (not necessarily uniform) tangent vector for 0 <= t <= 1
65
virtual Vec<D> GetTangent (const double t) const
66
{ cerr << "GetTangent not implemented for spline base-class" << endl; Vec<D> dummy; return dummy;}
67
virtual void GetDerivatives (const double t,
68
Point<D> & point,
69
Vec<D> & first,
70
Vec<D> & second) const {;}
71
/// partitionizes curve
72
void Partition (double h, double elto0,
73
Mesh & mesh, Point3dTree & searchtree, int segnr) const;
74
/// returns initial point on curve
75
virtual const GeomPoint<D> & StartPI () const = 0;
76
/// returns terminal point on curve
77
virtual const GeomPoint<D> & EndPI () const = 0;
78
/** writes curve description for fepp:
79
for implicitly given quadratic curves, the 6 coefficients of
80
the polynomial
81
$$ a x^2 + b y^2 + c x y + d x + e y + f = 0 $$
82
are written to ost */
83
void PrintCoeff (ostream & ost) const;
84
85
virtual void GetCoeff (Vector & coeffs) const = 0;
86
87
virtual void GetPoints (int n, ARRAY<Point<D> > & points);
88
89
/** calculates (2D) lineintersections:
90
for lines $$ a x + b y + c = 0 $$ the interecting points are calculated
91
and stored in points */
92
virtual void LineIntersections (const double a, const double b, const double c,
93
ARRAY < Point<D> > & points, const double eps) const
94
{points.SetSize(0);}
95
96
virtual double MaxCurvature(void) const = 0;
97
98
virtual string GetType(void) const {return "splinebase";}
99
100
virtual void Project (const Point<D> point, Point<D> & point_on_curve, double & t) const
101
{ cerr << "Project not implemented for spline base-class" << endl;}
102
103
virtual void GetRawData (ARRAY<double> & data) const
104
{ cerr << "GetRawData not implemented for spline base-class" << endl;}
105
106
};
107
108
109
/// Straight line form p1 to p2
110
template< int D >
111
class LineSeg : public SplineSeg<D>
112
{
113
///
114
GeomPoint<D> p1, p2;
115
//const GeomPoint<D> &p1, &p2;
116
public:
117
///
118
LineSeg (const GeomPoint<D> & ap1, const GeomPoint<D> & ap2);
119
///
120
virtual double Length () const;
121
///
122
virtual Point<D> GetPoint (double t) const;
123
///
124
virtual Vec<D> GetTangent (const double t) const;
125
126
127
virtual void GetDerivatives (const double t,
128
Point<D> & point,
129
Vec<D> & first,
130
Vec<D> & second) const;
131
///
132
virtual const GeomPoint<D> & StartPI () const { return p1; };
133
///
134
virtual const GeomPoint<D> & EndPI () const { return p2; }
135
///
136
virtual void GetCoeff (Vector & coeffs) const;
137
138
virtual string GetType(void) const {return "line";}
139
140
virtual void LineIntersections (const double a, const double b, const double c,
141
ARRAY < Point<D> > & points, const double eps) const;
142
143
virtual double MaxCurvature(void) const {return 0;}
144
145
virtual void Project (const Point<D> point, Point<D> & point_on_curve, double & t) const;
146
147
virtual void GetRawData (ARRAY<double> & data) const;
148
};
149
150
151
/// curve given by a rational, quadratic spline (including ellipses)
152
template< int D >
153
class SplineSeg3 : public SplineSeg<D>
154
{
155
///
156
GeomPoint<D> p1, p2, p3;
157
//const GeomPoint<D> &p1, &p2, &p3;
158
159
mutable double proj_latest_t;
160
public:
161
///
162
SplineSeg3 (const GeomPoint<D> & ap1,
163
const GeomPoint<D> & ap2,
164
const GeomPoint<D> & ap3);
165
///
166
virtual Point<D> GetPoint (double t) const;
167
///
168
virtual Vec<D> GetTangent (const double t) const;
169
170
171
virtual void GetDerivatives (const double t,
172
Point<D> & point,
173
Vec<D> & first,
174
Vec<D> & second) const;
175
///
176
virtual const GeomPoint<D> & StartPI () const { return p1; };
177
///
178
virtual const GeomPoint<D> & EndPI () const { return p3; }
179
///
180
virtual void GetCoeff (Vector & coeffs) const;
181
182
virtual string GetType(void) const {return "spline3";}
183
184
const GeomPoint<D> & TangentPoint (void) const { return p2; }
185
186
virtual void LineIntersections (const double a, const double b, const double c,
187
ARRAY < Point<D> > & points, const double eps) const;
188
189
virtual double MaxCurvature(void) const;
190
191
virtual void Project (const Point<D> point, Point<D> & point_on_curve, double & t) const;
192
193
virtual void GetRawData (ARRAY<double> & data) const;
194
};
195
196
197
// Gundolf Haase 8/26/97
198
/// A circle
199
template < int D >
200
class CircleSeg : public SplineSeg<D>
201
{
202
///
203
private:
204
GeomPoint<D> p1, p2, p3;
205
//const GeomPoint<D> &p1, &p2, &p3;
206
Point<D> pm;
207
double radius, w1,w3;
208
public:
209
///
210
CircleSeg (const GeomPoint<D> & ap1,
211
const GeomPoint<D> & ap2,
212
const GeomPoint<D> & ap3);
213
///
214
virtual Point<D> GetPoint (double t) const;
215
///
216
virtual const GeomPoint<D> & StartPI () const { return p1; }
217
///
218
virtual const GeomPoint<D> & EndPI () const { return p3; }
219
///
220
virtual void GetCoeff (Vector & coeffs) const;
221
///
222
double Radius() const { return radius; }
223
///
224
double StartAngle() const { return w1; }
225
///
226
double EndAngle() const { return w3; }
227
///
228
const Point<D> & MidPoint(void) const {return pm; }
229
230
virtual string GetType(void) const {return "circle";}
231
232
virtual void LineIntersections (const double a, const double b, const double c,
233
ARRAY < Point<D> > & points, const double eps) const;
234
235
virtual double MaxCurvature(void) const {return 1./radius;}
236
};
237
238
239
240
241
242
243
///
244
template<int D>
245
class DiscretePointsSeg : public SplineSeg<D>
246
{
247
ARRAY<Point<D> > pts;
248
GeomPoint<D> p1, p2;
249
public:
250
///
251
DiscretePointsSeg (const ARRAY<Point<D> > & apts);
252
///
253
virtual ~DiscretePointsSeg ();
254
///
255
virtual Point<D> GetPoint (double t) const;
256
///
257
virtual const GeomPoint<D> & StartPI () const { return p1; };
258
///
259
virtual const GeomPoint<D> & EndPI () const { return p2; }
260
///
261
virtual void GetCoeff (Vector & coeffs) const {;}
262
263
virtual double MaxCurvature(void) const {return 1;}
264
};
265
266
267
268
269
270
271
272
// calculates length of spline-curve
273
template<int D>
274
double SplineSeg<D> :: Length () const
275
{
276
Point<D> p, pold;
277
278
int i, n = 100;
279
double dt = 1.0 / n;
280
281
pold = GetPoint (0);
282
283
double l = 0;
284
for (i = 1; i <= n; i++)
285
{
286
p = GetPoint (i * dt);
287
l += Dist (p, pold);
288
pold = p;
289
}
290
return l;
291
}
292
293
294
295
// partitionizes spline curve
296
template<int D>
297
void SplineSeg<D> :: Partition (double h, double elto0,
298
Mesh & mesh, Point3dTree & searchtree, int segnr) const
299
{
300
int i, j;
301
double l, r1, r2, ra;
302
double lold, dt, frac;
303
int n = 100;
304
Point<D> p, pold, mark, oldmark;
305
ARRAY<double> curvepoints;
306
double edgelength, edgelengthold;
307
l = Length();
308
309
r1 = StartPI().refatpoint;
310
r2 = EndPI().refatpoint;
311
ra = reffak;
312
313
// cout << "Partition, l = " << l << ", h = " << h << endl;
314
CalcPartition (l, h, r1, r2, ra, elto0, curvepoints);
315
// cout << "curvepoints = " << curvepoints << endl;
316
317
dt = 1.0 / n;
318
319
l = 0;
320
j = 1;
321
322
pold = GetPoint (0);
323
lold = 0;
324
oldmark = pold;
325
edgelengthold = 0;
326
ARRAY<int> locsearch;
327
328
for (i = 1; i <= n; i++)
329
{
330
p = GetPoint (i*dt);
331
l = lold + Dist (p, pold);
332
while (j < curvepoints.Size() && (l >= curvepoints[j] || i == n))
333
{
334
frac = (curvepoints[j]-lold) / (l-lold);
335
mark = pold + frac * (p-pold);
336
edgelength = i*dt + (frac-1)*dt;
337
{
338
PointIndex pi1 = -1, pi2 = -1;
339
340
Point3d mark3(mark(0), mark(1), 0);
341
Point3d oldmark3(oldmark(0), oldmark(1), 0);
342
343
Vec<3> v (1e-4*h, 1e-4*h, 1e-4*h);
344
searchtree.GetIntersecting (oldmark3 - v, oldmark3 + v, locsearch);
345
if (locsearch.Size()) pi1 = locsearch[0];
346
347
searchtree.GetIntersecting (mark3 - v, mark3 + v, locsearch);
348
if (locsearch.Size()) pi2 = locsearch[0];
349
/*
350
for (PointIndex pk = PointIndex::BASE;
351
pk < mesh.GetNP()+PointIndex::BASE; pk++)
352
{
353
if (Dist (mesh[pk], oldmark3) < 1e-4 * h) pi1 = pk;
354
if (Dist (mesh[pk], mark3) < 1e-4 * h) pi2 = pk;
355
}
356
*/
357
358
359
// cout << "pi1 = " << pi1 << endl;
360
// cout << "pi2 = " << pi2 << endl;
361
362
if (pi1 == -1)
363
{
364
pi1 = mesh.AddPoint(oldmark3);
365
searchtree.Insert (oldmark3, pi1);
366
}
367
if (pi2 == -1)
368
{
369
pi2 = mesh.AddPoint(mark3);
370
searchtree.Insert (mark3, pi2);
371
}
372
373
// cout << "pi1 = " << pi1 << endl;
374
// cout << "pi2 = " << pi2 << endl;
375
376
Segment seg;
377
seg.edgenr = segnr;
378
seg.si = bc; // segnr;
379
seg.p1 = pi1;
380
seg.p2 = pi2;
381
seg.domin = leftdom;
382
seg.domout = rightdom;
383
seg.epgeominfo[0].edgenr = segnr;
384
seg.epgeominfo[0].dist = edgelengthold;
385
seg.epgeominfo[1].edgenr = segnr;
386
seg.epgeominfo[1].dist = edgelength;
387
seg.singedge_left = hpref_left;
388
seg.singedge_right = hpref_right;
389
mesh.AddSegment (seg);
390
}
391
392
oldmark = mark;
393
edgelengthold = edgelength;
394
j++;
395
}
396
397
pold = p;
398
lold = l;
399
}
400
}
401
402
403
template<int D>
404
void SplineSeg<D> :: GetPoints (int n, ARRAY<Point<D> > & points)
405
{
406
points.SetSize (n);
407
if (n >= 2)
408
for (int i = 0; i < n; i++)
409
points[i] = GetPoint(double(i) / (n-1));
410
}
411
412
template<int D>
413
void SplineSeg<D> :: PrintCoeff (ostream & ost) const
414
{
415
Vector u(6);
416
417
GetCoeff(u);
418
419
for ( int i=0; i<6; i++)
420
ost << u[i] << " ";
421
ost << endl;
422
}
423
424
425
426
/*
427
Implementation of line-segment from p1 to p2
428
*/
429
430
431
template<int D>
432
LineSeg<D> :: LineSeg (const GeomPoint<D> & ap1,
433
const GeomPoint<D> & ap2)
434
: p1(ap1), p2(ap2)
435
{
436
;
437
}
438
439
440
template<int D>
441
Point<D> LineSeg<D> :: GetPoint (double t) const
442
{
443
return p1 + t * (p2 - p1);
444
}
445
446
template<int D>
447
Vec<D> LineSeg<D> :: GetTangent (const double t) const
448
{
449
return p2-p1;
450
}
451
452
template<int D>
453
void LineSeg<D> :: GetDerivatives (const double t,
454
Point<D> & point,
455
Vec<D> & first,
456
Vec<D> & second) const
457
{
458
first = p2 - p1;
459
point = p1 + t * first;
460
second = 0;
461
}
462
463
464
template<int D>
465
double LineSeg<D> :: Length () const
466
{
467
return Dist (p1, p2);
468
}
469
470
471
template<int D>
472
void LineSeg<D> :: GetCoeff (Vector & coeffs) const
473
{
474
coeffs.SetSize(6);
475
476
double dx = p2(0) - p1(0);
477
double dy = p2(1) - p1(1);
478
479
coeffs[0] = coeffs[1] = coeffs[2] = 0;
480
coeffs[3] = -dy;
481
coeffs[4] = dx;
482
coeffs[5] = -dx * p1(1) + dy * p1(0);
483
}
484
485
486
487
template<int D>
488
void LineSeg<D> :: LineIntersections (const double a, const double b, const double c,
489
ARRAY < Point<D> > & points, const double eps) const
490
{
491
points.SetSize(0);
492
493
double denom = -a*p2(0)+a*p1(0)-b*p2(1)+b*p1(1);
494
if(fabs(denom) < 1e-20)
495
return;
496
497
double t = (a*p1(0)+b*p1(1)+c)/denom;
498
if((t > -eps) && (t < 1.+eps))
499
points.Append(GetPoint(t));
500
}
501
502
503
504
template<int D>
505
void LineSeg<D> :: Project (const Point<D> point, Point<D> & point_on_curve, double & t) const
506
{
507
Vec<D> v = p2-p1;
508
double l = v.Length();
509
v *= 1./l;
510
t = (point-p1)*v;
511
512
if(t<0) t = 0;
513
if(t>l) t = l;
514
515
point_on_curve = p1+t*v;
516
517
t *= 1./l;
518
}
519
520
521
template<int D>
522
void LineSeg<D> :: GetRawData (ARRAY<double> & data) const
523
{
524
data.Append(2);
525
for(int i=0; i<D; i++)
526
data.Append(p1[i]);
527
for(int i=0; i<D; i++)
528
data.Append(p2[i]);
529
}
530
531
532
template<int D>
533
void SplineSeg3<D> :: Project (const Point<D> point, Point<D> & point_on_curve, double & t) const
534
{
535
double t_old = -1;
536
537
if(proj_latest_t > 0. && proj_latest_t < 1.)
538
t = proj_latest_t;
539
else
540
t = 0.5;
541
542
Point<D> phi;
543
Vec<D> phip,phipp,phimp;
544
545
int i=0;
546
547
while(t > -0.5 && t < 1.5 && i<20 && fabs(t-t_old) > 1e-15 )
548
{
549
GetDerivatives(t,phi,phip,phipp);
550
551
t_old = t;
552
553
phimp = phi-point;
554
555
//t = min2(max2(t-(phip*phimp)/(phipp*phimp + phip*phip),0.),1.);
556
t -= (phip*phimp)/(phipp*phimp + phip*phip);
557
558
i++;
559
}
560
561
//if(i<10 && t > 0. && t < 1.)
562
if(i<20 && t > -0.4 && t < 1.4)
563
{
564
if(t < 0)
565
{
566
t = 0.;
567
}
568
if(t > 1)
569
{
570
t = 1.;
571
}
572
573
point_on_curve = GetPoint(t);
574
575
double dist = Dist(point,point_on_curve);
576
577
phi = GetPoint(0);
578
double auxdist = Dist(phi,point);
579
if(auxdist < dist)
580
{
581
t = 0.;
582
point_on_curve = phi;
583
dist = auxdist;
584
}
585
phi = GetPoint(1);
586
auxdist = Dist(phi,point);
587
if(auxdist < dist)
588
{
589
t = 1.;
590
point_on_curve = phi;
591
dist = auxdist;
592
}
593
}
594
else
595
{
596
double t0 = 0;
597
double t1 = 0.5;
598
double t2 = 1.;
599
600
double d0,d1,d2;
601
602
603
//(*testout) << "newtonersatz" << endl;
604
while(t2-t0 > 1e-8)
605
{
606
607
phi = GetPoint(t0); d0 = Dist(phi,point);
608
phi = GetPoint(t1); d1 = Dist(phi,point);
609
phi = GetPoint(t2); d2 = Dist(phi,point);
610
611
double a = (2.*d0 - 4.*d1 +2.*d2)/pow(t2-t0,2);
612
613
if(a <= 0)
614
{
615
if(d0 < d2)
616
t2 -= 0.3*(t2-t0);
617
else
618
t0 += 0.3*(t2-t0);
619
620
t1 = 0.5*(t2+t0);
621
}
622
else
623
{
624
double b = (d1-d0-a*(t1*t1-t0*t0))/(t1-t0);
625
626
double auxt1 = -0.5*b/a;
627
628
if(auxt1 < t0)
629
{
630
t2 -= 0.4*(t2-t0);
631
t0 = max2(0.,t0-0.1*(t2-t0));
632
}
633
else if (auxt1 > t2)
634
{
635
t0 += 0.4*(t2-t0);
636
t2 = min2(1.,t2+0.1*(t2-t0));
637
}
638
else
639
{
640
t1 = auxt1;
641
auxt1 = 0.25*(t2-t0);
642
t0 = max2(0.,t1-auxt1);
643
t2 = min2(1.,t1+auxt1);
644
}
645
646
t1 = 0.5*(t2+t0);
647
}
648
649
}
650
651
652
phi = GetPoint(t0); d0 = Dist(phi,point);
653
phi = GetPoint(t1); d1 = Dist(phi,point);
654
phi = GetPoint(t2); d2 = Dist(phi,point);
655
656
double mind = d0;
657
t = t0;
658
if(d1 < mind)
659
{
660
t = t1;
661
mind = d1;
662
}
663
if(d2 < mind)
664
{
665
t = t2;
666
mind = d2;
667
}
668
669
point_on_curve = GetPoint(t);
670
}
671
//(*testout) << " latest_t " << proj_latest_t << " t " << t << endl;
672
673
proj_latest_t = t;
674
}
675
676
677
678
679
template<int D>
680
SplineSeg3<D> :: SplineSeg3 (const GeomPoint<D> & ap1,
681
const GeomPoint<D> & ap2,
682
const GeomPoint<D> & ap3)
683
: p1(ap1), p2(ap2), p3(ap3)
684
{
685
proj_latest_t = 0.5;
686
}
687
688
template<int D>
689
Point<D> SplineSeg3<D> :: GetPoint (double t) const
690
{
691
double x, y, w;
692
double b1, b2, b3;
693
694
b1 = (1-t)*(1-t);
695
b2 = sqrt(2.0) * t * (1-t);
696
b3 = t * t;
697
698
x = p1(0) * b1 + p2(0) * b2 + p3(0) * b3;
699
y = p1(1) * b1 + p2(1) * b2 + p3(1) * b3;
700
w = b1 + b2 + b3;
701
702
if(D==3)
703
{
704
double z = p1(2) * b1 + p2(2) * b2 + p3(2) * b3;
705
return Point<D> (x/w, y/w, z/w);
706
}
707
else
708
return Point<D> (x/w, y/w);
709
}
710
711
712
713
template<int D>
714
void SplineSeg3<D> :: GetDerivatives (const double t,
715
Point<D> & point,
716
Vec<D> & first,
717
Vec<D> & second) const
718
{
719
Vec<D> v1(p1), v2(p2), v3(p3);
720
721
double b1 = (1.-t)*(1.-t);
722
double b2 = sqrt(2.)*t*(1.-t);
723
double b3 = t*t;
724
double w = b1+b2+b3;
725
b1 *= 1./w; b2 *= 1./w; b3 *= 1./w;
726
727
double b1p = 2.*(t-1.);
728
double b2p = sqrt(2.)*(1.-2.*t);
729
double b3p = 2.*t;
730
const double wp = b1p+b2p+b3p;
731
const double fac1 = wp/w;
732
b1p *= 1./w; b2p *= 1./w; b3p *= 1./w;
733
734
const double b1pp = 2.;
735
const double b2pp = -2.*sqrt(2.);
736
const double b3pp = 2.;
737
const double wpp = b1pp+b2pp+b3pp;
738
const double fac2 = (wpp*w-2.*wp*wp)/(w*w);
739
740
for(int i=0; i<D; i++)
741
point(i) = b1*p1(i) + b2*p2(i) + b3*p3(i);
742
743
744
first = (b1p - b1*fac1) * v1 +
745
(b2p - b2*fac1) * v2 +
746
(b3p - b3*fac1) * v3;
747
748
second = (b1pp/w - b1p*fac1 - b1*fac2) * v1 +
749
(b2pp/w - b2p*fac1 - b2*fac2) * v2 +
750
(b3pp/w - b3p*fac1 - b3*fac2) * v3;
751
}
752
753
754
755
template<int D>
756
Vec<D> SplineSeg3<D> :: GetTangent (const double t) const
757
{
758
const double b1 = (1.-t)*((sqrt(2.)-2.)*t-sqrt(2.));
759
const double b2 = sqrt(2.)*(1.-2.*t);
760
const double b3 = t*((sqrt(2.)-2)*t+2.);
761
762
763
Vec<D> retval;
764
for(int i=0; i<D; i++)
765
retval(i) = b1*p1(i) + b2*p2(i) + b3*p3(i);
766
767
return retval;
768
769
}
770
771
772
template<int D>
773
void SplineSeg3<D> :: GetCoeff (Vector & u) const
774
{
775
double t;
776
int i;
777
Point<D> p;
778
DenseMatrix a(6, 6);
779
DenseMatrix ata(6, 6);
780
Vector f(6);
781
782
u.SetSize(6);
783
784
// ata.SetSymmetric(1);
785
786
t = 0;
787
for (i = 1; i <= 5; i++, t += 0.25)
788
{
789
p = GetPoint (t);
790
a.Elem(i, 1) = p(0) * p(0);
791
a.Elem(i, 2) = p(1) * p(1);
792
a.Elem(i, 3) = p(0) * p(1);
793
a.Elem(i, 4) = p(0);
794
a.Elem(i, 5) = p(1);
795
a.Elem(i, 6) = 1;
796
}
797
a.Elem(6, 1) = 1;
798
799
CalcAtA (a, ata);
800
801
u = 0;
802
u.Elem(6) = 1;
803
a.MultTrans (u, f);
804
ata.Solve (f, u);
805
}
806
807
/*
808
template<int D>
809
double SplineSeg3<D> :: MaxCurvature(void) const
810
{
811
Vec<D> v1 = p1-p2;
812
Vec<D> v2 = p3-p2;
813
double l1 = v1.Length();
814
double l2 = v2.Length();
815
(*testout) << "v1 " << v1 << " v2 " << v2 << endl;
816
817
double cosalpha = v1*v2/(l1*l2);
818
819
(*testout) << "cosalpha " << cosalpha << endl;
820
821
return sqrt(cosalpha + 1.)/(min2(l1,l2)*(1.-cosalpha));
822
}
823
*/
824
825
826
template<int D>
827
void SplineSeg3<D> :: LineIntersections (const double a, const double b, const double c,
828
ARRAY < Point<D> > & points, const double eps) const
829
{
830
points.SetSize(0);
831
832
double t;
833
834
const double c1 = a*p1(0) - sqrt(2.)*a*p2(0) + a*p3(0)
835
+ b*p1(1) - sqrt(2.)*b*p2(1) + b*p3(1)
836
+ (2.-sqrt(2.))*c;
837
const double c2 = -2.*a*p1(0) + sqrt(2.)*a*p2(0) -2.*b*p1(1) + sqrt(2.)*b*p2(1) + (sqrt(2.)-2.)*c;
838
const double c3 = a*p1(0) + b*p1(1) + c;
839
840
if(fabs(c1) < 1e-20)
841
{
842
if(fabs(c2) < 1e-20)
843
return;
844
845
t = -c3/c2;
846
if((t > -eps) && (t < 1.+eps))
847
points.Append(GetPoint(t));
848
return;
849
}
850
851
const double discr = c2*c2-4.*c1*c3;
852
853
if(discr < 0)
854
return;
855
856
if(fabs(discr/(c1*c1)) < 1e-14)
857
{
858
t = -0.5*c2/c1;
859
if((t > -eps) && (t < 1.+eps))
860
points.Append(GetPoint(t));
861
return;
862
}
863
864
t = (-c2 + sqrt(discr))/(2.*c1);
865
if((t > -eps) && (t < 1.+eps))
866
points.Append(GetPoint(t));
867
868
t = (-c2 - sqrt(discr))/(2.*c1);
869
if((t > -eps) && (t < 1.+eps))
870
points.Append(GetPoint(t));
871
}
872
873
874
template < int D >
875
void SplineSeg3<D> :: GetRawData (ARRAY<double> & data) const
876
{
877
data.Append(3);
878
for(int i=0; i<D; i++)
879
data.Append(p1[i]);
880
for(int i=0; i<D; i++)
881
data.Append(p2[i]);
882
for(int i=0; i<D; i++)
883
data.Append(p3[i]);
884
}
885
886
887
//########################################################################
888
// circlesegment
889
890
template<int D>
891
CircleSeg<D> :: CircleSeg (const GeomPoint<D> & ap1,
892
const GeomPoint<D> & ap2,
893
const GeomPoint<D> & ap3)
894
: p1(ap1), p2(ap2), p3(ap3)
895
{
896
Vec<D> v1,v2;
897
898
v1 = p1 - p2;
899
v2 = p3 - p2;
900
901
Point<D> p1t(p1+v1);
902
Point<D> p2t(p3+v2);
903
904
// works only in 2D!!!!!!!!!
905
906
Line2d g1t,g2t;
907
908
g1t.P1() = Point<2>(p1(0),p1(1));
909
g1t.P2() = Point<2>(p1t(0),p1t(1));
910
g2t.P1() = Point<2>(p3(0),p3(1));
911
g2t.P2() = Point<2>(p2t(0),p2t(1));
912
913
Point<2> mp = CrossPoint (g1t,g2t);
914
915
pm(0) = mp(0); pm(1) = mp(1);
916
radius = Dist(pm,StartPI());
917
Vec2d auxv;
918
auxv.X() = p1(0)-pm(0); auxv.Y() = p1(1)-pm(1);
919
w1 = Angle(auxv);
920
auxv.X() = p3(0)-pm(0); auxv.Y() = p3(1)-pm(1);
921
w3 = Angle(auxv);
922
if ( fabs(w3-w1) > M_PI )
923
{
924
if ( w3>M_PI ) w3 -= 2*M_PI;
925
if ( w1>M_PI ) w1 -= 2*M_PI;
926
}
927
}
928
929
930
template<int D>
931
Point<D> CircleSeg<D> :: GetPoint (double t) const
932
{
933
if (t >= 1.0) { return p3; }
934
935
double phi = StartAngle() + t*(EndAngle()-StartAngle());
936
Vec<D> tmp(cos(phi),sin(phi));
937
938
return pm + Radius()*tmp;
939
}
940
941
template<int D>
942
void CircleSeg<D> :: GetCoeff (Vector & coeff) const
943
{
944
coeff[0] = coeff[1] = 1.0;
945
coeff[2] = 0.0;
946
coeff[3] = -2.0 * pm[0];
947
coeff[4] = -2.0 * pm[1];
948
coeff[5] = sqr(pm[0]) + sqr(pm[1]) - sqr(Radius());
949
}
950
951
952
template<int D>
953
void CircleSeg<D> :: LineIntersections (const double a, const double b, const double c,
954
ARRAY < Point<D> > & points, const double eps) const
955
{
956
points.SetSize(0);
957
958
double px=0,py=0;
959
960
if(fabs(b) > 1e-20)
961
py = -c/b;
962
else
963
px = -c/a;
964
965
const double c1 = a*a + b*b;
966
const double c2 = 2. * ( a*(py-pm(1)) - b*(px-pm(0)));
967
const double c3 = pow(px-pm(0),2) + pow(py-pm(1),2) - pow(Radius(),2);
968
969
const double discr = c2*c2 - 4*c1*c3;
970
971
if(discr < 0)
972
return;
973
974
ARRAY<double> t;
975
976
if(fabs(discr) < 1e-20)
977
t.Append(-0.5*c2/c1);
978
else
979
{
980
t.Append((-c2+sqrt(discr))/(2.*c1));
981
t.Append((-c2-sqrt(discr))/(2.*c1));
982
}
983
984
for(int i=0; i<t.Size(); i++)
985
{
986
Point<D> p (px-t[i]*b,py+t[i]*a);
987
988
double angle = atan2(p(1),p(0))+M_PI;
989
990
if(angle > StartAngle()-eps && angle < EndAngle()+eps)
991
points.Append(p);
992
}
993
}
994
995
996
997
998
template<int D>
999
DiscretePointsSeg<D> :: DiscretePointsSeg (const ARRAY<Point<D> > & apts)
1000
: pts (apts)
1001
{
1002
for(int i=0; i<D; i++)
1003
{
1004
p1(i) = apts[0](i);
1005
p2(i) = apts.Last()(i);
1006
}
1007
p1.refatpoint = true;
1008
p2.refatpoint = true;
1009
}
1010
1011
1012
template<int D>
1013
DiscretePointsSeg<D> :: ~DiscretePointsSeg ()
1014
{ ; }
1015
1016
template<int D>
1017
Point<D> DiscretePointsSeg<D> :: GetPoint (double t) const
1018
{
1019
double t1 = t * (pts.Size()-1);
1020
int segnr = int(t1);
1021
if (segnr < 0) segnr = 0;
1022
if (segnr >= pts.Size()) segnr = pts.Size()-1;
1023
1024
double rest = t1 - segnr;
1025
1026
return pts[segnr] + rest*Vec<D>(pts[segnr+1]-pts[segnr]);
1027
}
1028
1029
1030
1031
typedef GeomPoint<2> GeomPoint2d;
1032
typedef SplineSeg<2> SplineSegment;
1033
typedef LineSeg<2> LineSegment;
1034
typedef SplineSeg3<2> SplineSegment3;
1035
typedef CircleSeg<2> CircleSegment;
1036
typedef DiscretePointsSeg<2> DiscretePointsSegment;
1037
1038
1039
1040
1041
#endif
1042
1043