Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/ElmerGUI/netgen/libsrc/gprim/geomtest3d.cpp
3206 views
1
#include <mystdlib.h>
2
#include <myadt.hpp>
3
4
#include <linalg.hpp>
5
#include <gprim.hpp>
6
7
namespace netgen
8
{
9
int
10
IntersectTriangleLine (const Point<3> ** tri, const Point<3> ** line)
11
{
12
Vec3d vl(*line[0], *line[1]);
13
Vec3d vt1(*tri[0], *tri[1]);
14
Vec3d vt2(*tri[0], *tri[2]);
15
Vec3d vrs(*tri[0], *line[0]);
16
17
static DenseMatrix a(3), ainv(3);
18
static Vector rs(3), lami(3);
19
int i;
20
21
/*
22
(*testout) << "Tri-Line inters: " << endl
23
<< "tri = " << *tri[0] << ", " << *tri[1] << ", " << *tri[2] << endl
24
<< "line = " << *line[0] << ", " << *line[1] << endl;
25
*/
26
for (i = 1; i <= 3; i++)
27
{
28
a.Elem(i, 1) = -vl.X(i);
29
a.Elem(i, 2) = vt1.X(i);
30
a.Elem(i, 3) = vt2.X(i);
31
rs.Elem(i) = vrs.X(i);
32
}
33
34
double det = a.Det();
35
36
double arel = vl.Length() * vt1.Length() * vt2.Length();
37
/*
38
double amax = 0;
39
for (i = 1; i <= 9; i++)
40
if (fabs (a.Get(i)) > amax)
41
amax = fabs(a.Get(i));
42
*/
43
// new !!!!
44
if (fabs (det) <= 1e-10 * arel)
45
{
46
#ifdef DEVELOP
47
// line parallel to triangle !
48
// cout << "ERROR: IntersectTriangleLine degenerated" << endl;
49
// (*testout) << "WARNING: IntersectTriangleLine degenerated\n";
50
/*
51
(*testout) << "lin-tri intersection: " << endl
52
<< "line = " << *line[0] << " - " << *line[1] << endl
53
<< "tri = " << *tri[0] << " - " << *tri[1] << " - " << *tri[2] << endl
54
<< "lami = " << lami << endl
55
<< "pc = " << ( *line[0] + lami.Get(1) * vl ) << endl
56
<< " = " << ( *tri[0] + lami.Get(2) * vt1 + lami.Get(3) * vt2) << endl
57
<< " a = " << a << endl
58
<< " ainv = " << ainv << endl
59
<< " det(a) = " << det << endl
60
<< " rs = " << rs << endl;
61
*/
62
#endif
63
return 0;
64
}
65
66
CalcInverse (a, ainv);
67
ainv.Mult (rs, lami);
68
69
// (*testout) << "lami = " << lami << endl;
70
71
double eps = 1e-6;
72
if (
73
(lami.Get(1) >= -eps && lami.Get(1) <= 1+eps &&
74
lami.Get(2) >= -eps && lami.Get(3) >= -eps &&
75
lami.Get(2) + lami.Get(3) <= 1+eps) && !
76
(lami.Get(1) >= eps && lami.Get(1) <= 1-eps &&
77
lami.Get(2) >= eps && lami.Get(3) >= eps &&
78
lami.Get(2) + lami.Get(3) <= 1-eps) )
79
80
81
{
82
#ifdef DEVELOP
83
// cout << "WARNING: IntersectTriangleLine degenerated" << endl;
84
(*testout) << "WARNING: IntersectTriangleLine numerical inexact" << endl;
85
86
(*testout) << "lin-tri intersection: " << endl
87
<< "line = " << *line[0] << " - " << *line[1] << endl
88
<< "tri = " << *tri[0] << " - " << *tri[1] << " - " << *tri[2] << endl
89
<< "lami = " << lami << endl
90
<< "pc = " << ( *line[0] + lami.Get(1) * vl ) << endl
91
<< " = " << ( *tri[0] + lami.Get(2) * vt1 + lami.Get(3) * vt2) << endl
92
<< " a = " << a << endl
93
<< " ainv = " << ainv << endl
94
<< " det(a) = " << det << endl
95
<< " rs = " << rs << endl;
96
#endif
97
}
98
99
100
if (lami.Get(1) >= 0 && lami.Get(1) <= 1 &&
101
lami.Get(2) >= 0 && lami.Get(3) >= 0 && lami.Get(2) + lami.Get(3) <= 1)
102
{
103
104
return 1;
105
}
106
107
return 0;
108
}
109
110
111
112
113
114
int IntersectTetTriangle (const Point<3> ** tet, const Point<3> ** tri,
115
const int * tetpi, const int * tripi)
116
{
117
int i, j;
118
double diam = Dist (*tri[0], *tri[1]);
119
double epsrel = 1e-8;
120
double eps = diam * epsrel;
121
122
double eps2 = eps * eps;
123
int cnt = 0;
124
125
int tetp1 = -1, tetp2 = -1;
126
int trip1 = -1, trip2 = -1;
127
int tetp3, tetp4, trip3;
128
129
/*
130
for (i = 0; i < 4; i++)
131
loctetpi[i] = -1;
132
*/
133
134
135
if (!tetpi)
136
{
137
for (i = 0; i <= 2; i++)
138
{
139
// loctripi[i] = -1;
140
for (j = 0; j <= 3; j++)
141
{
142
if (Dist2 (*tet[j], *tri[i]) < eps2)
143
{
144
// loctripi[i] = j;
145
// loctetpi[j] = i;
146
cnt++;
147
tetp2 = tetp1;
148
tetp1 = j;
149
trip2 = trip1;
150
trip1 = i;
151
break;
152
}
153
}
154
}
155
}
156
else
157
{
158
for (i = 0; i <= 2; i++)
159
{
160
// loctripi[i] = -1;
161
for (j = 0; j <= 3; j++)
162
{
163
if (tetpi[j] == tripi[i])
164
{
165
// loctripi[i] = j;
166
// loctetpi[j] = i;
167
cnt++;
168
tetp2 = tetp1;
169
tetp1 = j;
170
trip2 = trip1;
171
trip1 = i;
172
break;
173
}
174
}
175
}
176
}
177
178
// (*testout) << "cnt = " << cnt << endl;
179
180
181
// (*testout) << "tet-trig inters, cnt = " << cnt << endl;
182
183
// cnt .. number of common points
184
switch (cnt)
185
{
186
case 0:
187
{
188
Vec3d no, n;
189
int inpi[3];
190
191
// check, if some trigpoint is in tet:
192
193
for (j = 0; j < 3; j++)
194
inpi[j] = 1;
195
196
for (i = 1; i <= 4; i++)
197
{
198
int pi1 = i % 4;
199
int pi2 = (i+1) % 4;
200
int pi3 = (i+2) % 4;
201
int pi4 = (i+3) % 4;
202
203
Vec3d v1 (*tet[pi1], *tet[pi2]);
204
Vec3d v2 (*tet[pi1], *tet[pi3]);
205
Vec3d v3 (*tet[pi1], *tet[pi4]);
206
Cross (v1, v2, n);
207
208
// n /= n.Length();
209
double nl = n.Length();
210
211
if (v3 * n > 0)
212
n *= -1;
213
214
int outeri = 1;
215
for (j = 0; j < 3; j++)
216
{
217
Vec3d v(*tet[pi1], *tri[j]);
218
if ( v * n < eps * nl)
219
outeri = 0;
220
else
221
inpi[j] = 0;
222
}
223
224
if (outeri)
225
return 0;
226
}
227
228
if (inpi[0] || inpi[1] || inpi[2])
229
{
230
return 1;
231
}
232
233
234
// check, if some tet edge intersects triangle:
235
const Point<3> * line[2], *tetf[3];
236
for (i = 0; i <= 2; i++)
237
for (j = i+1; j <= 3; j++)
238
{
239
line[0] = tet[i];
240
line[1] = tet[j];
241
242
if (IntersectTriangleLine (tri, &line[0]))
243
return 1;
244
}
245
246
// check, if triangle line intersects tet face:
247
for (i = 0; i <= 3; i++)
248
{
249
for (j = 0; j <= 2; j++)
250
tetf[j] = tet[(i+j) % 4];
251
252
for (j = 0; j <= 2; j++)
253
{
254
line[0] = tri[j];
255
line[1] = tri[(j+1) % 3];
256
257
if (IntersectTriangleLine (&tetf[0], &line[0]))
258
return 1;
259
}
260
}
261
262
263
return 0;
264
//GH break;
265
}
266
case 1:
267
{
268
trip2 = 0;
269
while (trip2 == trip1)
270
trip2++;
271
trip3 = 3 - trip1 - trip2;
272
273
tetp2 = 0;
274
while (tetp2 == tetp1)
275
tetp2++;
276
tetp3 = 0;
277
while (tetp3 == tetp1 || tetp3 == tetp2)
278
tetp3++;
279
tetp4 = 6 - tetp1 - tetp2 - tetp3;
280
281
Vec3d vtri1 = *tri[trip2] - *tri[trip1];
282
Vec3d vtri2 = *tri[trip3] - *tri[trip1];
283
Vec3d ntri;
284
Cross (vtri1, vtri2, ntri);
285
286
// tri durch tet ?
287
// fehlt noch
288
289
290
// test 3 tet-faces:
291
for (i = 1; i <= 3; i++)
292
{
293
Vec3d vtet1, vtet2;
294
switch (i)
295
{
296
case 1:
297
{
298
vtet1 = *tet[tetp2] - *tet[tetp1];
299
vtet2 = *tet[tetp3] - *tet[tetp1];
300
break;
301
}
302
case 2:
303
{
304
vtet1 = *tet[tetp3] - *tet[tetp1];
305
vtet2 = *tet[tetp4] - *tet[tetp1];
306
break;
307
}
308
case 3:
309
{
310
vtet1 = *tet[tetp4] - *tet[tetp1];
311
vtet2 = *tet[tetp2] - *tet[tetp1];
312
break;
313
}
314
}
315
316
Vec3d ntet;
317
Cross (vtet1, vtet2, ntet);
318
319
Vec3d crline = Cross (ntri, ntet);
320
321
double lcrline = crline.Length();
322
323
if (lcrline < eps * eps * eps * eps) // new change !
324
continue;
325
326
if (vtri1 * crline + vtri2 * crline < 0)
327
crline *= -1;
328
329
crline /= lcrline;
330
331
double lam1, lam2, lam3, lam4;
332
LocalCoordinates (vtri1, vtri2, crline, lam1, lam2);
333
LocalCoordinates (vtet1, vtet2, crline, lam3, lam4);
334
335
if (lam1 > -epsrel && lam2 > -epsrel &&
336
lam3 > -epsrel && lam4 > -epsrel)
337
{
338
339
/*
340
(*testout) << "lcrline = " << lcrline
341
<< " eps = " << eps << " diam = " << diam << endl;
342
343
(*testout) << "hit, cnt == 1 "
344
<< "lam1,2,3,4 = " << lam1 << ", "
345
<< lam2 << ", " << lam3 << ", " << lam4
346
<< "\n";
347
*/
348
return 1;
349
}
350
}
351
return 0;
352
//GH break;
353
}
354
case 2:
355
{
356
// common edge
357
tetp3 = 0;
358
while (tetp3 == tetp1 || tetp3 == tetp2)
359
tetp3++;
360
tetp4 = 6 - tetp1 - tetp2 - tetp3;
361
trip3 = 3 - trip1 - trip2;
362
363
// (*testout) << "trip1,2,3 = " << trip1 << ", " << trip2 << ", " << trip3 << endl;
364
// (*testout) << "tetp1,2,3,4 = " << tetp1 << ", " << tetp2
365
// << ", " << tetp3 << ", " << tetp4 << endl;
366
367
Vec3d vtri = *tri[trip3] - *tri[trip1];
368
Vec3d vtet1 = *tet[tetp3] - *tri[trip1];
369
Vec3d vtet2 = *tet[tetp4] - *tri[trip1];
370
371
Vec3d n = *tri[trip2] - *tri[trip1];
372
n /= n.Length();
373
374
vtet1 -= (n * vtet1) * n;
375
vtet2 -= (n * vtet2) * n;
376
377
378
double lam1, lam2;
379
LocalCoordinates (vtet1, vtet2, vtri, lam1, lam2);
380
381
if (lam1 < -epsrel || lam2 < -epsrel)
382
return 0;
383
else
384
{
385
/*
386
387
(*testout) << "vtet1 = " << vtet1 << endl;
388
(*testout) << "vtet2 = " << vtet2 << endl;
389
(*testout) << "vtri = " << vtri << endl;
390
(*testout) << "lam1 = " << lam1 << " lam2 = " << lam2 << endl;
391
(*testout) << (lam1 * (vtet1 * vtet1) + lam2 * (vtet1 * vtet2))
392
<< " = " << (vtet1 * vtri) << endl;
393
(*testout) << (lam1 * (vtet1 * vtet2) + lam2 * (vtet2 * vtet2))
394
<< " = " << (vtet2 * vtri) << endl;
395
396
(*testout) << "tet = ";
397
for (j = 0; j < 4; j++)
398
(*testout) << (*tet[j]) << " ";
399
(*testout) << endl;
400
(*testout) << "tri = ";
401
for (j = 0; j < 3; j++)
402
(*testout) << (*tri[j]) << " ";
403
(*testout) << endl;
404
405
(*testout) << "hit, cnt == 2" << endl;
406
*/
407
408
return 1;
409
}
410
411
break;
412
}
413
case 3:
414
{
415
// common face
416
return 0;
417
}
418
}
419
420
(*testout) << "hit, cnt = " << cnt << endl;
421
return 1;
422
}
423
424
425
426
427
428
int IntersectTetTriangleRef (const Point<3> ** tri, const int * tripi)
429
{
430
int i, j;
431
double eps = 1e-8;
432
double eps2 = eps * eps;
433
434
static Point<3> rtetp1(0, 0, 0);
435
static Point<3> rtetp2(1, 0, 0);
436
static Point<3> rtetp3(0, 1, 0);
437
static Point<3> rtetp4(0, 0, 1);
438
439
static const Point<3> * tet[] = { &rtetp1, &rtetp2, &rtetp3, &rtetp4 };
440
static int tetpi[] = { 1, 2, 3, 4 };
441
442
443
// return IntersectTetTriangle (tet, tri, tetpi, tripi);
444
445
446
int cnt = 0;
447
448
int tetp1 = -1, tetp2 = -1;
449
int trip1 = -1, trip2 = -1;
450
int tetp3, tetp4, trip3;
451
452
/*
453
if (!tetpi)
454
{
455
for (i = 0; i <= 2; i++)
456
{
457
for (j = 0; j <= 3; j++)
458
{
459
if (Dist2 (*tet[j], *tri[i]) < eps2)
460
{
461
cnt++;
462
tetp2 = tetp1;
463
tetp1 = j;
464
trip2 = trip1;
465
trip1 = i;
466
break;
467
}
468
}
469
}
470
}
471
else
472
*/
473
{
474
for (i = 0; i <= 2; i++)
475
{
476
for (j = 0; j <= 3; j++)
477
{
478
if (tetpi[j] == tripi[i])
479
{
480
cnt++;
481
tetp2 = tetp1;
482
tetp1 = j;
483
trip2 = trip1;
484
trip1 = i;
485
break;
486
}
487
}
488
}
489
}
490
491
// (*testout) << "cnt = " << cnt << endl;
492
493
494
switch (cnt)
495
{
496
case 0:
497
{
498
Vec3d no, n;
499
// int inpi[3];
500
int pside[3][4];
501
502
for (j = 0; j < 3; j++)
503
{
504
pside[j][0] = (*tri[j])(0) > -eps;
505
pside[j][1] = (*tri[j])(1) > -eps;
506
pside[j][2] = (*tri[j])(2) > -eps;
507
pside[j][3] = (*tri[j])(0) + (*tri[j])(1) + (*tri[j])(2) < 1+eps;
508
}
509
510
511
for (j = 0; j < 4; j++)
512
{
513
if (!pside[0][j] && !pside[1][j] && !pside[2][j])
514
return 0;
515
}
516
517
for (j = 0; j < 3; j++)
518
{
519
if (pside[j][0] && pside[j][1] && pside[j][2] && pside[j][3])
520
return 1;
521
}
522
523
524
const Point<3> * line[2], *tetf[3];
525
for (i = 0; i <= 2; i++)
526
for (j = i+1; j <= 3; j++)
527
{
528
line[0] = tet[i];
529
line[1] = tet[j];
530
531
if (IntersectTriangleLine (tri, &line[0]))
532
return 1;
533
}
534
535
for (i = 0; i <= 3; i++)
536
{
537
for (j = 0; j <= 2; j++)
538
tetf[j] = tet[(i+j) % 4];
539
540
for (j = 0; j <= 2; j++)
541
{
542
line[0] = tri[j];
543
line[1] = tri[(j+1) % 3];
544
545
if (IntersectTriangleLine (&tetf[0], &line[0]))
546
return 1;
547
}
548
}
549
550
551
return 0;
552
break;
553
}
554
case 1:
555
{
556
trip2 = 0;
557
if (trip2 == trip1)
558
trip2++;
559
trip3 = 3 - trip1 - trip2;
560
561
tetp2 = 0;
562
while (tetp2 == tetp1)
563
tetp2++;
564
tetp3 = 0;
565
while (tetp3 == tetp1 || tetp3 == tetp2)
566
tetp3++;
567
tetp4 = 6 - tetp1 - tetp2 - tetp3;
568
569
Vec3d vtri1 = *tri[trip2] - *tri[trip1];
570
Vec3d vtri2 = *tri[trip3] - *tri[trip1];
571
Vec3d ntri;
572
Cross (vtri1, vtri2, ntri);
573
574
// tri durch tet ?
575
576
/*
577
Vec3d vtet1(*tet[tetp1], *tet[tetp2]);
578
Vec3d vtet2(*tet[tetp1], *tet[tetp3]);
579
Vec3d vtet3(*tet[tetp1], *tet[tetp4]);
580
Vec3d sol;
581
582
SolveLinearSystem (vtet1, vtet2, vtet3, vtri1, sol);
583
if (sol.X() > 0 && sol.Y() > 0 && sol.Z() > 0)
584
return 1;
585
586
SolveLinearSystem (vtet1, vtet2, vtet3, vtri2, sol);
587
if (sol.X() > 0 && sol.Y() > 0 && sol.Z() > 0)
588
return 1;
589
*/
590
591
// test 3 tet-faces:
592
for (i = 1; i <= 3; i++)
593
{
594
Vec3d vtet1, vtet2;
595
switch (i)
596
{
597
case 1:
598
{
599
vtet1 = *tet[tetp2] - *tet[tetp1];
600
vtet2 = *tet[tetp3] - *tet[tetp1];
601
break;
602
}
603
case 2:
604
{
605
vtet1 = *tet[tetp3] - *tet[tetp1];
606
vtet2 = *tet[tetp4] - *tet[tetp1];
607
break;
608
}
609
case 3:
610
{
611
vtet1 = *tet[tetp4] - *tet[tetp1];
612
vtet2 = *tet[tetp2] - *tet[tetp1];
613
break;
614
}
615
}
616
617
Vec3d ntet;
618
Cross (vtet1, vtet2, ntet);
619
620
Vec3d crline = Cross (ntri, ntet);
621
622
double lcrline = crline.Length();
623
if (lcrline < eps * eps)
624
continue;
625
626
627
if (vtri1 * crline + vtri2 * crline < 0)
628
crline *= -1;
629
630
double lam1, lam2, lam3, lam4;
631
LocalCoordinates (vtri1, vtri2, crline, lam1, lam2);
632
LocalCoordinates (vtet1, vtet2, crline, lam3, lam4);
633
634
if (lam1 > -eps && lam2 > -eps &&
635
lam3 > -eps && lam4 > -eps)
636
{
637
// (*testout) << "hit, cnt == 1" << "\n";
638
return 1;
639
}
640
}
641
642
return 0;
643
break;
644
}
645
case 2:
646
{
647
// common edge
648
tetp3 = 0;
649
while (tetp3 == tetp1 || tetp3 == tetp2)
650
tetp3++;
651
tetp4 = 6 - tetp1 - tetp2 - tetp3;
652
trip3 = 3 - trip1 - trip2;
653
654
// (*testout) << "trip1,2,3 = " << trip1 << ", " << trip2 << ", " << trip3 << endl;
655
// (*testout) << "tetp1,2,3,4 = " << tetp1 << ", " << tetp2
656
// << ", " << tetp3 << ", " << tetp4 << endl;
657
658
Vec3d vtri = *tri[trip3] - *tri[trip1];
659
Vec3d vtet1 = *tet[tetp3] - *tri[trip1];
660
Vec3d vtet2 = *tet[tetp4] - *tri[trip1];
661
662
Vec3d n = *tri[trip2] - *tri[trip1];
663
n /= n.Length();
664
665
vtet1 -= (n * vtet1) * n;
666
vtet2 -= (n * vtet2) * n;
667
668
669
double lam1, lam2;
670
LocalCoordinates (vtet1, vtet2, vtri, lam1, lam2);
671
672
if (lam1 < -eps || lam2 < -eps)
673
return 0;
674
else
675
{
676
677
// (*testout) << "vtet1 = " << vtet1 << endl;
678
// (*testout) << "vtet2 = " << vtet2 << endl;
679
// (*testout) << "vtri = " << vtri << endl;
680
// (*testout) << "lam1 = " << lam1 << " lam2 = " << lam2 << endl;
681
682
// (*testout) << (lam1 * (vtet1 * vtet1) + lam2 * (vtet1 * vtet2))
683
// << " = " << (vtet1 * vtri) << endl;
684
// (*testout) << (lam1 * (vtet1 * vtet2) + lam2 * (vtet2 * vtet2))
685
// << " = " << (vtet2 * vtri) << endl;
686
687
// (*testout) << "tet = ";
688
// for (j = 0; j < 4; j++)
689
// (*testout) << (*tet[j]) << " ";
690
// (*testout) << endl;
691
// (*testout) << "tri = ";
692
// for (j = 0; j < 3; j++)
693
// (*testout) << (*tri[j]) << " ";
694
// (*testout) << endl;
695
696
// (*testout) << "hit, cnt == 2" << endl;
697
698
return 1;
699
}
700
701
break;
702
}
703
case 3:
704
{
705
// common face
706
return 0;
707
}
708
}
709
710
(*testout) << "hit, cnt = " << cnt << endl;
711
return 1;
712
}
713
714
715
716
717
718
719
720
721
722
723
724
int IntersectTriangleTriangle (const Point<3> ** tri1, const Point<3> ** tri2)
725
{
726
int i, j;
727
double diam = Dist (*tri1[0], *tri1[1]);
728
double epsrel = 1e-8;
729
double eps = diam * epsrel;
730
double eps2 = eps * eps;
731
732
733
734
int cnt = 0;
735
/*
736
int tri1pi[3];
737
int tri2pi[3];
738
*/
739
740
// int tri1p1 = -1;
741
/// int tri1p2 = -1;
742
// int tri2p1 = -1;
743
// int tri2p2 = -1;
744
// int tri1p3, tri2p3;
745
746
/*
747
for (i = 0; i < 3; i++)
748
tri1pi[i] = -1;
749
*/
750
for (i = 0; i <= 2; i++)
751
{
752
// tri2pi[i] = -1;
753
for (j = 0; j <= 2; j++)
754
{
755
if (Dist2 (*tri1[j], *tri2[i]) < eps2)
756
{
757
// tri2pi[i] = j;
758
// tri1pi[j] = i;
759
cnt++;
760
// tri1p2 = tri1p1;
761
// tri1p1 = j;
762
// tri2p2 = tri2p1;
763
// tri2p1 = i;
764
break;
765
}
766
}
767
}
768
769
switch (cnt)
770
{
771
case 0:
772
{
773
const Point<3> * line[2];
774
775
for (i = 0; i <= 2; i++)
776
{
777
line[0] = tri2[i];
778
line[1] = tri2[(i+1)%3];
779
780
if (IntersectTriangleLine (tri1, &line[0]))
781
{
782
(*testout) << "int1, line = " << *line[0] << " - " << *line[1] << endl;
783
return 1;
784
}
785
}
786
787
for (i = 0; i <= 2; i++)
788
{
789
line[0] = tri1[i];
790
line[1] = tri1[(i+1)%3];
791
792
if (IntersectTriangleLine (tri2, &line[0]))
793
{
794
(*testout) << "int2, line = " << *line[0] << " - " << *line[1] << endl;
795
return 1;
796
}
797
}
798
break;
799
}
800
default:
801
return 0;
802
}
803
804
return 0;
805
}
806
807
808
809
void
810
LocalCoordinates (const Vec3d & e1, const Vec3d & e2,
811
const Vec3d & v, double & lam1, double & lam2)
812
{
813
double m11 = e1 * e1;
814
double m12 = e1 * e2;
815
double m22 = e2 * e2;
816
double rs1 = v * e1;
817
double rs2 = v * e2;
818
819
double det = m11 * m22 - m12 * m12;
820
lam1 = (rs1 * m22 - rs2 * m12)/det;
821
lam2 = (m11 * rs2 - m12 * rs1)/det;
822
}
823
824
825
826
827
828
int CalcSphereCenter (const Point<3> ** pts, Point<3> & c)
829
{
830
Vec3d row1 (*pts[0], *pts[1]);
831
Vec3d row2 (*pts[0], *pts[2]);
832
Vec3d row3 (*pts[0], *pts[3]);
833
834
Vec3d rhs(0.5 * (row1*row1),
835
0.5 * (row2*row2),
836
0.5 * (row3*row3));
837
Transpose (row1, row2, row3);
838
839
Vec3d sol;
840
if (SolveLinearSystem (row1, row2, row3, rhs, sol))
841
{
842
(*testout) << "CalcSphereCenter: degenerated" << endl;
843
return 1;
844
}
845
846
c = *pts[0] + sol;
847
return 0;
848
}
849
850
851
852
853
854
int CalcTriangleCenter (const Point3d ** pts, Point3d & c)
855
{
856
static DenseMatrix a(2), inva(2);
857
static Vector rs(2), sol(2);
858
double h = Dist(*pts[0], *pts[1]);
859
860
Vec3d v1(*pts[0], *pts[1]);
861
Vec3d v2(*pts[0], *pts[2]);
862
863
rs.Elem(1) = v1 * v1;
864
rs.Elem(2) = v2 * v2;
865
866
a.Elem(1,1) = 2 * rs.Get(1);
867
a.Elem(1,2) = a.Elem(2,1) = 2 * (v1 * v2);
868
a.Elem(2,2) = 2 * rs.Get(2);
869
870
if (fabs (a.Det()) <= 1e-12 * h * h)
871
{
872
(*testout) << "CalcTriangleCenter: degenerated" << endl;
873
return 1;
874
}
875
876
CalcInverse (a, inva);
877
inva.Mult (rs, sol);
878
879
c = *pts[0];
880
v1 *= sol.Get(1);
881
v2 *= sol.Get(2);
882
883
c += v1;
884
c += v2;
885
886
return 0;
887
}
888
889
890
891
double ComputeCylinderRadius (const Point3d & p1,
892
const Point3d & p2,
893
const Point3d & p3,
894
const Point3d & p4)
895
{
896
Vec3d v12(p1, p2);
897
Vec3d v13(p1, p3);
898
Vec3d v14(p1, p4);
899
900
Vec3d n1 = Cross (v12, v13);
901
Vec3d n2 = Cross (v14, v12);
902
903
double n1l = n1.Length();
904
double n2l = n2.Length();
905
n1 /= n1l;
906
n2 /= n2l;
907
908
double v12len = v12.Length();
909
double h1 = n1l / v12len;
910
double h2 = n2l / v12len;
911
912
/*
913
(*testout) << "n1 = " << n1 << " n2 = " << n2
914
<< "h1 = " << h1 << " h2 = " << h2 << endl;
915
*/
916
return ComputeCylinderRadius (n1, n2, h1, h2);
917
}
918
919
920
921
922
/*
923
Two triangles T1 and T2 have normals n1 and n2.
924
The height over the common edge is h1, and h2.
925
*/
926
double ComputeCylinderRadius (const Vec3d & n1, const Vec3d & n2,
927
double h1, double h2)
928
{
929
Vec3d t1, t2;
930
double n11 = n1 * n1;
931
double n12 = n1 * n2;
932
double n22 = n2 * n2;
933
double det = n11 * n22 - n12 * n12;
934
935
if (fabs (det) < 1e-14 * n11 * n22)
936
return 1e20;
937
938
// a biorthogonal bases (ti * nj) = delta_ij:
939
t1 = (n22/det) * n1 + (-n12/det) * n2;
940
t2 = (-n12/det) * n1 + (n11/det) * n2;
941
942
// normalize:
943
t1 /= t1.Length();
944
t2 /= t2.Length();
945
946
/*
947
vector to center point has form
948
v = lam1 n1 + lam2 n2
949
and fulfills
950
t2 v = h1/2
951
t1 v = h2/2
952
*/
953
954
double lam1 = 0.5 * h2 / (n1 * t1);
955
double lam2 = 0.5 * h1 / (n2 * t2);
956
957
double rad = (lam1 * n1 + lam2 * n2).Length();
958
/*
959
(*testout) << "n1 = " << n1
960
<< " n2 = " << n2
961
<< " t1 = " << t1
962
<< " t2 = " << t2
963
<< " rad = " << rad << endl;
964
*/
965
return rad;
966
}
967
968
969
970
971
972
973
double MinDistLP2 (const Point2d & lp1, const Point2d & lp2, const Point2d & p)
974
{
975
Vec2d v(lp1, lp2);
976
Vec2d vlp(lp1, p);
977
978
// dist(lam) = \| vlp \|^2 - 2 lam (v1p, v) + lam^2 \| v \|^2
979
980
// lam = (v * vlp) / (v * v);
981
// if (lam < 0) lam = 0;
982
// if (lam > 1) lam = 1;
983
984
double num = v*vlp;
985
double den = v*v;
986
987
if (num <= 0)
988
return Dist2 (lp1, p);
989
990
if (num >= den)
991
return Dist2 (lp2, p);
992
993
if (den > 0)
994
{
995
return vlp.Length2() - num * num /den;
996
}
997
else
998
return vlp.Length2();
999
}
1000
1001
1002
1003
1004
double MinDistLP2 (const Point3d & lp1, const Point3d & lp2, const Point3d & p)
1005
{
1006
Vec3d v(lp1, lp2);
1007
Vec3d vlp(lp1, p);
1008
1009
// dist(lam) = \| vlp \|^2 - 2 lam (v1p, v) + lam^2 \| v \|^2
1010
1011
// lam = (v * vlp) / (v * v);
1012
// if (lam < 0) lam = 0;
1013
// if (lam > 1) lam = 1;
1014
1015
double num = v*vlp;
1016
double den = v*v;
1017
1018
if (num <= 0)
1019
return Dist2 (lp1, p);
1020
1021
if (num >= den)
1022
return Dist2 (lp2, p);
1023
1024
if (den > 0)
1025
{
1026
return vlp.Length2() - num * num /den;
1027
}
1028
else
1029
return vlp.Length2();
1030
}
1031
1032
1033
1034
double MinDistTP2 (const Point3d & tp1, const Point3d & tp2,
1035
const Point3d & tp3, const Point3d & p)
1036
{
1037
double lam1, lam2;
1038
double res;
1039
1040
LocalCoordinates (Vec3d (tp1, tp2), Vec3d (tp1, tp3),
1041
Vec3d (tp1, p), lam1, lam2);
1042
int in1 = lam1 >= 0;
1043
int in2 = lam2 >= 0;
1044
int in3 = lam1+lam2 <= 1;
1045
1046
if (in1 && in2 && in3)
1047
{
1048
Point3d pp = tp1 + lam1 * Vec3d(tp1, tp2) + lam2 * Vec3d (tp1, tp3);
1049
res = Dist2 (p, pp);
1050
}
1051
else
1052
{
1053
res = Dist2 (tp1, p);
1054
if (!in1)
1055
{
1056
double hv = MinDistLP2 (tp1, tp3, p);
1057
if (hv < res) res = hv;
1058
}
1059
if (!in2)
1060
{
1061
double hv = MinDistLP2 (tp1, tp2, p);
1062
if (hv < res) res = hv;
1063
}
1064
if (!in3)
1065
{
1066
double hv = MinDistLP2 (tp2, tp3, p);
1067
if (hv < res) res = hv;
1068
}
1069
/*
1070
double d1 = MinDistLP2 (tp1, tp2, p);
1071
double d2 = MinDistLP2 (tp1, tp3, p);
1072
double d3 = MinDistLP2 (tp2, tp3, p);
1073
res = min3 (d1, d2, d3);
1074
*/
1075
}
1076
1077
return res;
1078
1079
Vec3d pp1(tp1, p);
1080
Vec3d v1(tp1, tp2), v2(tp1, tp3);
1081
1082
double c = pp1.Length2();
1083
double cx = -2 * (pp1 * v1);
1084
double cy = -2 * (pp1 * v2);
1085
double cxx = v1.Length2();
1086
double cxy = 2 * (v1 * v2);
1087
double cyy = v2.Length2();
1088
1089
QuadraticPolynomial2V pol (-c, -cx, -cy, -cxx, -cxy, -cyy);
1090
double res2 = - pol.MaxUnitTriangle ();
1091
1092
if (fabs (res - res2) > 1e-8)
1093
cout << "res and res2 differ: " << res << " != " << res2 << endl;
1094
return res2;
1095
}
1096
1097
1098
// 0 checks !!!
1099
double MinDistLL2 (const Point3d & l1p1, const Point3d & l1p2,
1100
const Point3d & l2p1, const Point3d & l2p2)
1101
{
1102
// dist(lam1,lam2) = \| l2p1+lam2v2 - (l1p1+lam1 v1) \|
1103
// min !
1104
1105
Vec3d l1l2 (l1p1, l2p1);
1106
Vec3d v1 (l1p1, l1p2);
1107
Vec3d v2 (l2p1, l2p2);
1108
1109
double a11, a12, a22, rs1, rs2;
1110
double lam1, lam2, det;
1111
1112
a11 = v1*v1;
1113
a12 = -(v1*v2);
1114
a22 = v2*v2;
1115
rs1 = l1l2 * v1;
1116
rs2 = - (l1l2 * v2);
1117
1118
det = a11 * a22 - a12 * a12;
1119
if (det < 1e-14 * a11 * a22)
1120
det = 1e-14 * a11 * a22; // regularization should be stable
1121
1122
if (det < 1e-20)
1123
det = 1e-20;
1124
1125
1126
lam1 = (a22 * rs1 - a12 * rs2) / det;
1127
lam2 = (-a12 * rs1 + a11 * rs2) / det;
1128
1129
if (lam1 >= 0 && lam2 >= 0 && lam1 <= 1 && lam2 <= 1)
1130
{
1131
Vec3d v = l1l2 + (-lam1) * v1 + lam2 * v2;
1132
return v.Length2();
1133
}
1134
1135
double minv, hv;
1136
minv = MinDistLP2 (l1p1, l1p2, l2p1);
1137
hv = MinDistLP2 (l1p1, l1p2, l2p2);
1138
if (hv < minv) minv = hv;
1139
1140
hv = MinDistLP2 (l2p1, l2p2, l1p1);
1141
if (hv < minv) minv = hv;
1142
hv = MinDistLP2 (l2p1, l2p2, l1p2);
1143
if (hv < minv) minv = hv;
1144
1145
return minv;
1146
}
1147
1148
}
1149
1150
1151
1152