Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/meshgen2d/src/GeometryEdge.cpp
3196 views
1
#include "GeometryEdge.h"
2
#include "BGMesh.h"
3
#include <math.h>
4
#include <algorithm>
5
#include <iostream>
6
#include "coreGeometry.h"
7
8
static int nextTag = 1;
9
10
GeometryEdge::GeometryEdge( int nSegments )
11
{
12
tag = nextTag;
13
14
segments = nSegments;
15
16
boundaryTag = 0;
17
type = OUTER;
18
++nextTag;
19
}
20
21
GeometryEdge::GeometryEdge( const int t, int nSegments )
22
{
23
tag = t;
24
25
segments = nSegments;
26
27
boundaryTag = 0;
28
type = OUTER;
29
++nextTag;
30
}
31
32
void GeometryEdge::
33
exportNodes(std::vector<Node*>& strip, int direction)
34
{
35
if( direction < 0 )
36
{
37
std::reverse_copy( nodes.begin(), nodes.end(), std::back_inserter( strip ) );
38
}
39
else
40
{
41
std::copy( nodes.begin(), nodes.end(), std::back_inserter( strip ) );
42
}
43
}
44
45
void GeometryEdge::
46
elements(std::vector< BoundaryElement * >& strip, int direction)
47
{
48
int i, len = bels.size();
49
50
if( len == 0 ) // Not constructed yet
51
{
52
int nlen = nodes.size();
53
for( i = 0; i < (nlen - 1); ++i )
54
{
55
bels.push_back( new BoundaryElement( boundaryTag, nodes[i], nodes[i+1] ) );
56
}
57
58
len = bels.size();
59
}
60
61
if( direction < 0 )
62
{
63
for( i = 0; i < len; ++i ) bels[i]->flip( true );
64
std::reverse_copy( bels.begin(), bels.end(), std::back_inserter( strip ) );
65
}
66
else
67
{
68
for( i = 0; i < len; ++i ) bels[i]->flip( false );
69
std::copy( bels.begin(), bels.end(), std::back_inserter( strip ) );
70
}
71
}
72
73
void GeometryEdge::
74
midNodes( Node*& a, Node*& b, int dir )
75
{
76
int len = nodes.size();
77
int ta, tb;
78
79
ta = len / 2 - 1;
80
tb = ta + 1;
81
82
if( dir == 1 )
83
{
84
a = nodes[ta];
85
b = nodes[tb];
86
}
87
else
88
{
89
a = nodes[tb];
90
b = nodes[ta];
91
}
92
}
93
94
double GeometryEdge::interpolate(double x, double y)
95
{
96
double value = 0.0;
97
for (std::vector<BGMesh*>::iterator it = bgMeshes.begin(); it != bgMeshes.end(); it++)
98
{
99
double h = (*it)->interpolate(x, y);
100
if (value == 0.0 || h < value)
101
value = h;
102
}
103
104
return value;
105
}
106
107
void GeometryEdge::
108
discretize( NodeMap &allNodes )
109
{
110
if (segments == 0)
111
{
112
int len = dots.size() - 1;
113
for (int i = 0; i < len; i++)
114
{
115
discretizeGradedSegment(allNodes, dots[i], dots[i+1]);
116
if (i < len - 1)
117
nodes.pop_back();
118
}
119
}
120
else
121
{
122
int len = dots.size() - 1, i;
123
if (segments < len) segments = len;
124
125
double totLength = 0.0;
126
double *lengths = new double[len];
127
128
for (i = 0; i < len; i++)
129
{
130
lengths[i] = distance(dots[i]->x, dots[i]->y, dots[i+1]->x, dots[i+1]->y);
131
totLength += lengths[i];
132
}
133
134
int *segs = new int[len];
135
for (i = 0; i < len; i++)
136
segs[i] = 1;
137
138
int remaining = segments - len;
139
while (remaining > 0)
140
{
141
int longest = 0;
142
double length = lengths[0] / segs[0];
143
for (i = 1; i < len; i++)
144
{
145
double l = lengths[i] / segs[i];
146
if (l > length)
147
{
148
length = l;
149
longest = i;
150
}
151
}
152
153
segs[longest]++;
154
remaining--;
155
}
156
157
delete [] lengths;
158
159
for (i = 0; i < len; i++)
160
{
161
discretizeConstantSegment(segs[i], allNodes, dots[i], dots[i+1]);
162
if (i < len - 1)
163
nodes.pop_back();
164
}
165
166
delete [] segs;
167
}
168
}
169
170
void GeometryEdge::
171
discretizeConstantSegment( int nSeg, NodeMap& allNodes, GeometryNode *from, GeometryNode *to )
172
{
173
Node *first = allNodes[from->tag];
174
Node *last = allNodes[to->tag];
175
176
double dx = last->x - first->x;
177
double dy = last->y - first->y;
178
double length = sqrt(dx*dx + dy*dy);
179
double sx = dx / length;
180
double sy = dy / length;
181
double step = length / nSeg;
182
double bx = first->x;
183
double by = first->y;
184
185
from->setDelta( step );
186
to->setDelta( step );
187
188
nodes.push_back( first );
189
for( int i = 1; i < nSeg; ++i )
190
{
191
MeshNode *nd = new MeshNode(bx+i*step*sx, by+i*step*sy);
192
nd->boundarynode = true;
193
nodes.push_back( nd );
194
}
195
nodes.push_back( last );
196
}
197
198
void GeometryEdge::
199
discretizeGradedSegment( NodeMap& allNodes, GeometryNode *from, GeometryNode *to )
200
{
201
int i;
202
double lineLength = distance( from->x, from->y, to->x, to->y );
203
double grading[2];
204
205
double sx = (to->x - from->x) / lineLength;
206
double sy = (to->y - from->y) / lineLength;
207
208
double limit = lineLength;
209
double at = 0.0;
210
double predicted = interpolate(from->x, from->y);
211
212
std::vector< double > lengths;
213
int step = 0;
214
215
while( 1 )
216
{
217
double prev;
218
do
219
{
220
prev = predicted;
221
double center = at + predicted / 2.0;
222
// Avoid interpolating outside the domain
223
if (center > lineLength)
224
center = lineLength;
225
predicted = 0.5 * (predicted + interpolate(from->x + center * sx, from->y + center * sy));
226
}
227
while( fabs((prev - predicted)/lineLength) > 0.0000001 );
228
229
at += predicted;
230
231
if (at > limit - 0.01 * predicted)
232
break;
233
234
lengths.push_back( at );
235
++step;
236
}
237
238
double mult = lineLength / at;
239
for( i = 0; i < step; ++i)
240
{
241
lengths[i] *= mult;
242
}
243
244
Node *first = allNodes[from->tag];
245
Node *last = allNodes[to->tag];
246
nodes.push_back( first );
247
for( i = 0; i < step; ++i )
248
{
249
MeshNode *nd = new MeshNode( lengths[i]*sx + from->x, lengths[i]*sy + from->y );
250
nd->boundarynode = true;
251
nodes.push_back( nd );
252
}
253
nodes.push_back( last );
254
}
255
256
std::ostream& operator<< (std::ostream& o, const GeometryEdge& A)
257
{
258
const int len = A.nodes.size();
259
o << A.tag << ' ' << len << ' ';
260
for(int i = 0; i < len; ++i)
261
{
262
o << A.nodes[i]->tag << ' ';
263
}
264
o << std::endl;
265
return o;
266
}
267
268
void GeometryEdge::
269
getGridPoints(double ox, double oy, double cellsize, std::vector<int> &x, std::vector<int> &y, std::vector<double> &delta)
270
{
271
int i, len = dots.size();
272
for (i = 0; i < len - 1; i++)
273
{
274
double ax = dots[i]->x, ay = dots[i]->y;
275
double bx = dots[i+1]->x, by = dots[i+1]->y;
276
277
double ad = MAP(dots[i]->delta), bd = MAP(dots[i+1]->delta);
278
279
int h = (int)((ax - ox) / cellsize + 0.5);
280
int v = (int)((ay - oy) / cellsize + 0.5);
281
282
x.push_back(h);
283
y.push_back(v);
284
delta.push_back(ad);
285
286
double dx = bx - ax;
287
double dy = by - ay;
288
double d = sqrt(dx * dx + dy * dy);
289
dx /= d;
290
dy /= d;
291
double dd = bd - ad;
292
293
int endh = (int)((bx - ox) / cellsize + 0.5);
294
int endv = (int)((by - oy) / cellsize + 0.5);
295
296
if (endh == h && endv == v)
297
continue;
298
299
int hstep = endh > h ? 1 : -1;
300
int vstep = endv > v ? 1 : -1;
301
302
if (abs(endh - h) > abs(endv - v))
303
{
304
int pos = 0, num = abs(endv - v), div = abs(endh - h);
305
306
while ((h += hstep) != endh)
307
{
308
pos += num;
309
if (pos > div / 2)
310
{
311
v += vstep;
312
pos -= div;
313
}
314
315
double nx = ox + h * cellsize;
316
double ny = oy + v * cellsize;
317
double nd = ad + ((nx - ax) * dx + (ny - ay) * dy) / d * dd;
318
319
x.push_back(h);
320
y.push_back(v);
321
delta.push_back(nd);
322
}
323
}
324
else
325
{
326
int pos = 0, num = abs(endh - h), div = abs(endv - v);
327
328
while ((v += vstep) != endv)
329
{
330
pos += num;
331
if (pos > div / 2)
332
{
333
h += hstep;
334
pos -= div;
335
}
336
337
double nx = ox + h * cellsize;
338
double ny = oy + v * cellsize;
339
double nd = ad + ((nx - ax) * dx + (ny - ay) * dy) / d * dd;
340
341
x.push_back(h);
342
y.push_back(v);
343
delta.push_back(nd);
344
}
345
}
346
347
if (i == len - 2)
348
{
349
x.push_back(endh);
350
y.push_back(endv);
351
delta.push_back(bd);
352
}
353
}
354
}
355
356