Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/ElmerGUI/netgen/libsrc/csg/algprim.cpp
3206 views
1
#include <mystdlib.h>
2
3
4
#include <linalg.hpp>
5
#include <csg.hpp>
6
7
8
namespace netgen
9
{
10
11
double
12
QuadraticSurface :: CalcFunctionValue (const Point<3> & p) const
13
{
14
return p(0) * (cxx * p(0) + cxy * p(1) + cxz * p(2) + cx) +
15
p(1) * (cyy * p(1) + cyz * p(2) + cy) +
16
p(2) * (czz * p(2) + cz) + c1;
17
}
18
19
void
20
QuadraticSurface :: CalcGradient (const Point<3> & p, Vec<3> & grad) const
21
{
22
grad(0) = 2 * cxx * p(0) + cxy * p(1) + cxz * p(2) + cx;
23
grad(1) = 2 * cyy * p(1) + cxy * p(0) + cyz * p(2) + cy;
24
grad(2) = 2 * czz * p(2) + cxz * p(0) + cyz * p(1) + cz;
25
}
26
27
void
28
QuadraticSurface :: CalcHesse (const Point<3> & /* p */, Mat<3> & hesse) const
29
{
30
hesse(0,0) = 2 * cxx;
31
hesse(1,1) = 2 * cyy;
32
hesse(2,2) = 2 * czz;
33
hesse(0,1) = hesse(1,0) = cxy;
34
hesse(0,2) = hesse(2,0) = cxz;
35
hesse(1,2) = hesse(2,1) = cyz;
36
}
37
38
39
void QuadraticSurface :: Read (istream & ist)
40
{
41
ist >> cxx >> cyy >> czz >> cxy >> cxz >> cyz >> cx >> cy >> cz >> c1;
42
}
43
44
void QuadraticSurface :: Print (ostream & ost) const
45
{
46
ost << cxx << " " << cyy << " " << czz << " "
47
<< cxy << " " << cxz << " " << cyz << " "
48
<< cx << " " << cy << " " << cz << " "
49
<< c1;
50
}
51
52
53
void QuadraticSurface :: PrintCoeff (ostream & ost) const
54
{
55
ost << " cxx = " << cxx
56
<< " cyy = " << cyy
57
<< " czz = " << czz
58
<< " cxy = " << cxy
59
<< " cxz = " << cxz
60
<< " cyz = " << cyz
61
<< " cx = " << cx
62
<< " cy = " << cy
63
<< " cz = " << cz
64
<< " c1 = " << c1 << endl;
65
}
66
67
68
69
Point<3> QuadraticSurface :: GetSurfacePoint () const
70
{
71
MyError ("GetSurfacePoint called for QuadraticSurface");
72
return Point<3> (0, 0, 0);
73
}
74
75
76
Plane :: Plane (const Point<3> & ap, Vec<3> an)
77
{
78
eps_base = 1e-8;
79
80
p = ap;
81
n = an;
82
n.Normalize();
83
84
cxx = cyy = czz = cxy = cxz = cyz = 0;
85
cx = n(0); cy = n(1); cz = n(2);
86
c1 = - (cx * p(0) + cy * p(1) + cz * p(2));
87
}
88
89
Primitive * Plane :: Copy () const
90
{
91
return new Plane (p, n);
92
}
93
94
void Plane :: Transform (Transformation<3> & trans)
95
{
96
Point<3> hp;
97
Vec<3> hn;
98
trans.Transform (p, hp);
99
trans.Transform (n, hn);
100
p = hp;
101
n = hn;
102
103
cxx = cyy = czz = cxy = cxz = cyz = 0;
104
cx = n(0); cy = n(1); cz = n(2);
105
c1 = - (cx * p(0) + cy * p(1) + cz * p(2));
106
}
107
108
109
110
void Plane :: GetPrimitiveData (const char *& classname,
111
ARRAY<double> & coeffs) const
112
{
113
classname = "plane";
114
coeffs.SetSize (6);
115
coeffs.Elem(1) = p(0);
116
coeffs.Elem(2) = p(1);
117
coeffs.Elem(3) = p(2);
118
coeffs.Elem(4) = n(0);
119
coeffs.Elem(5) = n(1);
120
coeffs.Elem(6) = n(2);
121
}
122
123
void Plane :: SetPrimitiveData (ARRAY<double> & coeffs)
124
{
125
p(0) = coeffs.Elem(1);
126
p(1) = coeffs.Elem(2);
127
p(2) = coeffs.Elem(3);
128
n(0) = coeffs.Elem(4);
129
n(1) = coeffs.Elem(5);
130
n(2) = coeffs.Elem(6);
131
132
n.Normalize();
133
134
cxx = cyy = czz = cxy = cxz = cyz = 0;
135
cx = n(0); cy = n(1); cz = n(2);
136
c1 = - (cx * p(0) + cy * p(1) + cz * p(2));
137
}
138
139
Primitive * Plane :: CreateDefault ()
140
{
141
return new Plane (Point<3> (0,0,0), Vec<3> (0,0,1));
142
}
143
144
145
int Plane :: IsIdentic (const Surface & s2, int & inv, double eps) const
146
{
147
const Plane * ps2 = dynamic_cast<const Plane*>(&s2);
148
149
if(ps2)
150
{
151
Point<3> pp2 = ps2->GetSurfacePoint();
152
Vec<3> n2 = s2.GetNormalVector(pp2);
153
154
if(fabs(n*n2) < 1.-eps_base)
155
return 0;
156
157
if (fabs (s2.CalcFunctionValue(p)) > eps) return 0;
158
}
159
else
160
{
161
//(*testout) << "pos1" << endl;
162
if (fabs (s2.CalcFunctionValue(p)) > eps) return 0;
163
Vec<3> hv1, hv2;
164
hv1 = n.GetNormal ();
165
hv2 = Cross (n, hv1);
166
167
Point<3> hp = p + hv1;
168
//(*testout) << "pos2" << endl;
169
//(*testout) << "eps " << eps << " s2.CalcFunctionValue(hp) " << s2.CalcFunctionValue(hp) << endl;
170
if (fabs (s2.CalcFunctionValue(hp)) > eps) return 0;
171
//(*testout) << "pos3" << endl;
172
hp = p + hv2;
173
if (fabs (s2.CalcFunctionValue(hp)) > eps) return 0;
174
}
175
176
//(*testout) << "pos4" << endl;
177
Vec<3> n1, n2;
178
n1 = GetNormalVector (p);
179
n2 = s2.GetNormalVector (p);
180
inv = (n1 * n2 < 0);
181
//(*testout) << "inv " << inv << endl;
182
return 1;
183
}
184
185
186
187
void Plane :: DefineTangentialPlane (const Point<3> & ap1, const Point<3> & ap2)
188
{
189
Surface::DefineTangentialPlane (ap1, ap2);
190
}
191
192
193
void Plane :: ToPlane (const Point<3> & p3d,
194
Point<2> & pplane,
195
double h, int & zone) const
196
{
197
Vec<3> p1p;
198
199
p1p = p3d - p1;
200
p1p /= h;
201
pplane(0) = p1p * ex;
202
pplane(1) = p1p * ey;
203
zone = 0;
204
}
205
206
void Plane :: FromPlane (const Point<2> & pplane, Point<3> & p3d, double h) const
207
{
208
/*
209
Vec<3> p1p;
210
Point<2> pplane2 = pplane;
211
212
pplane2 *= h;
213
p1p = pplane2(0) * ex + pplane2(1) * ey;
214
p3d = p1 + p1p;
215
*/
216
p3d = p1 + (h * pplane(0)) * ex + (h * pplane(1)) * ey;
217
}
218
219
220
void Plane :: Project (Point<3> & p3d) const
221
{
222
double val = Plane::CalcFunctionValue (p3d);
223
p3d -= val * n;
224
}
225
226
INSOLID_TYPE Plane :: BoxInSolid (const BoxSphere<3> & box) const
227
{
228
int i;
229
double val;
230
Point<3> pp;
231
232
val = Plane::CalcFunctionValue (box.Center());
233
if (val > box.Diam() / 2) return IS_OUTSIDE;
234
if (val < -box.Diam() / 2) return IS_INSIDE;
235
236
if (val > 0)
237
{
238
/*
239
double modify =
240
((box.MaxX()-box.MinX()) * fabs (cx) +
241
(box.MaxY()-box.MinY()) * fabs (cy) +
242
(box.MaxZ()-box.MinZ()) * fabs (cz)) / 2;
243
*/
244
Vec<3> vdiag = box.PMax() - box.PMin();
245
double modify = (vdiag(0) * fabs (cx) +
246
vdiag(1) * fabs (cy) +
247
vdiag(2) * fabs (cz) ) / 2;
248
249
if (val - modify < 0)
250
return DOES_INTERSECT;
251
return IS_OUTSIDE;
252
253
// only outside or intersect possible
254
for (i = 0; i < 8; i++)
255
{
256
pp = box.GetPointNr (i);
257
val = Plane::CalcFunctionValue (pp);
258
if (val < 0)
259
return DOES_INTERSECT;
260
}
261
return IS_OUTSIDE;
262
}
263
else
264
{
265
/*
266
double modify =
267
((box.MaxX()-box.MinX()) * fabs (cx) +
268
(box.MaxY()-box.MinY()) * fabs (cy) +
269
(box.MaxZ()-box.MinZ()) * fabs (cz)) / 2;
270
*/
271
Vec<3> vdiag = box.PMax() - box.PMin();
272
double modify = (vdiag(0) * fabs (cx) +
273
vdiag(1) * fabs (cy) +
274
vdiag(2) * fabs (cz) ) / 2;
275
if (val + modify > 0)
276
return DOES_INTERSECT;
277
return IS_INSIDE;
278
279
280
// only inside or intersect possible
281
for (i = 0; i < 8; i++)
282
{
283
pp = box.GetPointNr (i);
284
val = Plane::CalcFunctionValue (pp);
285
if (val > 0)
286
return DOES_INTERSECT;
287
}
288
return IS_INSIDE;
289
}
290
291
292
293
/*
294
for (i = 1; i <= 8; i++)
295
{
296
box.GetPointNr (i, p);
297
val = CalcFunctionValue (p);
298
if (val > 0) inside = 0;
299
if (val < 0) outside = 0;
300
}
301
302
if (inside) return IS_INSIDE;
303
if (outside) return IS_OUTSIDE;
304
return DOES_INTERSECT;
305
*/
306
}
307
308
309
310
// double Plane :: CalcFunctionValue (const Point<3> & p3d) const
311
// {
312
// return cx * p3d(0) + cy * p3d(1) + cz * p3d(2) + c1;
313
// }
314
315
void Plane :: CalcGradient (const Point<3> & /* p */, Vec<3> & grad) const
316
{
317
grad(0) = cx;
318
grad(1) = cy;
319
grad(2) = cz;
320
}
321
322
void Plane :: CalcHesse (const Point<3> & /* p */, Mat<3> & hesse) const
323
{
324
hesse = 0;
325
}
326
327
double Plane :: HesseNorm () const
328
{
329
return 0;
330
}
331
332
333
Point<3> Plane :: GetSurfacePoint () const
334
{
335
return p;
336
}
337
338
339
void Plane :: GetTriangleApproximation
340
(TriangleApproximation & tas,
341
const Box<3> & boundingbox, double facets) const
342
{
343
// find triangle, such that
344
// boundingbox /cap plane is contained in it
345
346
Point<3> c = boundingbox.Center();
347
double r = boundingbox.Diam();
348
349
Project (c);
350
Vec<3> t1 = n.GetNormal();
351
Vec<3> t2 = Cross (n, t1);
352
353
t1.Normalize();
354
t2.Normalize();
355
356
tas.AddPoint (c + (-0.5 * r) * t2 + (sqrt(0.75) * r) * t1);
357
tas.AddPoint (c + (-0.5 * r) * t2 + (-sqrt(0.75) * r) * t1);
358
tas.AddPoint (c + r * t2);
359
360
tas.AddTriangle (TATriangle (0, 0, 1, 2));
361
}
362
363
364
365
366
Sphere :: Sphere (const Point<3> & ac, double ar)
367
{
368
c = ac;
369
r = ar;
370
371
cxx = cyy = czz = 0.5 / r;
372
cxy = cxz = cyz = 0;
373
cx = - c(0) / r;
374
cy = - c(1) / r;
375
cz = - c(2) / r;
376
c1 = (c(0) * c(0) + c(1) * c(1) + c(2) * c(2)) / (2 * r) - r / 2;
377
}
378
379
void Sphere :: GetPrimitiveData (const char *& classname, ARRAY<double> & coeffs) const
380
{
381
classname = "sphere";
382
coeffs.SetSize (4);
383
coeffs.Elem(1) = c(0);
384
coeffs.Elem(2) = c(1);
385
coeffs.Elem(3) = c(2);
386
coeffs.Elem(4) = r;
387
}
388
389
void Sphere :: SetPrimitiveData (ARRAY<double> & coeffs)
390
{
391
c(0) = coeffs.Elem(1);
392
c(1) = coeffs.Elem(2);
393
c(2) = coeffs.Elem(3);
394
r = coeffs.Elem(4);
395
396
cxx = cyy = czz = 0.5 / r;
397
cxy = cxz = cyz = 0;
398
cx = - c(0) / r;
399
cy = - c(1) / r;
400
cz = - c(2) / r;
401
c1 = (c(0) * c(0) + c(1) * c(1) + c(2) * c(2)) / (2 * r) - r / 2;
402
}
403
404
Primitive * Sphere :: CreateDefault ()
405
{
406
return new Sphere (Point<3> (0,0,0), 1);
407
}
408
409
410
411
Primitive * Sphere :: Copy () const
412
{
413
return new Sphere (c, r);
414
}
415
416
void Sphere :: Transform (Transformation<3> & trans)
417
{
418
Point<3> hp;
419
trans.Transform (c, hp);
420
c = hp;
421
422
cxx = cyy = czz = 0.5 / r;
423
cxy = cxz = cyz = 0;
424
cx = - c(0) / r;
425
cy = - c(1) / r;
426
cz = - c(2) / r;
427
c1 = (c(0) * c(0) + c(1) * c(1) + c(2) * c(2)) / (2 * r) - r / 2;
428
}
429
430
431
432
433
int Sphere :: IsIdentic (const Surface & s2, int & inv, double eps) const
434
{
435
const Sphere * sp2 = dynamic_cast<const Sphere*> (&s2);
436
437
if (!sp2) return 0;
438
439
if (Dist (sp2->c, c) > eps) return 0;
440
if (fabs (sp2->r - r) > eps) return 0;
441
442
inv = 0;
443
444
return 1;
445
}
446
447
448
void Sphere :: DefineTangentialPlane (const Point<3> & ap1, const Point<3> & ap2)
449
{
450
Surface::DefineTangentialPlane (ap1, ap2);
451
452
ez = p1 - c;
453
ez /= ez.Length();
454
455
ex = p2 - p1;
456
ex -= (ex * ez) * ez;
457
ex /= ex.Length();
458
459
ey = Cross (ez, ex);
460
}
461
462
463
void Sphere :: ToPlane (const Point<3> & p, Point<2> & pplane, double h, int & zone) const
464
{
465
Vec<3> p1p;
466
467
p1p = p - p1;
468
469
/*
470
if (p1p * ez < -r)
471
{
472
zone = -1;
473
pplane = Point<2> (1E8, 1E8);
474
}
475
else
476
{
477
zone = 0;
478
p1p /= h;
479
pplane(0) = p1p * ex;
480
pplane(1) = p1p * ey;
481
}
482
*/
483
484
Point<3> p1top = c + (c - p1);
485
486
Vec<3> p1topp = p - p1top;
487
Vec<3> p1topp1 = p1 - p1top;
488
Vec<3> lam;
489
// SolveLinearSystem (ex, ey, p1topp, p1topp1, lam);
490
491
Mat<3> m;
492
for (int i = 0; i < 3; i++)
493
{
494
m(i, 0) = ex(i);
495
m(i, 1) = ey(i);
496
m(i, 2) = p1topp(i);
497
}
498
m.Solve (p1topp1, lam);
499
500
pplane(0) = -lam(0) / h;
501
pplane(1) = -lam(1) / h;
502
503
if (lam(2) > 2)
504
zone = -1;
505
else
506
zone = 0;
507
}
508
509
void Sphere :: FromPlane (const Point<2> & pplane, Point<3> & p, double h) const
510
{
511
/*
512
// Vec<3> p1p;
513
double z;
514
Point<2> pplane2 (pplane);
515
516
pplane2(0) *= h;
517
pplane2(1) *= h;
518
z = -r + sqrt (sqr (r) - sqr (pplane2(0)) - sqr (pplane2(1)));
519
// p = p1;
520
p(0) = p1(0) + pplane2(0) * ex(0) + pplane2(1) * ey(0) + z * ez(0);
521
p(1) = p1(1) + pplane2(0) * ex(1) + pplane2(1) * ey(1) + z * ez(1);
522
p(2) = p1(2) + pplane2(0) * ex(2) + pplane2(1) * ey(2) + z * ez(2);
523
*/
524
525
Point<2> pplane2 (pplane);
526
527
pplane2(0) *= h;
528
pplane2(1) *= h;
529
530
p(0) = p1(0) + pplane2(0) * ex(0) + pplane2(1) * ey(0);
531
p(1) = p1(1) + pplane2(0) * ex(1) + pplane2(1) * ey(1);
532
p(2) = p1(2) + pplane2(0) * ex(2) + pplane2(1) * ey(2);
533
Project (p);
534
}
535
536
537
void Sphere :: Project (Point<3> & p) const
538
{
539
Vec<3> v;
540
v = p - c;
541
v *= (r / v.Length());
542
p = c + v;
543
}
544
545
546
INSOLID_TYPE Sphere :: BoxInSolid (const BoxSphere<3> & box) const
547
{
548
double dist;
549
dist = Dist (box.Center(), c);
550
551
if (dist - box.Diam()/2 > r) return IS_OUTSIDE;
552
if (dist + box.Diam()/2 < r) return IS_INSIDE;
553
return DOES_INTERSECT;
554
}
555
556
double Sphere :: HesseNorm () const
557
{
558
return 2 / r;
559
}
560
561
562
Point<3> Sphere :: GetSurfacePoint () const
563
{
564
return c + Vec<3> (r, 0, 0);
565
}
566
567
568
void Sphere :: GetTriangleApproximation
569
(TriangleApproximation & tas,
570
const Box<3> & boundingbox, double facets) const
571
{
572
int i, j;
573
double lg, bg;
574
int n = int(facets) + 1;
575
576
for (j = 0; j <= n; j++)
577
for (i = 0; i <= n; i++)
578
{
579
lg = 2 * M_PI * double (i) / n;
580
bg = M_PI * (double(j) / n - 0.5);
581
582
Point<3> p(c(0) + r * cos(bg) * sin (lg),
583
c(1) + r * cos(bg) * cos (lg),
584
c(2) + r * sin(bg));
585
tas.AddPoint (p);
586
}
587
588
for (j = 0; j < n; j++)
589
for (i = 0; i < n; i++)
590
{
591
int pi = i + (n+1) * j;
592
tas.AddTriangle (TATriangle (0, pi, pi+1, pi+n+2));
593
tas.AddTriangle (TATriangle (0, pi, pi+n+2, pi+n+1));
594
}
595
}
596
597
598
599
600
601
Ellipsoid ::
602
Ellipsoid (const Point<3> & aa,
603
const Vec<3> & av1, const Vec<3> & av2, const Vec<3> & av3)
604
{
605
a = aa;
606
v1 = av1;
607
v2 = av2;
608
v3 = av3;
609
610
CalcData();
611
}
612
613
614
void Ellipsoid :: CalcData ()
615
{
616
// f = (x-a, vl)^2 / |vl|^2 + (x-a, vs)^2 / |vs|^2 -1
617
// f = sum_{i=1}^3 (x-a,v_i)^2 / |vi|^4 - 1 = sum (x-a,hv_i)^2
618
619
Vec<3> hv1, hv2, hv3;
620
double lv1 = v1.Length2 ();
621
if (lv1 < 1e-32) lv1 = 1;
622
double lv2 = v2.Length2 ();
623
if (lv2 < 1e-32) lv2 = 1;
624
double lv3 = v3.Length2 ();
625
if (lv3 < 1e-32) lv3 = 1;
626
627
rmin = sqrt (min3 (lv1, lv2, lv3));
628
629
hv1 = (1.0 / lv1) * v1;
630
hv2 = (1.0 / lv2) * v2;
631
hv3 = (1.0 / lv3) * v3;
632
633
cxx = hv1(0) * hv1(0) + hv2(0) * hv2(0) + hv3(0) * hv3(0);
634
cyy = hv1(1) * hv1(1) + hv2(1) * hv2(1) + hv3(1) * hv3(1);
635
czz = hv1(2) * hv1(2) + hv2(2) * hv2(2) + hv3(2) * hv3(2);
636
637
cxy = 2 * (hv1(0) * hv1(1) + hv2(0) * hv2(1) + hv3(0) * hv3(1));
638
cxz = 2 * (hv1(0) * hv1(2) + hv2(0) * hv2(2) + hv3(0) * hv3(2));
639
cyz = 2 * (hv1(1) * hv1(2) + hv2(1) * hv2(2) + hv3(1) * hv3(2));
640
641
Vec<3> va (a);
642
c1 = sqr(va * hv1) + sqr(va * hv2) + sqr(va * hv3) - 1;
643
644
Vec<3> v = -2 * (va * hv1) * hv1 - 2 * (va * hv2) * hv2 - 2 * (va * hv3) * hv3;
645
cx = v(0);
646
cy = v(1);
647
cz = v(2);
648
}
649
650
651
INSOLID_TYPE Ellipsoid :: BoxInSolid (const BoxSphere<3> & box) const
652
{
653
// double grad = 2.0 / rmin;
654
// double grad = 3*(box.Center()-a).Length() / (rmin*rmin*rmin);
655
656
double ggrad = 1.0 / (rmin*rmin);
657
Vec<3> g;
658
double val = CalcFunctionValue (box.Center());
659
CalcGradient (box.Center(), g);
660
double grad = g.Length();
661
662
double r = box.Diam() / 2;
663
double maxval = grad * r + ggrad * r * r;
664
665
// (*testout) << "box = " << box << ", val = " << val << ", maxval = " << maxval << endl;
666
667
if (val > maxval) return IS_OUTSIDE;
668
if (val < -maxval) return IS_INSIDE;
669
return DOES_INTERSECT;
670
}
671
672
673
double Ellipsoid :: HesseNorm () const
674
{
675
return 1.0/ (rmin * rmin);
676
}
677
678
double Ellipsoid :: MaxCurvature () const
679
{
680
const double a2 = v1.Length2();
681
const double b2 = v2.Length2();
682
const double c2 = v3.Length2();
683
684
return max3 ( sqrt(a2)/min2(b2,c2), sqrt(b2)/min2(a2,c2), sqrt(c2)/min2(a2,b2) );
685
}
686
687
Point<3> Ellipsoid :: GetSurfacePoint () const
688
{
689
return a + v1;
690
}
691
692
693
694
void Ellipsoid :: GetTriangleApproximation
695
(TriangleApproximation & tas,
696
const Box<3> & boundingbox, double facets) const
697
{
698
int i, j;
699
double lg, bg;
700
int n = int(facets) + 1;
701
702
for (j = 0; j <= n; j++)
703
for (i = 0; i <= n; i++)
704
{
705
lg = 2 * M_PI * double (i) / n;
706
bg = M_PI * (double(j) / n - 0.5);
707
708
709
Point<3> p(a +
710
sin (bg) * v1 +
711
cos (bg) * sin (lg) * v2 +
712
cos (bg) * cos (lg) * v3);
713
714
tas.AddPoint (p);
715
}
716
717
for (j = 0; j < n; j++)
718
for (i = 0; i < n; i++)
719
{
720
int pi = i + (n+1) * j;
721
tas.AddTriangle (TATriangle (0, pi, pi+1, pi+n+2));
722
tas.AddTriangle (TATriangle (0, pi, pi+n+2, pi+n+1));
723
}
724
}
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
Cylinder :: Cylinder (ARRAY<double> & coeffs)
743
{
744
SetPrimitiveData(coeffs);
745
}
746
747
Cylinder :: Cylinder (const Point<3> & aa, const Point<3> & ab, double ar)
748
{
749
a = aa;
750
b = ab;
751
vab = (b - a);
752
vab /= vab.Length();
753
r = ar;
754
755
// ( <x,x> - 2 <x,a> + <a,a>
756
// - <x,vab>^2 + 2 <x,vab> <a, vab> - <a, vab>^2
757
// - r^2) / (2r) = 0
758
759
double hv;
760
cxx = cyy = czz = 0.5 / r;
761
cxy = cxz = cyz = 0;
762
cx = - a(0) / r;
763
cy = - a(1) / r;
764
cz = - a(2) / r;
765
c1 = (a(0) * a(0) + a(1) * a(1) + a(2) * a(2)) / (2 * r);
766
hv = a(0) * vab(0) + a(1) * vab(1) + a(2) * vab(2);
767
cxx -= vab(0) * vab(0) / (2 * r);
768
cyy -= vab(1) * vab(1) / (2 * r);
769
czz -= vab(2) * vab(2) / (2 * r);
770
cxy -= vab(0) * vab(1) / r;
771
cxz -= vab(0) * vab(2) / r;
772
cyz -= vab(1) * vab(2) / r;
773
cx += vab(0) * hv / r;
774
cy += vab(1) * hv / r;
775
cz += vab(2) * hv / r;
776
c1 -= hv * hv / (2 * r);
777
c1 -= r / 2;
778
// PrintCoeff ();
779
}
780
781
782
783
784
void Cylinder :: GetPrimitiveData (const char *& classname, ARRAY<double> & coeffs) const
785
{
786
classname = "cylinder";
787
coeffs.SetSize (7);
788
coeffs.Elem(1) = a(0);
789
coeffs.Elem(2) = a(1);
790
coeffs.Elem(3) = a(2);
791
coeffs.Elem(4) = b(0);
792
coeffs.Elem(5) = b(1);
793
coeffs.Elem(6) = b(2);
794
coeffs.Elem(7) = r;
795
}
796
797
void Cylinder :: SetPrimitiveData (ARRAY<double> & coeffs)
798
{
799
a(0) = coeffs.Elem(1);
800
a(1) = coeffs.Elem(2);
801
a(2) = coeffs.Elem(3);
802
b(0) = coeffs.Elem(4);
803
b(1) = coeffs.Elem(5);
804
b(2) = coeffs.Elem(6);
805
r = coeffs.Elem(7);
806
807
808
vab = (b - a);
809
vab /= vab.Length();
810
811
812
double hv;
813
cxx = cyy = czz = 0.5 / r;
814
cxy = cxz = cyz = 0;
815
cx = - a(0) / r;
816
cy = - a(1) / r;
817
cz = - a(2) / r;
818
c1 = (a(0) * a(0) + a(1) * a(1) + a(2) * a(2)) / (2 * r);
819
hv = a(0) * vab(0) + a(1) * vab(1) + a(2) * vab(2);
820
cxx -= vab(0) * vab(0) / (2 * r);
821
cyy -= vab(1) * vab(1) / (2 * r);
822
czz -= vab(2) * vab(2) / (2 * r);
823
cxy -= vab(0) * vab(1) / r;
824
cxz -= vab(0) * vab(2) / r;
825
cyz -= vab(1) * vab(2) / r;
826
cx += vab(0) * hv / r;
827
cy += vab(1) * hv / r;
828
cz += vab(2) * hv / r;
829
c1 -= hv * hv / (2 * r);
830
c1 -= r / 2;
831
}
832
833
Primitive * Cylinder :: CreateDefault ()
834
{
835
return new Cylinder (Point<3> (0,0,0), Point<3> (1,0,0), 1);
836
}
837
838
839
840
841
Primitive * Cylinder :: Copy () const
842
{
843
return new Cylinder (a, b, r);
844
}
845
846
847
int Cylinder :: IsIdentic (const Surface & s2, int & inv, double eps) const
848
{
849
const Cylinder * cyl2 = dynamic_cast<const Cylinder*> (&s2);
850
851
if (!cyl2) return 0;
852
853
if (fabs (cyl2->r - r) > eps) return 0;
854
855
Vec<3> v1 = b - a;
856
Vec<3> v2 = cyl2->a - a;
857
858
if ( fabs (v1 * v2) < (1-eps) * v1.Length() * v2.Length()) return 0;
859
v2 = cyl2->b - a;
860
if ( fabs (v1 * v2) < (1-eps) * v1.Length() * v2.Length()) return 0;
861
862
inv = 0;
863
return 1;
864
}
865
866
867
868
void Cylinder :: Transform (Transformation<3> & trans)
869
{
870
Point<3> hp;
871
trans.Transform (a, hp);
872
a = hp;
873
trans.Transform (b, hp);
874
b = hp;
875
876
vab = (b - a);
877
vab /= vab.Length();
878
879
// ( <x,x> - 2 <x,a> + <a,a>
880
// - <x,vab>^2 + 2 <x,vab> <a, vab> - <a, vab>^2
881
// - r^2) / (2r) = 0
882
883
double hv;
884
cxx = cyy = czz = 0.5 / r;
885
cxy = cxz = cyz = 0;
886
cx = - a(0) / r;
887
cy = - a(1) / r;
888
cz = - a(2) / r;
889
c1 = (a(0) * a(0) + a(1) * a(1) + a(2) * a(2)) / (2 * r);
890
hv = a(0) * vab(0) + a(1) * vab(1) + a(2) * vab(2);
891
cxx -= vab(0) * vab(0) / (2 * r);
892
cyy -= vab(1) * vab(1) / (2 * r);
893
czz -= vab(2) * vab(2) / (2 * r);
894
cxy -= vab(0) * vab(1) / r;
895
cxz -= vab(0) * vab(2) / r;
896
cyz -= vab(1) * vab(2) / r;
897
cx += vab(0) * hv / r;
898
cy += vab(1) * hv / r;
899
cz += vab(2) * hv / r;
900
c1 -= hv * hv / (2 * r);
901
c1 -= r / 2;
902
// PrintCoeff ();
903
}
904
905
906
907
908
909
910
911
912
913
void Cylinder :: DefineTangentialPlane (const Point<3> & ap1, const Point<3> & ap2)
914
{
915
Surface::DefineTangentialPlane (ap1, ap2);
916
917
ez = Center (p1, p2) - a;
918
ez -= (ez * vab) * vab;
919
ez /= ez.Length();
920
921
ex = p2 - p1;
922
ex -= (ex * ez) * ez;
923
ex /= ex.Length();
924
925
ey = Cross (ez, ex);
926
}
927
928
929
void Cylinder :: ToPlane (const Point<3> & p,
930
Point<2> & pplane,
931
double h, int & zone) const
932
{
933
Point<3> cp1p2 = Center (p1, p2);
934
Project (cp1p2);
935
936
Point<3> ccp1p2 = a + ( (cp1p2 - a) * vab ) * vab;
937
938
Vec<3> er = cp1p2 - ccp1p2;
939
er.Normalize();
940
Vec<3> ephi = Cross (vab, er);
941
942
double co, si;
943
Point<2> p1p, p2p, pp;
944
945
co = er * (p1 - ccp1p2);
946
si = ephi * (p1 - ccp1p2);
947
p1p(0) = r * atan2 (si, co);
948
p1p(1) = vab * (p1 - ccp1p2);
949
950
co = er * (p2 - ccp1p2);
951
si = ephi * (p2 - ccp1p2);
952
p2p(0) = r * atan2 (si, co);
953
p2p(1) = vab * (p2 - ccp1p2);
954
955
co = er * (p - ccp1p2);
956
si = ephi * (p - ccp1p2);
957
958
double phi = atan2 (si, co);
959
pp(0) = r * phi;
960
pp(1) = vab * (p - ccp1p2);
961
962
zone = 0;
963
if (phi > 1.57) zone = 1;
964
if (phi < -1.57) zone = 2;
965
966
967
968
Vec<2> e2x = p2p - p1p;
969
e2x /= e2x.Length();
970
971
Vec<2> e2y (-e2x(1), e2x(0));
972
973
Vec<2> p1pp = pp - p1p;
974
975
976
pplane(0) = (p1pp * e2x) / h;
977
pplane(1) = (p1pp * e2y) / h;
978
979
/*
980
(*testout) << "p1 = " << p1 << ", p2 = " << p2 << endl;
981
(*testout) << "p = " << p << ", pp = " << pp << ", pplane = " << pplane << endl;
982
*/
983
984
/*
985
Vec<3> p1p;
986
987
p1p = p - p1;
988
989
if (p1p * ez < -1 * r)
990
{
991
zone = -1;
992
pplane(0) = 1e8;
993
pplane(1) = 1e8;
994
}
995
else
996
{
997
zone = 0;
998
p1p /= h;
999
pplane(0) = p1p * ex;
1000
pplane(1) = p1p * ey;
1001
}
1002
*/
1003
}
1004
1005
void Cylinder :: FromPlane (const Point<2> & pplane, Point<3> & p, double h) const
1006
{
1007
Point<2> pplane2 (pplane);
1008
1009
pplane2(0) *= h;
1010
pplane2(1) *= h;
1011
1012
p(0) = p1(0) + pplane2(0) * ex(0) + pplane2(1) * ey(0);
1013
p(1) = p1(1) + pplane2(0) * ex(1) + pplane2(1) * ey(1);
1014
p(2) = p1(2) + pplane2(0) * ex(2) + pplane2(1) * ey(2);
1015
Project (p);
1016
}
1017
1018
1019
void Cylinder :: Project (Point<3> & p) const
1020
{
1021
Vec<3> v;
1022
Point<3> c;
1023
1024
c = a + ((p - a) * vab) * vab;
1025
v = p - c;
1026
v *= (r / v.Length());
1027
p = c + v;
1028
}
1029
/*
1030
int Cylinder :: RootInBox (const BoxSphere<3> & box) const
1031
{
1032
double dist;
1033
dist = sqrt (2 * CalcFunctionValue(box.Center()) * r + r * r);
1034
if (fabs (dist - r) > box.Diam()/2) return 0;
1035
return 2;
1036
}
1037
*/
1038
1039
INSOLID_TYPE Cylinder :: BoxInSolid (const BoxSphere<3> & box) const
1040
{
1041
double dist;
1042
// dist = sqrt (2 * CalcFunctionValue(box.Center()) * r + r * r);
1043
1044
dist = (2 * CalcFunctionValue(box.Center()) * r + r * r);
1045
if (dist <= 0) dist = 0;
1046
else dist = sqrt (dist + 1e-16);
1047
1048
if (dist - box.Diam()/2 > r) return IS_OUTSIDE;
1049
if (dist + box.Diam()/2 < r) return IS_INSIDE;
1050
return DOES_INTERSECT;
1051
}
1052
1053
1054
double Cylinder :: HesseNorm () const
1055
{
1056
return 2 / r;
1057
}
1058
1059
Point<3> Cylinder :: GetSurfacePoint () const
1060
{
1061
Vec<3> vr;
1062
if (fabs (vab(0)) > fabs(vab(2)))
1063
vr = Vec<3> (vab(1), -vab(0), 0);
1064
else
1065
vr = Vec<3> (0, -vab(2), vab(1));
1066
1067
vr *= (r / vr.Length());
1068
return a + vr;
1069
}
1070
1071
void Cylinder :: GetTriangleApproximation
1072
(TriangleApproximation & tas,
1073
const Box<3> & boundingbox, double facets) const
1074
{
1075
int i, j;
1076
double lg, bg;
1077
int n = int(facets) + 1;
1078
1079
Vec<3> lvab = b - a;
1080
Vec<3> n1 = lvab.GetNormal();
1081
Vec<3> n2 = Cross (lvab, n1);
1082
1083
n1.Normalize();
1084
n2.Normalize();
1085
1086
1087
for (j = 0; j <= n; j++)
1088
for (i = 0; i <= n; i++)
1089
{
1090
lg = 2 * M_PI * double (i) / n;
1091
bg = double(j) / n;
1092
1093
Point<3> p = a + (bg * lvab)
1094
+ ((r * cos(lg)) * n1)
1095
+ ((r * sin(lg)) * n2);
1096
1097
tas.AddPoint (p);
1098
}
1099
1100
for (j = 0; j < n; j++)
1101
for (i = 0; i < n; i++)
1102
{
1103
int pi = i + (n+1) * j;
1104
tas.AddTriangle (TATriangle (0, pi, pi+1, pi+n+2));
1105
tas.AddTriangle (TATriangle (0, pi, pi+n+2, pi+n+1));
1106
}
1107
}
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
EllipticCylinder ::
1118
EllipticCylinder (const Point<3> & aa,
1119
const Vec<3> & avl, const Vec<3> & avs)
1120
{
1121
a = aa;
1122
if(avl.Length2() > avs.Length2())
1123
{
1124
vl = avl;
1125
vs = avs;
1126
}
1127
else
1128
{
1129
vl = avs;
1130
vs = avl;
1131
}
1132
1133
CalcData();
1134
// Print (cout);
1135
}
1136
1137
1138
void EllipticCylinder :: CalcData ()
1139
{
1140
// f = (x-a, vl)^2 / |vl|^2 + (x-a, vs)^2 / |vs|^2 -1
1141
1142
Vec<3> hvl, hvs;
1143
double lvl = vl.Length2 ();
1144
if (lvl < 1e-32) lvl = 1;
1145
double lvs = vs.Length2 ();
1146
if (lvs < 1e-32) lvs = 1;
1147
1148
hvl = (1.0 / lvl) * vl;
1149
hvs = (1.0 / lvs) * vs;
1150
1151
cxx = hvl(0) * hvl(0) + hvs(0) * hvs(0);
1152
cyy = hvl(1) * hvl(1) + hvs(1) * hvs(1);
1153
czz = hvl(2) * hvl(2) + hvs(2) * hvs(2);
1154
1155
cxy = 2 * (hvl(0) * hvl(1) + hvs(0) * hvs(1));
1156
cxz = 2 * (hvl(0) * hvl(2) + hvs(0) * hvs(2));
1157
cyz = 2 * (hvl(1) * hvl(2) + hvs(1) * hvs(2));
1158
1159
Vec<3> va (a);
1160
c1 = pow(va * hvl,2) + pow(va * hvs,2) - 1;
1161
1162
Vec<3> v = -2 * (va * hvl) * hvl - 2 * (va * hvs) * hvs;
1163
cx = v(0);
1164
cy = v(1);
1165
cz = v(2);
1166
}
1167
1168
1169
INSOLID_TYPE EllipticCylinder :: BoxInSolid (const BoxSphere<3> & box) const
1170
{
1171
double grad = 2.0 / vs.Length ();
1172
double ggrad = 1.0 / vs.Length2 ();
1173
1174
double val = CalcFunctionValue (box.Center());
1175
double r = box.Diam() / 2;
1176
double maxval = grad * r + ggrad * r * r;
1177
1178
// (*testout) << "box = " << box << ", val = " << val << ", maxval = " << maxval << endl;
1179
1180
if (val > maxval) return IS_OUTSIDE;
1181
if (val < -maxval) return IS_INSIDE;
1182
return DOES_INTERSECT;
1183
}
1184
1185
1186
double EllipticCylinder :: HesseNorm () const
1187
{
1188
return 1.0/min(vs.Length2 (),vl.Length2());
1189
}
1190
1191
double EllipticCylinder :: MaxCurvature () const
1192
{
1193
double aa = vs.Length();
1194
double bb = vl.Length();
1195
1196
return max2(bb/(aa*aa),aa/(bb*bb));
1197
}
1198
1199
double EllipticCylinder :: MaxCurvatureLoc (const Point<3> & c,
1200
double rad) const
1201
{
1202
#ifdef JOACHIMxxx
1203
cout << "max curv local" << endl;
1204
return 0.02;
1205
#endif
1206
1207
// saubere Loesung wird noch notwendig !!!
1208
double aa = vs.Length();
1209
double bb = vl.Length();
1210
return max2(bb/(aa*aa),aa/(bb*bb));
1211
}
1212
1213
1214
1215
Point<3> EllipticCylinder :: GetSurfacePoint () const
1216
{
1217
return a + vl;
1218
}
1219
1220
1221
1222
void EllipticCylinder :: GetTriangleApproximation
1223
(TriangleApproximation & tas,
1224
const Box<3> & boundingbox, double facets) const
1225
{
1226
int i, j;
1227
double lg, bg;
1228
int n = int(facets) + 1;
1229
1230
Vec<3> axis = Cross (vl, vs);
1231
1232
for (j = 0; j <= n; j++)
1233
for (i = 0; i <= n; i++)
1234
{
1235
lg = 2 * M_PI * double (i) / n;
1236
bg = double(j) / n;
1237
1238
Point<3> p = a + (bg * axis)
1239
+ cos(lg) * vl + sin(lg) * vs;
1240
1241
tas.AddPoint (p);
1242
}
1243
1244
for (j = 0; j < n; j++)
1245
for (i = 0; i < n; i++)
1246
{
1247
int pi = i + (n+1) * j;
1248
tas.AddTriangle (TATriangle (0, pi, pi+1, pi+n+2));
1249
tas.AddTriangle (TATriangle (0, pi, pi+n+2, pi+n+1));
1250
}
1251
}
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
Cone :: Cone (const Point<3> & aa, const Point<3> & ab,
1263
double ara, double arb)
1264
{
1265
a = aa;
1266
b = ab;
1267
ra = ara;
1268
rb = arb;
1269
1270
CalcData();
1271
// Print (cout);
1272
}
1273
1274
1275
Primitive * Cone :: CreateDefault ()
1276
{
1277
return new Cone (Point<3> (0,0,0), Point<3> (1,0,0), 0.5, 0.2);
1278
}
1279
1280
1281
1282
1283
void Cone :: GetPrimitiveData (const char *& classname, ARRAY<double> & coeffs) const
1284
{
1285
classname = "cone";
1286
coeffs.SetSize (8);
1287
coeffs.Elem(1) = a(0);
1288
coeffs.Elem(2) = a(1);
1289
coeffs.Elem(3) = a(2);
1290
coeffs.Elem(4) = b(0);
1291
coeffs.Elem(5) = b(1);
1292
coeffs.Elem(6) = b(2);
1293
coeffs.Elem(7) = ra;
1294
coeffs.Elem(8) = rb;
1295
}
1296
1297
void Cone :: SetPrimitiveData (ARRAY<double> & coeffs)
1298
{
1299
a(0) = coeffs.Elem(1);
1300
a(1) = coeffs.Elem(2);
1301
a(2) = coeffs.Elem(3);
1302
b(0) = coeffs.Elem(4);
1303
b(1) = coeffs.Elem(5);
1304
b(2) = coeffs.Elem(6);
1305
ra = coeffs.Elem(7);
1306
rb = coeffs.Elem(8);
1307
1308
CalcData();
1309
}
1310
1311
void Cone :: CalcData ()
1312
{
1313
1314
minr = (ra < rb) ? ra : rb;
1315
1316
vab = b - a;
1317
vabl = vab.Length();
1318
1319
Vec<3> va (a);
1320
1321
//
1322
// f = r(P)^2 - R(z(P))^2
1323
//
1324
// z(P) = t0vec * P + t0 = (P-a, b-a)/(b-a,b-a)
1325
// R(z(P)) = t1vec * P + t1 = rb * z + ra * (1-z)
1326
// r(P)^2 =||P-a||^2 - ||a-b||^2 z^2k
1327
1328
1329
t0vec = vab;
1330
t0vec /= (vabl * vabl);
1331
t0 = -(va * vab) / (vabl * vabl);
1332
1333
t1vec = t0vec;
1334
t1vec *= (rb - ra);
1335
t1 = ra + (rb - ra) * t0;
1336
1337
cxx = cyy = czz = 1;
1338
cxy = cxz = cyz = 0;
1339
1340
cxx = 1 - (vab*vab) * t0vec(0) * t0vec(0) - t1vec(0) * t1vec(0);
1341
cyy = 1 - (vab*vab) * t0vec(1) * t0vec(1) - t1vec(1) * t1vec(1);
1342
czz = 1 - (vab*vab) * t0vec(2) * t0vec(2) - t1vec(2) * t1vec(2);
1343
1344
cxy = -2 * (vab * vab) * t0vec(0) * t0vec(1) - 2 * t1vec(0) * t1vec(1);
1345
cxz = -2 * (vab * vab) * t0vec(0) * t0vec(2) - 2 * t1vec(0) * t1vec(2);
1346
cyz = -2 * (vab * vab) * t0vec(1) * t0vec(2) - 2 * t1vec(1) * t1vec(2);
1347
1348
cx = -2 * a(0) - 2 * (vab * vab) * t0 * t0vec(0) - 2 * t1 * t1vec(0);
1349
cy = -2 * a(1) - 2 * (vab * vab) * t0 * t0vec(1) - 2 * t1 * t1vec(1);
1350
cz = -2 * a(2) - 2 * (vab * vab) * t0 * t0vec(2) - 2 * t1 * t1vec(2);
1351
1352
c1 = va.Length2() - (vab * vab) * t0 * t0 - t1 * t1;
1353
1354
1355
double maxr = max2(ra,rb);
1356
cxx /= maxr; cyy /= maxr; czz /= maxr;
1357
cxy /= maxr; cxz /= maxr; cyz /= maxr;
1358
cx /= maxr; cy /= maxr; cz /= maxr;
1359
c1 /= maxr;
1360
1361
1362
// (*testout) << "t0vec = " << t0vec << " t0 = " << t0 << endl;
1363
// (*testout) << "t1vec = " << t1vec << " t1 = " << t1 << endl;
1364
// PrintCoeff (*testout);
1365
}
1366
1367
1368
INSOLID_TYPE Cone :: BoxInSolid (const BoxSphere<3> & box) const
1369
{
1370
double rp, dist;
1371
1372
Vec<3> cv(box.Center());
1373
1374
rp = cv * t1vec + t1;
1375
dist = sqrt (CalcFunctionValue(box.Center()) *max2(ra,rb) + rp * rp) - rp;
1376
1377
if (dist - box.Diam() > 0) return IS_OUTSIDE;
1378
if (dist + box.Diam() < 0) return IS_INSIDE;
1379
return DOES_INTERSECT;
1380
}
1381
1382
1383
double Cone :: HesseNorm () const
1384
{
1385
return 2 / minr;
1386
}
1387
1388
1389
double Cone :: LocH (const Point<3> & p, double x,
1390
double c, double hmax) const
1391
{
1392
//double bloch = Surface::LocH (p, x, c, hmax);
1393
Vec<3> g;
1394
CalcGradient (p, g);
1395
1396
double lam = Abs(g);
1397
double meancurv =
1398
-( 2 * g(0)*g(1)*cxy - 2 * czz * (g(0)*g(0)+g(1)*g(1))
1399
+2 * g(1)*g(2)*cyz - 2 * cxx * (g(1)*g(1)+g(2)*g(2))
1400
+2 * g(0)*g(2)*cxz - 2 * cyy * (g(0)*g(0)+g(2)*g(2))) / (3*lam*lam*lam);
1401
1402
// cout << "type = " << typeid(*this).name() << ", baseh = " << bloch << ", meancurv = " << meancurv << endl;
1403
// return bloch;
1404
1405
meancurv = fabs (meancurv);
1406
if (meancurv < 1e-20) meancurv = 1e-20;
1407
1408
// cout << "c = " << c << ", safety = " << mparam.curvaturesafety << endl;
1409
double hcurv = 1.0/(4*meancurv*mparam.curvaturesafety);
1410
1411
return min2 (hmax, hcurv);
1412
}
1413
1414
1415
Point<3> Cone :: GetSurfacePoint () const
1416
{
1417
Vec<3> vr = vab.GetNormal ();
1418
1419
vr *= (ra / vr.Length());
1420
return a + vr;
1421
}
1422
1423
1424
1425
1426
1427
void Cone :: GetTriangleApproximation
1428
(TriangleApproximation & tas,
1429
const Box<3> & boundingbox, double facets) const
1430
{
1431
int i, j;
1432
double lg, bg;
1433
int n = int(facets) + 1;
1434
1435
Vec<3> lvab = b - a;
1436
Vec<3> n1 = lvab.GetNormal();
1437
Vec<3> n2 = Cross (lvab, n1);
1438
1439
n1.Normalize();
1440
n2.Normalize();
1441
1442
1443
for (j = 0; j <= n; j++)
1444
for (i = 0; i <= n; i++)
1445
{
1446
lg = 2 * M_PI * double (i) / n;
1447
bg = double(j) / n;
1448
1449
Point<3> p = a + (bg * lvab)
1450
+ (( (ra+(rb-ra)*bg) * cos(lg)) * n1)
1451
+ (( (ra+(rb-ra)*bg) * sin(lg)) * n2);
1452
1453
tas.AddPoint (p);
1454
}
1455
1456
for (j = 0; j < n; j++)
1457
for (i = 0; i < n; i++)
1458
{
1459
int pi = i + (n+1) * j;
1460
tas.AddTriangle (TATriangle (0, pi, pi+1, pi+n+2));
1461
tas.AddTriangle (TATriangle (0, pi, pi+n+2, pi+n+1));
1462
}
1463
}
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
/// Torus
1474
/// Lorenzo Codecasa ([email protected])
1475
/// April 27th, 2005
1476
///
1477
/// begin...
1478
Torus :: Torus (const Point<3> & ac, const Vec<3> & an, double aR, double ar)
1479
{
1480
c = ac;
1481
n = an;
1482
R = aR;
1483
r = ar;
1484
}
1485
1486
void Torus :: GetPrimitiveData (const char *& classname, ARRAY<double> & coeffs) const
1487
{
1488
classname = "torus";
1489
coeffs.SetSize (8);
1490
coeffs.Elem(1) = c(0);
1491
coeffs.Elem(2) = c(1);
1492
coeffs.Elem(3) = c(2);
1493
coeffs.Elem(4) = n(0);
1494
coeffs.Elem(5) = n(1);
1495
coeffs.Elem(6) = n(2);
1496
coeffs.Elem(7) = R;
1497
coeffs.Elem(8) = r;
1498
}
1499
1500
void Torus :: SetPrimitiveData (ARRAY<double> & coeffs)
1501
{
1502
c(0) = coeffs.Elem(1);
1503
c(1) = coeffs.Elem(2);
1504
c(2) = coeffs.Elem(3);
1505
n(0) = coeffs.Elem(4);
1506
n(1) = coeffs.Elem(5);
1507
n(2) = coeffs.Elem(6);
1508
R = coeffs.Elem(7);
1509
r = coeffs.Elem(8);
1510
}
1511
1512
Primitive * Torus :: CreateDefault ()
1513
{
1514
return new Torus (Point<3> (0,0,0), Vec<3> (0,0,1), 2, 1);
1515
}
1516
1517
Primitive * Torus :: Copy () const
1518
{
1519
return new Torus (c, n, R, r);
1520
}
1521
1522
void Torus :: Transform (Transformation<3> & trans)
1523
{
1524
Point<3> hc;
1525
trans.Transform (c, hc);
1526
c = hc;
1527
1528
Vec<3> hn;
1529
trans.Transform (n, hn);
1530
n = hn;
1531
}
1532
1533
int Torus :: IsIdentic (const Surface & s2, int & inv, double eps) const
1534
{
1535
const Torus * torus2 = dynamic_cast<const Torus*> (&s2);
1536
1537
if (!torus2) return 0;
1538
1539
if (fabs (torus2->R - R) > eps) return 0;
1540
1541
if (fabs (torus2->r - r) > eps) return 0;
1542
1543
Vec<3> v2 = torus2->n - n;
1544
if ( v2 * v2 > eps ) return 0;
1545
1546
v2 = torus2->c - c;
1547
if ( v2 * v2 > eps ) return 0;
1548
1549
inv = 0;
1550
return 1;
1551
}
1552
1553
double Torus :: CalcFunctionValue (const Point<3> & point) const
1554
{
1555
Vec<3> v1 = point - c;
1556
double a1 = v1(0) * v1(0) + v1(1) * v1(1) + v1(2) * v1(2);
1557
double a2 = n(0) * v1(0) + n(1) * v1(1) + n(2) * v1(2);
1558
double a3 = a1 + R * R - r * r;
1559
double a4 = n(0) * n(0) + n(1) * n(1) + n(2) * n(2);
1560
return ( a3 * a3 -4 * R * R * ( a1 - a2 * a2 / a4 ) ) / ( R * R * R );
1561
}
1562
1563
void Torus :: CalcGradient (const Point<3> & point, Vec<3> & grad) const
1564
{
1565
Vec<3> v1 = point - c;
1566
double a1 = v1(0) * v1(0) + v1(1) * v1(1) + v1(2) * v1(2);
1567
double a2 = n(0) * v1(0) + n(1) * v1(1) + n(2) * v1(2);
1568
double a3 = a1 - R * R - r * r;
1569
double a4 = n(0) * n(0) + n(1) * n(1) + n(2) * n(2);
1570
grad(0) = ( 4 * a3 * v1(0) + 8 * R * R * a2 / a4 * n(0) ) / ( R * R * R );
1571
grad(1) = ( 4 * a3 * v1(1) + 8 * R * R * a2 / a4 * n(1) ) / ( R * R * R );
1572
grad(2) = ( 4 * a3 * v1(2) + 8 * R * R * a2 / a4 * n(2) ) / ( R * R * R );
1573
}
1574
1575
void Torus :: CalcHesse (const Point<3> & point, Mat<3> & hesse) const
1576
{
1577
Vec<3> v1 = point - c;
1578
double a1 = v1(0) * v1(0) + v1(1) * v1(1) + v1(2) * v1(2);
1579
double a3 = a1 - R * R - r * r;
1580
double a4 = n(0) * n(0) + n(1) * n(1) + n(2) * n(2);
1581
hesse(0,0) = ( 4 * a3 + 8 * (v1(0) * v1(0) + (R * n(0)) * (R * n(0)) / a4 ) ) / ( R * R * R );
1582
hesse(1,1) = ( 4 * a3 + 8 * (v1(1) * v1(1) + (R * n(1)) * (R * n(1)) / a4 ) ) / ( R * R * R );
1583
hesse(2,2) = ( 4 * a3 + 8 * (v1(2) * v1(2) + (R * n(2)) * (R * n(2)) / a4 ) ) / ( R * R * R );
1584
hesse(0,1) = hesse(1,0) = 8 * (v1(0) * v1(1) + (R * n(0)) * (R * n(1)) / a4 ) / ( R * R * R );
1585
hesse(1,2) = hesse(2,1) = 8 * (v1(1) * v1(2) + (R * n(1)) * (R * n(2)) / a4) / ( R * R * R );
1586
hesse(0,2) = hesse(2,0) = 8 * (v1(0) * v1(2) + (R * n(0)) * (R * n(2)) / a4) / ( R * R * R );
1587
}
1588
1589
double Torus :: HesseNorm () const
1590
{
1591
return ( 2 / r + 2 / ( R - r ) );
1592
}
1593
1594
Point<3> Torus :: GetSurfacePoint () const
1595
{
1596
Vec<3> vn = n.GetNormal();
1597
return c + ( R + r ) * vn.Normalize();
1598
}
1599
1600
/// void Torus :: DefineTangentialPlane (const Point<3> & ap1, const Point<3> & ap2)
1601
/// {
1602
/// }
1603
1604
/// void Torus :: ToPlane (const Point<3> & p,
1605
/// Point<2> & pplane,
1606
/// double h, int & zone) const
1607
/// {
1608
/// }
1609
1610
/// void Torus :: FromPlane (const Point<2> & pplane, Point<3> & p, double h) const
1611
/// {
1612
/// }
1613
1614
/// void Torus :: Project (Point<3> & p) const
1615
/// {
1616
/// }
1617
1618
INSOLID_TYPE Torus :: BoxInSolid (const BoxSphere<3> & box) const
1619
{
1620
Vec<3> v1 = box.Center() - c;
1621
double a1 = v1(0) * v1(0) + v1(1) * v1(1) + v1(2) * v1(2);
1622
double a2 = n(0) * v1(0) + n(1) * v1(1) + n(2) * v1(2);
1623
double a4 = n(0) * n(0) + n(1) * n(1) + n(2) * n(2);
1624
1625
double dist = sqrt( a1 + R * R - 2 * R * sqrt( a1 - a2 * a2 / a4) );
1626
1627
if (dist - box.Diam()/2 > r) return IS_OUTSIDE;
1628
if (dist + box.Diam()/2 < r) return IS_INSIDE;
1629
return DOES_INTERSECT;
1630
}
1631
1632
void Torus :: GetTriangleApproximation (TriangleApproximation & tas,
1633
const Box<3> & boundingbox, double facets) const
1634
{
1635
int i, j;
1636
double lg, bg;
1637
int N = int(facets) + 1;
1638
1639
Vec<3> lvab = n ;
1640
lvab.Normalize();
1641
1642
Vec<3> n1 = lvab.GetNormal();
1643
n1.Normalize();
1644
1645
Vec<3> n2 = Cross(lvab, n1);
1646
n2.Normalize();
1647
1648
for (j = 0; j <= N; j++)
1649
for (i = 0; i <= N; i++)
1650
{
1651
lg = 2 * M_PI * double (i) / N;
1652
bg = 2 * M_PI * double(j) / N;
1653
1654
Point<3> p = c + ( R + r * cos(lg) ) * ( cos(bg) * n1 + sin(bg) * n2 ) + r * sin(lg) * n;
1655
tas.AddPoint (p);
1656
}
1657
1658
for (j = 0; j < N; j++)
1659
for (i = 0; i < N; i++)
1660
{
1661
int pi = i + (N+1) * j;
1662
tas.AddTriangle (TATriangle (0, pi, pi+1, pi+N+2));
1663
tas.AddTriangle (TATriangle (0, pi, pi+N+2, pi+N+1));
1664
}
1665
}
1666
1667
void Torus :: Read (istream & ist)
1668
{
1669
ist >> c(0) >> c(1) >> c(2) >> n(0) >> n(1) >> n(2) >> R >> r;
1670
}
1671
1672
void Torus :: Print (ostream & ost) const
1673
{
1674
ost << c(0) << " " << c(1) << " " << c(2) << " "
1675
<< n(0) << " " << n(1) << " " << n(2) << " "
1676
<< R << " " << r << endl;
1677
}
1678
1679
/// end...
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
}
1697
1698