00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <cmath>
00021 #include <limits>
00022 #include <algorithm>
00023
00024 #include <archon/math/matrix.H>
00025 #include <archon/math/functions.H>
00026
00027 #include <archon/util/polygon_mesher.H>
00028
00029 namespace Archon
00030 {
00031 namespace Utilities
00032 {
00033 using namespace std;
00034 using namespace Math;
00035
00036 namespace
00037 {
00038 struct PolygonException: MesherException
00039 {
00040 PolygonException(string l, string m): Utilities::Exception(l, m) {}
00041 };
00042
00043 struct Vertex
00044 {
00045 Vector2 p;
00046 int i;
00047 Vertex() {}
00048 Vertex(const Vector2 &p, int i): p(p), i(i) {}
00049 };
00050
00051 void splitX(const vector<Vertex> &polygon, double clip,
00052 const Matrix3x3 &m, MesherContext *context,
00053 vector<Vertex> &below, vector<Vertex> &above,
00054 Vertex &reuseVertex, bool &reuse, double z)
00055 {
00056 Vertex rv = reuseVertex, v = polygon[polygon.size()-1];
00057 bool r = reuse;
00058 reuse = false;
00059 for(unsigned i=0; i<polygon.size(); ++i)
00060 {
00061 Vertex w = polygon[i];
00062 if(w.p[0] >= clip)
00063 {
00064 if(v.p[0] >= clip) above.push_back(w);
00065 else
00066 {
00067 if(!r)
00068 {
00069 Vector2 s(clip, linInterp(clip, v.p[0], w.p[0], v.p[1], w.p[1]));
00070 rv = Vertex(s, context->addVertex(m * Vector3(s[0], s[1], z)));
00071 }
00072 above.push_back(rv);
00073 above.push_back(w);
00074 below.push_back(rv);
00075 }
00076 }
00077 else
00078 {
00079 if(v.p[0] >= clip)
00080 {
00081 Vector2 s(clip, linInterp(clip, v.p[0], w.p[0], v.p[1], w.p[1]));
00082 Vertex t = Vertex(s, context->addVertex(m * Vector3(s[0], s[1], z)));
00083 below.push_back(t);
00084 below.push_back(w);
00085 above.push_back(t);
00086 reuseVertex = t;
00087 reuse = true;
00088 }
00089 else below.push_back(w);
00090 }
00091 v = w;
00092 }
00093 }
00094
00095 void splitY(const vector<Vertex> &polygon, double clip,
00096 const Matrix3x3 &m, MesherContext *context,
00097 vector<Vertex> &below, vector<Vertex> &above,
00098 double z)
00099 {
00100 Vertex v = polygon[polygon.size()-1];
00101 for(unsigned i=0; i<polygon.size(); ++i)
00102 {
00103 Vertex w = polygon[i];
00104 if(w.p[1] >= clip)
00105 {
00106 if(v.p[1] >= clip) above.push_back(w);
00107 else
00108 {
00109 Vector2 s(linInterp(clip, v.p[1], w.p[1], v.p[0], w.p[0]), clip);
00110 Vertex t = Vertex(s, context->addVertex(m * Vector3(s[0], s[1], z)));
00111 above.push_back(t);
00112 above.push_back(w);
00113 below.push_back(t);
00114 }
00115 }
00116 else
00117 {
00118 if(v.p[1] >= clip)
00119 {
00120 Vector2 s(linInterp(clip, v.p[1], w.p[1], v.p[0], w.p[0]), clip);
00121 Vertex t = Vertex(s, context->addVertex(m * Vector3(s[0], s[1], z)));
00122 below.push_back(t);
00123 below.push_back(w);
00124 above.push_back(t);
00125 }
00126 else below.push_back(w);
00127 }
00128 v = w;
00129 }
00130 }
00131 }
00132
00133 void meshPolygon(const vector<Vector3> &polygon,
00134 double maxPatchSize,
00135 MesherContext *context)
00136 {
00137
00138 Vector3 basisu = polygon[1] - polygon[0];
00139 Vector3 basisv = polygon[polygon.size()-1] - polygon[0];
00140
00141 basisu.normalize();
00142 basisv.normalize();
00143
00144 Vector3 basisw = basisu * basisv;
00145 basisv = basisw * basisu;
00146
00147 basisv.normalize();
00148 basisw.normalize();
00149
00150 Matrix3x3 mat(basisu, basisv, basisw);
00151
00152 vector<Vertex> p1, p2, p3, p4;
00153 vector<Vertex> *poly = &p1, *stripe = &p2, *patch = &p3, *temp = &p4;
00154
00155
00156 double
00157 minX = numeric_limits<double>::max(),
00158 minY = numeric_limits<double>::max(),
00159 maxX = numeric_limits<double>::min(),
00160 maxY = numeric_limits<double>::min();
00161
00162 double z;
00163 Vector3 v;
00164 for(unsigned i=0; i<polygon.size(); ++i)
00165 {
00166 v = polygon[i] * mat;
00167 Vector2 w(v);
00168 if(i == 0) z = v[2];
00169
00170 if(w[0] < minX) minX = w[0];
00171 if(w[0] > maxX) maxX = w[0];
00172
00173 if(w[1] < minY) minY = w[1];
00174 if(w[1] > maxY) maxY = w[1];
00175
00176 poly->push_back(Vertex(w, context->addVertex
00177 (mat * Vector3(v[0], v[1], z))));
00178 }
00179
00180 const unsigned numberOfPatchesX =
00181 static_cast<unsigned>(ceil((maxX-minX)/maxPatchSize));
00182 const unsigned numberOfPatchesY =
00183 static_cast<unsigned>(ceil((maxY-minY)/maxPatchSize));
00184
00185 const double patchSizeX = (maxX-minX)/numberOfPatchesX;
00186 const double patchSizeY = (maxY-minY)/numberOfPatchesY;
00187
00188 Vertex *reuseVertex = new Vertex[numberOfPatchesX-1];
00189 bool *reuse = new bool[numberOfPatchesX-1];
00190
00191 for(unsigned i=0; i<numberOfPatchesX-1; ++i) reuse[i] = false;
00192
00193 for(unsigned y=0; y<numberOfPatchesY; ++y)
00194 {
00195 if(y < numberOfPatchesY-1)
00196 {
00197 temp->clear();
00198 stripe->clear();
00199 splitY(*poly, minY + (y+1) * patchSizeY, mat,
00200 context, *stripe, *temp, z);
00201 swap(poly, temp);
00202 }
00203 else swap(stripe, poly);
00204
00205 for(unsigned x=0; x<numberOfPatchesX; ++x)
00206 {
00207 if(x < numberOfPatchesX-1)
00208 {
00209 temp->clear();
00210 patch->clear();
00211 splitX(*stripe, minX + (x+1) * patchSizeX, mat, context,
00212 *patch, *temp, reuseVertex[x], reuse[x], z);
00213 swap(stripe, temp);
00214 }
00215 else swap(patch, stripe);
00216
00217 if(patch->size() == 0) continue;
00218
00219 if(patch->size() > 4)
00220 {
00221 int a = (*patch)[0].i;
00222 for(unsigned i=2; i<patch->size(); ++i)
00223 {
00224 vector<int> p;
00225 p.push_back(a);
00226 p.push_back((*patch)[i-1].i);
00227 p.push_back((*patch)[i].i);
00228 context->addPolygon(p);
00229 }
00230 }
00231 else
00232 {
00233 if(patch->size() < 3)
00234 ARCHON_THROW1(PolygonException, "Too few vertices");
00235 vector<int> p;
00236 p.push_back((*patch)[0].i);
00237 p.push_back((*patch)[1].i);
00238 p.push_back((*patch)[2].i);
00239 if(patch->size() == 4) p.push_back((*patch)[3].i);
00240 context->addPolygon(p);
00241 }
00242 }
00243 }
00244
00245 delete[] reuseVertex;
00246 delete[] reuse;
00247 }
00248
00249 namespace
00250 {
00251 struct Context: MesherContext
00252 {
00253 vector<Vector3> &vertices;
00254 vector<int> &polygons;
00255 Context(vector<Vector3> &vertices,
00256 vector<int> &polygons):
00257 vertices(vertices), polygons(polygons) {}
00258
00259 int addVertex(const Vector3 &v)
00260 {
00261 int i = vertices.size();
00262 vertices.push_back(v);
00263 return i;
00264 }
00265
00266 void addPolygon(const vector<int> &p)
00267 {
00268 polygons.insert(polygons.end(), p.begin(), p.end());
00269 polygons.push_back(-1);
00270 }
00271 };
00272 }
00273
00274 void meshPolygon(const vector<Vector3> &polygon,
00275 double maxPatchSize,
00276 vector<Vector3> &resultingVertices,
00277 vector<int> &resultingPolygons)
00278 {
00279 resultingVertices.clear();
00280 resultingPolygons.clear();
00281 Context context(resultingVertices, resultingPolygons);
00282 meshPolygon(polygon, maxPatchSize, &context);
00283 }
00284 }
00285 }
00286
00287