diff options
author | Juan Linietsky <reduzio@gmail.com> | 2014-02-09 22:10:30 -0300 |
---|---|---|
committer | Juan Linietsky <reduzio@gmail.com> | 2014-02-09 22:10:30 -0300 |
commit | 0b806ee0fc9097fa7bda7ac0109191c9c5e0a1ac (patch) | |
tree | 276c4d099e178eb67fbd14f61d77b05e3808e9e3 /core/math/triangulate.cpp | |
parent | 0e49da1687bc8192ed210947da52c9e5c5f301bb (diff) |
GODOT IS OPEN SOURCE
Diffstat (limited to 'core/math/triangulate.cpp')
-rw-r--r-- | core/math/triangulate.cpp | 168 |
1 files changed, 168 insertions, 0 deletions
diff --git a/core/math/triangulate.cpp b/core/math/triangulate.cpp new file mode 100644 index 0000000000..4a870def4b --- /dev/null +++ b/core/math/triangulate.cpp @@ -0,0 +1,168 @@ +/*************************************************************************/ +/* triangulate.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#include "triangulate.h" + +float Triangulate::get_area(const Vector<Vector2> &contour) +{ + + int n = contour.size(); + const Vector2 *c=&contour[0]; + + float A=0.0f; + + for(int p=n-1,q=0; q<n; p=q++) + { + A+= c[p].cross(c[q]); + } + return A*0.5f; +} + + /* + is_inside_triangle decides if a point P is Inside of the triangle + defined by A, B, C. + */ + +bool Triangulate::is_inside_triangle(float Ax, float Ay, + float Bx, float By, + float Cx, float Cy, + float Px, float Py) + +{ + float ax, ay, bx, by, cx, cy, apx, apy, bpx, bpy, cpx, cpy; + float cCROSSap, bCROSScp, aCROSSbp; + + ax = Cx - Bx; ay = Cy - By; + bx = Ax - Cx; by = Ay - Cy; + cx = Bx - Ax; cy = By - Ay; + apx= Px - Ax; apy= Py - Ay; + bpx= Px - Bx; bpy= Py - By; + cpx= Px - Cx; cpy= Py - Cy; + + aCROSSbp = ax*bpy - ay*bpx; + cCROSSap = cx*apy - cy*apx; + bCROSScp = bx*cpy - by*cpx; + + return ((aCROSSbp >= 0.0f) && (bCROSScp >= 0.0f) && (cCROSSap >= 0.0f)); +}; + +bool Triangulate::snip(const Vector<Vector2> &p_contour,int u,int v,int w,int n,int *V) +{ + int p; + float Ax, Ay, Bx, By, Cx, Cy, Px, Py; + const Vector2 *contour=&p_contour[0]; + + Ax = contour[V[u]].x; + Ay = contour[V[u]].y; + + Bx = contour[V[v]].x; + By = contour[V[v]].y; + + Cx = contour[V[w]].x; + Cy = contour[V[w]].y; + + if ( CMP_EPSILON > (((Bx-Ax)*(Cy-Ay)) - ((By-Ay)*(Cx-Ax))) ) return false; + + for (p=0;p<n;p++) + { + if( (p == u) || (p == v) || (p == w) ) continue; + Px = contour[V[p]].x; + Py = contour[V[p]].y; + if (is_inside_triangle(Ax,Ay,Bx,By,Cx,Cy,Px,Py)) return false; + } + + return true; +} + +bool Triangulate::triangulate(const Vector<Vector2> &contour,Vector<int> &result) +{ + /* allocate and initialize list of Vertices in polygon */ + + int n = contour.size(); + if ( n < 3 ) return false; + + + + int *V = (int*)alloca(sizeof(int)*n); + + /* we want a counter-clockwise polygon in V */ + + if ( 0.0f < get_area(contour) ) + for (int v=0; v<n; v++) V[v] = v; + else + for(int v=0; v<n; v++) V[v] = (n-1)-v; + + int nv = n; + + /* remove nv-2 Vertices, creating 1 triangle every time */ + int count = 2*nv; /* error detection */ + + for(int m=0, v=nv-1; nv>2; ) + { + /* if we loop, it is probably a non-simple polygon */ + if (0 >= (count--)) + { + //** Triangulate: ERROR - probable bad polygon! + return false; + } + + /* three consecutive vertices in current polygon, <u,v,w> */ + int u = v ; if (nv <= u) u = 0; /* previous */ + v = u+1; if (nv <= v) v = 0; /* new v */ + int w = v+1; if (nv <= w) w = 0; /* next */ + + if ( snip(contour,u,v,w,nv,V) ) + { + int a,b,c,s,t; + + /* true names of the vertices */ + a = V[u]; b = V[v]; c = V[w]; + + /* output Triangle */ + /* + result.push_back( contour[a] ); + result.push_back( contour[b] ); + result.push_back( contour[c] ); +*/ + + result.push_back( a ); + result.push_back( b ); + result.push_back( c ); + + m++; + + /* remove v from remaining polygon */ + for(s=v,t=v+1;t<nv;s++,t++) V[s] = V[t]; nv--; + + /* resest error detection counter */ + count = 2*nv; + } + } + + return true; +} |