jsketcher/src/org/poly2tri/geometry/polygon/Polygon.java
Val Erastov df53c08794 init
2014-08-11 20:20:49 -07:00

273 lines
7.2 KiB
Java

package org.poly2tri.geometry.polygon;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.poly2tri.triangulation.Triangulatable;
import org.poly2tri.triangulation.TriangulationContext;
import org.poly2tri.triangulation.TriangulationMode;
import org.poly2tri.triangulation.TriangulationPoint;
import org.poly2tri.triangulation.delaunay.DelaunayTriangle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Polygon implements Triangulatable
{
private final static Logger logger = LoggerFactory.getLogger( Polygon.class );
protected ArrayList<TriangulationPoint> _points = new ArrayList<TriangulationPoint>();
protected ArrayList<TriangulationPoint> _steinerPoints;
protected ArrayList<Polygon> _holes;
protected List<DelaunayTriangle> m_triangles;
protected PolygonPoint _last;
/**
* To create a polygon we need atleast 3 separate points
*
* @param p1
* @param p2
* @param p3
*/
public Polygon( PolygonPoint p1, PolygonPoint p2, PolygonPoint p3 )
{
p1._next = p2;
p2._next = p3;
p3._next = p1;
p1._previous = p3;
p2._previous = p1;
p3._previous = p2;
_points.add( p1 );
_points.add( p2 );
_points.add( p3 );
}
/**
* Requires atleast 3 points
* @param points - ordered list of points forming the polygon.
* No duplicates are allowed
*/
public Polygon( List<PolygonPoint> points )
{
// Lets do one sanity check that first and last point hasn't got same position
// Its something that often happen when importing polygon data from other formats
if( points.get(0).equals( points.get(points.size()-1) ) )
{
logger.warn( "Removed duplicate point");
points.remove( points.size()-1 );
}
_points.addAll( points );
}
/**
* Requires atleast 3 points
*
* @param points
*/
public Polygon( PolygonPoint[] points )
{
this( Arrays.asList( points ) );
}
public TriangulationMode getTriangulationMode()
{
return TriangulationMode.POLYGON;
}
public int pointCount()
{
int count = _points.size();
if( _steinerPoints != null )
{
count += _steinerPoints.size();
}
return count;
}
public void addSteinerPoint( TriangulationPoint point )
{
if( _steinerPoints == null )
{
_steinerPoints = new ArrayList<TriangulationPoint>();
}
_steinerPoints.add( point );
}
public void addSteinerPoints( List<TriangulationPoint> points )
{
if( _steinerPoints == null )
{
_steinerPoints = new ArrayList<TriangulationPoint>();
}
_steinerPoints.addAll( points );
}
public void clearSteinerPoints()
{
if( _steinerPoints != null )
{
_steinerPoints.clear();
}
}
/**
* Assumes: that given polygon is fully inside the current polygon
* @param poly - a subtraction polygon
*/
public void addHole( Polygon poly )
{
if( _holes == null )
{
_holes = new ArrayList<Polygon>();
}
_holes.add( poly );
// XXX: tests could be made here to be sure it is fully inside
// addSubtraction( poly.getPoints() );
}
/**
* Will insert a point in the polygon after given point
*
* @param a
* @param b
* @param p
*/
public void insertPointAfter( PolygonPoint a, PolygonPoint newPoint )
{
// Validate that
int index = _points.indexOf( a );
if( index != -1 )
{
newPoint.setNext( a.getNext() );
newPoint.setPrevious( a );
a.getNext().setPrevious( newPoint );
a.setNext( newPoint );
_points.add( index+1, newPoint );
}
else
{
throw new RuntimeException( "Tried to insert a point into a Polygon after a point not belonging to the Polygon" );
}
}
public void addPoints( List<PolygonPoint> list )
{
PolygonPoint first;
for( PolygonPoint p : list )
{
p.setPrevious( _last );
if( _last != null )
{
p.setNext( _last.getNext() );
_last.setNext( p );
}
_last = p;
_points.add( p );
}
first = (PolygonPoint)_points.get(0);
_last.setNext( first );
first.setPrevious( _last );
}
/**
* Will add a point after the last point added
*
* @param p
*/
public void addPoint(PolygonPoint p )
{
p.setPrevious( _last );
p.setNext( _last.getNext() );
_last.setNext( p );
_points.add( p );
}
public void removePoint( PolygonPoint p )
{
PolygonPoint next, prev;
next = p.getNext();
prev = p.getPrevious();
prev.setNext( next );
next.setPrevious( prev );
_points.remove( p );
}
public PolygonPoint getPoint()
{
return _last;
}
public List<TriangulationPoint> getPoints()
{
return _points;
}
public List<DelaunayTriangle> getTriangles()
{
return m_triangles;
}
public void addTriangle( DelaunayTriangle t )
{
m_triangles.add( t );
}
public void addTriangles( List<DelaunayTriangle> list )
{
m_triangles.addAll( list );
}
public void clearTriangulation()
{
if( m_triangles != null )
{
m_triangles.clear();
}
}
/**
* Creates constraints and populates the context with points
*/
public void prepareTriangulation( TriangulationContext<?> tcx )
{
if( m_triangles == null )
{
m_triangles = new ArrayList<DelaunayTriangle>( _points.size() );
}
else
{
m_triangles.clear();
}
// Outer constraints
for( int i = 0; i < _points.size()-1 ; i++ )
{
tcx.newConstraint( _points.get( i ), _points.get( i+1 ) );
}
tcx.newConstraint( _points.get( 0 ), _points.get( _points.size()-1 ) );
tcx.addPoints( _points );
// Hole constraints
if( _holes != null )
{
for( Polygon p : _holes )
{
for( int i = 0; i < p._points.size()-1 ; i++ )
{
tcx.newConstraint( p._points.get( i ), p._points.get( i+1 ) );
}
tcx.newConstraint( p._points.get( 0 ), p._points.get( p._points.size()-1 ) );
tcx.addPoints( p._points );
}
}
if( _steinerPoints != null )
{
tcx.addPoints( _steinerPoints );
}
}
}