/*
* Copyright (c) 2003-2009 jMonkeyEngine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* FontPolygon.java
*
* Created on 23. April 2006, 18:48
*
* To change this template, choose Tools | Template Manager
* and open the template in the editor.
*/
package automenta.spacenet.space.geom.text3d.math;
import com.ardor3d.math.Vector3;
import java.util.ArrayList;
import java.util.List;
/**
*
* @author Pirx
*/
public class ClosedPolygon
{
private List<Vector3> points = new ArrayList<Vector3>();
public void addPoint(Vector3 point)
{
if(points.size() > 0)
{
Vector3 lastpoint = points.get(points.size() - 1);
if(lastpoint.equals(point))
{
//logger.info("Skipping duplicate point.");
return;
}
}
if(points.size() > 1)
{
// Check they are not on a straight line
Vector3 p_1 = points.get(points.size()-2);
Vector3 p_2 = points.get(points.size()-1);
Vector3 v1 = new Vector3(p_2).subtractLocal(p_1).normalizeLocal();
Vector3 v2 = new Vector3(point).subtractLocal(p_2).normalizeLocal();
if(v1.equals(v2))
{
// Same direction, straight line, remove the last one in the vector
//logger.info("REMOVING THE LAST ONE, TO AVOID STRAIGHT LINES");
points.remove(points.size()-1);
}
}
points.add(point);
}
public void close()
{
if(points.size() > 3)
{
if(points.get(0).equals(points.get(points.size() - 1)))
{
//logger.info("Removing last, duplicate point.");
points.remove(points.size() - 1);
}
}
}
public List<Vector3> getPoints()
{
return points;
}
/*
public void createSides(List<Vector3> vertexList, List<Integer> indexList,
List<Vector3> normalList, float extrusion)
{
int startIndex = vertexList.size();
int size = points.size();
for (int i = 0; i < size; i++)
{
Vector3 point = points.get(i);
vertexList.add(new Vector3(point.x, point.y, 0));
vertexList.add(new Vector3(point.x, point.y, -extrusion));
int i1 = (i + 1) % size;
//first triangle
indexList.add(Integer.valueOf(startIndex + 2 * i));
indexList.add(Integer.valueOf(startIndex + 2 * i + 1));
indexList.add(Integer.valueOf(startIndex + 2 * i1));
//second triangle
indexList.add(Integer.valueOf(startIndex + 2 * i + 1));
indexList.add(Integer.valueOf(startIndex + 2 * i1 + 1));
indexList.add(Integer.valueOf(startIndex + 2 * i1));
int i0 = (i - 1 + size) % size;
Vector3 point0 = points.get(i0);
Vector3 point1 = points.get(i1);
Vector3 dir = point1.subtract(point0);
Vector3 normal = new Vector3(-dir.y, dir.x, 0).normalize();
normalList.add(normal);
normalList.add(normal);
}
}
private static float sqr(float a)
{
return a * a;
}
public Distance getMinDistance(FontPolygon fp)
{
int inIndex = -1;
int outIndex = -1;
float minDist = Float.MAX_VALUE;
for (int i = 0; i < points.size(); i++)
{
Vector3 outPoint = points.get(i);
for (int j = 0; j < fp.points.size(); j++)
{
Vector3 inPoint = fp.points.get(j);
float dist = sqr(outPoint.x - inPoint.x)
+ sqr(outPoint.y - inPoint.y);
if (dist <= minDist)
{
minDist = dist;
inIndex = j;
outIndex = i;
}
}
}
return new Distance(inIndex, outIndex, minDist);
}
//Assumptions:
//* this polygon is an outline
//* fp is a hole enclosed by this polygon
//* the connection between the closest points of both doesn't
// intersect with any other line (theoretically, there are counterexamples)
public void mergeHole(FontPolygon fp, Distance d)
{
List<Vector3> newPoints = new ArrayList<Vector3>();
for (int i = 0; i < points.size(); i++)
{
newPoints.add(points.get(i));
if (i == d.outIndex)
{
int fpSize = fp.points.size();
for (int j = 0; j <= fpSize; j++)
{
newPoints.add(fp.points.get((j + d.inIndex) % fpSize));
}
newPoints.add(points.get(i));
}
}
points = newPoints;
}
*/
public boolean isHole()
{
int size = points.size();
int rightMostPoint = 0;
for (int i = 0; i < size; i++)
{
if(points.get(i).getX() > points.get(rightMostPoint).getX())
rightMostPoint = i;
}
// Now we just need to see if the turn is right/left
{
Vector3 v1 = points.get((rightMostPoint - 1 + size) % size);
Vector3 v2 = points.get(rightMostPoint);
Vector3 v = points.get((rightMostPoint + 1) % size);
float turnang = (v2.getXf() - v1.getXf()) * (v.getYf() - v1.getYf()) - (v.getXf() - v1.getXf()) * (v2.getYf() - v1.getYf());
//logger.info("turnang:"+turnang);
return turnang > 0;
}
}
/*
public boolean isHoleOLD()
{
int size = points.size();
float[] dir = new float[size];
Vector3 lastPoint = points.get(0);
float turnang_sum = 0;
for (int i = 0; i < size; i++)
{
Vector3 newPoint = points.get((i + 1) % size);
//logger.info("newPoint:"+newPoint);
float dx = newPoint.x - lastPoint.x;
float dy = newPoint.y - lastPoint.y;
dir[i] = (float) Math.atan2(dy, dx);
lastPoint = newPoint;
{
Vector3 v1 = points.get((i - 1 + size) % size);
Vector3 v2 = points.get(i);
Vector3 v = points.get((i + 1) % size);
float turnang = (v2.x - v1.x) * (v.y - v1.y) - (v.x - v1.x) * (v2.y - v1.y);
turnang_sum += turnang;
//logger.info("turnang:"+turnang);
}
}
logger.info("turnang_sum:"+turnang_sum);
if(true)
return turnang_sum > 0;
float sum = 0;
for (int i = 0; i < size; i++)
{
float angle = dir[i] - dir[(i + 1) % size];
while (angle < -Math.PI)
{
logger.info("------------- "+angle+" < -"+Math.PI);
angle += FastMath.TWO_PI;
}
while (angle > Math.PI)
{
logger.info("------------- "+angle+" > "+Math.PI);
angle -= FastMath.TWO_PI;
}
sum += angle;
}
logger.info("sum:"+sum);
return sum < 0;
}
*/
/*
public void triangulate(List<Vector3> vertexList, List<Integer> indexList,
List<Vector3> normalList, boolean drawFront, boolean drawBack,
float extrusion)
{
List triangles = Triangulator.triangulate(points);
if (drawFront)
{
int startIndex = vertexList.size();
Vector3 frontNormal = new Vector3(0, 0, 1);
for (int i = 0; i < points.size(); i++)
{
vertexList.add(points.get(i));
normalList.add(frontNormal);
}
for (int i = 0; i < triangles.size(); i++)
{
int[] triangle = (int[]) triangles.get(i);
indexList.add(Integer.valueOf(triangle[0] + startIndex));
indexList.add(Integer.valueOf(triangle[1] + startIndex));
indexList.add(Integer.valueOf(triangle[2] + startIndex));
}
}
if (drawBack)
{
int startIndex = vertexList.size();
Vector3 backNormal = new Vector3(0, 0, -1);
for (int i = 0; i < points.size(); i++)
{
Vector3 point = points.get(i);
vertexList.add(new Vector3(point.x, point.y, -extrusion));
normalList.add(backNormal);
}
for (int i = 0; i < triangles.size(); i++)
{
int[] triangle = (int[]) triangles.get(i);
indexList.add(Integer.valueOf(triangle[0] + startIndex));
indexList.add(Integer.valueOf(triangle[2] + startIndex));
indexList.add(Integer.valueOf(triangle[1] + startIndex));
}
}
}
*/
public static class Distance
{
public int inIndex;
public int outIndex;
public float sqrDist;
public Distance(int inIndex, int outIndex, float sqrDist)
{
this.inIndex = inIndex;
this.outIndex = outIndex;
this.sqrDist = sqrDist;
}
}
}