Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/ElmerGUI/netgen/libsrc/csg/surface.cpp
3206 views
1
#include <mystdlib.h>
2
3
#include <myadt.hpp>
4
#include <csg.hpp>
5
6
#include <linalg.hpp>
7
#include <meshing.hpp>
8
9
10
namespace netgen
11
{
12
Surface :: Surface ()
13
{
14
maxh = 1e10;
15
name = new char[7];
16
strcpy (name, "noname");
17
bcprop = -1;
18
bcname = "default";
19
}
20
21
Surface :: ~Surface()
22
{
23
delete [] name;
24
}
25
26
27
void Surface :: SetName (const char * aname)
28
{
29
delete [] name;
30
name = new char[strlen (aname)+1];
31
strcpy (name, aname);
32
}
33
34
35
int Surface :: PointOnSurface (const Point<3> & p,
36
double eps) const
37
{
38
double val = CalcFunctionValue (p);
39
return fabs (val) < eps;
40
}
41
42
43
void Surface :: CalcHesse (const Point<3> & point, Mat<3> & hesse) const
44
{
45
double dx = 1e-5;
46
Point<3> hp1, hp2;
47
Vec<3> g1, g2;
48
49
for (int i = 0; i < 3; i++)
50
{
51
hp1 = point;
52
hp2 = point;
53
54
hp1(i) += dx;
55
hp2(i) -= dx;
56
57
CalcGradient (hp1, g1);
58
CalcGradient (hp2, g2);
59
60
for (int j = 0; j < 3; j++)
61
hesse(i, j) = (g1(j) - g2(j)) / (2 * dx);
62
}
63
}
64
65
/*
66
void Surface :: GetNormalVector (const Point<3> & p, Vec<3> & n) const
67
{
68
CalcGradient (p, n);
69
n.Normalize();
70
}
71
*/
72
Vec<3> Surface :: GetNormalVector (const Point<3> & p) const
73
{
74
Vec<3> n;
75
CalcGradient (p, n);
76
n.Normalize();
77
return n;
78
}
79
80
void Surface :: DefineTangentialPlane (const Point<3> & ap1,
81
const Point<3> & ap2)
82
{
83
p1 = ap1;
84
p2 = ap2;
85
86
ez = GetNormalVector (p1);
87
ex = p2 - p1;
88
ex -= (ex * ez) * ez;
89
ex.Normalize();
90
ey = Cross (ez, ex);
91
}
92
93
void Surface :: ToPlane (const Point<3> & p3d, Point<2> & pplane,
94
double h, int & zone) const
95
{
96
Vec<3> p1p, n;
97
98
n = GetNormalVector (p3d);
99
if (n * ez < 0)
100
{
101
zone = -1;
102
pplane(0) = 1e8;
103
pplane(1) = 1e9;
104
return;
105
}
106
107
p1p = p3d - p1;
108
pplane(0) = (p1p * ex) / h;
109
pplane(1) = (p1p * ey) / h;
110
zone = 0;
111
}
112
113
void Surface :: FromPlane (const Point<2> & pplane,
114
Point<3> & p3d, double h) const
115
{
116
p3d = p1
117
+ (h * pplane(0)) * ex
118
+ (h * pplane(1)) * ey;
119
120
Project (p3d);
121
}
122
123
void Surface :: Project (Point<3> & p) const
124
{
125
Vec<3> n;
126
double val;
127
128
for (int i = 1; i <= 10; i++)
129
{
130
val = CalcFunctionValue (p);
131
if (fabs (val) < 1e-12) return;
132
133
CalcGradient (p, n);
134
p -= (val / Abs2 (n)) * n;
135
}
136
}
137
138
void Surface :: SkewProject (Point<3> & p, const Vec<3> & direction) const
139
{
140
Point<3> startp(p);
141
double t_old(0),t_new(1);
142
Vec<3> grad;
143
for(int i=0; fabs(t_old-t_new) > 1e-20 && i<15; i++)
144
{
145
t_old = t_new;
146
CalcGradient(p,grad);
147
t_new = t_old - CalcFunctionValue(p)/(grad*direction);
148
p = startp + t_new*direction;
149
}
150
}
151
152
153
double Surface :: MaxCurvature () const
154
{
155
return 0.5 * HesseNorm ();
156
}
157
158
double Surface ::
159
MaxCurvatureLoc (const Point<3> & /* c */ , double /* rad */) const
160
{
161
return MaxCurvature ();
162
}
163
164
165
166
double Surface :: LocH (const Point<3> & p, double x,
167
double c, double hmax) const
168
// finds h <= hmax, s.t. h * \kappa_x*h < c
169
{
170
/*
171
double h, hmin, kappa;
172
hmin = 0;
173
174
while (hmin < 0.9 * hmax)
175
{
176
h = 0.5 * (hmin + hmax);
177
kappa = 2 * MaxCurvatureLoc (p, x * h);
178
179
if (kappa * h >= c)
180
hmax = h;
181
else
182
hmin = h;
183
}
184
return h;
185
*/
186
187
double hret;
188
double kappa = MaxCurvatureLoc (p, x*hmax);
189
190
kappa *= c * mparam.curvaturesafety;
191
192
if (hmax * kappa < 1)
193
hret = hmax;
194
else
195
hret = 1 / kappa;
196
197
if (maxh < hret)
198
hret = maxh;
199
200
return hret;
201
}
202
203
204
205
206
Primitive :: Primitive ()
207
{
208
surfaceids.SetSize (1);
209
surfaceactive.SetSize (1);
210
surfaceactive[0] = 1;
211
}
212
213
Primitive :: ~Primitive()
214
{
215
;
216
}
217
218
int Primitive :: GetSurfaceId (int i) const
219
{
220
return surfaceids[i];
221
}
222
223
void Primitive :: SetSurfaceId (int i, int id)
224
{
225
surfaceids[i] = id;
226
}
227
228
229
230
231
void Primitive :: GetPrimitiveData (const char *& classname,
232
ARRAY<double> & coeffs) const
233
{
234
classname = "undef";
235
coeffs.SetSize (0);
236
}
237
238
void Primitive :: SetPrimitiveData (ARRAY<double> & coeffs)
239
{
240
;
241
}
242
243
Primitive * Primitive :: CreatePrimitive (const char * classname)
244
{
245
if (strcmp (classname, "sphere") == 0)
246
return Sphere::CreateDefault();
247
if (strcmp (classname, "plane") == 0)
248
return Plane::CreateDefault();
249
if (strcmp (classname, "cylinder") == 0)
250
return Cylinder::CreateDefault();
251
if (strcmp (classname, "cone") == 0)
252
return Cone::CreateDefault();
253
if (strcmp (classname, "brick") == 0)
254
return Brick::CreateDefault();
255
256
257
stringstream ost;
258
ost << "Primitve::CreatePrimitive not implemented for " << classname << endl;
259
throw NgException (ost.str());
260
}
261
262
263
Primitive * Primitive :: Copy () const
264
{
265
stringstream ost;
266
ost << "Primitve::Copy not implemented for " << typeid(*this).name() << endl;
267
throw NgException (ost.str());
268
}
269
270
271
void Primitive :: Transform (Transformation<3> & trans)
272
{
273
stringstream ost;
274
ost << "Primitve::Transform not implemented for " << typeid(*this).name() << endl;
275
throw NgException (ost.str());
276
}
277
278
void Primitive :: GetTangentialSurfaceIndices (const Point<3> & p,
279
ARRAY<int> & surfind, double eps) const
280
{
281
for (int j = 0; j < GetNSurfaces(); j++)
282
if (fabs (GetSurface(j).CalcFunctionValue (p)) < eps)
283
if (!surfind.Contains (GetSurfaceId(j)))
284
surfind.Append (GetSurfaceId(j));
285
}
286
287
288
void Primitive ::
289
GetTangentialVecSurfaceIndices (const Point<3> & p, const Vec<3> & v,
290
ARRAY<int> & surfind, double eps) const
291
{
292
cout << "get tangvecsurfind not implemented" << endl;
293
surfind.SetSize (0);
294
}
295
296
void Primitive ::
297
GetTangentialVecSurfaceIndices2 (const Point<3> & p, const Vec<3> & v1, const Vec<3> & v2,
298
ARRAY<int> & surfind, double eps) const
299
{
300
for (int j = 0; j < GetNSurfaces(); j++)
301
{
302
if (fabs (GetSurface(j).CalcFunctionValue (p)) < eps)
303
{
304
Vec<3> grad;
305
GetSurface(j).CalcGradient (p, grad);
306
if (sqr (grad * v1) < 1e-6 * v1.Length2() * grad.Length2() &&
307
sqr (grad * v2) < 1e-6 * v2.Length2() * grad.Length2() ) // new, 18032006 JS
308
{
309
if (!surfind.Contains (GetSurfaceId(j)))
310
surfind.Append (GetSurfaceId(j));
311
}
312
}
313
}
314
}
315
316
317
318
319
INSOLID_TYPE Primitive ::
320
VecInSolid2 (const Point<3> & p,
321
const Vec<3> & v1,
322
const Vec<3> & v2,
323
double eps) const
324
{
325
//(*testout) << "Primitive::VecInSolid2" << endl;
326
Point<3> hp = p + 1e-3 * v1 + 1e-5 * v2;
327
328
INSOLID_TYPE res = PointInSolid (hp, eps);
329
// (*testout) << "vectorin2, type = " << typeid(*this).name() << ", res = " << res << endl;
330
331
return res;
332
}
333
334
INSOLID_TYPE Primitive ::
335
VecInSolid3 (const Point<3> & p,
336
const Vec<3> & v1,
337
const Vec<3> & v2,
338
double eps) const
339
{
340
//(*testout) << "Primitive::VecInSolid3" << endl;
341
return VecInSolid (p, v1, eps);
342
}
343
344
INSOLID_TYPE Primitive ::
345
VecInSolid4 (const Point<3> & p,
346
const Vec<3> & v,
347
const Vec<3> & v2,
348
const Vec<3> & m,
349
double eps) const
350
{
351
return VecInSolid2 (p, v, m, eps);
352
}
353
354
355
356
357
358
OneSurfacePrimitive :: OneSurfacePrimitive()
359
{
360
;
361
}
362
363
OneSurfacePrimitive :: ~OneSurfacePrimitive()
364
{
365
;
366
}
367
368
369
INSOLID_TYPE OneSurfacePrimitive ::
370
PointInSolid (const Point<3> & p,
371
double eps) const
372
{
373
double hv1 = (GetSurface(0).CalcFunctionValue(p));
374
if (hv1 <= -eps)
375
return IS_INSIDE;
376
if (hv1 >= eps)
377
return IS_OUTSIDE;
378
return DOES_INTERSECT;
379
}
380
381
382
INSOLID_TYPE OneSurfacePrimitive ::
383
VecInSolid (const Point<3> & p, const Vec<3> & v,
384
double eps) const
385
{
386
double hv1 = (GetSurface(0).CalcFunctionValue(p));
387
if (hv1 <= -eps)
388
return IS_INSIDE;
389
if (hv1 >= eps)
390
return IS_OUTSIDE;
391
392
393
Vec<3> hv;
394
GetSurface(0).CalcGradient (p, hv);
395
396
hv1 = v * hv;
397
398
if (hv1 <= -eps)
399
return IS_INSIDE;
400
if (hv1 >= eps)
401
return IS_OUTSIDE;
402
403
return DOES_INTERSECT;
404
}
405
406
407
INSOLID_TYPE OneSurfacePrimitive ::
408
VecInSolid2 (const Point<3> & p,
409
const Vec<3> & v1,
410
const Vec<3> & v2,
411
double eps) const
412
{
413
double hv1 = (GetSurface(0).CalcFunctionValue(p));
414
if (hv1 <= -eps)
415
return IS_INSIDE;
416
if (hv1 >= eps)
417
return IS_OUTSIDE;
418
419
Vec<3> hv;
420
421
GetSurface(0).CalcGradient (p, hv);
422
423
hv1 = v1 * hv;
424
if (hv1 <= -eps)
425
return IS_INSIDE;
426
if (hv1 >= eps)
427
return IS_OUTSIDE;
428
429
double hv2 = v2 * hv;
430
if (hv2 <= 0)
431
return IS_INSIDE;
432
else
433
return IS_OUTSIDE;
434
}
435
436
437
438
INSOLID_TYPE OneSurfacePrimitive ::
439
VecInSolid3 (const Point<3> & p, const Vec<3> & v, const Vec<3> & v2,
440
double eps) const
441
{
442
//(*testout) << "OneSurfacePrimitive::VecInSolid3" << endl;
443
double hv1 = (GetSurface(0).CalcFunctionValue(p));
444
if (hv1 <= -eps)
445
return IS_INSIDE;
446
if (hv1 >= eps)
447
return IS_OUTSIDE;
448
449
Vec<3> grad;
450
GetSurface(0).CalcGradient (p, grad);
451
452
hv1 = v * grad;
453
if (hv1 <= -eps) return IS_INSIDE;
454
if (hv1 >= eps) return IS_OUTSIDE;
455
456
Mat<3> hesse;
457
GetSurface(0).CalcHesse (p, hesse);
458
459
double hv2 = v2 * grad + v * (hesse * v);
460
461
if (hv2 <= -eps) return IS_INSIDE;
462
if (hv2 >= eps) return IS_OUTSIDE;
463
464
return DOES_INTERSECT;
465
}
466
467
468
469
470
INSOLID_TYPE OneSurfacePrimitive ::
471
VecInSolid4 (const Point<3> & p, const Vec<3> & v, const Vec<3> & v2,
472
const Vec<3> & m,
473
double eps) const
474
{
475
double hv1 = (GetSurface(0).CalcFunctionValue(p));
476
if (hv1 <= -eps)
477
return IS_INSIDE;
478
if (hv1 >= eps)
479
return IS_OUTSIDE;
480
481
Vec<3> grad;
482
GetSurface(0).CalcGradient (p, grad);
483
484
hv1 = v * grad;
485
if (hv1 <= -eps) return IS_INSIDE;
486
if (hv1 >= eps) return IS_OUTSIDE;
487
488
Mat<3> hesse;
489
GetSurface(0).CalcHesse (p, hesse);
490
491
double hv2 = v2 * grad + v * (hesse * v);
492
493
if (hv2 <= -eps) return IS_INSIDE;
494
if (hv2 >= eps) return IS_OUTSIDE;
495
496
497
double hv3 = m * grad;
498
if (hv3 <= -eps) return IS_INSIDE;
499
if (hv3 >= eps) return IS_OUTSIDE;
500
501
return DOES_INTERSECT;
502
}
503
504
505
506
507
508
509
510
int OneSurfacePrimitive :: GetNSurfaces() const
511
{
512
return 1;
513
}
514
515
Surface & OneSurfacePrimitive :: GetSurface (int i)
516
{
517
return *this;
518
}
519
520
const Surface & OneSurfacePrimitive :: GetSurface (int i) const
521
{
522
return *this;
523
}
524
525
526
527
528
529
530
void ProjectToEdge (const Surface * f1, const Surface * f2, Point<3> & hp)
531
{
532
Vec<2> rs, lam;
533
Vec<3> a1, a2;
534
Mat<2> a;
535
536
int i = 10;
537
while (i > 0)
538
{
539
i--;
540
rs(0) = f1 -> CalcFunctionValue (hp);
541
rs(1) = f2 -> CalcFunctionValue (hp);
542
f1->CalcGradient (hp, a1);
543
f2->CalcGradient (hp, a2);
544
545
double alpha = fabs(a1*a2)/sqrt(a1.Length2()*a2.Length2());
546
if(fabs(1.-alpha) < 1e-6)
547
{
548
if(fabs(rs(0)) >= fabs(rs(1)))
549
f1 -> Project(hp);
550
else
551
f2 -> Project(hp);
552
}
553
else
554
{
555
556
a(0,0) = a1 * a1;
557
a(0,1) = a(1,0) = a1 * a2;
558
a(1,1) = a2 * a2;
559
560
a.Solve (rs, lam);
561
562
hp -= lam(0) * a1 + lam(1) * a2;
563
}
564
565
if (Abs2 (rs) < 1e-24 && i > 1) i = 1;
566
}
567
}
568
}
569
570