Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/meshgen2d/src/Connect.cpp
3196 views
1
#include "Connect.h"
2
#include <algorithm>
3
#include "Vertex.h"
4
#include "TriangleElement.h"
5
#include "Border.h"
6
#include "BGMesh.h"
7
#include "Triple.h"
8
#include "PQ.h"
9
#include "MGError.h"
10
11
#include <list>
12
#include <vector>
13
#include <iostream>
14
#include <algorithm>
15
#ifdef _NO_STD_MINMAX
16
#include "minmaxpatch.h"
17
#endif
18
19
void Connect::
20
makeWorld()
21
{
22
double maxx, maxy, minx, miny;
23
int len = border.size();
24
25
maxx = minx = border[0]->x;
26
maxy = miny = border[0]->y;
27
for( int i = 1; i < len; ++i)
28
{
29
double tx = border[i]->x;
30
double ty = border[i]->y;
31
32
if( minx > tx) minx = tx;
33
else if( maxx < tx) maxx = tx;
34
35
if( miny > ty) miny = ty;
36
else if( maxy < ty) maxy = ty;
37
}
38
39
double dx = maxx - minx;
40
double dy = maxy - miny;
41
42
double diam = std::max( dx, dy );
43
44
double cx = (maxx + minx) / 2.0;
45
double cy = (maxy + miny) / 2.0;
46
47
world[0] = new MeshNode( -1, cx - dx, cy - dy );
48
world[1] = new MeshNode( -2, cx + dx, cy - dy );
49
world[2] = new MeshNode( -3, cx + dx, cy + dy );
50
world[3] = new MeshNode( -4, cx - dx, cy + dy );
51
52
std::vector< Vertex * > box;
53
getVertices( box, 2 );
54
55
box[0]->reset( world[0], world[1], world[2] );
56
box[1]->reset( world[2], world[3], world[0] );
57
58
box[0]->setVertices((Vertex *)0, (Vertex *)0, box[1]);
59
box[1]->setVertices((Vertex *)0, (Vertex *)0, box[0]);
60
61
root = box[0];
62
}
63
64
void Connect::initialize()
65
{
66
bounds->collectGeometryNodes( nodes );
67
bounds->collectGeometryEdges( edges, directions );
68
if(!bg->isInitialized()) bg->initialize( nodes, edges );
69
}
70
71
void Connect::
72
discretize(NodeMap& fixedNodes, NodeMap& allNodes, std::list< Element* >& allElements)
73
{
74
triangulate();
75
76
removeBoundaryConnectors();
77
78
exportNodes( allNodes, allElements );
79
}
80
81
82
void Connect::
83
triangulate()
84
{
85
int i;
86
int len;
87
88
bounds->collectNodesAndPairs( border, links );
89
90
makeWorld();
91
92
for (i = 0; i < fixedGeometryNodes.size(); i++)
93
{
94
MeshNode *nd = static_cast< MeshNode* >( fixedGeometryNodes[i] );
95
Vertex *vtx = root->firstAcceptableFound( nd->x, nd->y);
96
addSite( vtx, nd, true );
97
nd->fix();
98
recycle();
99
}
100
101
len = border.size();
102
int *indirect = new int[len];
103
for( i = 0; i < len; ++i)
104
{
105
indirect[i] = i;
106
}
107
std::random_shuffle(indirect, indirect + len);
108
109
// std::cout << "Inserting border" << std::endl;
110
for( i = 0; i < len; ++i)
111
{
112
int ind = indirect[i];
113
Vertex *vtx = root->firstAcceptableFound( border[ind]->x, border[ind]->y);
114
addSite( vtx, border[ind], true );
115
MeshNode *nd = static_cast< MeshNode* >( border[ind] );
116
nd->fix();
117
recycle();
118
}
119
120
delete [] indirect;
121
122
// Verify borders (no recovery!)
123
// std::cout << "Verifying borders" << std::endl;
124
125
len = border.size();
126
127
Vertex *verify = root;
128
for(i = 0; i < len; ++i)
129
{
130
int t1 = border[i]->tag, t2 = border[(i + 1) % len]->tag;
131
if( links.find( std::make_pair( std::min(t1, t2), std::max(t1, t2) ) ) !=
132
links.end() )
133
{
134
verify = verify->vertexOwning( border[i], border[(i + 1) % len] );
135
if(!verify)
136
{
137
blm_error("Initial triangulation is incomplete!",
138
"Please readjust your mesh parameters.");
139
}
140
}
141
}
142
// std::cout << "Verifying borders completed" << std::endl;
143
144
//
145
Vertex *vtx = root->vertexWith( border[0], border[1] );
146
147
vtx->labelBodies( tag, links );
148
}
149
150
void Connect::
151
exportNodes( NodeMap& allNodes, std::list< Element* >& allElements )
152
{
153
std::list< Vertex* >::iterator vxIt;
154
for( vxIt = allVertices.begin(); vxIt != allVertices.end(); ++vxIt )
155
{
156
Vertex *vtx = (*vxIt);
157
if( !(vtx->isDeleted() || vtx->isExternal()))
158
{
159
vtx->newTag();
160
allElements.push_back( vtx );
161
162
for(int i = 0; i < 3; ++i)
163
{
164
allNodes[ vtx->nodeAt(i)->tag ] = vtx->nodeAt(i);
165
}
166
}
167
}
168
169
// std::cout << "Nodes OK!" << std::endl;
170
171
std::vector< BoundaryElement * > bels;
172
bounds->collectBoundaryElements( bels );
173
174
// std::cout << "BoundaryElement I OK!" << std::endl;
175
176
int i, len;
177
Vertex *v = root;
178
len = bels.size();
179
180
for( i = 0; i < len; ++i )
181
{
182
v = bels[i]->setHolder( v );
183
}
184
// std::cout << "BoundaryElement II OK!" << std::endl;
185
}
186
187
bool Connect::
188
addSite( Vertex *vx, Node *nd, bool externalOK, bool splitOne, bool force)
189
{
190
int i, count;
191
Vertex *vtx;
192
Triple *trip, *tmp;
193
std::list< Triple * > tripleQueue;
194
195
hull.clear();
196
197
for( i = 2; i >= 0; --i )
198
{
199
trip = getTriple();
200
trip->from = vx->nodeAt(i);
201
trip->to = vx->nodeAt((i+1)%3);
202
trip->vtx = vx->vertices[i];
203
204
tripleQueue.push_back( trip );
205
}
206
207
vx->makeDeleted();
208
deleted.push_back( vx );
209
210
while( tripleQueue.size() > 0 )
211
{
212
trip = tripleQueue.back();
213
tripleQueue.pop_back();
214
215
vtx = trip->vtx;
216
if(vtx == (Vertex *)0)
217
{
218
hull.push_back( trip );
219
continue;
220
}
221
if( vtx->isDeleted() )
222
{
223
/*
224
If a vertex is deleted, we must have visited it during this loop.
225
Therefore, there must be a triple with reversed direction in the stack list.
226
We must remove both triples.
227
*/
228
tmp = tripleQueue.back();
229
if(tmp->from == trip->to && tmp->to == trip->from)
230
{
231
tripleQueue.pop_back();
232
}
233
else
234
{
235
tripleQueue.pop_front();
236
}
237
}
238
else
239
{
240
/*
241
Return status:
242
= 1 OK, destroyed
243
= 0 OK, not destroyed
244
= -1 NOT OK, external element destroyed
245
246
If retval = -1, abort the operation, clear buffers and indicate the same thing
247
for the upper level.
248
*/
249
int retval = vtx->isDestroyedBy(nd->x, nd->y, externalOK);
250
if(retval == 1)
251
{
252
vtx->makeDeleted();
253
deleted.push_back( vtx );
254
255
for(i = 0; i < 3; ++i) if(vtx->nodeAt(i) == trip->from) break;
256
257
tmp = getTriple();
258
tmp->from = vtx->nodeAt((i+1)%3);
259
tmp->to = vtx->nodeAt((i+2)%3);
260
tmp->vtx = vtx->vertices[(i+1)%3];
261
262
tripleQueue.push_back( tmp );
263
264
tmp = getTriple();
265
tmp->from = vtx->nodeAt(i);
266
tmp->to = vtx->nodeAt((i+1)%3);
267
tmp->vtx = vtx->vertices[i];
268
269
tripleQueue.push_back( tmp );
270
}
271
else if(retval == 0 || force)
272
{
273
hull.push_back( trip );
274
}
275
else
276
{
277
std::list< Vertex* >::iterator deletedIt;
278
for( deletedIt = deleted.begin(); deletedIt != deleted.end(); ++deletedIt )
279
{
280
(*deletedIt)->unDelete();
281
}
282
deleted.clear();
283
return false;
284
}
285
}
286
}
287
if (!externalOK && !splitOne && deleted.size() == 1)
288
return true;
289
290
// These parts should be separated!
291
count = hull.size();
292
293
getVertices( newVertices, count );
294
295
std::list<Triple *>::const_iterator hit;
296
for(hit = hull.begin(), i = 0; i < count; ++i, ++hit)
297
{
298
tmp = *hit;
299
newVertices[i]->reset( nd, tmp->from, tmp->to );
300
}
301
302
for(hit = hull.begin(), i = 0; i < count; ++i, ++hit)
303
{
304
tmp = *hit;
305
vtx = newVertices[i];
306
vtx->setVertices(newVertices[(i+count-1)%count],
307
tmp->vtx,
308
newVertices[(i+1)%count]);
309
310
if(tmp->vtx != (Vertex *)0)
311
{
312
if(tmp->vtx->nodeAt(0) == tmp->to)
313
tmp->vtx->replaceVertexWith(0, vtx);
314
else if(tmp->vtx->nodeAt(1) == tmp->to)
315
tmp->vtx->replaceVertexWith(1, vtx);
316
else if(tmp->vtx->nodeAt(2) == tmp->to)
317
tmp->vtx->replaceVertexWith(2, vtx);
318
}
319
}
320
321
root = newVertices.back();
322
323
return true;
324
}
325
326
void Connect::
327
recycle()
328
{
329
std::copy( deleted.begin(), deleted.end(), std::back_inserter( vertexStore ) );
330
deleted.erase( deleted.begin(), deleted.end() );
331
newVertices.erase( newVertices.begin(), newVertices.end() );
332
std::copy( hull.begin(), hull.end(), std::back_inserter( tripleStore ) );
333
hull.erase( hull.begin(), hull.end() );
334
}
335
336
void Connect::
337
getVertices( std::vector< Vertex * >& v, const int count )
338
{
339
int i;
340
341
for( i = 0; i < count; ++i )
342
{
343
if( vertexStore.empty() ) break;
344
v.push_back( vertexStore.back() );
345
vertexStore.pop_back();
346
}
347
348
for( ; i < count; ++i )
349
{
350
Vertex *vtx = new Vertex;
351
v.push_back( vtx );
352
allVertices.push_back( vtx );
353
}
354
}
355
356
Triple * Connect::
357
getTriple()
358
{
359
Triple *tmp;
360
if( tripleStore.empty() ) return new Triple;
361
else
362
{
363
tmp = tripleStore.back();
364
tripleStore.pop_back();
365
}
366
return tmp;
367
}
368
369
#include <queue>
370
#include <set>
371
#include "coreGeometry.h"
372
373
class Segment
374
{
375
public:
376
Node *a, *b;
377
double length;
378
};
379
380
class SegCompare
381
{
382
public:
383
bool operator() (const Segment *s0, const Segment *s1)
384
{
385
return s0->length < s1->length;
386
}
387
};
388
389
void Connect::
390
removeBoundaryConnectors()
391
{
392
const double sqrt3 = 1.7320508075688772935274463415059;
393
394
pq actives;
395
396
double ref;
397
std::list< Vertex* >::iterator vxIt;
398
for( vxIt = allVertices.begin(); vxIt != allVertices.end(); ++vxIt )
399
{
400
Vertex *vtx = (*vxIt);
401
if( !(vtx->isDeleted() || vtx->isExternal() ))
402
{
403
if( vtx->isBoundaryConnector(links) )
404
{
405
vtx->rightSize( 1.0 );
406
actives.insert( vtx );
407
}
408
}
409
}
410
411
while( actives.size() > 0 )
412
{
413
Vertex *vtx = actives.first();
414
415
if (!vtx->isBoundaryConnector(links))
416
continue;
417
418
int i;
419
double x, y;
420
421
for (i = 0; i < 3; i++)
422
{
423
int t0 = vtx->nodeAt(i)->tag, t1 = vtx->nodeAt((i+1)%3)->tag;
424
if (links.find(std::make_pair(std::min(t0, t1), std::max(t0, t1))) == links.end())
425
{
426
double dx0 = vtx->nodeAt(i)->x - vtx->nodeAt((i+2)%3)->x;
427
double dy0 = vtx->nodeAt(i)->y - vtx->nodeAt((i+2)%3)->y;
428
double dx1 = vtx->nodeAt((i+1)%3)->x - vtx->nodeAt((i+2)%3)->x;
429
double dy1 = vtx->nodeAt((i+1)%3)->y - vtx->nodeAt((i+2)%3)->y;
430
431
// r1 = sqrt(dx0*dx0+dy0*dy0)
432
// r2 = sqrt(dx1*dx1+dy1*dy1)
433
// theta1 = atan(dy0/dx0)
434
// theta2 = atan(dy1/dx1)
435
// (x + iy) = sqrt(r1*r2)*e^(i*(theta1+theta2)/2)
436
437
double x2y2 = dx0 * dx1 - dy0 * dy1; // x*x-y*y
438
double xy = dx0 * dy1 + dx1 * dy0; // 2*x*y
439
440
y = sqrt(0.5 * (sqrt(x2y2 * x2y2 + xy * xy) - x2y2));
441
x = 0.5 * xy / y;
442
443
if (dx0 * x + dy0 * y < 0.0)
444
{
445
x = -x;
446
y = -y;
447
}
448
449
x = vtx->nodeAt((i+2)%3)->x + x;
450
y = vtx->nodeAt((i+2)%3)->y + y;
451
452
break;
453
}
454
}
455
456
MeshNode *nd = new MeshNode( x, y ); //vtx->vx, vtx->vy );
457
458
if( addSite( vtx, nd, false, true, false) == true )
459
{
460
actives.removeRelevants( deleted );
461
462
int len = newVertices.size();
463
for( int i = 0; i < len; ++i )
464
{
465
newVertices[i]->setBody( 1 );
466
if( newVertices[i]->isBoundaryConnector(links) )
467
{
468
newVertices[i]->rightSize( 1.0 );
469
actives.insert( newVertices[i] );
470
}
471
}
472
}
473
474
recycle();
475
}
476
477
return;
478
}
479
480