Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/ElmerGUI/netgen/libsrc/csg/revolution.cpp
3206 views
1
#include <mystdlib.h>
2
3
#include <linalg.hpp>
4
#include <csg.hpp>
5
6
namespace netgen
7
{
8
void RevolutionFace :: Init(void)
9
{
10
const LineSeg<2> * line = dynamic_cast<const LineSeg<2>*>(spline);
11
const SplineSeg3<2> * spline3 = dynamic_cast<const SplineSeg3<2>*>(spline);
12
13
if(line)
14
{
15
checklines_start.Append(new Point<2>(line->StartPI()));
16
checklines_vec.Append(new Vec<2>(line->EndPI() - line->StartPI()));
17
(*checklines_vec.Last()) *= 1./pow(checklines_vec.Last()->Length(),2); //!!
18
}
19
else if (spline3)
20
{
21
checklines_start.Append(new Point<2>(spline3->EndPI()));
22
checklines_start.Append(new Point<2>(spline3->TangentPoint()));
23
checklines_start.Append(new Point<2>(spline3->StartPI()));
24
checklines_vec.Append(new Vec<2>(spline3->StartPI() - spline3->EndPI()));
25
(*checklines_vec.Last()) *= 1./pow(checklines_vec.Last()->Length(),2); //!!
26
checklines_vec.Append(new Vec<2>(spline3->EndPI() - spline3->TangentPoint()));
27
(*checklines_vec.Last()) *= 1./pow(checklines_vec.Last()->Length(),2); //!!
28
checklines_vec.Append(new Vec<2>(spline3->TangentPoint() - spline3->StartPI()));
29
(*checklines_vec.Last()) *= 1./pow(checklines_vec.Last()->Length(),2); //!!
30
31
}
32
33
for(int i=0; i<checklines_vec.Size(); i++)
34
{
35
checklines_normal.Append(new Vec<2>);
36
(*checklines_normal.Last())(0) = - (*checklines_vec[i])(1);
37
(*checklines_normal.Last())(1) = (*checklines_vec[i])(0);
38
checklines_normal.Last()->Normalize();
39
}
40
}
41
42
RevolutionFace :: RevolutionFace(const SplineSeg<2> & spline_in,
43
const Point<3> & p,
44
const Vec<3> & vec,
45
bool first,
46
bool last,
47
const int id_in) :
48
spline(&spline_in), p0(p), v_axis(vec), isfirst(first), islast(last), id(id_in)
49
{
50
deletable = false;
51
Init();
52
}
53
54
55
RevolutionFace :: RevolutionFace(const ARRAY<double> & raw_data)
56
{
57
deletable = true;
58
59
int pos = 0;
60
61
ARRAY< Point<2> > p(3);
62
63
int stype = int(raw_data[pos]); pos++;
64
65
for(int i=0; i<stype; i++)
66
{
67
p[i](0) = raw_data[pos]; pos++;
68
p[i](1) = raw_data[pos]; pos++;
69
}
70
71
if(stype == 2)
72
{
73
spline = new LineSeg<2>(GeomPoint<2>(p[0],1),
74
GeomPoint<2>(p[1],1));
75
//(*testout) << "appending LineSeg<2> " << p[0]
76
// << " to " << p[1] << endl;
77
}
78
else if(stype == 3)
79
{
80
spline = new SplineSeg3<2>(GeomPoint<2>(p[0],1),
81
GeomPoint<2>(p[1],1),
82
GeomPoint<2>(p[2],1));
83
//(*testout) << "appending SplineSeg<3> "
84
// << p[0] << " -- " << p[1] << " -- " << p[2] << endl;
85
}
86
87
for(int i=0; i<3; i++)
88
{
89
p0(i) = raw_data[pos];
90
pos++;
91
}
92
for(int i=0; i<3; i++)
93
{
94
v_axis(i) = raw_data[pos];
95
pos++;
96
}
97
isfirst = (raw_data[pos] > 0.9);
98
pos++;
99
islast = (raw_data[pos] < 0.1);
100
pos++;
101
102
103
}
104
105
106
RevolutionFace :: ~RevolutionFace()
107
{
108
for(int i=0; i<checklines_start.Size(); i++)
109
{
110
delete checklines_start[i];
111
delete checklines_vec[i];
112
delete checklines_normal[i];
113
}
114
115
if(deletable)
116
delete spline;
117
}
118
119
void RevolutionFace :: CalcProj(const Point<3> & point3d, Point<2> & point2d,
120
const Vec<3> & vector3d, Vec<2> & vector2d) const
121
{
122
Vec<3> pmp0 = point3d-p0;
123
CalcProj0(pmp0,point2d);
124
Vec<3> y=pmp0-point2d(0)*v_axis; y.Normalize();
125
vector2d(0) = vector3d*v_axis;
126
vector2d(1) = vector3d*y;
127
}
128
129
130
void RevolutionFace :: CalcProj(const Point<3> & point3d, Point<2> & point2d) const
131
{
132
Vec<3> pmp0 = point3d-p0;
133
CalcProj0(pmp0,point2d);
134
}
135
136
void RevolutionFace :: CalcProj0(const Vec<3> & point3d_minus_p0, Point<2> & point2d) const
137
{
138
point2d(0) = point3d_minus_p0 * v_axis;
139
point2d(1) = sqrt( point3d_minus_p0 * point3d_minus_p0 - point2d(0)*point2d(0) );
140
}
141
142
143
int RevolutionFace ::IsIdentic (const Surface & s2, int & inv, double eps) const
144
{
145
const RevolutionFace * rev2 = dynamic_cast<const RevolutionFace*>(&s2);
146
147
if(!rev2) return 0;
148
149
if(rev2 == this)
150
return 1;
151
152
return 0;
153
}
154
155
double RevolutionFace :: CalcFunctionValue (const Point<3> & point) const
156
{
157
if(spline_coefficient.Size() == 0)
158
spline->GetCoeff(spline_coefficient);
159
160
Point<2> p;
161
CalcProj(point,p);
162
163
return spline_coefficient(0)*p(0)*p(0) + spline_coefficient(1)*p(1)*p(1)
164
+ spline_coefficient(2)*p(0)*p(1) + spline_coefficient(3)*p(0)
165
+ spline_coefficient(4)*p(1) + spline_coefficient(5);
166
}
167
168
void RevolutionFace :: CalcGradient (const Point<3> & point, Vec<3> & grad) const
169
{
170
if(spline_coefficient.Size() == 0)
171
spline->GetCoeff(spline_coefficient);
172
173
Vec<3> point_minus_p0 = point-p0;
174
175
Point<2> p;
176
CalcProj0(point_minus_p0,p);
177
178
const double dFdxbar = 2.*spline_coefficient(0)*p(0) + spline_coefficient(2)*p(1) + spline_coefficient(3);
179
180
if(fabs(p(1)) > 1e-10)
181
{
182
const double dFdybar = 2.*spline_coefficient(1)*p(1) + spline_coefficient(2)*p(0) + spline_coefficient(4);
183
184
grad(0) = dFdxbar*v_axis(0) + dFdybar * ( point_minus_p0(0)-v_axis(0)*p(0) )/p(1);
185
grad(1) = dFdxbar*v_axis(1) + dFdybar * ( point_minus_p0(1)-v_axis(1)*p(0) )/p(1);
186
grad(2) = dFdxbar*v_axis(2) + dFdybar * ( point_minus_p0(2)-v_axis(2)*p(0) )/p(1);
187
//(*testout) << "grad1("<<point<<") = " << grad << endl;
188
}
189
else
190
{
191
grad(0) = dFdxbar*v_axis(0);
192
grad(1) = dFdxbar*v_axis(1);
193
grad(2) = dFdxbar*v_axis(2);
194
//(*testout) << "grad2("<<point<<") = " << grad << endl;
195
}
196
}
197
198
199
void RevolutionFace :: CalcHesse (const Point<3> & point, Mat<3> & hesse) const
200
{
201
if(spline_coefficient.Size() == 0)
202
spline->GetCoeff(spline_coefficient);
203
204
Vec<3> point_minus_p0 = point-p0;
205
206
Point<2> p;
207
CalcProj0(point_minus_p0,p);
208
209
210
if(fabs(p(1)) > 1e-10)
211
{
212
const double dFdybar = 2.*spline_coefficient(1)*p(1) + spline_coefficient(2)*p(0) + spline_coefficient(4);
213
214
const double aux = -pow(p(1),-3);
215
const double aux0 = point_minus_p0(0) - v_axis(0)*p(0);
216
const double aux1 = point_minus_p0(1) - v_axis(1)*p(0);
217
const double aux2 = point_minus_p0(2) - v_axis(2)*p(0);
218
219
220
const double dybardx = aux0/p(1);
221
const double dybardy = aux1/p(1);
222
const double dybardz = aux2/p(1);
223
224
const double dybardxx = aux*aux0*aux0 + (1.-v_axis(0)*v_axis(0))/p(1);
225
const double dybardyy = aux*aux1*aux1 + (1.-v_axis(1)*v_axis(1))/p(1);
226
const double dybardzz = aux*aux2*aux2 + (1.-v_axis(2)*v_axis(2))/p(1);
227
const double dybardxy = aux*aux0*aux1 - v_axis(0)*v_axis(1)/p(1);
228
const double dybardxz = aux*aux0*aux2 - v_axis(0)*v_axis(2)/p(1);
229
const double dybardyz = aux*aux1*aux2 - v_axis(1)*v_axis(2)/p(1);
230
231
hesse(0,0) = 2.*spline_coefficient(0)*v_axis(0)*v_axis(0) + 2.*spline_coefficient(2)*v_axis(0)*dybardx + 2.*spline_coefficient(1)*dybardx*dybardx
232
+ dFdybar*dybardxx;
233
hesse(1,1) = 2.*spline_coefficient(0)*v_axis(1)*v_axis(1) + 2.*spline_coefficient(2)*v_axis(1)*dybardy + 2.*spline_coefficient(1)*dybardy*dybardy
234
+ dFdybar*dybardyy;
235
hesse(2,2) = 2.*spline_coefficient(0)*v_axis(2)*v_axis(2) + 2.*spline_coefficient(2)*v_axis(2)*dybardz + 2.*spline_coefficient(1)*dybardz*dybardz
236
+ dFdybar*dybardzz;
237
238
hesse(0,1) = hesse(1,0) = 2.*spline_coefficient(0)*v_axis(0)*v_axis(1) + spline_coefficient(2)*v_axis(0)*dybardy + spline_coefficient(2)*dybardx*v_axis(1)
239
+ 2.*spline_coefficient(2)*dybardx*dybardy + dFdybar*dybardxy;
240
hesse(0,2) = hesse(2,0) = 2.*spline_coefficient(0)*v_axis(0)*v_axis(2) + spline_coefficient(2)*v_axis(0)*dybardz + spline_coefficient(2)*dybardx*v_axis(2)
241
+ 2.*spline_coefficient(2)*dybardx*dybardz + dFdybar*dybardxz;
242
hesse(1,2) = hesse(2,1) = 2.*spline_coefficient(0)*v_axis(1)*v_axis(2) + spline_coefficient(2)*v_axis(1)*dybardz + spline_coefficient(2)*dybardy*v_axis(2)
243
+ 2.*spline_coefficient(2)*dybardy*dybardz + dFdybar*dybardyz;
244
245
//(*testout) << "hesse1: " << hesse <<endl;
246
}
247
else if (fabs(spline_coefficient(2)) + fabs(spline_coefficient(4)) < 1.e-9 &&
248
fabs(spline_coefficient(0)) > 1e-10)
249
{
250
double aux = spline_coefficient(0)-spline_coefficient(1);
251
252
hesse(0,0) = aux*v_axis(0)*v_axis(0) + spline_coefficient(1);
253
hesse(0,0) = aux*v_axis(1)*v_axis(1) + spline_coefficient(1);
254
hesse(0,0) = aux*v_axis(2)*v_axis(2) + spline_coefficient(1);
255
256
hesse(0,1) = hesse(1,0) = aux*v_axis(0)*v_axis(1);
257
hesse(0,2) = hesse(2,0) = aux*v_axis(0)*v_axis(2);
258
hesse(1,2) = hesse(2,1) = aux*v_axis(1)*v_axis(2);
259
//(*testout) << "hesse2: " << hesse <<endl;
260
261
}
262
else if (fabs(spline_coefficient(1)) + fabs(spline_coefficient(3)) + fabs(spline_coefficient(4)) + fabs(spline_coefficient(5)) < 1.e-9) // line
263
{
264
hesse = 0;
265
//(*testout) << "hesse3: " << hesse <<endl;
266
}
267
else
268
{
269
(*testout) << "hesse4: " << hesse <<endl;
270
}
271
}
272
273
274
275
double RevolutionFace ::HesseNorm () const
276
{
277
if (fabs(spline_coefficient(1)) + fabs(spline_coefficient(3)) + fabs(spline_coefficient(4)) + fabs(spline_coefficient(5)) < 1.e-9) // line
278
return 0;
279
280
if (fabs(spline_coefficient(2)) + fabs(spline_coefficient(4)) < 1.e-9 &&
281
fabs(spline_coefficient(0)) > 1e-10)
282
return 2.*max2(fabs(spline_coefficient(0)),fabs(spline_coefficient(1)));
283
284
285
double alpha = fabs(spline_coefficient(2)*(spline->StartPI()(0)-spline->EndPI()(0))) /
286
max2(fabs(spline->StartPI()(1)),fabs(spline->EndPI()(1)));
287
288
return max2(2.*fabs(spline_coefficient(0))+sqrt(2.)*fabs(spline_coefficient(2)),
289
2.*fabs(spline_coefficient(1))+spline_coefficient(2)+1.5*alpha);
290
}
291
292
double RevolutionFace :: MaxCurvature() const
293
{
294
double retval = spline->MaxCurvature();
295
296
ARRAY < Point<2> > checkpoints;
297
298
const SplineSeg3<2> * ss3 = dynamic_cast<const SplineSeg3<2> *>(spline);
299
const LineSeg<2> * ls = dynamic_cast<const LineSeg<2> *>(spline);
300
301
if(ss3)
302
{
303
checkpoints.Append(ss3->StartPI());
304
checkpoints.Append(ss3->TangentPoint());
305
checkpoints.Append(ss3->TangentPoint());
306
checkpoints.Append(ss3->EndPI());
307
}
308
else if(ls)
309
{
310
checkpoints.Append(ls->StartPI());
311
checkpoints.Append(ls->EndPI());
312
}
313
314
for(int i=0; i<checkpoints.Size(); i+=2)
315
{
316
Vec<2> v = checkpoints[i+1]-checkpoints[i];
317
Vec<2> n(v(1),-v(0)); n.Normalize();
318
319
//if(ss3)
320
// (*testout) << "n " << n << endl;
321
322
if(fabs(n(1)) < 1e-15)
323
continue;
324
325
double t1 = -checkpoints[i](1)/n(1);
326
double t2 = -checkpoints[i+1](1)/n(1);
327
328
double c1 = (t1 > 0) ? (1./t1) : -1;
329
double c2 = (t2 > 0) ? (1./t2) : -1;
330
331
//if(ss3)
332
// (*testout) << "t1 " << t1 << " t2 " << t2 << " c1 " << c1 << " c2 " << c2 << endl;
333
334
if(c1 > retval)
335
retval = c1;
336
if(c2 > retval)
337
retval = c2;
338
}
339
340
//if(ss3)
341
// (*testout) << "curvature " << retval << endl;
342
343
return retval;
344
345
/*
346
347
348
// find smallest y value of spline:
349
ARRAY<double> testt;
350
351
if(!isfirst)
352
testt.Append(0);
353
if(!islast)
354
testt.Append(1);
355
356
const SplineSegment3 * s3 = dynamic_cast<const SplineSegment3 *>(&spline);
357
358
if(s3)
359
{
360
double denom = (2.-sqrt(2.))*(s3->EndPI()(1) - s3->StartPI()(1));
361
362
if(fabs(denom) < 1e-20)
363
testt.Append(0.5);
364
else
365
{
366
double sD = sqrt(pow(s3->TangentPoint()(1) - s3->StartPI()(1),2)+
367
pow(s3->TangentPoint()(1) - s3->EndPI()(1),2));
368
testt.Append((s3->StartPI()(1)*(sqrt(2.)-1.) - sqrt(2.)*s3->TangentPoint()(1) + s3->EndPI()(1) + sD)/denom);
369
testt.Append((s3->StartPI()(1)*(sqrt(2.)-1.) - sqrt(2.)*s3->TangentPoint()(1) + s3->EndPI()(1) - sD)/denom);
370
}
371
}
372
373
double miny = fabs(spline.GetPoint(testt[0])(1));
374
for(int i=1; i<testt.Size(); i++)
375
{
376
double thisy = fabs(spline.GetPoint(testt[i])(1));
377
if(thisy < miny)
378
miny = thisy;
379
}
380
381
return max2(splinecurvature,1./miny);
382
*/
383
}
384
385
void RevolutionFace :: Project (Point<3> & p) const
386
{
387
Point<2> p2d;
388
389
CalcProj(p,p2d);
390
391
const Vec<3> y = (p-p0)-p2d(0)*v_axis;
392
const double yl = y.Length();
393
394
double dummy;
395
396
spline->Project(p2d,p2d,dummy);
397
398
p = p0 + p2d(0)*v_axis;
399
400
if(yl > 1e-20*Dist(spline->StartPI(),spline->EndPI()))
401
p+= (p2d(1)/yl)*y;
402
}
403
404
405
406
407
Point<3> RevolutionFace :: GetSurfacePoint () const
408
{
409
Vec<3> random_vec(0.760320,-0.241175,0.60311534);
410
411
Vec<3> n = Cross(v_axis,random_vec); n.Normalize();
412
413
Point<2> sp = spline->GetPoint(0.5);
414
415
Point<3> retval = p0 + sp(0)*v_axis + sp(1)*n;
416
417
return retval;
418
}
419
420
421
void RevolutionFace :: Print (ostream & str) const
422
{
423
if(spline_coefficient.Size() == 0)
424
spline->GetCoeff(spline_coefficient);
425
426
str << p0(0) << " " << p0(1) << " " << p0(2) << " "
427
<< v_axis(0) << " " << v_axis(1) << " " << v_axis(2) << " ";
428
for(int i=0; i<6; i++) str << spline_coefficient(i) << " ";
429
str << endl;
430
}
431
432
433
void RevolutionFace :: GetTriangleApproximation (TriangleApproximation & tas,
434
const Box<3> & boundingbox,
435
double facets) const
436
{
437
Vec<3> random_vec(0.760320,-0.241175,0.60311534);
438
439
Vec<3> v1 = Cross(v_axis,random_vec); v1.Normalize();
440
Vec<3> v2 = Cross(v1,v_axis); v2.Normalize();
441
442
int n = int(2.*facets) + 1;
443
444
int i,j;
445
double phi;
446
Point<3> p;
447
448
for(i=0; i<=n; i++)
449
{
450
Point<2> sp = spline->GetPoint(double(i)/double(n));
451
for(j=0; j<=n; j++)
452
{
453
phi = 2.*M_PI*double(j)/double(n);
454
455
p = p0 + sp(0)*v_axis + sp(1)*cos(phi)*v1 + sp(1)*sin(phi)*v2;
456
tas.AddPoint(p);
457
}
458
}
459
460
for(i=0; i<n; i++)
461
for(j=0; j<n; j++)
462
{
463
int pi = (n+1)*i+j;
464
465
tas.AddTriangle( TATriangle (id, pi,pi+1,pi+n+1));
466
tas.AddTriangle( TATriangle (id, pi+1,pi+n+1,pi+n+2));
467
}
468
}
469
470
471
bool RevolutionFace :: BoxIntersectsFace(const Box<3> & box) const
472
{
473
Point<3> center = box.Center();
474
475
Project(center);
476
477
return (Dist(box.Center(),center) < 0.5*box.Diam());
478
}
479
480
481
/*
482
bool RevolutionFace :: BoxIntersectsFace (const BoxSphere<3> & box, bool & uncertain) const
483
{
484
Point<2> c,pmin,pmax;
485
CalcProj(box.Center(),c);
486
double aux = box.Diam()/sqrt(8.);
487
pmin(0) = c(0)-aux; pmin(1) = c(1)-aux;
488
pmax(0) = c(0)+aux; pmax(1) = c(1)+aux;
489
490
BoxSphere<2> box2d(pmin,pmax);
491
return BoxIntersectsFace(box2d, uncertain);
492
}
493
494
bool RevolutionFace :: BoxIntersectsFace (const BoxSphere<2> & box, bool & uncertain) const
495
{
496
const LineSegment * line = dynamic_cast<const LineSegment*>(&spline);
497
const SplineSegment3 * spline3 = dynamic_cast<const SplineSegment3*>(&spline);
498
499
bool always_right = true, always_left = true;
500
501
bool retval = false;
502
bool thisint;
503
bool intdirect = false;
504
bool inttangent = false;
505
uncertain = false;
506
507
if(line) inttangent = true;
508
509
for(int i=0; i<checklines_start.Size(); i++)
510
{
511
Vec<2> b = box.Center()- (*checklines_start[i]);
512
513
double d;
514
515
double checkdist = b * (*checklines_vec[i]);
516
double ncomp = b * (*checklines_normal[i]);
517
518
if(checkdist < 0)
519
d = b.Length();
520
else if (checkdist > 1)
521
{
522
if(spline3)
523
d = Dist(box.Center(),*checklines_start[(i+1)%3]);
524
else
525
d = Dist(box.Center(),(*checklines_start[i])
526
+ pow(checklines_vec[i]->Length(),2)*(*checklines_vec[i]));
527
}
528
else
529
d = fabs(ncomp);
530
531
thisint = (box.Diam() >= 2.*d);
532
retval = retval || thisint;
533
if(thisint)
534
{
535
if(i==0)
536
intdirect = true;
537
else
538
inttangent = true;
539
}
540
541
if(ncomp > 0) always_right = false;
542
else if(ncomp < 0) always_left = false;
543
}
544
545
if(retval && !(intdirect && inttangent))
546
uncertain = true;
547
548
if(!retval && spline3 && (always_right || always_left))
549
{
550
retval = true;
551
uncertain = true;
552
}
553
554
return retval;
555
}
556
*/
557
558
559
INSOLID_TYPE RevolutionFace :: PointInFace (const Point<3> & p, const double eps) const
560
{
561
Point<2> p2d;
562
CalcProj(p,p2d);
563
564
double val = spline_coefficient(0)*p2d(0)*p2d(0) + spline_coefficient(1)*p2d(1)*p2d(1) + spline_coefficient(2)*p2d(0)*p2d(1) +
565
spline_coefficient(3)*p2d(0) + spline_coefficient(4)*p2d(1) + spline_coefficient(5);
566
567
if(val > eps)
568
return IS_OUTSIDE;
569
if(val < -eps)
570
return IS_INSIDE;
571
572
return DOES_INTERSECT;
573
}
574
575
576
577
void RevolutionFace :: GetRawData(ARRAY<double> & data) const
578
{
579
data.DeleteAll();
580
spline->GetRawData(data);
581
for(int i=0; i<3; i++)
582
data.Append(p0(i));
583
for(int i=0; i<3; i++)
584
data.Append(v_axis(i));
585
data.Append((isfirst) ? 1. : 0.);
586
data.Append((islast) ? 1. : 0.);
587
}
588
589
590
591
Revolution :: Revolution(const Point<3> & p0_in,
592
const Point<3> & p1_in,
593
const SplineGeometry2d & spline_in) :
594
p0(p0_in), p1(p1_in), splinecurve(spline_in),
595
nsplines(spline_in.GetNSplines())
596
{
597
surfaceactive.SetSize(0);
598
surfaceids.SetSize(0);
599
600
v_axis = p1-p0;
601
602
v_axis.Normalize();
603
604
if(splinecurve.GetSpline(0).StartPI()(1) <= 0. &&
605
splinecurve.GetSpline(nsplines-1).EndPI()(1) <= 0.)
606
type = 2;
607
else if (Dist(splinecurve.GetSpline(0).StartPI(),
608
splinecurve.GetSpline(nsplines-1).EndPI()) < 1e-7)
609
type = 1;
610
else
611
cerr << "Surface of revolution cannot be constructed" << endl;
612
613
for(int i=0; i<splinecurve.GetNSplines(); i++)
614
{
615
RevolutionFace * face = new RevolutionFace(splinecurve.GetSpline(i),
616
p0,v_axis,
617
type==2 && i==0,
618
type==2 && i==splinecurve.GetNSplines()-1);
619
faces.Append(face);
620
surfaceactive.Append(1);
621
surfaceids.Append(0);
622
}
623
}
624
625
Revolution::~Revolution()
626
{
627
for(int i=0; i<faces.Size(); i++)
628
delete faces[i];
629
}
630
631
632
INSOLID_TYPE Revolution :: BoxInSolid (const BoxSphere<3> & box) const
633
{
634
for(int i=0; i<faces.Size(); i++)
635
if(faces[i]->BoxIntersectsFace(box))
636
return DOES_INTERSECT;
637
638
639
return PointInSolid(box.Center(),0);
640
641
642
/*
643
Point<2> c,pmin,pmax;
644
faces[0]->CalcProj(box.Center(),c);
645
double aux = box.Diam()/sqrt(8.);
646
pmin(0) = c(0)-aux; pmin(1) = c(1)-aux;
647
pmax(0) = c(0)+aux; pmax(1) = c(1)+aux;
648
649
650
BoxSphere<2> box2d(pmin,pmax);
651
652
bool intersection = false;
653
bool uncertain = true;
654
655
for(int i=0; !(intersection && !uncertain) && i<faces.Size(); i++)
656
{
657
bool thisintersects;
658
bool thisuncertain;
659
thisintersects = faces[i]->BoxIntersectsFace(box2d,thisuncertain);
660
intersection = intersection || thisintersects;
661
if(thisintersects && !thisuncertain)
662
uncertain = false;
663
}
664
665
if(intersection)
666
{
667
if(!uncertain)
668
return DOES_INTERSECT;
669
else
670
{
671
ARRAY < Point<3> > pext(2);
672
Point<3> p;
673
674
pext[0] = box.PMin();
675
pext[1] = box.PMax();
676
677
INSOLID_TYPE position;
678
bool firsttime = true;
679
680
for(int i=0; i<2; i++)
681
for(int j=0; j<2; j++)
682
for(int k=0; k<2; k++)
683
{
684
p(0) = pext[i](0);
685
p(1) = pext[j](1);
686
p(2) = pext[k](2);
687
INSOLID_TYPE ppos = PointInSolid(p,0);
688
if(ppos == DOES_INTERSECT)
689
return DOES_INTERSECT;
690
691
if(firsttime)
692
{
693
firsttime = false;
694
position = ppos;
695
}
696
if(position != ppos)
697
return DOES_INTERSECT;
698
}
699
return position;
700
701
}
702
}
703
704
return PointInSolid(box.Center(),0);
705
*/
706
}
707
708
INSOLID_TYPE Revolution :: PointInSolid (const Point<3> & p,
709
double eps) const
710
{
711
Point<2> p2d;
712
faces[0]->CalcProj(p,p2d);
713
714
int intersections_before(0), intersections_after(0);
715
double randomx = 7.42357;
716
double randomy = 1.814756;
717
randomx *= 1./sqrt(randomx*randomx+randomy*randomy);
718
randomy *= 1./sqrt(randomx*randomx+randomy*randomy);
719
720
721
const double a = randomy;
722
const double b = -randomx;
723
const double c = -a*p2d(0)-b*p2d(1);
724
725
ARRAY < Point<2> > points;
726
727
//(*testout) << "face intersections at: " << endl;
728
for(int i=0; i<faces.Size(); i++)
729
{
730
faces[i]->GetSpline().LineIntersections(a,b,c,points,eps);
731
732
for(int j=0; j<points.Size(); j++)
733
{
734
double t = (points[j](0)-p2d(0))/randomx;
735
736
//(*testout) << t << endl;
737
if ( t < -eps )
738
intersections_before++;
739
else if ( t > eps )
740
intersections_after++;
741
else
742
{
743
intersecting_face = i;
744
return DOES_INTERSECT;
745
}
746
}
747
}
748
749
if(intersections_before % 2 == 0)
750
return IS_OUTSIDE;
751
else
752
return IS_INSIDE;
753
}
754
755
INSOLID_TYPE Revolution :: VecInSolid (const Point<3> & p,
756
const Vec<3> & v,
757
double eps) const
758
{
759
INSOLID_TYPE pInSolid = PointInSolid(p,eps);
760
761
if(pInSolid != DOES_INTERSECT)
762
{
763
//(*testout) << "pInSolid" << endl;
764
return pInSolid;
765
}
766
767
ARRAY<int> intersecting_faces;
768
769
for(int i=0; i<faces.Size(); i++)
770
if(faces[i]->PointInFace(p,eps) == DOES_INTERSECT)
771
intersecting_faces.Append(i);
772
773
Vec<3> hv;
774
775
if(intersecting_faces.Size() == 1)
776
{
777
faces[intersecting_faces[0]]->CalcGradient(p,hv);
778
779
double hv1;
780
hv1 = v * hv;
781
782
if (hv1 <= -eps)
783
return IS_INSIDE;
784
if (hv1 >= eps)
785
return IS_OUTSIDE;
786
787
return DOES_INTERSECT;
788
}
789
else if(intersecting_faces.Size() == 2)
790
{
791
Point<2> p2d;
792
Vec<2> v2d;
793
faces[intersecting_faces[0]]->CalcProj(p,p2d,v,v2d);
794
795
if(Dist(faces[intersecting_faces[0]]->GetSpline().StartPI(),p2d) <
796
Dist(faces[intersecting_faces[0]]->GetSpline().EndPI(),p2d))
797
{
798
int aux = intersecting_faces[0];
799
intersecting_faces[0] = intersecting_faces[1];
800
intersecting_faces[1] = aux;
801
}
802
803
const SplineSeg3<2> * splinesegment3 =
804
dynamic_cast<const SplineSeg3<2> *>(&faces[intersecting_faces[0]]->GetSpline());
805
const LineSeg<2> * linesegment =
806
dynamic_cast<const LineSeg<2> *>(&faces[intersecting_faces[0]]->GetSpline());
807
808
Vec<2> t1,t2;
809
810
if(linesegment)
811
t1 = linesegment->StartPI() - linesegment->EndPI();
812
else if(splinesegment3)
813
t1 = splinesegment3->TangentPoint() - splinesegment3->EndPI();
814
815
linesegment =
816
dynamic_cast<const LineSeg<2> *>(&faces[intersecting_faces[1]]->GetSpline());
817
splinesegment3 =
818
dynamic_cast<const SplineSeg3<2> *>(&faces[intersecting_faces[1]]->GetSpline());
819
820
if(linesegment)
821
t2 = linesegment->EndPI() - linesegment->StartPI();
822
else if(splinesegment3)
823
t2 = splinesegment3->TangentPoint() - splinesegment3->StartPI();
824
825
t1.Normalize();
826
t2.Normalize();
827
828
double d1 = v2d*t1;
829
double d2 = v2d*t2;
830
831
Vec<2> n;
832
833
if(d1 > d2)
834
{
835
n(0) = t1(1);
836
n(1) = -t1(0);
837
}
838
else
839
{
840
n(0) = -t2(1);
841
n(1) = t2(0);
842
}
843
844
double d = v2d*n;
845
846
if(d > eps)
847
return IS_OUTSIDE;
848
else if (d < -eps)
849
return IS_INSIDE;
850
else
851
return DOES_INTERSECT;
852
853
854
}
855
else
856
{
857
cerr << "Jo gibt's denn des?" << endl;
858
}
859
860
return DOES_INTERSECT;
861
}
862
863
INSOLID_TYPE Revolution :: VecInSolid2 (const Point<3> & p,
864
const Vec<3> & v1,
865
const Vec<3> & v2,
866
double eps) const
867
{
868
INSOLID_TYPE ret1 = VecInSolid(p,v1,eps);
869
if(ret1 != DOES_INTERSECT)
870
return ret1;
871
872
return VecInSolid(p,v2,eps);
873
}
874
875
int Revolution :: GetNSurfaces() const
876
{
877
return faces.Size();
878
}
879
880
Surface & Revolution :: GetSurface (int i)
881
{
882
return *faces[i];
883
}
884
885
const Surface & Revolution :: GetSurface (int i) const
886
{
887
return *faces[i];
888
}
889
890
891
void Revolution :: Reduce (const BoxSphere<3> & box)
892
{
893
//bool dummy;
894
for(int i=0; i<faces.Size(); i++)
895
surfaceactive[i] = (faces[i]->BoxIntersectsFace(box));
896
//surfaceactive[i] = (faces[i]->BoxIntersectsFace(box,dummy));
897
}
898
899
void Revolution :: UnReduce ()
900
{
901
for(int i=0; i<faces.Size(); i++)
902
surfaceactive[i] = true;
903
}
904
}
905
906