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