#include "BGMesh.h" #include "BGVertex.h" #include #include #include "coreGeometry.h" void BGGridMesh:: initialize(std::vector< GeometryNode* >& nodes, std::vector< GeometryEdge* >& edges) { initialized = true; std::cout << "Calculating background mesh" << std::endl; int i; int len = nodes.size(); double mean = MAP(nodes[0]->delta); double mindelta = nodes[0]->delta; double minx = nodes[0]->x, maxx = minx, miny = nodes[0]->y, maxy = miny; for( i = 1; i < len; ++i ) { mean += MAP(nodes[i]->delta); if (nodes[i]->delta < mindelta) mindelta = nodes[i]->delta; if (nodes[i]->x < minx) minx = nodes[i]->x; if (nodes[i]->x > maxx) maxx = nodes[i]->x; if (nodes[i]->y < miny) miny = nodes[i]->y; if (nodes[i]->y > maxy) maxy = nodes[i]->y; } mean /= len; width = maxx - minx; height = maxy - miny; ox = minx; oy = miny; cellsize = mindelta * cellsize; nh = (int)ceil(width / cellsize) + 1; width = (nh - 1) * cellsize; nv = (int)ceil(height / cellsize) + 1; height = (nv - 1) * cellsize; nh += 2; nv += 2; ox -= cellsize; oy -= cellsize; width += 2.0 * cellsize; height += 2.0 * cellsize; grid = new double[nh * nv]; bool *mask = new bool[nh * nv]; for (i = 0; i < nh * nv; i++) { grid[i] = mean; mask[i] = false; } for (i = 0; i < len; i++) { int h = (int)((nodes[i]->x - ox) / cellsize + 0.5); int v = (int)((nodes[i]->y - oy) / cellsize + 0.5); grid[v*nh+h] = MAP(nodes[i]->delta); mask[v*nh+h] = true; } len = edges.size(); for (i = 0; i < len; i++) { std::vector x, y; std::vector delta; edges[i]->getGridPoints(ox, oy, cellsize, x, y, delta); for (int j = 0; j < x.size(); j++) { grid[y[j]*nh+x[j]] = delta[j]; mask[y[j]*nh+x[j]] = true; } } std::vector > stack; stack.push_back(std::make_pair(0, 0)); while (!stack.empty()) { std::pair p = stack.back(); stack.pop_back(); int h = p.first, v = p.second; mask[v*nh+h] = true; if (h > 0 && !mask[v*nh+h-1]) stack.push_back(std::make_pair(h-1, v)); if (h < nh - 1 && !mask[v*nh+h+1]) stack.push_back(std::make_pair(h+1, v)); if (v > 0 && !mask[(v-1)*nh+h]) stack.push_back(std::make_pair(h, v-1)); if (v < nv - 1 && !mask[(v+1)*nh+h]) stack.push_back(std::make_pair(h, v+1)); } int niters = 0; double error = 1e100, last; do { niters++; last = error; error = 0.0; int i, j; for (int c = 0; c < 200; c++) { for (j = 0; j < nv; j++) { for (i = 0; i < nh; i++) { if (mask[j*nh+i]) continue; double v = 0.0; int n = 0; if (i > 0) { v += grid[j*nh+i-1]; n++; } if (i < nh - 1) { v += grid[j*nh+i+1]; n++; } if (j > 0) { v += grid[(j-1)*nh+i]; n++; } if (j < nv - 1) { v += grid[(j+1)*nh+i]; n++; } grid[j*nh+i] = v / n; } } } for (j = 0; j < nv; j++) { for (i = 0; i < nh; i++) { if (mask[j*nh+i]) continue; double residual = 0.0; double v = grid[j*nh+i]; if (i > 0) residual += grid[j*nh+i-1] - v; if (i < nh - 1) residual += grid[j*nh+i+1] - v; if (j > 0) residual += grid[(j-1)*nh+i] - v; if (j < nv - 1) residual += grid[(j+1)*nh+i] - v; residual /= cellsize; double e = fabs(residual); if (e > error) error = e; } } } while (error > 0.00001); } double BGGridMesh:: interpolate( const double ix, const double iy ) { int h = (int)((ix - ox) / cellsize); int v = (int)((iy - oy) / cellsize); if (h < 0) h = 0; if (h > nh - 1) h = nh - 1; if (v < 0) v = 0; if (v > nv - 1) v = nv - 1; double xoff = (ix - (ox + h * cellsize)) / cellsize, yoff = (iy - (oy + v * cellsize)) / cellsize; return UNMAP((1.0 - xoff) * (1.0 - yoff) * grid[v*nh+h] + xoff * (1.0 - yoff) * grid[v*nh+h+1] + (1.0 - xoff) * yoff * grid[(v+1)*nh+h] + xoff * yoff * grid[(v+1)*nh+h+1]); }