/* Danger from the Deep - Open source submarine simulation Copyright (C) 2003-2006 Thorsten Jordan, Luis Barrancos and others. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ // a simple polygon triangulation algorithm // (C) Thorsten Jordan #include "triangulate.h" using namespace std; /* how it works: polygon (point list) are points p_0....p_n-1 i = 0 while point list contains more than three points take first point on list (index i) if p_i, p_i+1, p_i+2 don't form a triangle (angle at p_i+1 is >= 180°), i:=i+1, continue for all j in from [i+3, i[ (cyclic indices!) check if p_j is in triangle p_i, p_i+1, p_i+2 if all points are outside, then add triangle i,i+1,i+2, remove p_i+1 from point list else i:=i+1 (rotate list) end */ bool triangulate::is_inside_triangle(const vector2& a, const vector2& b, const vector2& c, const vector2& p) { double s, t; bool solved = (p-a).solve(b-a, c-a, s, t); if (!solved) return true; return (s >= 0 && t >= 0 && s <= 1 && t <= 1 && s+t <= 1); } #include #include #include int failcount = 0; vector triangulate::compute(const vector& vertices) { vector indices; if (vertices.size() < 3) return indices; // error! indices.reserve(3*vertices.size()); // fixme: use a vector and mark entries as "erased" (-1) // next then steps over erased entries. // count number of valid entries separately. // that is much easier and faster. // fixme 2: use delaunay condition to check triangles. But maybe the triangulation then fails some // times... vector vl; vl.reserve(vertices.size()); unsigned vl_size = vertices.size(); for (unsigned l = 0; l < vertices.size(); ++l) vl.push_back(l); unsigned i0 = 0; unsigned i1 = 1; unsigned i2 = 2; // fixme: 2004/02/14, with the new map the lockups reoccour. why?! int iscorrecttests=0; int notriangpossible=0; int polyscreated=0; int haengt=0; // fixme: hack to avoid lock ups. why do they occour? reasons maybe: // 1) there are double points in the input, that means polygon edges are degenerated // or too short. OCCOUR, fixme, SEE COASTSEGMENT.CPP // 2) the polygon is self-intersecting. ???? CHECK // 3) polygon is inverted (hole), that means polylines are all in wrong direction AVOIDED, FIXED // 4) if several points are on one line a,b,c,d and one is beside (e) // and a triangle d,e,a is formed, the polygon's AREA is triangulated, but // b,c are on line a-d. -> change is_inside test, what about epsilon?! AVOIDED, FIXED // check these cases (1,2) while (vl_size > 3) { ++haengt; if(haengt>8000){ cout<<"TRIANGULATE: LOCKUP DETECTED! ("< void triangulate::debug_test(const vector& vertices, const string& outputfile) { cout << "testing in \"" << outputfile << "\"\n"; int nverts = int(vertices.size()); vector idx = compute(vertices); #if 1 for (int j = 0; j < nverts; ++j) { // show poly also idx.push_back(j); idx.push_back(j); idx.push_back((j+1)%nverts); } #endif int nfaces = int(idx.size())/3; ofstream out(outputfile.c_str()); out << "OFF\n" << nverts << " " << nfaces << " 0\n"; for (int i = 0; i < nverts; ++i) { out << vertices[i].x << " " << vertices[i].y << " 0.0\n"; } for (int i = 0; i < nfaces; ++i) { out << "3 " << idx[i*3+0] << " " << idx[i*3+1] << " " << idx[i*3+2] << "\n"; } } /* // triang test int main(int argc, char** argv) { int nverts = 50; if (argc > 1) nverts = atoi(argv[1]); vector verts; for (unsigned i = 0; i < nverts; ++i) { double f = 2*3.14159f*i/nverts; vector2 d(cos(f), sin(f)); double l = 50.0f+30.0f*rand()/RAND_MAX; verts.push_back(d*l); } vector idx = triangulate::debug_test(verts, "test.off"); } */