Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/ElmerGUI/netgen/libsrc/csg/specpoin.cpp
3206 views
1
#include <mystdlib.h>
2
#include <meshing.hpp>
3
#include <csg.hpp>
4
5
6
/*
7
Special Point calculation uses the global Flags:
8
9
relydegtest when to rely on degeneration ?
10
calccp calculate points of intersection ?
11
cpeps1 eps for degenerated poi
12
calcep calculate points of extreme coordinates ?
13
epeps1 eps for degenerated edge
14
epeps2 eps for axis parallel pec
15
epspointdist eps for distance of special points
16
*/
17
18
19
#undef DEVELOP
20
//#define DEVELOP
21
22
23
namespace netgen
24
{
25
ARRAY<Box<3> > boxes;
26
27
28
void ProjectToEdge (const Surface * f1, const Surface * f2, Point<3> & hp);
29
30
31
32
SpecialPoint :: SpecialPoint (const SpecialPoint & sp)
33
{
34
p = sp.p;
35
v = sp.v;
36
s1 = sp.s1;
37
s2 = sp.s2;
38
s1_orig = sp.s1_orig;
39
s2_orig = sp.s2_orig;
40
layer = sp.layer;
41
unconditional = sp.unconditional;
42
}
43
44
SpecialPoint & SpecialPoint :: operator= (const SpecialPoint & sp)
45
{
46
p = sp.p;
47
v = sp.v;
48
s1 = sp.s1;
49
s2 = sp.s2;
50
s1_orig = sp.s1_orig;
51
s2_orig = sp.s2_orig;
52
layer = sp.layer;
53
unconditional = sp.unconditional;
54
return *this;
55
}
56
57
58
void SpecialPoint :: Print (ostream & str) const
59
{
60
str << "p = " << p << " v = " << v
61
<< " s1/s2 = " << s1 << "/" << s2;
62
str << " layer = " << layer
63
<< " unconditional = " << unconditional
64
<< endl;
65
}
66
67
68
static ARRAY<int> numprim_hist;
69
70
SpecialPointCalculation :: SpecialPointCalculation ()
71
{
72
ideps = 1e-9;
73
}
74
75
void SpecialPointCalculation ::
76
CalcSpecialPoints (const CSGeometry & ageometry,
77
ARRAY<MeshPoint> & apoints)
78
{
79
geometry = &ageometry;
80
points = &apoints;
81
82
size = geometry->MaxSize();
83
(*testout) << "Find Special Points" << endl;
84
(*testout) << "maxsize = " << size << endl;
85
86
cpeps1 = 1e-6;
87
epeps1 = 1e-3;
88
epeps2 = 1e-6;
89
90
epspointdist2 = sqr (size * 1e-8);
91
relydegtest = size * 1e-4;
92
93
94
BoxSphere<3> box (Point<3> (-size, -size, -size),
95
Point<3> ( size, size, size));
96
97
box.CalcDiamCenter();
98
PrintMessage (3, "main-solids: ", geometry->GetNTopLevelObjects());
99
100
numprim_hist.SetSize (geometry->GetNSurf()+1);
101
numprim_hist = 0;
102
103
for (int i = 0; i < geometry->GetNTopLevelObjects(); i++)
104
{
105
const TopLevelObject * tlo = geometry->GetTopLevelObject(i);
106
107
(*testout) << "tlo " << i << ":" << endl
108
<< *tlo->GetSolid() << endl;
109
110
if (tlo->GetSolid())
111
{
112
ARRAY<Point<3> > hpts;
113
tlo->GetSolid()->CalcOnePrimitiveSpecialPoints (box, hpts);
114
// if (hpts.Size())
115
// cout << "oneprimitivespecialpoints = " << hpts << endl;
116
for (int j = 0; j < hpts.Size(); j++)
117
AddPoint (hpts[j], tlo->GetLayer());
118
}
119
120
CalcSpecialPointsRec (tlo->GetSolid(), tlo->GetLayer(),
121
box, 1, 1, 1);
122
}
123
124
125
geometry->DeleteIdentPoints();
126
for (int i = 0; i < geometry->GetNIdentifications(); i++)
127
{
128
CloseSurfaceIdentification * ident =
129
dynamic_cast<CloseSurfaceIdentification * >(geometry->identifications[i]);
130
131
if(!ident || !ident->IsSkewIdentification())
132
continue;
133
134
for(int j=0; j<points->Size(); j++)
135
{
136
if(fabs(ident->GetSurface1().CalcFunctionValue((*points)[j])) < 1e-15)
137
{
138
Point<3> auxpoint = (*points)[j];
139
ident->GetSurface2().SkewProject(auxpoint,ident->GetDirection());
140
geometry->AddIdentPoint(auxpoint);
141
geometry->AddIdentPoint((*points)[j]);
142
AddPoint (auxpoint,1);
143
144
#ifdef DEVELOP
145
(*testout) << "added identpoint " << auxpoint << "; proj. of "
146
<< (*points)[j] << endl;
147
#endif
148
break;
149
}
150
}
151
}
152
153
154
// add user point:
155
for (int i = 0; i < geometry->GetNUserPoints(); i++)
156
AddPoint (geometry->GetUserPoint(i), 1);
157
158
159
PrintMessage (3, "Found points ", apoints.Size());
160
161
for (int i = 0; i < boxesinlevel.Size(); i++)
162
(*testout) << "level " << i << " has "
163
<< boxesinlevel[i] << " boxes" << endl;
164
(*testout) << "numprim_histogramm = " << endl << numprim_hist << endl;
165
}
166
167
168
169
void SpecialPointCalculation ::
170
CalcSpecialPointsRec (const Solid * sol, int layer,
171
const BoxSphere<3> & box,
172
int level, bool calccp, bool calcep)
173
{
174
// boxes.Append (box);
175
176
#ifdef DEVELOP
177
*testout << "lev " << level << ", box = " << box << endl;
178
*testout << "calccp = " << calccp << ", calcep = " << calcep << endl;
179
*testout << "locsol = " << *sol << endl;
180
#endif
181
182
if (multithread.terminate)
183
{
184
*testout << "boxes = " << boxes << endl;
185
*testout << "boxesinlevel = " << boxesinlevel << endl;
186
throw NgException ("Meshing stopped");
187
}
188
189
190
if (!sol) return;
191
192
if (level >= 100)
193
{
194
MyStr err =
195
MyStr("Problems in CalcSpecialPoints\nPoint: ") + MyStr (box.Center());
196
throw NgException (err.c_str());
197
}
198
199
200
bool decision;
201
bool possiblecrossp, possibleexp; // possible cross or extremalpoint
202
bool surecrossp = 0, sureexp = 0; // sure ...
203
204
static ARRAY<int> locsurf; // attention: array is static
205
206
static int cntbox = 0;
207
cntbox++;
208
209
if (level <= boxesinlevel.Size())
210
boxesinlevel.Elem(level)++;
211
else
212
boxesinlevel.Append (1);
213
214
/*
215
numprim = sol -> NumPrimitives();
216
sol -> GetSurfaceIndices (locsurf);
217
*/
218
219
geometry -> GetIndependentSurfaceIndices (sol, box, locsurf);
220
int numprim = locsurf.Size();
221
222
#ifdef DEVELOP
223
(*testout) << "numprim = " << numprim << endl;
224
#endif
225
226
numprim_hist[numprim]++;
227
228
Point<3> p = box.Center();
229
230
231
// explicit solution for planes only and at most one quadratic
232
if (numprim <= 5)
233
{
234
int nplane = 0, nquad = 0, quadi = -1;
235
const QuadraticSurface *qsurf = 0, *qsurfi;
236
237
for (int i = 0; i < numprim; i++)
238
{
239
qsurfi = dynamic_cast<const QuadraticSurface*>
240
(geometry->GetSurface(locsurf[i]));
241
242
if (qsurfi) nquad++;
243
if (dynamic_cast<const Plane*> (qsurfi))
244
nplane++;
245
else
246
{
247
quadi = i;
248
qsurf = qsurfi;
249
}
250
}
251
252
/*
253
if (nquad == numprim && nplane == numprim-2)
254
return;
255
*/
256
257
#ifdef DEVELOP
258
(*testout) << "nquad " << nquad << " nplane " << nplane << endl;
259
#endif
260
261
if (nquad == numprim && nplane >= numprim-1)
262
{
263
ARRAY<Point<3> > pts;
264
ARRAY<int> surfids;
265
266
for (int k1 = 0; k1 < numprim - 2; k1++)
267
for (int k2 = k1 + 1; k2 < numprim - 1; k2++)
268
for (int k3 = k2 + 1; k3 < numprim; k3++)
269
if (k1 != quadi && k2 != quadi && k3 != quadi)
270
{
271
ComputeCrossPoints (dynamic_cast<const Plane*> (geometry->GetSurface(locsurf[k1])),
272
dynamic_cast<const Plane*> (geometry->GetSurface(locsurf[k2])),
273
dynamic_cast<const Plane*> (geometry->GetSurface(locsurf[k3])),
274
pts);
275
276
for (int j = 0; j < pts.Size(); j++)
277
if (Dist (pts[j], box.Center()) < box.Diam()/2)
278
{
279
Solid * tansol;
280
sol -> TangentialSolid (pts[j], tansol, surfids, 1e-9*size);
281
282
if(!tansol)
283
continue;
284
285
bool ok1 = false, ok2 = false, ok3 = false;
286
int rep1 = geometry->GetSurfaceClassRepresentant(locsurf[k1]);
287
int rep2 = geometry->GetSurfaceClassRepresentant(locsurf[k2]);
288
int rep3 = geometry->GetSurfaceClassRepresentant(locsurf[k3]);
289
for(int jj=0; jj<surfids.Size(); jj++)
290
{
291
int actrep = geometry->GetSurfaceClassRepresentant(surfids[jj]);
292
if(actrep == rep1) ok1 = true;
293
if(actrep == rep2) ok2 = true;
294
if(actrep == rep3) ok3 = true;
295
}
296
297
298
if (tansol && ok1 && ok2 && ok3)
299
// if (sol -> IsIn (pts[j], 1e-6*size) && !sol->IsStrictIn (pts[j], 1e-6*size))
300
{
301
if (AddPoint (pts[j], layer))
302
(*testout) << "cross point found, 1: " << pts[j] << endl;
303
}
304
delete tansol;
305
}
306
}
307
308
309
if (qsurf)
310
{
311
for (int k1 = 0; k1 < numprim - 1; k1++)
312
for (int k2 = k1 + 1; k2 < numprim; k2++)
313
if (k1 != quadi && k2 != quadi)
314
{
315
ComputeCrossPoints (dynamic_cast<const Plane*> (geometry->GetSurface(locsurf[k1])),
316
dynamic_cast<const Plane*> (geometry->GetSurface(locsurf[k2])),
317
qsurf, pts);
318
//(*testout) << "checking pot. crosspoints: " << pts << endl;
319
320
for (int j = 0; j < pts.Size(); j++)
321
if (Dist (pts[j], box.Center()) < box.Diam()/2)
322
{
323
Solid * tansol;
324
sol -> TangentialSolid (pts[j], tansol, surfids, 1e-9*size);
325
326
if(!tansol)
327
continue;
328
329
bool ok1 = false, ok2 = false, ok3 = true;//false;
330
int rep1 = geometry->GetSurfaceClassRepresentant(locsurf[k1]);
331
int rep2 = geometry->GetSurfaceClassRepresentant(locsurf[k2]);
332
//int rep3 = geometry->GetSurfaceClassRepresentant(quadi);
333
for(int jj=0; jj<surfids.Size(); jj++)
334
{
335
int actrep = geometry->GetSurfaceClassRepresentant(surfids[jj]);
336
if(actrep == rep1) ok1 = true;
337
if(actrep == rep2) ok2 = true;
338
//if(actrep == rep3) ok3 = true;
339
}
340
341
342
if (tansol && ok1 && ok2 && ok3)
343
//if (sol -> IsIn (pts[j], 1e-6*size) && !sol->IsStrictIn (pts[j], 1e-6*size) )
344
{
345
if (AddPoint (pts[j], layer))
346
(*testout) << "cross point found, 2: " << pts[j] << endl;
347
}
348
delete tansol;
349
}
350
}
351
352
353
for (int k1 = 0; k1 < numprim; k1++)
354
if (k1 != quadi)
355
{
356
ComputeExtremalPoints (dynamic_cast<const Plane*> (geometry->GetSurface(locsurf[k1])),
357
qsurf, pts);
358
359
for (int j = 0; j < pts.Size(); j++)
360
if (Dist (pts[j], box.Center()) < box.Diam()/2)
361
{
362
Solid * tansol;
363
sol -> TangentialSolid (pts[j], tansol, surfids, 1e-9*size);
364
if (tansol)
365
// sol -> IsIn (pts[j], 1e-6*size) && !sol->IsStrictIn (pts[j], 1e-6*size) )
366
{
367
if (AddPoint (pts[j], layer))
368
(*testout) << "extremal point found, 1: " << pts[j] << endl;
369
}
370
delete tansol;
371
}
372
}
373
}
374
375
return;
376
}
377
}
378
379
380
381
possiblecrossp = (numprim >= 3) && calccp;
382
surecrossp = 0;
383
384
if (possiblecrossp && (locsurf.Size() <= 5 || level > 50))
385
{
386
decision = 1;
387
surecrossp = 0;
388
389
for (int k1 = 1; k1 <= locsurf.Size() - 2; k1++)
390
for (int k2 = k1 + 1; k2 <= locsurf.Size() - 1; k2++)
391
for (int k3 = k2 + 1; k3 <= locsurf.Size(); k3++)
392
{
393
int nc, deg;
394
nc = CrossPointNewtonConvergence
395
(geometry->GetSurface(locsurf.Get(k1)),
396
geometry->GetSurface(locsurf.Get(k2)),
397
geometry->GetSurface(locsurf.Get(k3)), box );
398
399
deg = CrossPointDegenerated
400
(geometry->GetSurface(locsurf.Get(k1)),
401
geometry->GetSurface(locsurf.Get(k2)),
402
geometry->GetSurface(locsurf.Get(k3)), box );
403
404
if (!nc && !deg) decision = 0;
405
if (nc) surecrossp = 1;
406
}
407
408
#ifdef DEVELOP
409
(*testout) << "dec = " << decision << ", surcp = " << surecrossp << endl;
410
#endif
411
412
if (decision && surecrossp)
413
{
414
for (int k1 = 1; k1 <= locsurf.Size() - 2; k1++)
415
for (int k2 = k1 + 1; k2 <= locsurf.Size() - 1; k2++)
416
for (int k3 = k2 + 1; k3 <= locsurf.Size(); k3++)
417
{
418
if (CrossPointNewtonConvergence
419
(geometry->GetSurface(locsurf.Get(k1)),
420
geometry->GetSurface(locsurf.Get(k2)),
421
geometry->GetSurface(locsurf.Get(k3)), box ) )
422
{
423
424
Point<3> pp = p;
425
CrossPointNewton
426
(geometry->GetSurface(locsurf.Get(k1)),
427
geometry->GetSurface(locsurf.Get(k2)),
428
geometry->GetSurface(locsurf.Get(k3)), pp);
429
430
BoxSphere<3> hbox (pp, pp);
431
hbox.Increase (1e-8*size);
432
433
if (pp(0) > box.PMin()(0) - 1e-5*size &&
434
pp(0) < box.PMax()(0) + 1e-5*size &&
435
pp(1) > box.PMin()(1) - 1e-5*size &&
436
pp(1) < box.PMax()(1) + 1e-5*size &&
437
pp(2) > box.PMin()(2) - 1e-5*size &&
438
pp(2) < box.PMax()(2) + 1e-5*size &&
439
sol -> IsIn (pp, 1e-6*size) && !sol->IsStrictIn (pp, 1e-6*size) &&
440
!CrossPointDegenerated
441
(geometry->GetSurface(locsurf.Get(k1)),
442
geometry->GetSurface(locsurf.Get(k2)),
443
geometry->GetSurface(locsurf.Get(k3)), hbox ))
444
445
{
446
// AddCrossPoint (locsurf, sol, p);
447
BoxSphere<3> boxp (pp, pp);
448
boxp.Increase (1e-3*size);
449
boxp.CalcDiamCenter();
450
ARRAY<int> locsurf2;
451
452
geometry -> GetIndependentSurfaceIndices (sol, boxp, locsurf2);
453
454
bool found1 = false, found2 = false, found3 = false;
455
for (int i = 0; i < locsurf2.Size(); i++)
456
{
457
if (locsurf2[i] == locsurf.Get(k1)) found1 = true;
458
if (locsurf2[i] == locsurf.Get(k2)) found2 = true;
459
if (locsurf2[i] == locsurf.Get(k3)) found3 = true;
460
}
461
462
if (found1 && found2 && found3)
463
if (AddPoint (pp, layer))
464
{
465
(*testout) << "Crosspoint found: " << pp
466
<< " diam = " << box.Diam()
467
<< ", surfs: "
468
<< locsurf.Get(k1) << ","
469
<< locsurf.Get(k2) << ","
470
<< locsurf.Get(k3) << endl;
471
}
472
}
473
}
474
}
475
}
476
477
if (decision)
478
possiblecrossp = 0;
479
}
480
481
482
possibleexp = (numprim >= 2) && calcep;
483
484
// (*testout) << "l = " << level << "locsize = " << locsurf.Size() << " possexp = " << possibleexp << "\n";
485
if (possibleexp && (numprim <= 5 || level >= 50))
486
{
487
decision = 1;
488
sureexp = 0;
489
490
/*
491
(*testout) << "extremal surfs = ";
492
for (int k5 = 0; k5 < locsurf.Size(); k5++)
493
(*testout) << typeid(*geometry->GetSurface(locsurf[k5])).name() << " ";
494
(*testout) << "\n";
495
*/
496
497
for (int k1 = 0; k1 < locsurf.Size() - 1; k1++)
498
for (int k2 = k1+1; k2 < locsurf.Size(); k2++)
499
{
500
const Surface * surf1 = geometry->GetSurface(locsurf[k1]);
501
const Surface * surf2 = geometry->GetSurface(locsurf[k2]);
502
/*
503
(*testout) << "edgecheck, types = " << typeid(*surf1).name() << ", " << typeid(*surf2).name()
504
<< "edge-newton-conv = " << EdgeNewtonConvergence (surf1, surf2, p)
505
<< "edge-deg = " << EdgeDegenerated (surf1, surf2, box)
506
<< "\n";
507
*/
508
509
if (EdgeNewtonConvergence (surf1, surf2, p) )
510
sureexp = 1;
511
else
512
{
513
if (!EdgeDegenerated (surf1, surf2, box))
514
decision = 0;
515
}
516
}
517
518
// (*testout) << "l = " << level << " dec/sureexp = " << decision << sureexp << endl;
519
520
if (decision && sureexp)
521
{
522
for (int k1 = 0; k1 < locsurf.Size() - 1; k1++)
523
for (int k2 = k1+1; k2 < locsurf.Size(); k2++)
524
{
525
const Surface * surf1 = geometry->GetSurface(locsurf[k1]);
526
const Surface * surf2 = geometry->GetSurface(locsurf[k2]);
527
528
if (EdgeNewtonConvergence (surf1, surf2, p))
529
{
530
EdgeNewton (surf1, surf2, p);
531
532
Point<3> pp;
533
if (IsEdgeExtremalPoint (surf1, surf2, p, pp, box.Diam()/2))
534
{
535
(*testout) << "extremalpoint (nearly) found:" << pp << endl;
536
537
if (Dist (pp, box.Center()) < box.Diam()/2 &&
538
sol -> IsIn (pp, 1e-6*size) && !sol->IsStrictIn (pp, 1e-6*size) )
539
{
540
if (AddPoint (pp, layer))
541
(*testout) << "Extremal point found: " << pp << endl;//"(eps="<<1e-9*size<<")"<< endl;
542
}
543
}
544
}
545
}
546
}
547
if (decision)
548
possibleexp = 0;
549
}
550
551
552
// (*testout) << "l = " << level << " poss cp/ep sure exp = " << possiblecrossp << " " << possibleexp << " " << sureexp << "\n";
553
if (possiblecrossp || possibleexp)
554
{
555
BoxSphere<3> sbox;
556
for (int i = 0; i < 8; i++)
557
{
558
box.GetSubBox (i, sbox);
559
sbox.Increase (1e-4 * sbox.Diam());
560
561
Solid * redsol = sol -> GetReducedSolid (sbox);
562
563
if (redsol)
564
{
565
CalcSpecialPointsRec (redsol, layer, sbox, level+1, calccp, calcep);
566
delete redsol;
567
}
568
}
569
}
570
}
571
572
573
574
575
576
/******* Tests for Point of intersection **********************/
577
578
579
580
bool SpecialPointCalculation ::
581
CrossPointNewtonConvergence (const Surface * f1,
582
const Surface * f2,
583
const Surface * f3,
584
const BoxSphere<3> & box)
585
{
586
Vec<3> grad, rs, x;
587
Mat<3> jacobi, inv;
588
Point<3> p = box.Center();
589
590
f1->CalcGradient (p, grad);
591
jacobi(0,0) = grad(0);
592
jacobi(0,1) = grad(1);
593
jacobi(0,2) = grad(2);
594
595
f2->CalcGradient (p, grad);
596
jacobi(1,0) = grad(0);
597
jacobi(1,1) = grad(1);
598
jacobi(1,2) = grad(2);
599
600
f3->CalcGradient (p, grad);
601
jacobi(2,0) = grad(0);
602
jacobi(2,1) = grad(1);
603
jacobi(2,2) = grad(2);
604
605
if (fabs (Det (jacobi)) > 1e-8)
606
{
607
double gamma = f1 -> HesseNorm() + f2 -> HesseNorm() + f3 -> HesseNorm();
608
if (gamma == 0.0) return 1;
609
610
CalcInverse (jacobi, inv);
611
612
rs(0) = f1->CalcFunctionValue (p);
613
rs(1) = f2->CalcFunctionValue (p);
614
rs(2) = f3->CalcFunctionValue (p);
615
616
x = inv * rs;
617
618
double beta = 0;
619
for (int i = 0; i < 3; i++)
620
{
621
double sum = 0;
622
for (int j = 0; j < 3; j++)
623
sum += fabs (inv(i,j));
624
if (sum > beta) beta = sum;
625
}
626
double eta = Abs (x);
627
628
629
#ifdef DEVELOP
630
*testout << "check Newton: " << "beta = " << beta << ", gamma = " << gamma << ", eta = " << eta << endl;
631
double rad = 1.0 / (beta * gamma);
632
*testout << "rad = " << rad << endl;
633
#endif
634
635
return (beta * gamma * eta < 0.1) && (2 > box.Diam()*beta*gamma);
636
}
637
return 0;
638
639
}
640
641
642
643
644
bool SpecialPointCalculation ::
645
CrossPointDegenerated (const Surface * f1,
646
const Surface * f2,
647
const Surface * f3,
648
const BoxSphere<3> & box) const
649
{
650
Mat<3> mat;
651
Vec<3> g1, g2, g3;
652
double normprod;
653
654
if (box.Diam() > relydegtest) return 0;
655
656
f1->CalcGradient (box.Center(), g1);
657
normprod = Abs2 (g1);
658
659
f2->CalcGradient (box.Center(), g2);
660
normprod *= Abs2 (g2);
661
662
f3->CalcGradient (box.Center(), g3);
663
normprod *= Abs2 (g3);
664
665
for (int i = 0; i < 3; i++)
666
{
667
mat(i,0) = g1(i);
668
mat(i,1) = g2(i);
669
mat(i,2) = g3(i);
670
}
671
672
return sqr (Det (mat)) < sqr(cpeps1) * normprod;
673
}
674
675
676
677
678
679
void SpecialPointCalculation :: CrossPointNewton (const Surface * f1,
680
const Surface * f2,
681
const Surface * f3, Point<3> & p)
682
{
683
Vec<3> g1, g2, g3;
684
Vec<3> rs, sol;
685
Mat<3> mat;
686
687
int i = 10;
688
while (i > 0)
689
{
690
i--;
691
rs(0) = f1->CalcFunctionValue (p);
692
rs(1) = f2->CalcFunctionValue (p);
693
rs(2) = f3->CalcFunctionValue (p);
694
695
f1->CalcGradient (p, g1);
696
f2->CalcGradient (p, g2);
697
f3->CalcGradient (p, g3);
698
699
for (int j = 0; j < 3; j++)
700
{
701
mat(0, j) = g1(j);
702
mat(1, j) = g2(j);
703
mat(2, j) = g3(j);
704
}
705
mat.Solve (rs, sol);
706
if (sol.Length2() < 1e-24 && i > 1) i = 1;
707
708
#ifdef DEVELOP
709
*testout << "CrossPointNewton, err = " << sol.Length2() << endl;
710
#endif
711
p -= sol;
712
}
713
}
714
715
716
717
718
/******* Tests for Point on edges **********************/
719
720
721
722
723
bool SpecialPointCalculation ::
724
EdgeNewtonConvergence (const Surface * f1, const Surface * f2,
725
const Point<3> & p)
726
{
727
Vec<3> g1, g2, sol;
728
Vec<2> vrs;
729
Mat<2,3> mat;
730
Mat<3,2> inv;
731
732
f1->CalcGradient (p, g1);
733
f2->CalcGradient (p, g2);
734
735
if ( sqr(g1 * g2) < (1 - 1e-8) * Abs2 (g1) * Abs2 (g2))
736
{
737
double gamma = f1 -> HesseNorm() + f2 -> HesseNorm();
738
if (gamma < 1e-32) return 1;
739
gamma = sqr (gamma);
740
741
for (int i = 0; i < 3; i++)
742
{
743
mat(0,i) = g1(i);
744
mat(1,i) = g2(i);
745
}
746
747
CalcInverse (mat, inv);
748
749
vrs(0) = f1->CalcFunctionValue (p);
750
vrs(1) = f2->CalcFunctionValue (p);
751
sol = inv * vrs;
752
753
double beta = 0;
754
for (int i = 0; i < 3; i++)
755
for (int j = 0; j < 2; j++)
756
beta += inv(i,j) * inv(i,j);
757
// beta = sqrt (beta);
758
759
double eta = Abs2 (sol);
760
761
// alpha = beta * gamma * eta;
762
return (beta * gamma * eta < 0.01);
763
}
764
return 0;
765
}
766
767
768
769
770
bool SpecialPointCalculation ::
771
EdgeDegenerated (const Surface * f1,
772
const Surface * f2,
773
const BoxSphere<3> & box) const
774
{
775
// perform newton steps. normals parallel ?
776
// if not decideable: return 0
777
778
Point<3> p = box.Center();
779
Vec<3> g1, g2, sol;
780
Vec<2> vrs;
781
Mat<2,3> mat;
782
783
int i = 20;
784
while (i > 0)
785
{
786
if (Dist2 (p, box.Center()) > sqr(box.Diam()))
787
return 0;
788
789
i--;
790
vrs(0) = f1->CalcFunctionValue (p);
791
vrs(1) = f2->CalcFunctionValue (p);
792
793
f1->CalcGradient (p, g1);
794
f2->CalcGradient (p, g2);
795
796
if ( sqr (g1 * g2) > (1 - 1e-10) * Abs2 (g1) * Abs2 (g2))
797
return 1;
798
799
for (int j = 0; j < 3; j++)
800
{
801
mat(0,j) = g1(j);
802
mat(1,j) = g2(j);
803
}
804
mat.Solve (vrs, sol);
805
806
if (Abs2 (sol) < 1e-24 && i > 1) i = 1;
807
p -= sol;
808
}
809
810
return 0;
811
}
812
813
814
815
816
817
818
void SpecialPointCalculation :: EdgeNewton (const Surface * f1,
819
const Surface * f2, Point<3> & p)
820
{
821
Vec<3> g1, g2, sol;
822
Vec<2> vrs;
823
Mat<2,3> mat;
824
825
int i = 10;
826
while (i > 0)
827
{
828
i--;
829
vrs(0) = f1->CalcFunctionValue (p);
830
vrs(1) = f2->CalcFunctionValue (p);
831
832
f1->CalcGradient (p, g1);
833
f2->CalcGradient (p, g2);
834
835
//(*testout) << "p " << p << " f1 " << vrs(0) << " f2 " << vrs(1) << " g1 " << g1 << " g2 " << g2 << endl;
836
837
for (int j = 0; j < 3; j++)
838
{
839
mat(0,j) = g1(j);
840
mat(1,j) = g2(j);
841
}
842
mat.Solve (vrs, sol);
843
844
if (Abs2 (sol) < 1e-24 && i > 1) i = 1;
845
p -= sol;
846
}
847
}
848
849
850
851
bool SpecialPointCalculation ::
852
IsEdgeExtremalPoint (const Surface * f1, const Surface * f2,
853
const Point<3> & p, Point<3> & pp, double rad)
854
{
855
Vec<3> g1, g2, t, t1, t2;
856
857
f1->CalcGradient (p, g1);
858
f2->CalcGradient (p, g2);
859
860
t = Cross (g1, g2);
861
t.Normalize();
862
863
Point<3> p1 = p + rad * t;
864
Point<3> p2 = p - rad * t;
865
866
EdgeNewton (f1, f2, p1);
867
EdgeNewton (f1, f2, p2);
868
869
f1->CalcGradient (p1, g1);
870
f2->CalcGradient (p1, g2);
871
t1 = Cross (g1, g2);
872
t1.Normalize();
873
874
f1->CalcGradient (p2, g1);
875
f2->CalcGradient (p2, g2);
876
t2 = Cross (g1, g2);
877
t2.Normalize();
878
879
double val = 1e-8 * rad * rad;
880
for (int j = 0; j < 3; j++)
881
if ( (t1(j) * t2(j) < -val) )
882
{
883
pp = p;
884
ExtremalPointNewton (f1, f2, j+1, pp);
885
return 1;
886
}
887
888
return 0;
889
}
890
891
892
893
894
895
896
897
898
899
/********** Tests of Points of extremal coordinates ****************/
900
901
902
void SpecialPointCalculation :: ExtremalPointNewton (const Surface * f1,
903
const Surface * f2,
904
int dir, Point<3> & p)
905
{
906
Vec<3> g1, g2, v, curv;
907
Vec<3> rs, x, y1, y2, y;
908
Mat<3> h1, h2;
909
Mat<3> jacobi;
910
911
int i = 50;
912
while (i > 0)
913
{
914
i--;
915
rs(0) = f1->CalcFunctionValue (p);
916
rs(1) = f2->CalcFunctionValue (p);
917
918
f1 -> CalcGradient (p, g1);
919
f2 -> CalcGradient (p, g2);
920
921
f1 -> CalcHesse (p, h1);
922
f2 -> CalcHesse (p, h2);
923
924
v = Cross (g1, g2);
925
926
rs(2) = v(dir-1);
927
928
jacobi(0,0) = g1(0);
929
jacobi(0,1) = g1(1);
930
jacobi(0,2) = g1(2);
931
932
jacobi(1,0) = g2(0);
933
jacobi(1,1) = g2(1);
934
jacobi(1,2) = g2(2);
935
936
937
switch (dir)
938
{
939
case 1:
940
{
941
y1(0) = 0;
942
y1(1) = g2(2);
943
y1(2) = -g2(1);
944
y2(0) = 0;
945
y2(1) = -g1(2);
946
y2(2) = g1(1);
947
break;
948
}
949
case 2:
950
{
951
y1(0) = -g2(2);
952
y1(1) = 0;
953
y1(2) = g2(0);
954
y2(0) = g1(2);
955
y2(1) = 0;
956
y2(2) = -g1(0);
957
break;
958
}
959
case 3:
960
{
961
y1(0) = g2(1);
962
y1(1) = -g2(0);
963
y1(2) = 0;
964
y2(0) = -g1(1);
965
y2(1) = g1(0);
966
y2(2) = 0;
967
break;
968
}
969
}
970
971
y = h1 * y1 + h2 * y2;
972
973
jacobi(2,0) = y(0);
974
jacobi(2,1) = y(1);
975
jacobi(2,2) = y(2);
976
977
/*
978
(*testout) << "p " << p << " f1 " << rs(0) << " f2 " << rs(1) << endl
979
<< " jacobi " << jacobi << endl
980
<< " rhs " << rs << endl;
981
*/
982
983
jacobi.Solve (rs, x);
984
985
if (Abs2 (x) < 1e-24 && i > 1)
986
{
987
i = 1;
988
}
989
990
991
double minval(Abs2(rs)),minfac(1);
992
double startval(minval);
993
for(double fac = 1; fac > 1e-7; fac *= 0.6)
994
{
995
Point<3> testpoint = p-fac*x;
996
997
rs(0) = f1->CalcFunctionValue (testpoint);
998
rs(1) = f2->CalcFunctionValue (testpoint);
999
1000
f1 -> CalcGradient (testpoint, g1);
1001
f2 -> CalcGradient (testpoint, g2);
1002
1003
v = Cross (g1, g2);
1004
1005
rs(2) = v(dir-1);
1006
1007
double val = Abs2(rs);
1008
1009
if(val < minval)
1010
{
1011
minfac = fac;
1012
if(val < 0.5 * startval)
1013
break;
1014
minval = val;
1015
}
1016
1017
}
1018
p -= minfac*x;
1019
1020
1021
//p -= x;
1022
}
1023
1024
1025
if (Abs2 (x) > 1e-20)
1026
{
1027
(*testout) << "Error: extremum Newton not convergent" << endl;
1028
(*testout) << "dir = " << dir << endl;
1029
(*testout) << "p = " << p << endl;
1030
(*testout) << "x = " << x << endl;
1031
}
1032
}
1033
1034
void SpecialPointCalculation ::
1035
ComputeCrossPoints (const Plane * plane1,
1036
const Plane * plane2,
1037
const Plane * plane3,
1038
ARRAY<Point<3> > & pts)
1039
{
1040
Mat<3> mat;
1041
Vec<3> rhs, sol;
1042
Point<3> p0(0,0,0);
1043
1044
pts.SetSize (0);
1045
for (int i = 0; i < 3; i++)
1046
{
1047
const Plane * pi(NULL);
1048
switch (i)
1049
{
1050
case 0: pi = plane1; break;
1051
case 1: pi = plane2; break;
1052
case 2: pi = plane3; break;
1053
}
1054
1055
double val;
1056
Vec<3> hvec;
1057
val = pi -> CalcFunctionValue(p0);
1058
pi -> CalcGradient (p0, hvec);
1059
1060
for (int j = 0; j < 3; j++)
1061
mat(i,j) = hvec(j);
1062
rhs(i) = -val;
1063
}
1064
1065
if (fabs (Det (mat)) > 1e-8)
1066
{
1067
mat.Solve (rhs, sol);
1068
pts.Append (Point<3> (sol));
1069
}
1070
}
1071
1072
1073
1074
1075
1076
void SpecialPointCalculation ::
1077
ComputeCrossPoints (const Plane * plane1,
1078
const Plane * plane2,
1079
const QuadraticSurface * quadric,
1080
ARRAY<Point<3> > & pts)
1081
{
1082
Mat<2,3> mat;
1083
Mat<3,2> inv;
1084
Vec<2> rhs;
1085
Vec<3> sol, t;
1086
Point<3> p0(0,0,0);
1087
1088
pts.SetSize (0);
1089
for (int i = 0; i < 2; i++)
1090
{
1091
const Plane * pi(NULL);
1092
switch (i)
1093
{
1094
case 0: pi = plane1; break;
1095
case 1: pi = plane2; break;
1096
}
1097
1098
double val;
1099
Vec<3> hvec;
1100
val = pi -> CalcFunctionValue(p0);
1101
pi -> CalcGradient (p0, hvec);
1102
1103
for (int j = 0; j < 3; j++)
1104
mat(i,j) = hvec(j);
1105
rhs(i) = -val;
1106
}
1107
CalcInverse (mat, inv);
1108
sol = inv * rhs;
1109
t = Cross (mat.Row(0), mat.Row(1));
1110
1111
if (t.Length() > 1e-8)
1112
{
1113
Point<3> p (sol);
1114
// quadratic on p + s t = 0
1115
double quad_a;
1116
Vec<3> quad_b;
1117
Mat<3> quad_c;
1118
1119
quad_a = quadric -> CalcFunctionValue(p);
1120
quadric -> CalcGradient (p, quad_b);
1121
quadric -> CalcHesse (p, quad_c);
1122
1123
double a, b, c;
1124
a = quad_a;
1125
b = quad_b * t;
1126
c = 0.5 * t * (quad_c * t);
1127
1128
// a + s b + s^2 c = 0;
1129
double disc = b*b-4*a*c;
1130
if (disc > 1e-10 * fabs (b))
1131
{
1132
disc = sqrt (disc);
1133
double s1 = (-b-disc) / (2*c);
1134
double s2 = (-b+disc) / (2*c);
1135
1136
pts.Append (p + s1 * t);
1137
pts.Append (p + s2 * t);
1138
}
1139
}
1140
}
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
void SpecialPointCalculation ::
1154
ComputeExtremalPoints (const Plane * plane,
1155
const QuadraticSurface * quadric,
1156
ARRAY<Point<3> > & pts)
1157
{
1158
// 3 equations:
1159
// surf1 = 0 <===> plane_a + plane_b x = 0;
1160
// surf2 = 0 <===> quad_a + quad_b x + x^T quad_c x = 0
1161
// (grad 1 x grad 2)(i) = 0 <====> (grad 1 x e_i) . grad_2 = 0
1162
1163
pts.SetSize (0);
1164
1165
Point<3> p0(0,0,0);
1166
double plane_a, quad_a;
1167
Vec<3> plane_b, quad_b, ei;
1168
Mat<3> quad_c;
1169
1170
plane_a = plane -> CalcFunctionValue(p0);
1171
plane -> CalcGradient (p0, plane_b);
1172
1173
quad_a = quadric -> CalcFunctionValue(p0);
1174
quadric -> CalcGradient (p0, quad_b);
1175
quadric -> CalcHesse (p0, quad_c);
1176
for (int i = 0; i < 3; i++)
1177
for (int j = 0; j < 3; j++)
1178
quad_c(i,j) *= 0.5;
1179
1180
for (int dir = 0; dir <= 2; dir++)
1181
{
1182
ei = 0.0; ei(dir) = 1;
1183
Vec<3> v1 = Cross (plane_b, ei);
1184
1185
// grad_2 . v1 ... linear:
1186
double g2v1_c = v1 * quad_b;
1187
Vec<3> g2v1_l = 2.0 * (quad_c * v1);
1188
1189
// find line of two linear equations:
1190
1191
Vec<2> rhs;
1192
Vec<3> sol;
1193
Mat<2,3> mat;
1194
1195
for (int j = 0; j < 3; j++)
1196
{
1197
mat(0,j) = plane_b(j);
1198
mat(1,j) = g2v1_l(j);
1199
}
1200
rhs(0) = -plane_a;
1201
rhs(1) = -g2v1_c;
1202
1203
Vec<3> t = Cross (plane_b, g2v1_l);
1204
if (Abs2(t) > 0)
1205
{
1206
mat.Solve (rhs, sol);
1207
1208
// solve quadratic equation along line sol + alpha t ....
1209
double a = quad_a + quad_b * sol + sol * (quad_c * sol);
1210
double b = quad_b * t + 2 * (sol * (quad_c * t));
1211
double c = t * (quad_c * t);
1212
1213
// solve a + b alpha + c alpha^2:
1214
1215
if (fabs (c) > 1e-32)
1216
{
1217
double disc = sqr (0.5*b/c) - a/c;
1218
if (disc > 0)
1219
{
1220
disc = sqrt (disc);
1221
double alpha1 = -0.5*b/c + disc;
1222
double alpha2 = -0.5*b/c - disc;
1223
1224
pts.Append (Point<3> (sol+alpha1*t));
1225
pts.Append (Point<3> (sol+alpha2*t));
1226
/*
1227
cout << "sol1 = " << sol + alpha1 * t
1228
<< ", sol2 = " << sol + alpha2 * t << endl;
1229
*/
1230
}
1231
}
1232
}
1233
}
1234
}
1235
1236
1237
1238
1239
1240
1241
/*
1242
bool SpecialPointCalculation :: ExtremalPointPossible (const Surface * f1,
1243
const Surface * f2,
1244
int dir,
1245
const BoxSphere<3> & box)
1246
{
1247
double hn1, hn2, gn1, gn2;
1248
Point<3> p;
1249
Vec<3> g1, g2, v;
1250
double f3;
1251
double r = box.Diam()/2;
1252
1253
p = box.Center();
1254
1255
f1 -> CalcGradient (p, g1);
1256
f2 -> CalcGradient (p, g2);
1257
1258
gn1 = g1.Length();
1259
gn2 = g2.Length();
1260
1261
hn1 = f1 -> HesseNorm ();
1262
hn2 = f2 -> HesseNorm ();
1263
1264
v = Cross (g1, g2);
1265
f3 = fabs (v(dir-1));
1266
1267
// (*testout) << "f3 = " << f3 << " r = " << r
1268
// << "normbound = "
1269
// << (hn1 * (gn2 + r * hn2) + hn2 * (gn1 + r * hn1)) << endl;
1270
1271
return (f3 <= 3 * r * (hn1 * (gn2 + r * hn2) + hn2 * (gn1 + r * hn1)));
1272
}
1273
1274
1275
1276
bool SpecialPointCalculation ::
1277
ExtremalPointNewtonConvergence (const Surface * f1, const Surface * f2,
1278
int dir,
1279
const BoxSphere<3> & box)
1280
{
1281
return box.Diam() < 1e-8;
1282
}
1283
1284
1285
bool SpecialPointCalculation ::
1286
ExtremalPointDegenerated (const Surface * f1, const Surface * f2,
1287
int dir, const BoxSphere<3> & box)
1288
{
1289
double gn1, gn2;
1290
Point<3> p;
1291
Vec<3> g1, g2, v;
1292
double maxderiv;
1293
double minv;
1294
Vec<3> curv, t;
1295
Vec<2> rs, x;
1296
Mat<3> h1, h2;
1297
Mat<2> a, inv;
1298
double leftside;
1299
1300
if (box.Diam() > relydegtest) return 0;
1301
1302
p = box.Center();
1303
1304
f1 -> CalcGradient (p, g1);
1305
f2 -> CalcGradient (p, g2);
1306
gn1 = g1.Length();
1307
gn2 = g2.Length();
1308
1309
v = Cross (g1, g2);
1310
if (Abs (v) < epeps1 * gn1 * gn2) return 1; // irregular edge
1311
1312
f1 -> CalcHesse (p, h1);
1313
f2 -> CalcHesse (p, h2);
1314
1315
// hn1 = f1 -> HesseNorm ();
1316
// hn2 = f2 -> HesseNorm ();
1317
1318
t = v;
1319
a(0, 0) = g1 * g1;
1320
a(0, 1) =
1321
a(1, 0) = g1 * g2;
1322
a(1, 1) = g2 * g2;
1323
1324
rs(0) = g1(dir-1);
1325
rs(1) = g2(dir-1);
1326
1327
a.Solve (rs, x);
1328
1329
// (*testout) << "g1 = " << g1 << " g2 = " << g2 << endl;
1330
// (*testout) << "lam = " << x << endl;
1331
// (*testout) << "h2 = " << h2 << endl;
1332
1333
leftside = fabs (x(0) * ( t * (h1 * t)) +
1334
x(1) * ( t * (h2 * t)));
1335
1336
// (*testout) << "leftside = " << leftside << endl;
1337
1338
if (leftside < epeps2 * Abs2 (v)) return 1;
1339
1340
return 0;
1341
}
1342
*/
1343
1344
1345
bool SpecialPointCalculation :: AddPoint (const Point<3> & p, int layer)
1346
{
1347
for (int i = 0; i < points->Size(); i++)
1348
if (Dist2 ( (*points)[i], p) < epspointdist2 &&
1349
(*points)[i].GetLayer() == layer)
1350
return false;
1351
1352
points->Append (MeshPoint(p, layer));
1353
PrintMessageCR (3, "Found points ", points->Size());
1354
return true;
1355
}
1356
1357
1358
1359
1360
1361
1362
1363
void SpecialPointCalculation ::
1364
AnalyzeSpecialPoints (const CSGeometry & ageometry,
1365
ARRAY<MeshPoint> & apoints,
1366
ARRAY<SpecialPoint> & specpoints)
1367
{
1368
ARRAY<int> surfind, rep_surfind, surfind2, rep_surfind2, surfind3;
1369
1370
ARRAY<Vec<3> > normalvecs;
1371
Vec<3> nsurf;
1372
1373
ARRAY<int> specpoint2point;
1374
specpoints.SetSize (0);
1375
1376
geometry = &ageometry;
1377
1378
double geomsize = ageometry.MaxSize();
1379
1380
(*testout) << "AnalyzeSpecialPoints\n";
1381
1382
if (!apoints.Size()) return;
1383
1384
1385
1386
#ifdef VERTSORT
1387
for (int i = 0; i < apoints.Size(); i++)
1388
for (int j = 0; j < apoints.Size()-1; j++)
1389
if (apoints[j](2) > apoints[j+1](2))
1390
swap (apoints[j], apoints[j+1]);
1391
#endif
1392
1393
1394
1395
1396
1397
1398
1399
Box<3> bbox (apoints[0], apoints[0]);
1400
for (int i = 1; i < apoints.Size(); i++)
1401
bbox.Add (apoints[i]);
1402
bbox.Increase (0.1 * bbox.Diam());
1403
1404
//testout->precision(20);
1405
(*testout) << "bbox = " << bbox << endl;
1406
(*testout) << "points = " << apoints << endl;
1407
1408
Point3dTree searchtree (bbox.PMin(), bbox.PMax());
1409
ARRAY<int> locsearch;
1410
1411
for (int si = 0; si < ageometry.GetNTopLevelObjects(); si++)
1412
{
1413
const TopLevelObject * tlo = ageometry.GetTopLevelObject(si);
1414
1415
const Solid * sol = tlo->GetSolid();
1416
const Surface * surf = tlo->GetSurface();
1417
1418
1419
for (int i = 0; i < apoints.Size(); i++)
1420
{
1421
Point<3> p = apoints[i];
1422
1423
#ifdef DEVELOP
1424
*testout << " test point " << p << endl;
1425
#endif
1426
1427
if (tlo->GetLayer() != apoints[i].GetLayer())
1428
continue;
1429
1430
Solid * locsol;
1431
sol -> TangentialSolid (p, locsol, surfind, ideps*geomsize);
1432
1433
1434
1435
rep_surfind.SetSize (surfind.Size());
1436
int num_indep_surfs = 0;
1437
1438
for (int j = 0; j < surfind.Size(); j++)
1439
{
1440
rep_surfind[j] = ageometry.GetSurfaceClassRepresentant (surfind[j]);
1441
bool found = false;
1442
for (int k = 0; !found && k < j; k++)
1443
found = (rep_surfind[k] == rep_surfind[j]);
1444
if(!found)
1445
num_indep_surfs++;
1446
}
1447
1448
1449
#ifdef DEVELOP
1450
*testout << "surfs = " << surfind << endl;
1451
*testout << "rep_surfs = " << rep_surfind << endl;
1452
#endif
1453
1454
if (!locsol) continue;
1455
1456
// get all surface indices,
1457
if (surf)
1458
{
1459
// locsol -> GetSurfaceIndices (surfind);
1460
bool hassurf = 0;
1461
for (int m = 0; m < surfind.Size(); m++)
1462
if (ageometry.GetSurface(surfind[m]) == surf)
1463
hassurf = 1;
1464
1465
if (!hassurf)
1466
continue;
1467
1468
nsurf = surf->GetNormalVector (p);
1469
}
1470
1471
/*
1472
// get independent surfaces of tangential solid
1473
BoxSphere<3> box(p,p);
1474
box.Increase (1e-6*geomsize);
1475
box.CalcDiamCenter();
1476
ageometry.GetIndependentSurfaceIndices (locsol, box, surfind);
1477
*/
1478
1479
// ageometry.GetIndependentSurfaceIndices (surfind);
1480
1481
1482
normalvecs.SetSize(surfind.Size());
1483
for (int j = 0; j < surfind.Size(); j++)
1484
normalvecs[j] =
1485
ageometry.GetSurface(surfind[j]) -> GetNormalVector(apoints[i]);
1486
1487
1488
for (int j = 0; j < normalvecs.Size(); j++)
1489
for (int k = 0; k < normalvecs.Size(); k++)
1490
{
1491
if (rep_surfind[j] == rep_surfind[k]) continue;
1492
//if (j == k) continue;
1493
1494
Vec<3> t;
1495
1496
if (dynamic_cast<const Polyhedra*> (ageometry.surf2prim[surfind[j]]) &&
1497
ageometry.surf2prim[surfind[j]] ==
1498
ageometry.surf2prim[surfind[k]])
1499
{
1500
t = ageometry.surf2prim[surfind[j]] ->
1501
SpecialPointTangentialVector (p, surfind[j], surfind[k]);
1502
}
1503
else
1504
{
1505
t = Cross (normalvecs[j], normalvecs[k]);
1506
}
1507
1508
1509
if (Abs2 (t) < 1e-8)
1510
continue;
1511
1512
#ifdef DEVELOP
1513
*testout << " tangential vector " << t << endl;
1514
#endif
1515
1516
t.Normalize();
1517
1518
1519
// try tangential direction t
1520
if (surf && fabs (nsurf * t) > 1e-6)
1521
continue;
1522
1523
1524
#ifdef DEVELOP
1525
*testout << " j " << j << " k " << k << endl;
1526
#endif
1527
1528
if (!surf)
1529
{
1530
// compute second order approximation
1531
// c(s) = p + s t + s*s/2 t2
1532
Vec<3> gradj, gradk;
1533
Mat<3> hessej, hessek;
1534
ageometry.GetSurface (surfind[j]) -> CalcGradient (p, gradj);
1535
ageometry.GetSurface (surfind[k]) -> CalcGradient (p, gradk);
1536
ageometry.GetSurface (surfind[j]) -> CalcHesse (p, hessej);
1537
ageometry.GetSurface (surfind[k]) -> CalcHesse (p, hessek);
1538
1539
Vec<2> rhs;
1540
Vec<3> t2;
1541
Mat<2,3> mat;
1542
Mat<3,2> inv;
1543
for (int l = 0; l < 3; l++)
1544
{
1545
mat(0,l) = gradj(l);
1546
mat(1,l) = gradk(l);
1547
}
1548
rhs(0) = -t * (hessej * t);
1549
rhs(1) = -t * (hessek * t);
1550
1551
CalcInverse (mat, inv);
1552
t2 = inv * rhs;
1553
1554
1555
/*
1556
ageometry.GetIndependentSurfaceIndices
1557
(locsol, p, t, surfind2);
1558
*/
1559
1560
Solid * locsol2;
1561
locsol -> TangentialSolid3 (p, t, t2, locsol2, surfind2, ideps*geomsize);
1562
if (!locsol2) continue;
1563
1564
// locsol2 -> GetTangentialSurfaceIndices3 (p, t, t2, surfind2, 1e-9*geomsize);
1565
1566
rep_surfind2.SetSize (surfind2.Size());
1567
for (int j2 = 0; j2 < surfind2.Size(); j2++)
1568
rep_surfind2[j2] = ageometry.GetSurfaceClassRepresentant (surfind2[j2]);
1569
1570
#ifdef DEVELOP
1571
(*testout) << "surfind2 = " << endl << surfind2 << endl;
1572
#endif
1573
ARRAY<int> surfind2_aux(surfind2);
1574
ageometry.GetIndependentSurfaceIndices (surfind2_aux);
1575
#ifdef DEVELOP
1576
(*testout) << "surfind2,rep = " << endl << surfind2_aux << endl;
1577
#endif
1578
1579
bool ok = true;
1580
1581
// intersecting surfaces must be in second order tangential solid
1582
/*
1583
if (!surfind2.Contains(surfind[j]) ||
1584
!surfind2.Contains(surfind[k]))
1585
ok = false;
1586
*/
1587
if (!surfind2_aux.Contains(rep_surfind[j]) ||
1588
!surfind2_aux.Contains(rep_surfind[k]))
1589
ok = false;
1590
1591
#ifdef DEVELOP
1592
(*testout) << "ok,1 = " << ok << endl;
1593
#endif
1594
1595
// there must be 2 different tangential faces to the edge
1596
int cnt_tang_faces = 0;
1597
for (int l = 0; l < surfind2.Size(); l++)
1598
{
1599
Vec<3> nv =
1600
ageometry.GetSurface(surfind2[l]) -> GetNormalVector(p);
1601
1602
1603
Vec<3> m1 = Cross (t, nv);
1604
Vec<3> m2 = -m1;
1605
bool isface1 = 0, isface2 = 0;
1606
1607
Solid * locsol3;
1608
1609
// locsol2 -> TangentialSolid2 (p, m1, locsol3, surfind3, 1e-9*geomsize);
1610
locsol -> TangentialEdgeSolid (p, t, t2, m1, locsol3, surfind3, ideps*geomsize);
1611
1612
//ageometry.GetIndependentSurfaceIndices (surfind3);
1613
1614
if (surfind3.Contains(surfind2[l]))
1615
isface1 = 1;
1616
delete locsol3;
1617
1618
// locsol2 -> TangentialSolid2 (p, m2, locsol3, surfind3, 1e-9*geomsize);
1619
locsol -> TangentialEdgeSolid (p, t, t2, m2, locsol3, surfind3, ideps*geomsize);
1620
1621
// ageometry.GetIndependentSurfaceIndices (surfind3);
1622
1623
1624
if (surfind3.Contains(surfind2[l]))
1625
isface2 = 1;
1626
delete locsol3;
1627
1628
if (isface1 != isface2)
1629
cnt_tang_faces++;
1630
}
1631
1632
#ifdef DEVELOP
1633
(*testout) << "cnt_tang = " << cnt_tang_faces << endl;
1634
#endif
1635
1636
if (cnt_tang_faces < 1)
1637
ok = false;
1638
1639
delete locsol2;
1640
if (!ok) continue;
1641
}
1642
1643
1644
// edge must be on tangential surface
1645
bool isedge =
1646
locsol->VectorIn (p, t) &&
1647
!locsol->VectorStrictIn (p, t);
1648
1649
#ifdef DEVELOP
1650
(*testout) << "isedge,1 = " << isedge << "\n";
1651
#endif
1652
1653
// there must exist at least two different faces on edge
1654
if (isedge)
1655
{
1656
// *testout << "succ 1" << endl;
1657
int cnts = 0;
1658
for (int m = 0; m < surfind.Size(); m++)
1659
{
1660
if (fabs (normalvecs[m] * t) > 1e-6)
1661
continue;
1662
1663
Vec<3> s = Cross (normalvecs[m], t);
1664
Vec<3> t2a = t + 0.01 *s;
1665
Vec<3> t2b = t - 0.01 *s;
1666
1667
bool isface =
1668
(locsol->VectorIn (p, t2a, 1e-6*geomsize) &&
1669
!locsol->VectorStrictIn (p, t2a, 1e-6*geomsize))
1670
||
1671
(locsol->VectorIn (p, t2b, 1e-6*geomsize) &&
1672
!locsol->VectorStrictIn (p, t2b, 1e-6*geomsize));
1673
1674
/*
1675
bool isface =
1676
(locsol->VectorIn (p, t2a) &&
1677
!locsol->VectorStrictIn (p, t2a))
1678
||
1679
(locsol->VectorIn (p, t2b) &&
1680
!locsol->VectorStrictIn (p, t2b));
1681
*/
1682
1683
if (isface)
1684
{
1685
cnts++;
1686
}
1687
}
1688
if (cnts < 2) isedge = 0;
1689
}
1690
1691
if (isedge)
1692
{
1693
#ifdef DEVELOP
1694
*testout << "success" << endl;
1695
#endif
1696
int spi = -1;
1697
1698
const double searchradius = 1e-4*geomsize;//1e-5*geomsize;
1699
searchtree.GetIntersecting (apoints[i]-Vec3d(searchradius,searchradius,searchradius),
1700
apoints[i]+Vec3d(searchradius,searchradius,searchradius),
1701
locsearch);
1702
1703
for (int m = 0; m < locsearch.Size(); m++)
1704
{
1705
if (Dist2 (specpoints[locsearch[m]].p, apoints[i]) < 1e-10*geomsize
1706
&& Abs2(specpoints[locsearch[m]].v - t) < 1e-8)
1707
{
1708
spi = locsearch[m];
1709
break;
1710
}
1711
}
1712
1713
1714
if (spi == -1)
1715
{
1716
spi = specpoints.Append (SpecialPoint()) - 1;
1717
specpoint2point.Append (i);
1718
specpoints.Last().unconditional = 0;
1719
searchtree.Insert (apoints[i], spi);
1720
}
1721
1722
if(!specpoints[spi].unconditional)
1723
{
1724
specpoints[spi].p = apoints[i];
1725
specpoints[spi].v = t;
1726
//if (surfind.Size() >= 3)
1727
if (num_indep_surfs >= 3)
1728
specpoints[spi].unconditional = 1;
1729
specpoints[spi].s1 = rep_surfind[j];
1730
specpoints[spi].s2 = rep_surfind[k];
1731
specpoints[spi].s1_orig = surfind[j];
1732
specpoints[spi].s2_orig = surfind[k];
1733
specpoints[spi].layer = apoints[i].GetLayer();
1734
for (int up = 0; up < geometry->GetNUserPoints(); up++)
1735
if (Dist (geometry->GetUserPoint(up), apoints[i]) < 1e-8*geomsize)
1736
specpoints[spi].unconditional = 1;
1737
for (int ip = 0; ip < geometry->GetNIdentPoints(); ip++)
1738
if (Dist (geometry->GetIdentPoint(ip), apoints[i]) < 1e-8*geomsize)
1739
specpoints[spi].unconditional = 1;
1740
}
1741
}
1742
1743
}
1744
1745
delete locsol;
1746
}
1747
}
1748
1749
/*
1750
BitArray testuncond (specpoints.Size());
1751
testuncond.Clear();
1752
for(int i = 0; i<specpoints.Size(); i++)
1753
{
1754
if(testuncond.Test(i))
1755
continue;
1756
1757
ARRAY<int> same;
1758
same.Append(i);
1759
1760
for(int j = i+1; j<specpoints.Size(); j++)
1761
{
1762
if(Dist(specpoints[i].p,specpoints[j].p) < 1e-20)
1763
{
1764
same.Append(j);
1765
testuncond.Set(j);
1766
}
1767
}
1768
1769
if(same.Size() < 3)
1770
for(int j=0; j<same.Size(); j++)
1771
{
1772
(*testout) << "setting " << specpoints[same[j]].p << "; " << specpoints[same[j]].v << "; "
1773
<<specpoints[same[j]].unconditional << " to conditional" << endl;
1774
specpoints[same[j]].unconditional=0;
1775
}
1776
}
1777
*/
1778
1779
1780
// if special point is unconditional on some solid,
1781
// it must be unconditional everywhere:
1782
1783
BitArray uncond (apoints.Size());
1784
uncond.Clear();
1785
1786
for (int i = 0; i < specpoints.Size(); i++)
1787
if (specpoints[i].unconditional)
1788
uncond.Set (specpoint2point[i]);
1789
1790
for (int i = 0; i < specpoints.Size(); i++)
1791
specpoints[i].unconditional =
1792
uncond.Test (specpoint2point[i]) ? 1 : 0;
1793
}
1794
}
1795
1796