Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/ElmerGUI/netgen/libsrc/stlgeom/stlgeom.cpp
3206 views
1
#include <mystdlib.h>
2
3
#include <myadt.hpp>
4
#include <linalg.hpp>
5
#include <gprim.hpp>
6
7
#include <meshing.hpp>
8
9
#include "stlgeom.hpp"
10
11
12
namespace netgen
13
{
14
15
//globalen searchtree fuer gesamte geometry aktivieren
16
int geomsearchtreeon = 0;
17
18
int usechartnormal = 1;
19
20
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
21
22
void STLMeshing (STLGeometry & geom,
23
Mesh & mesh)
24
{
25
geom.Clear();
26
geom.BuildEdges();
27
geom.MakeAtlas(mesh);
28
geom.CalcFaceNums();
29
geom.AddFaceEdges();
30
geom.LinkEdges();
31
32
mesh.ClearFaceDescriptors();
33
for (int i = 1; i <= geom.GetNOFaces(); i++)
34
mesh.AddFaceDescriptor (FaceDescriptor (i, 1, 0, 0));
35
}
36
37
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
38
//+++++++++++++++++++ STL GEOMETRY ++++++++++++++++++++++++++++
39
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
40
41
42
STLGeometry :: STLGeometry()
43
: edges(), edgesperpoint(),
44
normals(), externaledges(),
45
atlas(), chartmark(),
46
lines(), outerchartspertrig(), vicinity(), markedtrigs(), markedsegs(),
47
lineendpoints(), spiralpoints(), selectedmultiedge()
48
{
49
edgedata = new STLEdgeDataList(*this);
50
externaledges.SetSize(0);
51
Clear();
52
meshchart = 0; // initialize all ?? JS
53
54
if (geomsearchtreeon)
55
searchtree = new Box3dTree (GetBoundingBox().PMin() - Vec3d(1,1,1),
56
GetBoundingBox().PMax() + Vec3d(1,1,1));
57
else
58
searchtree = NULL;
59
60
status = STL_GOOD;
61
statustext = "Good Geometry";
62
smoothedges = NULL;
63
}
64
65
STLGeometry :: ~STLGeometry()
66
{
67
delete edgedata;
68
}
69
70
void STLGeometry :: STLInfo(double* data)
71
{
72
data[0] = GetNT();
73
74
Box<3> b = GetBoundingBox();
75
data[1] = b.PMin()(0);
76
data[2] = b.PMax()(0);
77
data[3] = b.PMin()(1);
78
data[4] = b.PMax()(1);
79
data[5] = b.PMin()(2);
80
data[6] = b.PMax()(2);
81
82
int i;
83
84
int cons = 1;
85
for (i = 1; i <= GetNT(); i++)
86
{
87
if (NONeighbourTrigs(i) != 3) {cons = 0;}
88
}
89
data[7] = cons;
90
}
91
92
void STLGeometry :: MarkNonSmoothNormals()
93
{
94
95
PrintFnStart("Mark Non-Smooth Normals");
96
97
int i,j;
98
99
markedtrigs.SetSize(GetNT());
100
101
for (i = 1; i <= GetNT(); i++)
102
{
103
SetMarkedTrig(i, 0);
104
}
105
106
double dirtyangle = stlparam.yangle/180.*M_PI;
107
108
int cnt = 0;
109
int lp1,lp2;
110
for (i = 1; i <= GetNT(); i++)
111
{
112
for (j = 1; j <= NONeighbourTrigs(i); j++)
113
{
114
if (GetAngle(i, NeighbourTrig(i,j)) > dirtyangle)
115
{
116
GetTriangle(i).GetNeighbourPoints(GetTriangle(NeighbourTrig(i,j)), lp1, lp2);
117
if (!IsEdge(lp1,lp2))
118
{
119
if (!IsMarkedTrig(i)) {SetMarkedTrig(i,1); cnt++;}
120
}
121
}
122
}
123
}
124
125
PrintMessage(5,"marked ",cnt," non-smooth trig-normals");
126
127
}
128
129
void STLGeometry :: SmoothNormals()
130
{
131
multithread.terminate = 0;
132
133
// UseExternalEdges();
134
135
BuildEdges();
136
137
138
DenseMatrix m(3), hm(3);
139
Vector rhs(3), sol(3), hv(3), hv2(3);
140
141
Vec<3> ri;
142
143
double wnb = stldoctor.smoothnormalsweight; // neigbour normal weight
144
double wgeom = 1-wnb; // geometry normal weight
145
146
147
// minimize
148
// wgeom sum_T \sum ri \| ri^T (n - n_geom) \|^2
149
// + wnb sum_SE \| ri x (n - n_nb) \|^2
150
151
int i, j, k, l;
152
int nt = GetNT();
153
154
PushStatusF("Smooth Normals");
155
156
//int testmode;
157
158
for (i = 1; i <= nt; i++)
159
{
160
161
SetThreadPercent( 100.0 * (double)i / (double)nt);
162
163
const STLTriangle & trig = GetTriangle (i);
164
165
m = 0;
166
rhs = 0;
167
168
// normal of geometry:
169
Vec<3> ngeom = trig.GeomNormal(points);
170
ngeom.Normalize();
171
172
for (j = 1; j <= 3; j++)
173
{
174
int pi1 = trig.PNumMod (j);
175
int pi2 = trig.PNumMod (j+1);
176
177
// edge vector
178
ri = GetPoint (pi2) - GetPoint (pi1);
179
180
for (k = 0; k < 3; k++)
181
for (l = 0; l < 3; l++)
182
hm.Elem(k+1, l+1) = wgeom * ri(k) * ri(l);
183
184
185
for (k = 0; k < 3; k++)
186
hv.Elem(k+1) = ngeom(k);
187
188
hm.Mult (hv, hv2);
189
/*
190
if (testmode)
191
(*testout) << "add vec " << hv2 << endl
192
<< " add m " << hm << endl;
193
*/
194
rhs.Add (1, hv2);
195
m += hm;
196
197
198
int nbt = 0;
199
int fp1,fp2;
200
for (k = 1; k <= NONeighbourTrigs(i); k++)
201
{
202
trig.GetNeighbourPoints(GetTriangle(NeighbourTrig(i, k)),fp1,fp2);
203
if (fp1 == pi1 && fp2 == pi2)
204
{
205
nbt = NeighbourTrig(i, k);
206
}
207
}
208
209
if (!nbt)
210
{
211
cerr << "ERROR: stlgeom::Smoothnormals, nbt = 0" << endl;
212
}
213
214
// smoothed normal
215
Vec<3> nnb = GetTriangle(nbt).Normal(); // neighbour normal
216
nnb.Normalize();
217
218
if (!IsEdge(pi1,pi2))
219
{
220
double lr2 = ri * ri;
221
for (k = 0; k < 3; k++)
222
{
223
for (l = 0; l < k; l++)
224
{
225
hm.Elem(k+1, l+1) = -wnb * ri(k) * ri(l);
226
hm.Elem(l+1, k+1) = -wnb * ri(k) * ri(l);
227
}
228
229
hm.Elem(k+1, k+1) = wnb * (lr2 - ri(k) * ri(k));
230
}
231
232
for (k = 0; k < 3; k++)
233
hv.Elem(k+1) = nnb(k);
234
235
hm.Mult (hv, hv2);
236
/*
237
if (testmode)
238
(*testout) << "add nb vec " << hv2 << endl
239
<< " add nb m " << hm << endl;
240
*/
241
242
rhs.Add (1, hv2);
243
m += hm;
244
}
245
}
246
247
m.Solve (rhs, sol);
248
Vec3d newn(sol.Get(1), sol.Get(2), sol.Get(3));
249
newn /= (newn.Length() + 1e-24);
250
251
GetTriangle(i).SetNormal(newn);
252
// setnormal (sol);
253
}
254
255
/*
256
for (i = 1; i <= nt; i++)
257
SetMarkedTrig(i, 0);
258
259
260
261
int crloop;
262
for (crloop = 1; crloop <= 3; crloop++)
263
{
264
265
// find critical:
266
267
ARRAY<INDEX_2> critpairs;
268
for (i = 1; i <= nt; i++)
269
{
270
const STLTriangle & trig = GetTriangle (i);
271
272
Vec3d ngeom = GetTriangleNormal (i); // trig.Normal(points);
273
ngeom /= (ngeom.Length() + 1e-24);
274
275
for (j = 1; j <= 3; j++)
276
{
277
int pi1 = trig.PNumMod (j);
278
int pi2 = trig.PNumMod (j+1);
279
280
int nbt = 0;
281
int fp1,fp2;
282
for (k = 1; k <= NONeighbourTrigs(i); k++)
283
{
284
trig.GetNeighbourPoints(GetTriangle(NeighbourTrig(i, k)),fp1,fp2);
285
if (fp1 == pi1 && fp2 == pi2)
286
{
287
nbt = NeighbourTrig(i, k);
288
}
289
}
290
291
if (!nbt)
292
{
293
cerr << "ERROR: stlgeom::Smoothnormals, nbt = 0" << endl;
294
}
295
296
Vec3d nnb = GetTriangleNormal(nbt); // neighbour normal
297
nnb /= (nnb.Length() + 1e-24);
298
299
if (!IsEdge(pi1,pi2))
300
{
301
if (Angle (nnb, ngeom) > 150 * M_PI/180)
302
{
303
SetMarkedTrig(i, 1);
304
SetMarkedTrig(nbt, 1);
305
critpairs.Append (INDEX_2 (i, nbt));
306
}
307
}
308
309
}
310
}
311
312
if (!critpairs.Size())
313
{
314
break;
315
}
316
317
if (critpairs.Size())
318
{
319
320
ARRAY<int> friends;
321
double area1 = 0, area2 = 0;
322
323
for (i = 1; i <= critpairs.Size(); i++)
324
{
325
int tnr1 = critpairs.Get(i).I1();
326
int tnr2 = critpairs.Get(i).I2();
327
(*testout) << "t1 = " << tnr1 << ", t2 = " << tnr2
328
<< " angle = " << Angle (GetTriangleNormal (tnr1),
329
GetTriangleNormal (tnr2))
330
<< endl;
331
332
// who has more friends ?
333
int side;
334
area1 = 0;
335
area2 = 0;
336
for (side = 1; side <= 2; side++)
337
{
338
friends.SetSize (0);
339
friends.Append ( (side == 1) ? tnr1 : tnr2);
340
341
for (j = 1; j <= 3; j++)
342
{
343
int fsize = friends.Size();
344
for (k = 1; k <= fsize; k++)
345
{
346
int testtnr = friends.Get(k);
347
Vec3d ntt = GetTriangleNormal(testtnr);
348
ntt /= (ntt.Length() + 1e-24);
349
350
for (l = 1; l <= NONeighbourTrigs(testtnr); l++)
351
{
352
int testnbnr = NeighbourTrig(testtnr, l);
353
Vec3d nbt = GetTriangleNormal(testnbnr);
354
nbt /= (nbt.Length() + 1e-24);
355
356
if (Angle (nbt, ntt) < 15 * M_PI/180)
357
{
358
int ii;
359
int found = 0;
360
for (ii = 1; ii <= friends.Size(); ii++)
361
{
362
if (friends.Get(ii) == testnbnr)
363
{
364
found = 1;
365
break;
366
}
367
}
368
if (!found)
369
friends.Append (testnbnr);
370
}
371
}
372
}
373
}
374
375
// compute area:
376
for (k = 1; k <= friends.Size(); k++)
377
{
378
double area =
379
GetTriangle (friends.Get(k)).Area(points);
380
381
if (side == 1)
382
area1 += area;
383
else
384
area2 += area;
385
}
386
387
}
388
389
(*testout) << "area1 = " << area1 << " area2 = " << area2 << endl;
390
if (area1 < 0.1 * area2)
391
{
392
Vec3d n = GetTriangleNormal (tnr1);
393
n *= -1;
394
SetTriangleNormal(tnr1, n);
395
}
396
if (area2 < 0.1 * area1)
397
{
398
Vec3d n = GetTriangleNormal (tnr2);
399
n *= -1;
400
SetTriangleNormal(tnr2, n);
401
}
402
}
403
}
404
}
405
*/
406
407
calcedgedataanglesnew = 1;
408
PopStatus();
409
}
410
411
412
int STLGeometry :: AddEdge(int ap1, int ap2)
413
{
414
STLEdge e(ap1,ap2);
415
e.SetLeftTrig(GetLeftTrig(ap1,ap2));
416
e.SetRightTrig(GetRightTrig(ap1,ap2));
417
return edges.Append(e);
418
}
419
420
void STLGeometry :: STLDoctorConfirmEdge()
421
{
422
StoreEdgeData();
423
if (GetSelectTrig() >= 1 && GetSelectTrig() <= GetNT() && GetNodeOfSelTrig())
424
{
425
if (stldoctor.selectmode == 1)
426
{
427
int ap1 = GetTriangle(GetSelectTrig()).PNum(GetNodeOfSelTrig());
428
int ap2 = GetTriangle(GetSelectTrig()).PNumMod(GetNodeOfSelTrig()+1);
429
edgedata->Elem(edgedata->GetEdgeNum(ap1,ap2)).SetStatus (ED_CONFIRMED);
430
}
431
else if (stldoctor.selectmode == 3 || stldoctor.selectmode == 4)
432
{
433
int i;
434
for (i = 1; i <= selectedmultiedge.Size(); i++)
435
{
436
int ap1 = selectedmultiedge.Get(i).i1;
437
int ap2 = selectedmultiedge.Get(i).i2;
438
edgedata->Elem(edgedata->GetEdgeNum(ap1,ap2)).SetStatus (ED_CONFIRMED);
439
}
440
}
441
}
442
}
443
444
void STLGeometry :: STLDoctorCandidateEdge()
445
{
446
StoreEdgeData();
447
if (GetSelectTrig() >= 1 && GetSelectTrig() <= GetNT() && GetNodeOfSelTrig())
448
{
449
if (stldoctor.selectmode == 1)
450
{
451
int ap1 = GetTriangle(GetSelectTrig()).PNum(GetNodeOfSelTrig());
452
int ap2 = GetTriangle(GetSelectTrig()).PNumMod(GetNodeOfSelTrig()+1);
453
edgedata->Elem(edgedata->GetEdgeNum(ap1,ap2)).SetStatus (ED_CANDIDATE);
454
}
455
else if (stldoctor.selectmode == 3 || stldoctor.selectmode == 4)
456
{
457
int i;
458
for (i = 1; i <= selectedmultiedge.Size(); i++)
459
{
460
int ap1 = selectedmultiedge.Get(i).i1;
461
int ap2 = selectedmultiedge.Get(i).i2;
462
edgedata->Elem(edgedata->GetEdgeNum(ap1,ap2)).SetStatus (ED_CANDIDATE);
463
}
464
}
465
}
466
}
467
468
void STLGeometry :: STLDoctorExcludeEdge()
469
{
470
StoreEdgeData();
471
if (GetSelectTrig() >= 1 && GetSelectTrig() <= GetNT() && GetNodeOfSelTrig())
472
{
473
if (stldoctor.selectmode == 1)
474
{
475
int ap1 = GetTriangle(GetSelectTrig()).PNum(GetNodeOfSelTrig());
476
int ap2 = GetTriangle(GetSelectTrig()).PNumMod(GetNodeOfSelTrig()+1);
477
edgedata->Elem(edgedata->GetEdgeNum(ap1,ap2)).SetStatus(ED_EXCLUDED);
478
}
479
else if (stldoctor.selectmode == 3 || stldoctor.selectmode == 4)
480
{
481
int i;
482
for (i = 1; i <= selectedmultiedge.Size(); i++)
483
{
484
int ap1 = selectedmultiedge.Get(i).i1;
485
int ap2 = selectedmultiedge.Get(i).i2;
486
edgedata->Elem(edgedata->GetEdgeNum(ap1,ap2)).SetStatus(ED_EXCLUDED);
487
}
488
}
489
}
490
}
491
492
void STLGeometry :: STLDoctorUndefinedEdge()
493
{
494
StoreEdgeData();
495
if (GetSelectTrig() >= 1 && GetSelectTrig() <= GetNT() && GetNodeOfSelTrig())
496
{
497
if (stldoctor.selectmode == 1)
498
{
499
int ap1 = GetTriangle(GetSelectTrig()).PNum(GetNodeOfSelTrig());
500
int ap2 = GetTriangle(GetSelectTrig()).PNumMod(GetNodeOfSelTrig()+1);
501
edgedata->Elem(edgedata->GetEdgeNum(ap1,ap2)).SetStatus(ED_UNDEFINED);
502
}
503
else if (stldoctor.selectmode == 3 || stldoctor.selectmode == 4)
504
{
505
int i;
506
for (i = 1; i <= selectedmultiedge.Size(); i++)
507
{
508
int ap1 = selectedmultiedge.Get(i).i1;
509
int ap2 = selectedmultiedge.Get(i).i2;
510
edgedata->Elem(edgedata->GetEdgeNum(ap1,ap2)).SetStatus(ED_UNDEFINED);
511
}
512
}
513
}
514
}
515
516
void STLGeometry :: STLDoctorSetAllUndefinedEdges()
517
{
518
edgedata->ResetAll();
519
}
520
521
void STLGeometry :: STLDoctorEraseCandidateEdges()
522
{
523
StoreEdgeData();
524
edgedata->ChangeStatus(ED_CANDIDATE, ED_UNDEFINED);
525
}
526
527
void STLGeometry :: STLDoctorConfirmCandidateEdges()
528
{
529
StoreEdgeData();
530
edgedata->ChangeStatus(ED_CANDIDATE, ED_CONFIRMED);
531
}
532
533
void STLGeometry :: STLDoctorConfirmedToCandidateEdges()
534
{
535
StoreEdgeData();
536
edgedata->ChangeStatus(ED_CONFIRMED, ED_CANDIDATE);
537
}
538
539
void STLGeometry :: STLDoctorDirtyEdgesToCandidates()
540
{
541
StoreEdgeData();
542
}
543
544
void STLGeometry :: STLDoctorLongLinesToCandidates()
545
{
546
StoreEdgeData();
547
}
548
549
twoint STLGeometry :: GetNearestSelectedDefinedEdge()
550
{
551
Point<3> pestimate = Center(GetTriangle(GetSelectTrig()).center,
552
GetPoint(GetTriangle(GetSelectTrig()).PNum(GetNodeOfSelTrig())));
553
//Point3d pestimate = GetTriangle(GetSelectTrig()).center;
554
555
int i, j, en;
556
ARRAY<int> vic;
557
GetVicinity(GetSelectTrig(),4,vic);
558
559
560
twoint fedg;
561
fedg.i1 = 0;
562
fedg.i2 = 0;
563
double mindist = 1E50;
564
double dist;
565
Point<3> p;
566
567
for (i = 1; i <= vic.Size(); i++)
568
{
569
const STLTriangle& t = GetTriangle(vic.Get(i));
570
for (j = 1; j <= 3; j++)
571
{
572
en = edgedata->GetEdgeNum(t.PNum(j),t.PNumMod(j+1));
573
if (edgedata->Get(en).GetStatus() != ED_UNDEFINED)
574
{
575
p = pestimate;
576
dist = GetDistFromLine(GetPoint(t.PNum(j)),GetPoint(t.PNumMod(j+1)),p);
577
if (dist < mindist)
578
{
579
mindist = dist;
580
fedg.i1 = t.PNum(j);
581
fedg.i2 = t.PNumMod(j+1);
582
}
583
}
584
}
585
}
586
return fedg;
587
}
588
589
void STLGeometry :: BuildSelectedMultiEdge(twoint ep)
590
{
591
if (edgedata->Size() == 0 ||
592
!GetEPPSize())
593
{
594
return;
595
}
596
597
selectedmultiedge.SetSize(0);
598
int tenum = GetTopEdgeNum (ep.i1, ep.i2);
599
600
if (edgedata->Get(tenum).GetStatus() == ED_UNDEFINED)
601
{
602
twoint epnew = GetNearestSelectedDefinedEdge();
603
if (epnew.i1)
604
{
605
ep = epnew;
606
tenum = GetTopEdgeNum (ep.i1, ep.i2);
607
}
608
}
609
610
selectedmultiedge.Append(twoint(ep));
611
612
if (edgedata->Get(tenum).GetStatus() == ED_UNDEFINED)
613
{
614
return;
615
}
616
617
edgedata->BuildLineWithEdge(ep.i1,ep.i2,selectedmultiedge);
618
}
619
620
void STLGeometry :: BuildSelectedEdge(twoint ep)
621
{
622
if (edgedata->Size() == 0 ||
623
!GetEPPSize())
624
{
625
return;
626
}
627
628
selectedmultiedge.SetSize(0);
629
630
selectedmultiedge.Append(twoint(ep));
631
}
632
633
void STLGeometry :: BuildSelectedCluster(twoint ep)
634
{
635
if (edgedata->Size() == 0 ||
636
!GetEPPSize())
637
{
638
return;
639
}
640
641
selectedmultiedge.SetSize(0);
642
643
int tenum = GetTopEdgeNum (ep.i1, ep.i2);
644
645
if (edgedata->Get(tenum).GetStatus() == ED_UNDEFINED)
646
{
647
twoint epnew = GetNearestSelectedDefinedEdge();
648
if (epnew.i1)
649
{
650
ep = epnew;
651
tenum = GetTopEdgeNum (ep.i1, ep.i2);
652
}
653
}
654
655
selectedmultiedge.Append(twoint(ep));
656
657
if (edgedata->Get(tenum).GetStatus() == ED_UNDEFINED)
658
{
659
return;
660
}
661
662
edgedata->BuildClusterWithEdge(ep.i1,ep.i2,selectedmultiedge);
663
}
664
665
void STLGeometry :: ImportEdges()
666
{
667
StoreEdgeData();
668
669
PrintMessage(5, "import edges from file 'edges.ng'");
670
ifstream fin("edges.ng");
671
672
int ne;
673
fin >> ne;
674
675
ARRAY<Point<3> > eps;
676
677
int i;
678
Point<3> p;
679
for (i = 1; i <= 2*ne; i++)
680
{
681
fin >> p(0);
682
fin >> p(1);
683
fin >> p(2);
684
eps.Append(p);
685
}
686
AddEdges(eps);
687
}
688
689
void STLGeometry :: AddEdges(const ARRAY<Point<3> >& eps)
690
{
691
int i;
692
int ne = eps.Size()/2;
693
694
ARRAY<int> epsi;
695
Box<3> bb = GetBoundingBox();
696
bb.Increase(1);
697
698
Point3dTree ptree (bb.PMin(),
699
bb.PMax());
700
ARRAY<int> pintersect;
701
702
double gtol = GetBoundingBox().Diam()/1.E10;
703
Point<3> p;
704
705
for (i = 1; i <= GetNP(); i++)
706
{
707
p = GetPoint(i);
708
ptree.Insert (p, i);
709
}
710
711
int error = 0;
712
for (i = 1; i <= 2*ne; i++)
713
{
714
p = eps.Get(i);
715
Point3d pmin = p - Vec3d (gtol, gtol, gtol);
716
Point3d pmax = p + Vec3d (gtol, gtol, gtol);
717
718
ptree.GetIntersecting (pmin, pmax, pintersect);
719
if (pintersect.Size() > 1)
720
{
721
PrintError("Found too much points in epsilon-dist");
722
error = 1;
723
}
724
else if (pintersect.Size() == 0)
725
{
726
error = 1;
727
PrintError("edgepoint does not exist!");
728
PrintMessage(5,"p=",Point3d(eps.Get(i)));
729
}
730
else
731
{
732
epsi.Append(pintersect.Get(1));
733
}
734
}
735
736
if (error) return;
737
738
int en;
739
for (i = 1; i <= ne; i++)
740
{
741
if (epsi.Get(2*i-1) == epsi.Get(2*i)) {PrintError("Edge with zero length!");}
742
else
743
{
744
en = edgedata->GetEdgeNum(epsi.Get(2*i-1),epsi.Get(2*i));
745
edgedata->Elem(en).SetStatus (ED_CONFIRMED);
746
}
747
}
748
749
}
750
751
752
753
void STLGeometry :: ImportExternalEdges(const char * filename)
754
{
755
//AVL edges!!!!!!
756
757
ifstream inf (filename);
758
char ch;
759
//int cnt = 0;
760
int records, units, i, j;
761
PrintFnStart("Import edges from ",filename);
762
763
const int flen=30;
764
char filter[flen+1];
765
filter[flen] = 0;
766
char buf[20];
767
768
ARRAY<Point3d> importpoints;
769
ARRAY<int> importlines;
770
ARRAY<int> importpnums;
771
772
while (inf.good())
773
{
774
inf.get(ch);
775
// (*testout) << cnt << ": " << ch << endl;
776
777
for (i = 0; i < flen; i++)
778
filter[i] = filter[i+1];
779
filter[flen-1] = ch;
780
// (*testout) << filter << endl;
781
782
if (strcmp (filter+flen-7, "RECORDS") == 0)
783
{
784
inf.get(ch); // '='
785
inf >> records;
786
}
787
if (strcmp (filter+flen-5, "UNITS") == 0)
788
{
789
inf.get(ch); // '='
790
inf >> units;
791
}
792
793
if (strcmp (filter+flen-17, "EDGE NODE NUMBERS") == 0)
794
{
795
int nodenr;
796
importlines.SetSize (units);
797
for (i = 1; i <= units; i++)
798
{
799
inf >> nodenr;
800
importlines.Elem(i) = nodenr;
801
// (*testout) << nodenr << endl;
802
}
803
}
804
805
if (strcmp (filter+flen-23, "EDGE POINT COORD IN DIR") == 0)
806
{
807
int coord;
808
809
inf >> coord;
810
811
importpoints.SetSize (units);
812
813
inf >> ch;
814
inf.putback (ch);
815
816
for (i = 1; i <= units; i++)
817
{
818
for (j = 0; j < 12; j++)
819
inf.get (buf[j]);
820
buf[12] = 0;
821
822
importpoints.Elem(i).X(coord) = 1000 * atof (buf);
823
}
824
}
825
}
826
827
/*
828
(*testout) << "lines: " << endl;
829
for (i = 1; i <= importlines.Size(); i++)
830
(*testout) << importlines.Get(i) << endl;
831
(*testout) << "points: " << endl;
832
for (i = 1; i <= importpoints.Size(); i++)
833
(*testout) << importpoints.Get(i) << endl;
834
*/
835
836
837
838
importpnums.SetSize (importpoints.Size());
839
840
841
Box3d bb (GetBoundingBox().PMin() + Vec3d (-1,-1,-1),
842
GetBoundingBox().PMax() + Vec3d (1, 1, 1));
843
844
Point3dTree ptree (bb.PMin(),
845
bb.PMax());
846
847
848
PrintMessage(7,"stl - bb: ",bb.PMin(), " - ", bb.PMax());
849
850
Box3d ebb;
851
ebb.SetPoint (importpoints.Get(1));
852
for (i = 1; i <= importpoints.Size(); i++)
853
ebb.AddPoint (importpoints.Get(i));
854
PrintMessage(7,"edgep - bb: ", ebb.PMin(), " - ", ebb.PMax());
855
856
ARRAY<int> pintersect;
857
858
double gtol = GetBoundingBox().Diam()/1.E6;
859
860
for (i = 1; i <= GetNP(); i++)
861
{
862
Point3d p = GetPoint(i);
863
// (*testout) << "stlpt: " << p << endl;
864
ptree.Insert (p, i);
865
}
866
867
868
for (i = 1; i <= importpoints.Size(); i++)
869
{
870
Point3d p = importpoints.Get(i);
871
Point3d pmin = p - Vec3d (gtol, gtol, gtol);
872
Point3d pmax = p + Vec3d (gtol, gtol, gtol);
873
874
ptree.GetIntersecting (pmin, pmax, pintersect);
875
if (pintersect.Size() > 1)
876
{
877
importpnums.Elem(i) = 0;
878
PrintError("Found too many points in epsilon-dist");
879
}
880
else if (pintersect.Size() == 0)
881
{
882
importpnums.Elem(i) = 0;
883
PrintError("Edgepoint does not exist!");
884
}
885
else
886
{
887
importpnums.Elem(i) = pintersect.Get(1);
888
}
889
}
890
891
// if (!error)
892
{
893
PrintMessage(7,"found all edge points in stl file");
894
895
896
StoreEdgeData();
897
898
int oldp = 0;
899
900
for (i = 1; i <= importlines.Size(); i++)
901
{
902
int newp = importlines.Get(i);
903
if (!importpnums.Get(abs(newp)))
904
newp = 0;
905
906
if (oldp && newp)
907
{
908
int en = edgedata->GetEdgeNum(importpnums.Get(oldp),
909
importpnums.Get(abs(newp)));
910
edgedata->Elem(en).SetStatus (ED_CONFIRMED);
911
}
912
913
if (newp < 0)
914
oldp = 0;
915
else
916
oldp = newp;
917
}
918
}
919
920
921
}
922
923
924
925
void STLGeometry :: ExportEdges()
926
{
927
PrintFnStart("Save edges to file 'edges.ng'");
928
929
ofstream fout("edges.ng");
930
fout.precision(16);
931
932
int n = edgedata->GetNConfEdges();
933
934
fout << n << endl;
935
936
int i;
937
for (i = 1; i <= edgedata->Size(); i++)
938
{
939
if (edgedata->Get(i).GetStatus() == ED_CONFIRMED)
940
{
941
const STLTopEdge & e = edgedata->Get(i);
942
fout << GetPoint(e.PNum(1))(0) << " " << GetPoint(e.PNum(1))(1) << " " << GetPoint(e.PNum(1))(2) << endl;
943
fout << GetPoint(e.PNum(2))(0) << " " << GetPoint(e.PNum(2))(1) << " " << GetPoint(e.PNum(2))(2) << endl;
944
}
945
}
946
947
}
948
949
void STLGeometry :: LoadEdgeData(const char* file)
950
{
951
StoreEdgeData();
952
953
PrintFnStart("Load edges from file '", file, "'");
954
ifstream fin(file);
955
956
edgedata->Read(fin);
957
958
// calcedgedataanglesnew = 1;
959
}
960
961
void STLGeometry :: SaveEdgeData(const char* file)
962
{
963
PrintFnStart("save edges to file '", file, "'");
964
ofstream fout(file);
965
966
edgedata->Write(fout);
967
}
968
969
970
971
972
973
974
975
/*
976
void STLGeometry :: SaveExternalEdges()
977
{
978
ofstream fout("externaledgesp3.ng");
979
fout.precision(16);
980
981
int n = NOExternalEdges();
982
fout << n << endl;
983
984
int i;
985
for (i = 1; i <= n; i++)
986
{
987
twoint e = GetExternalEdge(i);
988
fout << GetPoint(e.i1)(0) << " " << GetPoint(e.i1)(1) << " " << GetPoint(e.i1)(2) << endl;
989
fout << GetPoint(e.i2)(0) << " " << GetPoint(e.i2)(1) << " " << GetPoint(e.i2)(2) << endl;
990
}
991
992
}
993
*/
994
void STLGeometry :: StoreExternalEdges()
995
{
996
storedexternaledges.SetSize(0);
997
undoexternaledges = 1;
998
int i;
999
for (i = 1; i <= externaledges.Size(); i++)
1000
{
1001
storedexternaledges.Append(externaledges.Get(i));
1002
}
1003
1004
}
1005
1006
void STLGeometry :: UndoExternalEdges()
1007
{
1008
if (!undoexternaledges)
1009
{
1010
PrintMessage(1, "undo not further possible!");
1011
return;
1012
}
1013
RestoreExternalEdges();
1014
undoexternaledges = 0;
1015
}
1016
1017
void STLGeometry :: RestoreExternalEdges()
1018
{
1019
externaledges.SetSize(0);
1020
int i;
1021
for (i = 1; i <= storedexternaledges.Size(); i++)
1022
{
1023
externaledges.Append(storedexternaledges.Get(i));
1024
}
1025
1026
}
1027
1028
1029
void STLGeometry :: AddExternalEdgeAtSelected()
1030
{
1031
StoreExternalEdges();
1032
if (GetSelectTrig() >= 1 && GetSelectTrig() <= GetNT())
1033
{
1034
int ap1 = GetTriangle(GetSelectTrig()).PNum(GetNodeOfSelTrig());
1035
int ap2 = GetTriangle(GetSelectTrig()).PNumMod(GetNodeOfSelTrig()+1);
1036
if (!IsExternalEdge(ap1,ap2)) {AddExternalEdge(ap1,ap2);}
1037
}
1038
}
1039
1040
void STLGeometry :: AddClosedLinesToExternalEdges()
1041
{
1042
StoreExternalEdges();
1043
1044
int i, j;
1045
for (i = 1; i <= GetNLines(); i++)
1046
{
1047
STLLine* l = GetLine(i);
1048
if (l->StartP() == l->EndP())
1049
{
1050
for (j = 1; j < l->NP(); j++)
1051
{
1052
int ap1 = l->PNum(j);
1053
int ap2 = l->PNum(j+1);
1054
1055
if (!IsExternalEdge(ap1,ap2)) {AddExternalEdge(ap1,ap2);}
1056
}
1057
}
1058
}
1059
}
1060
1061
void STLGeometry :: AddLongLinesToExternalEdges()
1062
{
1063
StoreExternalEdges();
1064
1065
double diamfact = stldoctor.dirtytrigfact;
1066
double diam = GetBoundingBox().Diam();
1067
1068
int i, j;
1069
for (i = 1; i <= GetNLines(); i++)
1070
{
1071
STLLine* l = GetLine(i);
1072
if (l->GetLength(points) >= diamfact*diam)
1073
{
1074
for (j = 1; j < l->NP(); j++)
1075
{
1076
int ap1 = l->PNum(j);
1077
int ap2 = l->PNum(j+1);
1078
1079
if (!IsExternalEdge(ap1,ap2)) {AddExternalEdge(ap1,ap2);}
1080
}
1081
}
1082
}
1083
}
1084
1085
void STLGeometry :: AddAllNotSingleLinesToExternalEdges()
1086
{
1087
StoreExternalEdges();
1088
1089
int i, j;
1090
for (i = 1; i <= GetNLines(); i++)
1091
{
1092
STLLine* l = GetLine(i);
1093
if (GetNEPP(l->StartP()) > 1 || GetNEPP(l->EndP()) > 1)
1094
{
1095
for (j = 1; j < l->NP(); j++)
1096
{
1097
int ap1 = l->PNum(j);
1098
int ap2 = l->PNum(j+1);
1099
1100
if (!IsExternalEdge(ap1,ap2)) {AddExternalEdge(ap1,ap2);}
1101
}
1102
}
1103
}
1104
}
1105
1106
void STLGeometry :: DeleteDirtyExternalEdges()
1107
{
1108
//delete single triangle edges and single edge-lines in clusters"
1109
StoreExternalEdges();
1110
1111
int i, j;
1112
for (i = 1; i <= GetNLines(); i++)
1113
{
1114
STLLine* l = GetLine(i);
1115
if (l->NP() <= 3 || (l->StartP() == l->EndP() && l->NP() == 4))
1116
{
1117
for (j = 1; j < l->NP(); j++)
1118
{
1119
int ap1 = l->PNum(j);
1120
int ap2 = l->PNum(j+1);
1121
1122
if (IsExternalEdge(ap1,ap2)) {DeleteExternalEdge(ap1,ap2);}
1123
}
1124
}
1125
}
1126
}
1127
1128
void STLGeometry :: AddExternalEdgesFromGeomLine()
1129
{
1130
StoreExternalEdges();
1131
if (GetSelectTrig() >= 1 && GetSelectTrig() <= GetNT())
1132
{
1133
int ap1 = GetTriangle(GetSelectTrig()).PNum(GetNodeOfSelTrig());
1134
int ap2 = GetTriangle(GetSelectTrig()).PNumMod(GetNodeOfSelTrig()+1);
1135
1136
if (IsEdge(ap1,ap2))
1137
{
1138
int edgenum = IsEdgeNum(ap1,ap2);
1139
if (!IsExternalEdge(ap1,ap2)) {AddExternalEdge(ap1,ap2);}
1140
1141
int noend = 1;
1142
int startp = ap1;
1143
int laste = edgenum;
1144
int np1, np2;
1145
while (noend)
1146
{
1147
if (GetNEPP(startp) == 2)
1148
{
1149
if (GetEdgePP(startp,1) != laste) {laste = GetEdgePP(startp,1);}
1150
else {laste = GetEdgePP(startp,2);}
1151
np1 = GetEdge(laste).PNum(1);
1152
np2 = GetEdge(laste).PNum(2);
1153
1154
if (!IsExternalEdge(np1, np2)) {AddExternalEdge(np1, np2);}
1155
else {noend = 0;}
1156
if (np1 != startp) {startp = np1;}
1157
else {startp = np2;}
1158
}
1159
else {noend = 0;}
1160
}
1161
1162
startp = ap2;
1163
laste = edgenum;
1164
noend = 1;
1165
while (noend)
1166
{
1167
if (GetNEPP(startp) == 2)
1168
{
1169
if (GetEdgePP(startp,1) != laste) {laste = GetEdgePP(startp,1);}
1170
else {laste = GetEdgePP(startp,2);}
1171
np1 = GetEdge(laste).PNum(1);
1172
np2 = GetEdge(laste).PNum(2);
1173
1174
if (!IsExternalEdge(np1, np2)) {AddExternalEdge(np1, np2);}
1175
else {noend = 0;}
1176
if (np1 != startp) {startp = np1;}
1177
else {startp = np2;}
1178
}
1179
else {noend = 0;}
1180
}
1181
1182
}
1183
1184
}
1185
1186
}
1187
1188
void STLGeometry :: ClearEdges()
1189
{
1190
edgesfound = 0;
1191
edges.SetSize(0);
1192
//edgedata->SetSize(0);
1193
// externaledges.SetSize(0);
1194
edgesperpoint.SetSize(0);
1195
undoexternaledges = 0;
1196
1197
}
1198
1199
void STLGeometry :: STLDoctorBuildEdges()
1200
{
1201
// if (!trigsconverted) {return;}
1202
ClearEdges();
1203
1204
meshlines.SetSize(0);
1205
FindEdgesFromAngles();
1206
}
1207
1208
void STLGeometry :: DeleteExternalEdgeAtSelected()
1209
{
1210
StoreExternalEdges();
1211
if (GetSelectTrig() >= 1 && GetSelectTrig() <= GetNT())
1212
{
1213
int ap1 = GetTriangle(GetSelectTrig()).PNum(GetNodeOfSelTrig());
1214
int ap2 = GetTriangle(GetSelectTrig()).PNumMod(GetNodeOfSelTrig()+1);
1215
if (IsExternalEdge(ap1,ap2)) {DeleteExternalEdge(ap1,ap2);}
1216
}
1217
}
1218
1219
void STLGeometry :: DeleteExternalEdgeInVicinity()
1220
{
1221
StoreExternalEdges();
1222
if (!stldoctor.showvicinity || vicinity.Size() != GetNT()) {return;}
1223
1224
int i, j, ap1, ap2;
1225
1226
for (i = 1; i <= GetNT(); i++)
1227
{
1228
if (vicinity.Elem(i))
1229
{
1230
for (j = 1; j <= 3; j++)
1231
{
1232
ap1 = GetTriangle(i).PNum(j);
1233
ap2 = GetTriangle(i).PNumMod(j+1);
1234
1235
if (IsExternalEdge(ap1,ap2))
1236
{
1237
DeleteExternalEdge(ap1,ap2);
1238
}
1239
}
1240
}
1241
}
1242
}
1243
1244
void STLGeometry :: BuildExternalEdgesFromEdges()
1245
{
1246
StoreExternalEdges();
1247
1248
if (GetNE() == 0) {PrintWarning("Edges possibly not generated!");}
1249
1250
int i;
1251
externaledges.SetSize(0);
1252
1253
for (i = 1; i <= GetNE(); i++)
1254
{
1255
STLEdge e = GetEdge(i);
1256
AddExternalEdge(e.PNum(1), e.PNum(2));
1257
}
1258
1259
}
1260
1261
1262
void STLGeometry :: AddExternalEdge(int ap1, int ap2)
1263
{
1264
externaledges.Append(twoint(ap1,ap2));
1265
}
1266
1267
void STLGeometry :: DeleteExternalEdge(int ap1, int ap2)
1268
{
1269
1270
int i;
1271
int found = 0;
1272
for (i = 1; i <= NOExternalEdges(); i++)
1273
{
1274
if ((GetExternalEdge(i).i1 == ap1 && GetExternalEdge(i).i2 == ap2) ||
1275
(GetExternalEdge(i).i1 == ap2 && GetExternalEdge(i).i2 == ap1)) {found = 1;};
1276
if (found && i < NOExternalEdges())
1277
{
1278
externaledges.Elem(i) = externaledges.Get(i+1);
1279
}
1280
}
1281
if (!found) {PrintWarning("edge not found");}
1282
else
1283
{
1284
externaledges.SetSize(externaledges.Size()-1);
1285
}
1286
1287
}
1288
1289
int STLGeometry :: IsExternalEdge(int ap1, int ap2)
1290
{
1291
int i;
1292
for (i = 1; i <= NOExternalEdges(); i++)
1293
{
1294
if ((GetExternalEdge(i).i1 == ap1 && GetExternalEdge(i).i2 == ap2) ||
1295
(GetExternalEdge(i).i1 == ap2 && GetExternalEdge(i).i2 == ap1)) {return 1;};
1296
}
1297
return 0;
1298
}
1299
1300
void STLGeometry :: DestroyDirtyTrigs()
1301
{
1302
1303
PrintFnStart("Destroy dirty triangles");
1304
PrintMessage(5,"original number of triangles=", GetNT());
1305
1306
//destroy every triangle with other than 3 neighbours;
1307
int changed = 1;
1308
int i, j, k;
1309
while (changed)
1310
{
1311
changed = 0;
1312
Clear();
1313
1314
for (i = 1; i <= GetNT(); i++)
1315
{
1316
int dirty = NONeighbourTrigs(i) < 3;
1317
1318
for (j = 1; j <= 3; j++)
1319
{
1320
int pnum = GetTriangle(i).PNum(j);
1321
/*
1322
if (pnum == 1546)
1323
{
1324
// for (k = 1; k <= NOTrigsPerPoint(pnum); k++)
1325
}
1326
*/
1327
if (NOTrigsPerPoint(pnum) <= 2)
1328
dirty = 1;
1329
}
1330
1331
int pi1 = GetTriangle(i).PNum(1);
1332
int pi2 = GetTriangle(i).PNum(2);
1333
int pi3 = GetTriangle(i).PNum(3);
1334
if (pi1 == pi2 || pi1 == pi3 || pi2 == pi3)
1335
{
1336
PrintMessage(5,"triangle with Volume 0: ", i, " nodes: ", pi1, ", ", pi2, ", ", pi3);
1337
dirty = 1;
1338
}
1339
1340
if (dirty)
1341
{
1342
for (k = i+1; k <= GetNT(); k++)
1343
{
1344
trias.Elem(k-1) = trias.Get(k);
1345
// readtrias: not longer permanent, JS
1346
// readtrias.Elem(k-1) = readtrias.Get(k);
1347
}
1348
int size = GetNT();
1349
trias.SetSize(size-1);
1350
// readtrias.SetSize(size-1);
1351
changed = 1;
1352
break;
1353
}
1354
}
1355
}
1356
1357
FindNeighbourTrigs();
1358
PrintMessage(5,"final number of triangles=", GetNT());
1359
}
1360
1361
void STLGeometry :: CalcNormalsFromGeometry()
1362
{
1363
int i;
1364
for (i = 1; i <= GetNT(); i++)
1365
{
1366
const STLTriangle & tr = GetTriangle(i);
1367
const Point3d& ap1 = GetPoint(tr.PNum(1));
1368
const Point3d& ap2 = GetPoint(tr.PNum(2));
1369
const Point3d& ap3 = GetPoint(tr.PNum(3));
1370
1371
Vec3d normal = Cross (ap2-ap1, ap3-ap1);
1372
1373
if (normal.Length() != 0)
1374
{
1375
normal /= (normal.Length());
1376
}
1377
GetTriangle(i).SetNormal(normal);
1378
}
1379
PrintMessage(5,"Normals calculated from geometry!!!");
1380
1381
calcedgedataanglesnew = 1;
1382
}
1383
1384
void STLGeometry :: SetSelectTrig(int trig)
1385
{
1386
stldoctor.selecttrig = trig;
1387
}
1388
1389
int STLGeometry :: GetSelectTrig() const
1390
{
1391
return stldoctor.selecttrig;
1392
}
1393
1394
void STLGeometry :: SetNodeOfSelTrig(int n)
1395
{
1396
stldoctor.nodeofseltrig = n;
1397
}
1398
1399
int STLGeometry :: GetNodeOfSelTrig() const
1400
{
1401
return stldoctor.nodeofseltrig;
1402
}
1403
1404
void STLGeometry :: MoveSelectedPointToMiddle()
1405
{
1406
if (GetSelectTrig() >= 1 && GetSelectTrig() <= GetNT())
1407
{
1408
int p = GetTriangle(GetSelectTrig()).PNum(GetNodeOfSelTrig());
1409
Point<3> pm(0.,0.,0.); //Middlevector;
1410
Point<3> p0(0.,0.,0.);
1411
PrintMessage(5,"original point=", Point3d(GetPoint(p)));
1412
1413
int i;
1414
int cnt = 0;
1415
for (i = 1; i <= trigsperpoint.EntrySize(p); i++)
1416
{
1417
const STLTriangle& tr = GetTriangle(trigsperpoint.Get(p,i));
1418
int j;
1419
for (j = 1; j <= 3; j++)
1420
{
1421
if (tr.PNum(j) != p)
1422
{
1423
cnt++;
1424
pm(0) += GetPoint(tr.PNum(j))(0);
1425
pm(1) += GetPoint(tr.PNum(j))(1);
1426
pm(2) += GetPoint(tr.PNum(j))(2);
1427
}
1428
}
1429
}
1430
1431
Point<3> origp = GetPoint(p);
1432
double fact = 0.2;
1433
1434
SetPoint(p, p0 + fact*(1./(double)cnt)*(pm-p0)+(1.-fact)*(origp-p0));
1435
1436
PrintMessage(5,"middle point=", Point3d (GetPoint(p)));
1437
1438
PrintMessage(5,"moved point ", Point3d (p));
1439
1440
}
1441
}
1442
1443
void STLGeometry :: PrintSelectInfo()
1444
{
1445
1446
//int trig = GetSelectTrig();
1447
//int p = GetTriangle(trig).PNum(GetNodeOfSelTrig());
1448
1449
PrintMessage(1,"touch triangle ", GetSelectTrig()
1450
, ", local node ", GetNodeOfSelTrig()
1451
, " (=", GetTriangle(GetSelectTrig()).PNum(GetNodeOfSelTrig()), ")");
1452
if (AtlasMade() && GetSelectTrig() >= 1 && GetSelectTrig() <= GetNT())
1453
{
1454
PrintMessage(1," chartnum=",GetChartNr(GetSelectTrig()));
1455
/*
1456
PointBetween(Center(Center(GetPoint(GetTriangle(270).PNum(1)),
1457
GetPoint(GetTriangle(270).PNum(2))),
1458
GetPoint(GetTriangle(270).PNum(3))),270,
1459
Center(Center(GetPoint(GetTriangle(trig).PNum(1)),
1460
GetPoint(GetTriangle(trig).PNum(2))),
1461
GetPoint(GetTriangle(trig).PNum(3))),trig);
1462
*/
1463
//PointBetween(Point3d(5.7818, 7.52768, 4.14879),260,Point3d(6.80292, 6.55392, 4.70184),233);
1464
}
1465
}
1466
1467
void STLGeometry :: ShowSelectedTrigChartnum()
1468
{
1469
int st = GetSelectTrig();
1470
1471
if (st >= 1 && st <= GetNT() && AtlasMade())
1472
PrintMessage(1,"selected trig ", st, " has chartnumber ", GetChartNr(st));
1473
}
1474
1475
void STLGeometry :: ShowSelectedTrigCoords()
1476
{
1477
int st = GetSelectTrig();
1478
1479
/*
1480
//testing!!!!
1481
ARRAY<int> trigs;
1482
GetSortedTrianglesAroundPoint(GetTriangle(st).PNum(GetNodeOfSelTrig()),st,trigs);
1483
*/
1484
1485
if (st >= 1 && st <= GetNT())
1486
{
1487
PrintMessage(1, "coordinates of selected trig ", st, ":");
1488
PrintMessage(1, " p1 = ", GetTriangle(st).PNum(1), " = ",
1489
Point3d (GetPoint(GetTriangle(st).PNum(1))));
1490
PrintMessage(1, " p2 = ", GetTriangle(st).PNum(2), " = ",
1491
Point3d (GetPoint(GetTriangle(st).PNum(2))));
1492
PrintMessage(1, " p3 = ", GetTriangle(st).PNum(3), " = ",
1493
Point3d (GetPoint(GetTriangle(st).PNum(3))));
1494
}
1495
}
1496
1497
void STLGeometry :: LoadMarkedTrigs()
1498
{
1499
PrintFnStart("load marked trigs from file 'markedtrigs.ng'");
1500
ifstream fin("markedtrigs.ng");
1501
1502
int n;
1503
fin >> n;
1504
if (n != GetNT() || n == 0) {PrintError("Not a suitable marked-trig-file!"); return;}
1505
1506
int i, m;
1507
for (i = 1; i <= n; i++)
1508
{
1509
fin >> m;
1510
SetMarkedTrig(i, m);
1511
}
1512
1513
fin >> n;
1514
if (n != 0)
1515
{
1516
1517
Point<3> ap1, ap2;
1518
for (i = 1; i <= n; i++)
1519
{
1520
fin >> ap1(0); fin >> ap1(1); fin >> ap1(2);
1521
fin >> ap2(0); fin >> ap2(1); fin >> ap2(2);
1522
AddMarkedSeg(ap1,ap2);
1523
}
1524
}
1525
}
1526
1527
void STLGeometry :: SaveMarkedTrigs()
1528
{
1529
PrintFnStart("save marked trigs to file 'markedtrigs.ng'");
1530
ofstream fout("markedtrigs.ng");
1531
1532
int n = GetNT();
1533
fout << n << endl;
1534
1535
int i;
1536
for (i = 1; i <= n; i++)
1537
{
1538
fout << IsMarkedTrig(i) << "\n";
1539
}
1540
1541
n = GetNMarkedSegs();
1542
fout << n << endl;
1543
1544
Point<3> ap1,ap2;
1545
for (i = 1; i <= n; i++)
1546
{
1547
GetMarkedSeg(i,ap1,ap2);
1548
fout << ap1(0) << " " << ap1(1) << " " << ap1(2) << " ";
1549
fout << ap2(0) << " " << ap2(1) << " " << ap2(2) << " " << "\n";
1550
}
1551
1552
}
1553
1554
void STLGeometry :: NeighbourAnglesOfSelectedTrig()
1555
{
1556
int st = GetSelectTrig();
1557
1558
if (st >= 1 && st <= GetNT())
1559
{
1560
int i;
1561
PrintMessage(1,"Angle to triangle ", st, ":");
1562
for (i = 1; i <= NONeighbourTrigs(st); i++)
1563
{
1564
PrintMessage(1," triangle ", NeighbourTrig(st,i), ": angle = ",
1565
180./M_PI*GetAngle(st, NeighbourTrig(st,i)), "�",
1566
", calculated = ", 180./M_PI*Angle(GetTriangle(st).GeomNormal(points),
1567
GetTriangle(NeighbourTrig(st,i)).GeomNormal(points)), "�");
1568
}
1569
}
1570
}
1571
1572
void STLGeometry :: GetVicinity(int starttrig, int size, ARRAY<int>& vic)
1573
{
1574
if (starttrig == 0 || starttrig > GetNT()) {return;}
1575
1576
ARRAY<int> vicarray;
1577
vicarray.SetSize(GetNT());
1578
1579
int i;
1580
for (i = 1; i <= vicarray.Size(); i++)
1581
{
1582
vicarray.Elem(i) = 0;
1583
}
1584
1585
vicarray.Elem(starttrig) = 1;
1586
1587
int j = 0,k;
1588
1589
ARRAY <int> list1;
1590
list1.SetSize(0);
1591
ARRAY <int> list2;
1592
list2.SetSize(0);
1593
list1.Append(starttrig);
1594
1595
while (j < size)
1596
{
1597
j++;
1598
for (i = 1; i <= list1.Size(); i++)
1599
{
1600
for (k = 1; k <= NONeighbourTrigs(i); k++)
1601
{
1602
int nbtrig = NeighbourTrig(list1.Get(i),k);
1603
if (nbtrig && vicarray.Get(nbtrig) == 0)
1604
{
1605
list2.Append(nbtrig);
1606
vicarray.Elem(nbtrig) = 1;
1607
}
1608
}
1609
}
1610
list1.SetSize(0);
1611
for (i = 1; i <= list2.Size(); i++)
1612
{
1613
list1.Append(list2.Get(i));
1614
}
1615
list2.SetSize(0);
1616
}
1617
1618
vic.SetSize(0);
1619
for (i = 1; i <= vicarray.Size(); i++)
1620
{
1621
if (vicarray.Get(i)) {vic.Append(i);}
1622
}
1623
}
1624
1625
void STLGeometry :: CalcVicinity(int starttrig)
1626
{
1627
if (starttrig == 0 || starttrig > GetNT()) {return;}
1628
1629
vicinity.SetSize(GetNT());
1630
1631
if (!stldoctor.showvicinity) {return;}
1632
1633
int i;
1634
for (i = 1; i <= vicinity.Size(); i++)
1635
{
1636
vicinity.Elem(i) = 0;
1637
}
1638
1639
vicinity.Elem(starttrig) = 1;
1640
1641
int j = 0,k;
1642
1643
ARRAY <int> list1;
1644
list1.SetSize(0);
1645
ARRAY <int> list2;
1646
list2.SetSize(0);
1647
list1.Append(starttrig);
1648
1649
// int cnt = 1;
1650
while (j < stldoctor.vicinity)
1651
{
1652
j++;
1653
for (i = 1; i <= list1.Size(); i++)
1654
{
1655
for (k = 1; k <= NONeighbourTrigs(i); k++)
1656
{
1657
int nbtrig = NeighbourTrig(list1.Get(i),k);
1658
if (nbtrig && vicinity.Get(nbtrig) == 0)
1659
{
1660
list2.Append(nbtrig);
1661
vicinity.Elem(nbtrig) = 1;
1662
//cnt++;
1663
}
1664
}
1665
}
1666
list1.SetSize(0);
1667
for (i = 1; i <= list2.Size(); i++)
1668
{
1669
list1.Append(list2.Get(i));
1670
}
1671
list2.SetSize(0);
1672
}
1673
1674
}
1675
1676
int STLGeometry :: Vicinity(int trig) const
1677
{
1678
if (trig <= vicinity.Size() && trig >=1)
1679
{
1680
return vicinity.Get(trig);
1681
}
1682
else {PrintSysError("In STLGeometry::Vicinity");}
1683
return 0;
1684
}
1685
1686
void STLGeometry :: InitMarkedTrigs()
1687
{
1688
markedtrigs.SetSize(GetNT());
1689
int i;
1690
for (i = 1; i <= GetNT(); i++)
1691
{
1692
SetMarkedTrig(i, 0);
1693
}
1694
}
1695
1696
void STLGeometry :: MarkDirtyTrigs()
1697
{
1698
PrintFnStart("mark dirty trigs");
1699
int i,j;
1700
1701
markedtrigs.SetSize(GetNT());
1702
1703
for (i = 1; i <= GetNT(); i++)
1704
{
1705
SetMarkedTrig(i, 0);
1706
}
1707
1708
int found;
1709
double dirtyangle = stlparam.yangle/2./180.*M_PI;
1710
int cnt = 0;
1711
for (i = 1; i <= GetNT(); i++)
1712
{
1713
found = 0;
1714
for (j = 1; j <= NONeighbourTrigs(i); j++)
1715
{
1716
if (GetAngle(i, NeighbourTrig(i,j)) > dirtyangle)
1717
{
1718
found++;
1719
}
1720
}
1721
if (found && GetTriangle(i).MinHeight(points) <
1722
stldoctor.dirtytrigfact*GetTriangle(i).MaxLength(points))
1723
{
1724
SetMarkedTrig(i, 1); cnt++;
1725
}
1726
/*
1727
else if (found == 3)
1728
{
1729
SetMarkedTrig(i, 1); cnt++;
1730
}
1731
*/
1732
}
1733
1734
PrintMessage(1, "marked ", cnt, " dirty trigs");
1735
}
1736
1737
1738
void STLGeometry :: MarkTopErrorTrigs()
1739
{
1740
int cnt = 0;
1741
markedtrigs.SetSize(GetNT());
1742
for (int i = 1; i <= GetNT(); i++)
1743
{
1744
const STLTriangle & trig = GetTriangle(i);
1745
1746
SetMarkedTrig(i, trig.flags.toperror);
1747
if (trig.flags.toperror) cnt++;
1748
}
1749
PrintMessage(1,"marked ", cnt, " inconsistent triangles");
1750
}
1751
1752
1753
1754
double STLGeometry :: CalcTrigBadness(int i)
1755
{
1756
int j;
1757
double maxbadness = 0;
1758
int ap1, ap2;
1759
for (j = 1; j <= NONeighbourTrigs(i); j++)
1760
{
1761
GetTriangle(i).GetNeighbourPoints(GetTriangle(NeighbourTrig(i,j)), ap1, ap2);
1762
1763
if (!IsEdge(ap1,ap2) && GetGeomAngle(i, NeighbourTrig(i,j)) > maxbadness)
1764
{
1765
maxbadness = GetGeomAngle(i, NeighbourTrig(i,j));
1766
}
1767
}
1768
return maxbadness;
1769
1770
}
1771
1772
void STLGeometry :: GeomSmoothRevertedTrigs()
1773
{
1774
//double revertedangle = stldoctor.smoothangle/180.*M_PI;
1775
double fact = stldoctor.dirtytrigfact;
1776
1777
MarkRevertedTrigs();
1778
1779
int i, j, k, l, p;
1780
1781
for (i = 1; i <= GetNT(); i++)
1782
{
1783
if (IsMarkedTrig(i))
1784
{
1785
for (j = 1; j <= 3; j++)
1786
{
1787
double origbadness = CalcTrigBadness(i);
1788
1789
p = GetTriangle(i).PNum(j);
1790
Point<3> pm(0.,0.,0.); //Middlevector;
1791
Point<3> p0(0.,0.,0.);
1792
1793
int cnt = 0;
1794
1795
for (k = 1; k <= trigsperpoint.EntrySize(p); k++)
1796
{
1797
const STLTriangle& tr = GetTriangle(trigsperpoint.Get(p,k));
1798
for (l = 1; l <= 3; l++)
1799
{
1800
if (tr.PNum(l) != p)
1801
{
1802
cnt++;
1803
pm(0) += GetPoint(tr.PNum(l))(0);
1804
pm(1) += GetPoint(tr.PNum(l))(1);
1805
pm(2) += GetPoint(tr.PNum(l))(2);
1806
}
1807
}
1808
}
1809
Point3d origp = GetPoint(p);
1810
Point3d newp = p0 + fact*(1./(double)cnt)*(pm-p0)+(1.-fact)*(origp-p0);
1811
1812
SetPoint(p, newp);
1813
1814
if (CalcTrigBadness(i) > 0.9*origbadness) {SetPoint(p,origp); PrintDot('f');}
1815
else {PrintDot('s');}
1816
}
1817
}
1818
}
1819
MarkRevertedTrigs();
1820
}
1821
1822
void STLGeometry :: MarkRevertedTrigs()
1823
{
1824
int i,j;
1825
if (edgesperpoint.Size() != GetNP()) {BuildEdges();}
1826
1827
PrintFnStart("mark reverted trigs");
1828
1829
InitMarkedTrigs();
1830
1831
int found;
1832
double revertedangle = stldoctor.smoothangle/180.*M_PI;
1833
1834
int cnt = 0;
1835
int ap1, ap2;
1836
for (i = 1; i <= GetNT(); i++)
1837
{
1838
found = 0;
1839
for (j = 1; j <= NONeighbourTrigs(i); j++)
1840
{
1841
GetTriangle(i).GetNeighbourPoints(GetTriangle(NeighbourTrig(i,j)), ap1, ap2);
1842
1843
if (!IsEdge(ap1,ap2))
1844
{
1845
if (GetGeomAngle(i, NeighbourTrig(i,j)) > revertedangle)
1846
{
1847
found = 1;
1848
break;
1849
}
1850
}
1851
}
1852
1853
if (found)
1854
{
1855
SetMarkedTrig(i, 1); cnt++;
1856
}
1857
1858
}
1859
1860
PrintMessage(5, "found ", cnt, " reverted trigs");
1861
1862
1863
}
1864
1865
void STLGeometry :: SmoothDirtyTrigs()
1866
{
1867
PrintFnStart("smooth dirty trigs");
1868
1869
MarkDirtyTrigs();
1870
1871
int i,j;
1872
int changed = 1;
1873
int ap1, ap2;
1874
1875
while (changed)
1876
{
1877
changed = 0;
1878
for (i = 1; i <= GetNT(); i++)
1879
{
1880
if (IsMarkedTrig(i))
1881
{
1882
int foundtrig = 0;
1883
double maxlen = 0;
1884
// JS: darf normalvector nicht ueber kurze Seite erben
1885
maxlen = GetTriangle(i).MaxLength(GetPoints()) / 2.1; //JG: bei flachem dreieck auch kurze Seite
1886
1887
for (j = 1; j <= NONeighbourTrigs(i); j++)
1888
{
1889
if (!IsMarkedTrig(NeighbourTrig(i,j)))
1890
{
1891
GetTriangle(i).GetNeighbourPoints(GetTriangle(NeighbourTrig(i,j)),ap1,ap2);
1892
if (Dist(GetPoint(ap1),GetPoint(ap2)) >= maxlen)
1893
{
1894
foundtrig = NeighbourTrig(i,j);
1895
maxlen = Dist(GetPoint(ap1),GetPoint(ap2));
1896
}
1897
}
1898
}
1899
if (foundtrig)
1900
{
1901
GetTriangle(i).SetNormal(GetTriangle(foundtrig).Normal());
1902
changed = 1;
1903
SetMarkedTrig(i,0);
1904
}
1905
}
1906
}
1907
}
1908
1909
calcedgedataanglesnew = 1;
1910
1911
1912
MarkDirtyTrigs();
1913
1914
int cnt = 0;
1915
for (i = 1; i <= GetNT(); i++)
1916
{
1917
if (IsMarkedTrig(i)) {cnt++;}
1918
}
1919
1920
PrintMessage(5,"NO marked dirty trigs=", cnt);
1921
1922
}
1923
1924
int STLGeometry :: IsMarkedTrig(int trig) const
1925
{
1926
if (trig <= markedtrigs.Size() && trig >=1)
1927
{
1928
return markedtrigs.Get(trig);
1929
}
1930
else {PrintSysError("In STLGeometry::IsMarkedTrig");}
1931
1932
return 0;
1933
}
1934
1935
void STLGeometry :: SetMarkedTrig(int trig, int num)
1936
{
1937
if (trig <= markedtrigs.Size() && trig >=1)
1938
{
1939
markedtrigs.Elem(trig) = num;
1940
}
1941
else {PrintSysError("In STLGeometry::SetMarkedTrig");}
1942
}
1943
1944
void STLGeometry :: Clear()
1945
{
1946
PrintFnStart("Clear");
1947
1948
surfacemeshed = 0;
1949
surfaceoptimized = 0;
1950
volumemeshed = 0;
1951
1952
selectedmultiedge.SetSize(0);
1953
meshlines.SetSize(0);
1954
// neighbourtrigs.SetSize(0);
1955
outerchartspertrig.SetSize(0);
1956
atlas.SetSize(0);
1957
ClearMarkedSegs();
1958
ClearSpiralPoints();
1959
ClearLineEndPoints();
1960
1961
SetSelectTrig(0);
1962
SetNodeOfSelTrig(1);
1963
facecnt = 0;
1964
1965
SetThreadPercent(100.);
1966
1967
ClearEdges();
1968
}
1969
1970
double STLGeometry :: Area()
1971
{
1972
double ar = 0;
1973
int i;
1974
for (i = 1; i <= GetNT(); i++)
1975
{
1976
ar += GetTriangle(i).Area(points);
1977
}
1978
return ar;
1979
}
1980
1981
double STLGeometry :: GetAngle(int t1, int t2)
1982
{
1983
return Angle(GetTriangle(t1).Normal(),GetTriangle(t2).Normal());
1984
}
1985
1986
double STLGeometry :: GetGeomAngle(int t1, int t2)
1987
{
1988
Vec3d n1 = GetTriangle(t1).GeomNormal(points);
1989
Vec3d n2 = GetTriangle(t2).GeomNormal(points);
1990
return Angle(n1,n2);
1991
}
1992
1993
1994
void STLGeometry :: InitSTLGeometry(const ARRAY<STLReadTriangle> & readtrias)
1995
{
1996
PrintFnStart("Init STL Geometry");
1997
STLTopology::InitSTLGeometry(readtrias);
1998
1999
int i, k;
2000
2001
//const double geometry_tol_fact = 1E8; //distances lower than max_box_size/tol are ignored
2002
2003
int np = GetNP();
2004
PrintMessage(5,"NO points= ", GetNP());
2005
normals.SetSize(GetNP());
2006
ARRAY<int> normal_cnt(GetNP()); // counts number of added normals in a point
2007
2008
for (i = 1; i <= np; i++)
2009
{
2010
normal_cnt.Elem(i) = 0;
2011
normals.Elem(i) = Vec3d (0,0,0);
2012
}
2013
2014
for(i = 1; i <= GetNT(); i++)
2015
{
2016
// STLReadTriangle t = GetReadTriangle(i);
2017
// STLTriangle st;
2018
2019
Vec<3> n = GetTriangle(i).Normal ();
2020
2021
for (k = 1; k <= 3; k++)
2022
{
2023
int pi = GetTriangle(i).PNum(k);
2024
2025
normal_cnt.Elem(pi)++;
2026
SetNormal(pi, GetNormal(pi) + n);
2027
}
2028
}
2029
2030
//normalize the normals
2031
for (i = 1; i <= GetNP(); i++)
2032
{
2033
SetNormal(i,1./(double)normal_cnt.Get(i)*GetNormal(i));
2034
}
2035
2036
trigsconverted = 1;
2037
2038
vicinity.SetSize(GetNT());
2039
markedtrigs.SetSize(GetNT());
2040
for (i = 1; i <= GetNT(); i++)
2041
{
2042
markedtrigs.Elem(i) = 0;
2043
vicinity.Elem(i) = 1;
2044
}
2045
2046
ha_points.SetSize(GetNP());
2047
for (i = 1; i <= GetNP(); i++)
2048
ha_points.Elem(i) = 0;
2049
2050
calcedgedataanglesnew = 0;
2051
edgedatastored = 0;
2052
edgedata->Clear();
2053
2054
2055
if (GetStatus() == STL_ERROR) return;
2056
2057
CalcEdgeData();
2058
CalcEdgeDataAngles();
2059
2060
ClearLineEndPoints();
2061
2062
CheckGeometryOverlapping();
2063
}
2064
2065
void STLGeometry :: TopologyChanged()
2066
{
2067
calcedgedataanglesnew = 1;
2068
}
2069
2070
int STLGeometry :: CheckGeometryOverlapping()
2071
{
2072
int i, j, k;
2073
2074
Box<3> geombox = GetBoundingBox();
2075
Point<3> pmin = geombox.PMin();
2076
Point<3> pmax = geombox.PMax();
2077
2078
Box3dTree setree(pmin, pmax);
2079
ARRAY<int> inters;
2080
2081
int oltrigs = 0;
2082
markedtrigs.SetSize(GetNT());
2083
2084
for (i = 1; i <= GetNT(); i++)
2085
SetMarkedTrig(i, 0);
2086
2087
for (i = 1; i <= GetNT(); i++)
2088
{
2089
const STLTriangle & tri = GetTriangle(i);
2090
2091
Point<3> tpmin = tri.box.PMin();
2092
Point<3> tpmax = tri.box.PMax();
2093
Vec<3> diag = tpmax - tpmin;
2094
2095
tpmax = tpmax + 0.001 * diag;
2096
tpmin = tpmin - 0.001 * diag;
2097
2098
setree.Insert (tpmin, tpmax, i);
2099
}
2100
2101
for (i = 1; i <= GetNT(); i++)
2102
{
2103
const STLTriangle & tri = GetTriangle(i);
2104
2105
Point<3> tpmin = tri.box.PMin();
2106
Point<3> tpmax = tri.box.PMax();
2107
2108
setree.GetIntersecting (tpmin, tpmax, inters);
2109
2110
for (j = 1; j <= inters.Size(); j++)
2111
{
2112
const STLTriangle & tri2 = GetTriangle(inters.Get(j));
2113
2114
const Point<3> *trip1[3], *trip2[3];
2115
Point<3> hptri1[3], hptri2[3];
2116
/*
2117
for (k = 1; k <= 3; k++)
2118
{
2119
trip1[k-1] = &GetPoint (tri.PNum(k));
2120
trip2[k-1] = &GetPoint (tri2.PNum(k));
2121
}
2122
*/
2123
2124
for (k = 0; k < 3; k++)
2125
{
2126
hptri1[k] = GetPoint (tri[k]);
2127
hptri2[k] = GetPoint (tri2[k]);
2128
trip1[k] = &hptri1[k];
2129
trip2[k] = &hptri2[k];
2130
}
2131
2132
if (IntersectTriangleTriangle (&trip1[0], &trip2[0]))
2133
{
2134
oltrigs++;
2135
PrintMessage(5,"Intersecting Triangles: trig ",i," with ",inters.Get(j),"!");
2136
SetMarkedTrig(i, 1);
2137
SetMarkedTrig(inters.Get(j), 1);
2138
}
2139
}
2140
}
2141
2142
PrintMessage(3,"Check Geometry Overlapping: overlapping triangles = ",oltrigs);
2143
return oltrigs;
2144
}
2145
2146
/*
2147
void STLGeometry :: InitSTLGeometry()
2148
{
2149
STLTopology::InitSTLGeometry();
2150
2151
int i, j, k;
2152
2153
const double geometry_tol_fact = 1E8; //distances lower than max_box_size/tol are ignored
2154
2155
2156
trias.SetSize(0);
2157
points.SetSize(0);
2158
normals.SetSize(0);
2159
2160
ARRAY<int> normal_cnt; // counts number of added normals in a point
2161
2162
Box3d bb (GetBoundingBox().PMin() + Vec3d (-1,-1,-1),
2163
GetBoundingBox().PMax() + Vec3d (1, 1, 1));
2164
2165
Point3dTree pointtree (bb.PMin(),
2166
bb.PMax());
2167
ARRAY<int> pintersect;
2168
2169
double gtol = GetBoundingBox().CalcDiam()/geometry_tol_fact;
2170
2171
for(i = 1; i <= GetReadNT(); i++)
2172
{
2173
//if (i%500==499) {(*mycout) << (double)i/(double)GetReadNT()*100. << "%" << endl;}
2174
2175
STLReadTriangle t = GetReadTriangle(i);
2176
STLTriangle st;
2177
Vec3d n = t.normal;
2178
2179
for (k = 0; k < 3; k++)
2180
{
2181
Point3d p = t.pts[k];
2182
2183
Point3d pmin = p - Vec3d (gtol, gtol, gtol);
2184
Point3d pmax = p + Vec3d (gtol, gtol, gtol);
2185
2186
pointtree.GetIntersecting (pmin, pmax, pintersect);
2187
2188
if (pintersect.Size() > 1)
2189
(*mycout) << "found too much " << char(7) << endl;
2190
int foundpos = 0;
2191
if (pintersect.Size())
2192
foundpos = pintersect.Get(1);
2193
2194
if (foundpos)
2195
{
2196
normal_cnt[foundpos]++;
2197
SetNormal(foundpos,GetNormal(foundpos)+n);
2198
// (*testout) << "found p " << p << endl;
2199
}
2200
else
2201
{
2202
foundpos = AddPoint(p);
2203
AddNormal(n);
2204
normal_cnt.Append(1);
2205
2206
pointtree.Insert (p, foundpos);
2207
}
2208
//(*mycout) << "foundpos=" << foundpos << endl;
2209
st.pts[k] = foundpos;
2210
}
2211
2212
if ( (st.pts[0] == st.pts[1]) ||
2213
(st.pts[0] == st.pts[2]) ||
2214
(st.pts[1] == st.pts[2]) )
2215
{
2216
(*mycout) << "ERROR: STL Triangle degenerated" << endl;
2217
}
2218
else
2219
{
2220
// do not add ? js
2221
AddTriangle(st);
2222
}
2223
//(*mycout) << "TRIG" << i << " = " << st << endl;
2224
2225
}
2226
//normal the normals
2227
for (i = 1; i <= GetNP(); i++)
2228
{
2229
SetNormal(i,1./(double)normal_cnt[i]*GetNormal(i));
2230
}
2231
2232
trigsconverted = 1;
2233
2234
vicinity.SetSize(GetNT());
2235
markedtrigs.SetSize(GetNT());
2236
for (i = 1; i <= GetNT(); i++)
2237
{
2238
markedtrigs.Elem(i) = 0;
2239
vicinity.Elem(i) = 1;
2240
}
2241
2242
ha_points.SetSize(GetNP());
2243
for (i = 1; i <= GetNP(); i++)
2244
ha_points.Elem(i) = 0;
2245
2246
calcedgedataanglesnew = 0;
2247
edgedatastored = 0;
2248
edgedata->Clear();
2249
2250
CalcEdgeData();
2251
CalcEdgeDataAngles();
2252
2253
ClearLineEndPoints();
2254
2255
(*mycout) << "done" << endl;
2256
}
2257
*/
2258
2259
2260
2261
void STLGeometry :: SetLineEndPoint(int pn)
2262
{
2263
if (pn <1 || pn > lineendpoints.Size()) {PrintSysError("Illegal pnum in SetLineEndPoint!!!"); return; }
2264
lineendpoints.Elem(pn) = 1;
2265
}
2266
2267
int STLGeometry :: IsLineEndPoint(int pn)
2268
{
2269
// return 0;
2270
if (pn <1 || pn > lineendpoints.Size())
2271
{PrintSysError("Illegal pnum in IsLineEndPoint!!!"); return 0;}
2272
return lineendpoints.Get(pn);
2273
}
2274
2275
void STLGeometry :: ClearLineEndPoints()
2276
{
2277
lineendpoints.SetSize(GetNP());
2278
int i;
2279
for (i = 1; i <= GetNP(); i++)
2280
{
2281
lineendpoints.Elem(i) = 0;
2282
}
2283
}
2284
2285
int STLGeometry :: IsEdge(int ap1, int ap2)
2286
{
2287
int i,j;
2288
for (i = 1; i <= GetNEPP(ap1); i++)
2289
{
2290
for (j = 1; j <= GetNEPP(ap2); j++)
2291
{
2292
if (GetEdgePP(ap1,i) == GetEdgePP(ap2,j)) {return 1;}
2293
}
2294
}
2295
return 0;
2296
}
2297
2298
int STLGeometry :: IsEdgeNum(int ap1, int ap2)
2299
{
2300
int i,j;
2301
for (i = 1; i <= GetNEPP(ap1); i++)
2302
{
2303
for (j = 1; j <= GetNEPP(ap2); j++)
2304
{
2305
if (GetEdgePP(ap1,i) == GetEdgePP(ap2,j)) {return GetEdgePP(ap1,i);}
2306
}
2307
}
2308
return 0;
2309
}
2310
2311
2312
void STLGeometry :: BuildEdges()
2313
{
2314
//PrintFnStart("build edges");
2315
edges.SetSize(0);
2316
meshlines.SetSize(0);
2317
FindEdgesFromAngles();
2318
}
2319
2320
void STLGeometry :: UseExternalEdges()
2321
{
2322
int i;
2323
for (i = 1; i <= NOExternalEdges(); i++)
2324
{
2325
AddEdge(GetExternalEdge(i).i1,GetExternalEdge(i).i2);
2326
}
2327
//BuildEdgesPerPointy();
2328
}
2329
2330
void STLGeometry :: UndoEdgeChange()
2331
{
2332
if (edgedatastored)
2333
{
2334
RestoreEdgeData();
2335
}
2336
else
2337
{
2338
PrintWarning("no edge undo possible");
2339
}
2340
}
2341
2342
2343
void STLGeometry :: StoreEdgeData()
2344
{
2345
// edgedata_store = *edgedata;
2346
2347
edgedata->Store();
2348
edgedatastored = 1;
2349
2350
// put stlgeom-edgedata to stltopology edgedata
2351
/*
2352
int i;
2353
for (i = 1; i <= GetNTE(); i++)
2354
{
2355
const STLTopEdge & topedge = GetTopEdge (i);
2356
int ednum = edgedata->GetEdgeNum (topedge.PNum(1),
2357
topedge.PNum(2));
2358
topedges.Elem(i).SetStatus (edgedata->Get (ednum).status);
2359
}
2360
*/
2361
}
2362
2363
void STLGeometry :: RestoreEdgeData()
2364
{
2365
// *edgedata = edgedata_store;
2366
edgedata->Restore();
2367
edgedatastored=0;
2368
}
2369
2370
2371
void STLGeometry :: CalcEdgeData()
2372
{
2373
PushStatus("Calc Edge Data");
2374
2375
int np1, np2;
2376
int i;
2377
2378
int ecnt = 0;
2379
edgedata->SetSize(GetNT()/2*3);
2380
2381
for (i = 1; i <= GetNT(); i++)
2382
{
2383
SetThreadPercent((double)i/(double)GetNT()*100.);
2384
2385
const STLTriangle & t1 = GetTriangle(i);
2386
2387
for (int j = 1; j <= NONeighbourTrigs(i); j++)
2388
{
2389
int nbti = NeighbourTrig(i,j);
2390
if (nbti > i)
2391
{
2392
const STLTriangle & t2 = GetTriangle(nbti);
2393
2394
if (t1.IsNeighbourFrom(t2))
2395
{
2396
ecnt++; if (ecnt > edgedata->Size()) {PrintError("In Calc edge data, illegal geometry");}
2397
2398
t1.GetNeighbourPoints(t2,np1,np2);
2399
2400
/* ang = GetAngle(i,nbti);
2401
if (ang < -M_PI) {ang += 2*M_PI;}*/
2402
2403
2404
// edgedata->Add(STLEdgeData(0, np1, np2, i, nbti),ecnt);
2405
edgedata->Elem(ecnt).SetStatus(ED_UNDEFINED);
2406
2407
// edgedata->Elem(ecnt).top = this;
2408
// edgedata->Elem(ecnt).topedgenr = GetTopEdgeNum (np1, np2);
2409
}
2410
}
2411
}
2412
}
2413
2414
//BuildEdgesPerPoint();
2415
PopStatus();
2416
}
2417
2418
void STLGeometry :: CalcEdgeDataAngles()
2419
{
2420
PrintMessage(5,"calc edge data angles");
2421
2422
int i;
2423
2424
for (i = 1; i <= GetNTE(); i++)
2425
{
2426
STLTopEdge & edge = GetTopEdge (i);
2427
double cosang =
2428
GetTriangle(edge.TrigNum(1)).Normal() *
2429
GetTriangle(edge.TrigNum(2)).Normal();
2430
edge.SetCosAngle (cosang);
2431
}
2432
2433
for (i = 1; i <= edgedata->Size(); i++)
2434
{
2435
/*
2436
const STLEdgeData& e = edgedata->Get(i);
2437
ang = GetAngle(e.lt,e.rt);
2438
if (ang < -M_PI) {ang += 2*M_PI;}
2439
edgedata->Elem(i).angle = fabs(ang);
2440
*/
2441
}
2442
2443
}
2444
2445
void STLGeometry :: FindEdgesFromAngles()
2446
{
2447
// PrintFnStart("find edges from angles");
2448
2449
double min_edge_angle = stlparam.yangle/180.*M_PI;
2450
double cont_min_edge_angle = stlparam.contyangle/180.*M_PI;
2451
2452
double cos_min_edge_angle = cos (min_edge_angle);
2453
double cos_cont_min_edge_angle = cos (cont_min_edge_angle);
2454
2455
if (calcedgedataanglesnew) {CalcEdgeDataAngles(); calcedgedataanglesnew = 0;}
2456
2457
int i;
2458
for (i = 1; i <= edgedata->Size(); i++)
2459
{
2460
STLTopEdge & sed = edgedata->Elem(i);
2461
if (sed.GetStatus() == ED_CANDIDATE ||
2462
sed.GetStatus() == ED_UNDEFINED)
2463
{
2464
if (sed.CosAngle() <= cos_min_edge_angle)
2465
{
2466
sed.SetStatus (ED_CANDIDATE);
2467
}
2468
else
2469
{
2470
sed.SetStatus(ED_UNDEFINED);
2471
}
2472
}
2473
}
2474
2475
if (stlparam.contyangle < stlparam.yangle)
2476
{
2477
int changed = 1;
2478
int its = 0;
2479
while (changed && stlparam.contyangle < stlparam.yangle)
2480
{
2481
its++;
2482
//(*mycout) << "." << flush;
2483
changed = 0;
2484
for (i = 1; i <= edgedata->Size(); i++)
2485
{
2486
STLTopEdge & sed = edgedata->Elem(i);
2487
if (sed.CosAngle() <= cos_cont_min_edge_angle
2488
&& sed.GetStatus() == ED_UNDEFINED &&
2489
(edgedata->GetNConfCandEPP(sed.PNum(1)) == 1 ||
2490
edgedata->GetNConfCandEPP(sed.PNum(2)) == 1))
2491
{
2492
changed = 1;
2493
sed.SetStatus (ED_CANDIDATE);
2494
}
2495
}
2496
}
2497
}
2498
2499
int confcand = 0;
2500
if (edgedata->GetNConfEdges() == 0)
2501
{
2502
confcand = 1;
2503
}
2504
2505
for (i = 1; i <= edgedata->Size(); i++)
2506
{
2507
STLTopEdge & sed = edgedata->Elem(i);
2508
if (sed.GetStatus() == ED_CONFIRMED ||
2509
(sed.GetStatus() == ED_CANDIDATE && confcand))
2510
{
2511
STLEdge se(sed.PNum(1),sed.PNum(2));
2512
se.SetLeftTrig(sed.TrigNum(1));
2513
se.SetRightTrig(sed.TrigNum(2));
2514
AddEdge(se);
2515
}
2516
}
2517
BuildEdgesPerPoint();
2518
2519
2520
2521
//(*mycout) << "its for continued angle = " << its << endl;
2522
PrintMessage(5,"built ", GetNE(), " edges with yellow angle = ", stlparam.yangle, " degree");
2523
2524
}
2525
2526
/*
2527
void STLGeometry :: FindEdgesFromAngles()
2528
{
2529
double yangle = stlparam.yangle;
2530
char * savetask = multithread.task;
2531
multithread.task = "find edges";
2532
2533
const double min_edge_angle = yangle/180.*M_PI;
2534
2535
int np1, np2;
2536
double ang;
2537
int i;
2538
2539
//(*mycout) << "area=" << Area() << endl;
2540
2541
for (i = 1; i <= GetNT(); i++)
2542
{
2543
multithread.percent = (double)i/(double)GetReadNT()*100.;
2544
2545
const STLTriangle & t1 = GetTriangle(i);
2546
//NeighbourTrigs(nt,i);
2547
2548
for (int j = 1; j <= NONeighbourTrigs(i); j++)
2549
{
2550
int nbti = NeighbourTrig(i,j);
2551
if (nbti > i)
2552
{
2553
const STLTriangle & t2 = GetTriangle(nbti);
2554
2555
if (t1.IsNeighbourFrom(t2))
2556
{
2557
ang = GetAngle(i,nbti);
2558
if (ang < -M_PI*0.5) {ang += 2*M_PI;}
2559
2560
t1.GetNeighbourPoints(t2,np1,np2);
2561
2562
if (fabs(ang) >= min_edge_angle)
2563
{
2564
STLEdge se(np1,np2);
2565
se.SetLeftTrig(i);
2566
se.SetRightTrig(nbti);
2567
AddEdge(se);
2568
}
2569
}
2570
}
2571
}
2572
}
2573
2574
(*mycout) << "added " << GetNE() << " edges" << endl;
2575
2576
//BuildEdgesPerPoint();
2577
2578
multithread.percent = 100.;
2579
multithread.task = savetask;
2580
2581
}
2582
*/
2583
void STLGeometry :: BuildEdgesPerPoint()
2584
{
2585
//cout << "*** build edges per point" << endl;
2586
edgesperpoint.SetSize(GetNP());
2587
2588
//add edges to points
2589
int i;
2590
for (i = 1; i <= GetNE(); i++)
2591
{
2592
//(*mycout) << "EDGE " << GetEdge(i).PNum(1) << " - " << GetEdge(i).PNum(2) << endl;
2593
for (int j = 1; j <= 2; j++)
2594
{
2595
AddEdgePP(GetEdge(i).PNum(j),i);
2596
}
2597
}
2598
}
2599
2600
void STLGeometry :: AddFaceEdges()
2601
{
2602
PrintFnStart("Add starting edges for faces");
2603
2604
//f�r Kugel eine STLLine hinzuf�gen (Vorteil: verfeinerbar, unabh�ngig von Aufl�sung der Geometrie!!!):
2605
//Grenze von 1. gefundener chart
2606
2607
ARRAY<int> edgecnt;
2608
ARRAY<int> chartindex;
2609
edgecnt.SetSize(GetNOFaces());
2610
chartindex.SetSize(GetNOFaces());
2611
2612
int i,j;
2613
for (i = 1; i <= GetNOFaces(); i++)
2614
{
2615
edgecnt.Elem(i) = 0;
2616
chartindex.Elem(i) = 0;
2617
}
2618
2619
for (i = 1; i <= GetNT(); i++)
2620
{
2621
int fn = GetTriangle(i).GetFaceNum();
2622
if (!chartindex.Get(fn)) {chartindex.Elem(fn) = GetChartNr(i);}
2623
for (j = 1; j <= 3; j++)
2624
{
2625
edgecnt.Elem(fn) += GetNEPP(GetTriangle(i).PNum(j));
2626
}
2627
}
2628
2629
for (i = 1; i <= GetNOFaces(); i++)
2630
{
2631
if (!edgecnt.Get(i)) {PrintMessage(5,"Face", i, " has no edge!");}
2632
}
2633
2634
int changed = 0;
2635
int k, ap1, ap2;
2636
for (i = 1; i <= GetNOFaces(); i++)
2637
{
2638
if (!edgecnt.Get(i))
2639
{
2640
const STLChart& c = GetChart(chartindex.Get(i));
2641
for (j = 1; j <= c.GetNChartT(); j++)
2642
{
2643
const STLTriangle& t1 = GetTriangle(c.GetChartTrig(j));
2644
for (k = 1; k <= 3; k++)
2645
{
2646
int nt = NeighbourTrig(c.GetChartTrig(j),k);
2647
if (GetChartNr(nt) != chartindex.Get(i))
2648
{
2649
t1.GetNeighbourPoints(GetTriangle(nt),ap1,ap2);
2650
AddEdge(ap1,ap2);
2651
changed = 1;
2652
}
2653
}
2654
}
2655
}
2656
2657
}
2658
2659
if (changed) BuildEdgesPerPoint();
2660
2661
}
2662
2663
void STLGeometry :: LinkEdges()
2664
{
2665
PushStatusF("Link Edges");
2666
PrintMessage(5,"have now ", GetNE(), " edges with yellow angle = ", stlparam.yangle, " degree");
2667
2668
int i;
2669
2670
lines.SetSize(0);
2671
int starte(0);
2672
int edgecnt = 0;
2673
int found;
2674
int rev(0); //indicates, that edge is inserted reverse
2675
2676
//worked edges
2677
ARRAY<int> we(GetNE());
2678
2679
//setlineendpoints; wenn 180�, dann keine endpunkte
2680
//nur punkte mit 2 edges kommen in frage, da bei mehr oder weniger punkten ohnehin ein meshpoint hinkommt
2681
2682
Vec3d v1,v2;
2683
double cos_eca = cos(stlparam.edgecornerangle/180.*M_PI);
2684
int ecnt = 0;
2685
int lp1, lp2;
2686
if (stlparam.edgecornerangle < 180)
2687
{
2688
for (i = 1; i <= GetNP(); i++)
2689
{
2690
if (GetNEPP(i) == 2)
2691
{
2692
if (GetEdge(GetEdgePP(i,1)).PNum(2) == GetEdge(GetEdgePP(i,2)).PNum(1) ||
2693
GetEdge(GetEdgePP(i,1)).PNum(1) == GetEdge(GetEdgePP(i,2)).PNum(2))
2694
{
2695
lp1 = 1; lp2 = 2;
2696
}
2697
else
2698
{
2699
lp1 = 2; lp2 = 1;
2700
}
2701
2702
v1 = Vec3d(GetPoint(GetEdge(GetEdgePP(i,1)).PNum(1)),
2703
GetPoint(GetEdge(GetEdgePP(i,1)).PNum(2)));
2704
v2 = Vec3d(GetPoint(GetEdge(GetEdgePP(i,2)).PNum(lp1)),
2705
GetPoint(GetEdge(GetEdgePP(i,2)).PNum(lp2)));
2706
if ((v1*v2)/sqrt(v1.Length2()*v2.Length2()) < cos_eca)
2707
{
2708
//(*testout) << "add edgepoint " << i << endl;
2709
SetLineEndPoint(i);
2710
ecnt++;
2711
}
2712
}
2713
}
2714
}
2715
PrintMessage(5, "added ", ecnt, " mesh_points due to edge corner angle (",
2716
stlparam.edgecornerangle, " degree)");
2717
2718
for (i = 1; i <= GetNE(); i++) {we.Elem(i) = 0;}
2719
2720
while(edgecnt < GetNE())
2721
{
2722
SetThreadPercent((double)edgecnt/(double)GetNE()*100.);
2723
2724
STLLine* line = new STLLine(this);
2725
2726
//find start edge
2727
int j = 1;
2728
found = 0;
2729
//try second time, if only rings are left!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2730
int second = 0;
2731
2732
//find a starting edge at point with 1 or more than 2 edges or at lineendpoint
2733
while (!found && j<=GetNE())
2734
{
2735
if (!we.Get(j))
2736
{
2737
if (GetNEPP(GetEdge(j).PNum(1)) != 2 || IsLineEndPoint(GetEdge(j).PNum(1)))
2738
{
2739
starte = j;
2740
found = 1;
2741
rev = 0;
2742
}
2743
else
2744
if (GetNEPP(GetEdge(j).PNum(2)) != 2 || IsLineEndPoint(GetEdge(j).PNum(2)))
2745
{
2746
starte = j;
2747
found = 1;
2748
rev = 1;
2749
}
2750
else if (second)
2751
{
2752
starte = j;
2753
found = 1;
2754
rev = 0; //0 or 1 are possible
2755
}
2756
}
2757
j++;
2758
if (!second && j == GetNE()) {second = 1; j = 1;}
2759
}
2760
2761
if (!found) {PrintSysError("No starting edge found, edgecnt=", edgecnt, ", GETNE=", GetNE());}
2762
2763
line->AddPoint(GetEdge(starte).PNum(1+rev));
2764
line->AddPoint(GetEdge(starte).PNum(2-rev));
2765
if (!rev)
2766
{
2767
line->AddLeftTrig(GetEdge(starte).LeftTrig());
2768
line->AddRightTrig(GetEdge(starte).RightTrig());
2769
}
2770
else
2771
{
2772
line->AddLeftTrig(GetEdge(starte).RightTrig());
2773
line->AddRightTrig(GetEdge(starte).LeftTrig());
2774
}
2775
edgecnt++; we.Elem(starte) = 1;
2776
2777
//add segments to line as long as segments other than starting edge are found or lineendpoint is reached
2778
found = 1;
2779
int other;
2780
while(found)
2781
{
2782
found = 0;
2783
int fp = GetEdge(starte).PNum(2-rev);
2784
if (GetNEPP(fp) == 2 && !IsLineEndPoint(fp))
2785
{
2786
//find the "other" edge of point fp
2787
other = 0;
2788
if (GetEdgePP(fp,1) == starte) {other = 1;}
2789
2790
starte = GetEdgePP(fp,1+other);
2791
2792
//falls ring -> aufhoeren !!!!!!!!!!!
2793
if (!we.Elem(starte))
2794
{
2795
found = 1;
2796
rev = 0;
2797
if (GetEdge(starte).PNum(2) == fp) {rev = 1;}
2798
else if (GetEdge(starte).PNum(1) != fp) {PrintSysError("In Link Edges!");}
2799
2800
line->AddPoint(GetEdge(starte).PNum(2-rev));
2801
if (!rev)
2802
{
2803
line->AddLeftTrig(GetEdge(starte).LeftTrig());
2804
line->AddRightTrig(GetEdge(starte).RightTrig());
2805
}
2806
else
2807
{
2808
line->AddLeftTrig(GetEdge(starte).RightTrig());
2809
line->AddRightTrig(GetEdge(starte).LeftTrig());
2810
}
2811
edgecnt++; we.Elem(starte) = 1;
2812
}
2813
}
2814
}
2815
AddLine(line);
2816
}
2817
PrintMessage(5,"number of lines generated = ", GetNLines());
2818
2819
//check, which lines must have at least one midpoint
2820
INDEX_2_HASHTABLE<int> lineht(GetNLines()+1);
2821
2822
for (i = 1; i <= GetNLines(); i++)
2823
{
2824
if (GetLine(i)->StartP() == GetLine(i)->EndP())
2825
{
2826
GetLine(i)->DoSplit();
2827
}
2828
}
2829
2830
for (i = 1; i <= GetNLines(); i++)
2831
{
2832
INDEX_2 lineep (GetLine(i)->StartP(),GetLine(i)->EndP());
2833
lineep.Sort();
2834
2835
if (lineht.Used (lineep))
2836
{
2837
GetLine(i)->DoSplit();
2838
int other = lineht.Get(lineep);
2839
GetLine(other)->DoSplit();
2840
}
2841
else
2842
{
2843
lineht.Set (lineep, i);
2844
}
2845
}
2846
2847
for (i = 1; i <= GetNLines(); i++)
2848
{
2849
STLLine* line = GetLine(i);
2850
for (int ii = 1; ii <= line->GetNS(); ii++)
2851
{
2852
int ap1, ap2;
2853
line->GetSeg(ii,ap1,ap2);
2854
// (*mycout) << "SEG " << p1 << " - " << p2 << endl;
2855
}
2856
}
2857
2858
PopStatus();
2859
}
2860
2861
int STLGeometry :: GetNOBodys()
2862
{
2863
int markedtrigs1 = 0;
2864
int starttrig = 1;
2865
int i, k, nnt;
2866
int bodycnt = 0;
2867
2868
ARRAY<int> bodynum(GetNT());
2869
2870
for (i = 1; i <= GetNT(); i++)
2871
bodynum.Elem(i)=0;
2872
2873
2874
while (markedtrigs1 < GetNT())
2875
{
2876
for (i = starttrig; i <= GetNT(); i++)
2877
{
2878
if (!bodynum.Get(i))
2879
{
2880
starttrig = i;
2881
break;
2882
}
2883
}
2884
//add all triangles around starttriangle, which is reachable without going over an edge
2885
ARRAY<int> todolist;
2886
ARRAY<int> nextlist;
2887
bodycnt++;
2888
markedtrigs1++;
2889
bodynum.Elem(starttrig) = bodycnt;
2890
todolist.Append(starttrig);
2891
2892
while(todolist.Size())
2893
{
2894
for (i = 1; i <= todolist.Size(); i++)
2895
{
2896
//const STLTriangle& tt = GetTriangle(todolist.Get(i));
2897
for (k = 1; k <= NONeighbourTrigs(todolist.Get(i)); k++)
2898
{
2899
nnt = NeighbourTrig(todolist.Get(i),k);
2900
if (!bodynum.Get(nnt))
2901
{
2902
nextlist.Append(nnt);
2903
bodynum.Elem(nnt) = bodycnt;
2904
markedtrigs1++;
2905
}
2906
}
2907
}
2908
2909
todolist.SetSize(0);
2910
for (i = 1; i <= nextlist.Size(); i++)
2911
{
2912
todolist.Append(nextlist.Get(i));
2913
}
2914
nextlist.SetSize(0);
2915
}
2916
}
2917
PrintMessage(3, "Geometry has ", bodycnt, " separated bodys");
2918
2919
return bodycnt;
2920
}
2921
2922
void STLGeometry :: CalcFaceNums()
2923
{
2924
int markedtrigs1 = 0;
2925
int starttrig(0);
2926
int laststarttrig = 1;
2927
int i, k, nnt;
2928
facecnt = 0;
2929
2930
2931
for (i = 1; i <= GetNT(); i++)
2932
GetTriangle(i).SetFaceNum(0);
2933
2934
2935
while (markedtrigs1 < GetNT())
2936
{
2937
for (i = laststarttrig; i <= GetNT(); i++)
2938
{
2939
if (!GetTriangle(i).GetFaceNum())
2940
{
2941
starttrig = i;
2942
laststarttrig = i;
2943
break;
2944
}
2945
}
2946
//add all triangles around starttriangle, which is reachable without going over an edge
2947
ARRAY<int> todolist;
2948
ARRAY<int> nextlist;
2949
facecnt++;
2950
markedtrigs1++;
2951
GetTriangle(starttrig).SetFaceNum(facecnt);
2952
todolist.Append(starttrig);
2953
int ap1, ap2;
2954
2955
while(todolist.Size())
2956
{
2957
for (i = 1; i <= todolist.Size(); i++)
2958
{
2959
const STLTriangle& tt = GetTriangle(todolist.Get(i));
2960
for (k = 1; k <= NONeighbourTrigs(todolist.Get(i)); k++)
2961
{
2962
nnt = NeighbourTrig(todolist.Get(i),k);
2963
STLTriangle& nt = GetTriangle(nnt);
2964
if (!nt.GetFaceNum())
2965
{
2966
tt.GetNeighbourPoints(nt,ap1,ap2);
2967
if (!IsEdge(ap1,ap2))
2968
{
2969
nextlist.Append(nnt);
2970
nt.SetFaceNum(facecnt);
2971
markedtrigs1++;
2972
}
2973
}
2974
}
2975
}
2976
2977
todolist.SetSize(0);
2978
for (i = 1; i <= nextlist.Size(); i++)
2979
{
2980
todolist.Append(nextlist.Get(i));
2981
}
2982
nextlist.SetSize(0);
2983
}
2984
}
2985
GetNOBodys();
2986
PrintMessage(3,"generated ", facecnt, " faces");
2987
}
2988
2989
void STLGeometry :: ClearSpiralPoints()
2990
{
2991
spiralpoints.SetSize(GetNP());
2992
int i;
2993
for (i = 1; i <= spiralpoints.Size(); i++)
2994
{
2995
spiralpoints.Elem(i) = 0;
2996
}
2997
}
2998
2999
3000
void STLGeometry :: BuildSmoothEdges ()
3001
{
3002
if (smoothedges) delete smoothedges;
3003
3004
smoothedges = new INDEX_2_HASHTABLE<int> (GetNE()/10 + 1);
3005
3006
3007
// Jack: Ok ?
3008
// UseExternalEdges();
3009
3010
PushStatusF("Build Smooth Edges");
3011
3012
int i, j;//, k, l;
3013
int nt = GetNT();
3014
Vec3d ng1, ng2;
3015
3016
for (i = 1; i <= nt; i++)
3017
{
3018
if (multithread.terminate)
3019
{PopStatus();return;}
3020
3021
SetThreadPercent(100.0 * (double)i / (double)nt);
3022
3023
const STLTriangle & trig = GetTriangle (i);
3024
3025
ng1 = trig.GeomNormal(points);
3026
ng1 /= (ng1.Length() + 1e-24);
3027
3028
for (j = 1; j <= 3; j++)
3029
{
3030
int nbt = NeighbourTrig (i, j);
3031
3032
ng2 = GetTriangle(nbt).GeomNormal(points);
3033
ng2 /= (ng2.Length() + 1e-24);
3034
3035
3036
int pi1, pi2;
3037
3038
trig.GetNeighbourPoints(GetTriangle(nbt), pi1, pi2);
3039
3040
if (!IsEdge(pi1,pi2))
3041
{
3042
if (ng1 * ng2 < 0)
3043
{
3044
PrintMessage(7,"smoothedge found");
3045
INDEX_2 i2(pi1, pi2);
3046
i2.Sort();
3047
smoothedges->Set (i2, 1);
3048
}
3049
}
3050
}
3051
}
3052
3053
PopStatus();
3054
}
3055
3056
3057
3058
3059
3060
int STLGeometry :: IsSmoothEdge (int pi1, int pi2) const
3061
{
3062
if (!smoothedges)
3063
return 0;
3064
INDEX_2 i2(pi1, pi2);
3065
i2.Sort();
3066
return smoothedges->Used (i2);
3067
}
3068
3069
3070
3071
3072
//function is not used now
3073
int IsInArray(int n, const ARRAY<int>& ia)
3074
{
3075
int i;
3076
for (i = 1; i <= ia.Size(); i++)
3077
{
3078
if (ia.Get(i) == n) {return 1;}
3079
}
3080
return 0;
3081
}
3082
3083
void STLGeometry :: AddConeAndSpiralEdges()
3084
{
3085
PrintMessage(5,"have now ", GetNE(), " edges with yellow angle = ", stlparam.yangle, " degree");
3086
3087
PrintFnStart("AddConeAndSpiralEdges");
3088
3089
int i,j,k,n;
3090
// int changed = 0;
3091
3092
//check edges, where inner chart and no outer chart come together without an edge
3093
int np1, np2, nt;
3094
int cnt = 0;
3095
3096
for (i = 1; i <= GetNOCharts(); i++)
3097
{
3098
STLChart& chart = GetChart(i);
3099
for (j = 1; j <= chart.GetNChartT(); j++)
3100
{
3101
int t = chart.GetChartTrig(j);
3102
const STLTriangle& tt = GetTriangle(t);
3103
3104
for (k = 1; k <= 3; k++)
3105
{
3106
nt = NeighbourTrig(t,k);
3107
if (GetChartNr(nt) != i && !TrigIsInOC(nt,i))
3108
{
3109
tt.GetNeighbourPoints(GetTriangle(nt),np1,np2);
3110
if (!IsEdge(np1,np2))
3111
{
3112
STLEdge se(np1,np2);
3113
se.SetLeftTrig(t);
3114
se.SetRightTrig(nt);
3115
int edgenum = AddEdge(se);
3116
AddEdgePP(np1,edgenum);
3117
AddEdgePP(np2,edgenum);
3118
//changed = 1;
3119
PrintWarning("Found a spiral like structure: chart=", i,
3120
", trig=", t, ", p1=", np1, ", p2=", np2);
3121
cnt++;
3122
}
3123
}
3124
}
3125
}
3126
3127
}
3128
3129
PrintMessage(5, "found ", cnt, " spiral like structures");
3130
PrintMessage(5, "added ", cnt, " edges due to spiral like structures");
3131
3132
cnt = 0;
3133
int edgecnt = 0;
3134
3135
ARRAY<int> trigsaroundp;
3136
ARRAY<int> chartpointchecked; //gets number of chart, if in this chart already checked
3137
chartpointchecked.SetSize(GetNP());
3138
3139
for (i = 1; i <= GetNP(); i++)
3140
{
3141
chartpointchecked.Elem(i) = 0;
3142
}
3143
3144
int onoc, notonoc, tpp, pn;
3145
int ap1, ap2, tn1, tn2, l, problem;
3146
3147
if (!stldoctor.conecheck) {PrintWarning("++++++++++++ \ncone checking deactivated by user!!!!!\n+++++++++++++++"); return ;}
3148
3149
PushStatus("Find Critical Points");
3150
3151
int addedges = 0;
3152
3153
for (i = 1; i <= GetNOCharts(); i++)
3154
{
3155
SetThreadPercent((double)i/(double)GetNOCharts()*100.);
3156
if (multithread.terminate)
3157
{PopStatus();return;}
3158
3159
STLChart& chart = GetChart(i);
3160
for (j = 1; j <= chart.GetNChartT(); j++)
3161
{
3162
int t = chart.GetChartTrig(j);
3163
const STLTriangle& tt = GetTriangle(t);
3164
3165
for (k = 1; k <= 3; k++)
3166
{
3167
pn = tt.PNum(k);
3168
if (chartpointchecked.Get(pn) == i)
3169
{continue;}
3170
3171
int checkpoint = 0;
3172
for (n = 1; n <= trigsperpoint.EntrySize(pn); n++)
3173
{
3174
if (trigsperpoint.Get(pn,n) != t &&
3175
GetChartNr(trigsperpoint.Get(pn,n)) != i &&
3176
!TrigIsInOC(trigsperpoint.Get(pn,n),i)) {checkpoint = 1;};
3177
}
3178
if (checkpoint)
3179
{
3180
chartpointchecked.Elem(pn) = i;
3181
3182
int worked = 0;
3183
int spworked = 0;
3184
GetSortedTrianglesAroundPoint(pn,t,trigsaroundp);
3185
trigsaroundp.Append(t);
3186
3187
problem = 0;
3188
for (l = 2; l <= trigsaroundp.Size()-1; l++)
3189
{
3190
tn1 = trigsaroundp.Get(l-1);
3191
tn2 = trigsaroundp.Get(l);
3192
const STLTriangle& t1 = GetTriangle(tn1);
3193
const STLTriangle& t2 = GetTriangle(tn2);
3194
t1.GetNeighbourPoints(t2, ap1, ap2);
3195
if (IsEdge(ap1,ap2)) break;
3196
3197
if (GetChartNr(tn2) != i && !TrigIsInOC(tn2,i)) {problem = 1;}
3198
}
3199
3200
if (problem)
3201
{
3202
for (l = 2; l <= trigsaroundp.Size()-1; l++)
3203
{
3204
tn1 = trigsaroundp.Get(l-1);
3205
tn2 = trigsaroundp.Get(l);
3206
const STLTriangle& t1 = GetTriangle(tn1);
3207
const STLTriangle& t2 = GetTriangle(tn2);
3208
t1.GetNeighbourPoints(t2, ap1, ap2);
3209
if (IsEdge(ap1,ap2)) break;
3210
3211
if ((GetChartNr(tn1) == i && GetChartNr(tn2) != i && TrigIsInOC(tn2,i)) ||
3212
(GetChartNr(tn2) == i && GetChartNr(tn1) != i && TrigIsInOC(tn1,i)))
3213
{
3214
if (addedges || !GetNEPP(pn))
3215
{
3216
STLEdge se(ap1,ap2);
3217
se.SetLeftTrig(tn1);
3218
se.SetRightTrig(tn2);
3219
int edgenum = AddEdge(se);
3220
AddEdgePP(ap1,edgenum);
3221
AddEdgePP(ap2,edgenum);
3222
edgecnt++;
3223
}
3224
if (!addedges && !GetSpiralPoint(pn))
3225
{
3226
SetSpiralPoint(pn);
3227
spworked = 1;
3228
}
3229
worked = 1;
3230
}
3231
}
3232
}
3233
//backwards:
3234
problem = 0;
3235
for (l = trigsaroundp.Size()-1; l >= 2; l--)
3236
{
3237
tn1 = trigsaroundp.Get(l+1);
3238
tn2 = trigsaroundp.Get(l);
3239
const STLTriangle& t1 = GetTriangle(tn1);
3240
const STLTriangle& t2 = GetTriangle(tn2);
3241
t1.GetNeighbourPoints(t2, ap1, ap2);
3242
if (IsEdge(ap1,ap2)) break;
3243
3244
if (GetChartNr(tn2) != i && !TrigIsInOC(tn2,i)) {problem = 1;}
3245
}
3246
if (problem)
3247
for (l = trigsaroundp.Size()-1; l >= 2; l--)
3248
{
3249
tn1 = trigsaroundp.Get(l+1);
3250
tn2 = trigsaroundp.Get(l);
3251
const STLTriangle& t1 = GetTriangle(tn1);
3252
const STLTriangle& t2 = GetTriangle(tn2);
3253
t1.GetNeighbourPoints(t2, ap1, ap2);
3254
if (IsEdge(ap1,ap2)) break;
3255
3256
if ((GetChartNr(tn1) == i && GetChartNr(tn2) != i && TrigIsInOC(tn2,i)) ||
3257
(GetChartNr(tn2) == i && GetChartNr(tn1) != i && TrigIsInOC(tn1,i)))
3258
{
3259
if (addedges || !GetNEPP(pn))
3260
{
3261
STLEdge se(ap1,ap2);
3262
se.SetLeftTrig(tn1);
3263
se.SetRightTrig(tn2);
3264
int edgenum = AddEdge(se);
3265
AddEdgePP(ap1,edgenum);
3266
AddEdgePP(ap2,edgenum);
3267
edgecnt++;
3268
}
3269
if (!addedges && !GetSpiralPoint(pn))
3270
{
3271
SetSpiralPoint(pn);
3272
spworked = 1;
3273
//if (GetNEPP(pn) == 0) {(*mycout) << "ERROR: spiralpoint with no edge found!" << endl;}
3274
}
3275
worked = 1;
3276
}
3277
}
3278
3279
if (worked)
3280
{
3281
//(*testout) << "set edgepoint due to spirals: pn=" << i << endl;
3282
SetLineEndPoint(pn);
3283
}
3284
if (spworked)
3285
{
3286
/*
3287
(*mycout) << "Warning: Critical Point " << tt.PNum(k)
3288
<< "( chart " << i << ", trig " << t
3289
<< ") has been neutralized!!!" << endl;
3290
*/
3291
cnt++;
3292
}
3293
// markedpoints.Elem(tt.PNum(k)) = 1;
3294
}
3295
}
3296
}
3297
}
3298
PrintMessage(5, "found ", cnt, " critical points!");
3299
PrintMessage(5, "added ", edgecnt, " edges due to critical points!");
3300
3301
PopStatus();
3302
3303
//search points where inner chart and outer chart and "no chart" trig come together at edge-point
3304
3305
PrintMessage(7,"search for special chart points");
3306
for (i = 1; i <= GetNOCharts(); i++)
3307
{
3308
STLChart& chart = GetChart(i);
3309
for (j = 1; j <= chart.GetNChartT(); j++)
3310
{
3311
int t = chart.GetChartTrig(j);
3312
const STLTriangle& tt = GetTriangle(t);
3313
3314
for (k = 1; k <= 3; k++)
3315
{
3316
pn = tt.PNum(k);
3317
if (GetNEPP(pn) == 2)
3318
{
3319
onoc = 0;
3320
notonoc = 0;
3321
for (n = 1; n <= trigsperpoint.EntrySize(pn); n++)
3322
{
3323
tpp = trigsperpoint.Get(pn,n);
3324
if (tpp != t && GetChartNr(tpp) != i)
3325
{
3326
if (TrigIsInOC(tpp,i)) {onoc = 1;}
3327
if (!TrigIsInOC(tpp,i)) {notonoc = 1;}
3328
}
3329
}
3330
if (onoc && notonoc && !IsLineEndPoint(pn))
3331
{
3332
GetSortedTrianglesAroundPoint(pn,t,trigsaroundp);
3333
int here = 1; //we start on this side of edge, !here = there
3334
int thereOC = 0;
3335
int thereNotOC = 0;
3336
for (l = 2; l <= trigsaroundp.Size(); l++)
3337
{
3338
GetTriangle(trigsaroundp.Get(l-1)).
3339
GetNeighbourPoints(GetTriangle(trigsaroundp.Get(l)), ap1, ap2);
3340
if (IsEdge(ap1,ap2)) {here = (here+1)%2;}
3341
if (!here && TrigIsInOC(trigsaroundp.Get(l),i)) {thereOC = 1;}
3342
if (!here && !TrigIsInOC(trigsaroundp.Get(l),i)) {thereNotOC = 1;}
3343
}
3344
if (thereOC && thereNotOC)
3345
{
3346
//(*mycout) << "Special OCICnotC - point " << pn << " found!" << endl;
3347
//(*testout) << "set edgepoint due to spirals: pn=" << i << endl;
3348
SetLineEndPoint(pn);
3349
}
3350
}
3351
}
3352
}
3353
}
3354
}
3355
PrintMessage(5,"have now ", GetNE(), " edges with yellow angle = ", stlparam.yangle, " degree");
3356
}
3357
3358
//get trigs at a point, started with starttrig, then every left
3359
void STLGeometry :: GetSortedTrianglesAroundPoint(int p, int starttrig, ARRAY<int>& trigs)
3360
{
3361
int acttrig = starttrig;
3362
trigs.SetAllocSize(trigsperpoint.EntrySize(p));
3363
trigs.SetSize(0);
3364
trigs.Append(acttrig);
3365
int i, j, t, ap1, ap2, locindex1(0), locindex2(0);
3366
3367
//(*mycout) << "trigs around point " << p << endl;
3368
3369
int end = 0;
3370
while (!end)
3371
{
3372
const STLTriangle& at = GetTriangle(acttrig);
3373
for (i = 1; i <= trigsperpoint.EntrySize(p); i++)
3374
{
3375
t = trigsperpoint.Get(p,i);
3376
const STLTriangle& nt = GetTriangle(t);
3377
if (at.IsNeighbourFrom(nt))
3378
{
3379
at.GetNeighbourPoints(nt, ap1, ap2);
3380
if (ap2 == p) {Swap(ap1,ap2);}
3381
if (ap1 != p) {PrintSysError("In GetSortedTrianglesAroundPoint!!!");}
3382
3383
for (j = 1; j <= 3; j++)
3384
{
3385
if (at.PNum(j) == ap1) {locindex1 = j;};
3386
if (at.PNum(j) == ap2) {locindex2 = j;};
3387
}
3388
if ((locindex2+1)%3+1 == locindex1)
3389
{
3390
if (t != starttrig)
3391
{
3392
trigs.Append(t);
3393
// (*mycout) << "trig " << t << endl;
3394
acttrig = t;
3395
}
3396
else
3397
{
3398
end = 1;
3399
}
3400
break;
3401
}
3402
}
3403
}
3404
}
3405
3406
}
3407
3408
/*
3409
int STLGeometry :: NeighbourTrig(int trig, int nr) const
3410
{
3411
return neighbourtrigs.Get(trig,nr);
3412
}
3413
*/
3414
3415
3416
3417
void STLGeometry :: SmoothGeometry ()
3418
{
3419
int i, j, k;
3420
3421
double maxerr0, maxerr;
3422
3423
for (i = 1; i <= GetNP(); i++)
3424
{
3425
if (GetNEPP(i)) continue;
3426
3427
maxerr0 = 0;
3428
for (j = 1; j <= NOTrigsPerPoint(i); j++)
3429
{
3430
int tnum = TrigPerPoint(i, j);
3431
double err = Angle (GetTriangle(tnum).Normal (),
3432
GetTriangle(tnum).GeomNormal(GetPoints()));
3433
if (err > maxerr0)
3434
maxerr0 = err;
3435
}
3436
3437
Point3d pi = GetPoint (i);
3438
if (maxerr0 < 1.1) continue; // about 60 degree
3439
3440
maxerr0 /= 2; // should be at least halfen
3441
3442
for (k = 1; k <= NOTrigsPerPoint(i); k++)
3443
{
3444
const STLTriangle & trig = GetTriangle (TrigPerPoint (i, k));
3445
Point3d c = Center(GetPoint (trig.PNum(1)),
3446
GetPoint (trig.PNum(2)),
3447
GetPoint (trig.PNum(3)));
3448
3449
Point3d np = pi + 0.1 * (c - pi);
3450
SetPoint (i, np);
3451
3452
maxerr = 0;
3453
for (j = 1; j <= NOTrigsPerPoint(i); j++)
3454
{
3455
int tnum = TrigPerPoint(i, j);
3456
double err = Angle (GetTriangle(tnum).Normal (),
3457
GetTriangle(tnum).GeomNormal(GetPoints()));
3458
if (err > maxerr)
3459
maxerr = err;
3460
}
3461
3462
if (maxerr < maxerr0)
3463
{
3464
pi = np;
3465
}
3466
}
3467
3468
SetPoint (i, pi);
3469
}
3470
}
3471
}
3472
3473