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
GeometryEdge(int nSegments)10 GeometryEdge::GeometryEdge( int nSegments )
11 {
12 tag = nextTag;
13
14 segments = nSegments;
15
16 boundaryTag = 0;
17 type = OUTER;
18 ++nextTag;
19 }
20
GeometryEdge(const int t,int nSegments)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::
exportNodes(std::vector<Node * > & strip,int direction)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::
elements(std::vector<BoundaryElement * > & strip,int direction)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::
midNodes(Node * & a,Node * & b,int dir)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
interpolate(double x,double y)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::
discretize(NodeMap & allNodes)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::
discretizeConstantSegment(int nSeg,NodeMap & allNodes,GeometryNode * from,GeometryNode * to)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::
discretizeGradedSegment(NodeMap & allNodes,GeometryNode * from,GeometryNode * to)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
operator <<(std::ostream & o,const GeometryEdge & A)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::
getGridPoints(double ox,double oy,double cellsize,std::vector<int> & x,std::vector<int> & y,std::vector<double> & delta)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