/**
* Copyright 2013 The Loon Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package loon.physics;
import loon.core.geom.Vector2f;
public class PTriangulator
{
PPolygon local;
int numTriangles;
private int numVertices;
PPolygon[] triangles;
private PVertexLoop vers;
public PTriangulator()
{
}
private float calcArea(Vector2f v1, Vector2f v2, Vector2f v3)
{
return (v1.cross(v2) + v2.cross(v3) + v3.cross(v1)) * 0.5F;
}
private float getCross(PVertexLoop v)
{
return (v.v.x - v.next.v.x) * (v.prev.v.y - v.v.y) - (v.v.y - v.next.v.y) * (v.prev.v.x - v.v.x);
}
private PVertexLoop getEar(PVertexLoop v)
{
for(int i = 0; i < numVertices; i++)
{
if(getCross(v) <= 0.0F && !pointInPolygon(v)){
return v;
}
v = v.next;
}
return null;
}
private void makeVertexList(Vector2f vertices[])
{
numVertices = vertices.length;
vers = new PVertexLoop(vertices[0].x, vertices[0].y);
PVertexLoop list = vers;
for(int i = 1; i < numVertices; i++)
{
PVertexLoop next = new PVertexLoop(vertices[i].x, vertices[i].y);
list.next = next;
next.prev = list;
list = next;
}
vers.prev = list;
list.next = vers;
}
private boolean pointInPolygon(PVertexLoop v)
{
PVertexLoop prev = v.prev;
PVertexLoop next = v.next;
float nor = prev.v.sub(v.v).cross(prev.v.sub(next.v));
PVertexLoop list = vers;
for(int i = 0; i < numVertices; i++)
{
boolean hit = true;
if(list == prev || list == v || list == next){
hit = false;
}
Vector2f t1 = prev.v;
Vector2f t2 = v.v;
if(list.v.sub(t1).cross(list.v.sub(t2)) * nor < 0.0F)
{
hit = false;
} else
{
t1 = v.v;
t2 = next.v;
if(list.v.sub(t1).cross(list.v.sub(t2)) * nor < 0.0F)
{
hit = false;
} else
{
t1 = next.v;
t2 = prev.v;
if(list.v.sub(t1).cross(list.v.sub(t2)) * nor < 0.0F){
hit = false;
}
}
}
if(hit){
return true;
}
list = list.next;
}
return false;
}
private void removeVertex(PVertexLoop v)
{
v.prev.next = v.next;
v.next.prev = v.prev;
numVertices--;
}
private void triangulate()
{
if(numVertices < 3){
return;
}
PVertexLoop list = vers;
for(int i = 0; i < numVertices; i++)
{
if(vers.v.x > list.v.x){
vers = list;
}
list = list.next;
}
vers = getEar(vers);
if(vers == null){
return;
}
if(calcArea(vers.prev.v, vers.v, vers.next.v) > 1E-008F){
triangles[numTriangles++] = new PPolygon(new Vector2f[] {
vers.prev.v, vers.v, vers.next.v
});
}
removeVertex(vers);
vers = vers.next;
triangulate();
}
public void triangulate(Vector2f[] vertices, int numVers)
{
triangles = new PPolygon[numVers - 2];
local = new PPolygon(vertices);
if(!local.isClockwise())
{
Vector2f newVertices[] = new Vector2f[numVers];
int num = 0;
for(int i = numVers - 1; i >= 0; i--){
newVertices[num++] = vertices[i];
}
makeVertexList(newVertices);
} else
{
makeVertexList(vertices);
}
numVertices = numVers;
triangulate();
}
}