/*
* This license does NOT supersede the original license of GPC. Please see:
* http://www.cs.man.ac.uk/~toby/alan/software/#Licensing
*
* The SEI Software Open Source License, Version 1.0
*
* Copyright (c) 2004, Solution Engineering, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Solution Engineering, Inc. (http://www.seisw.com/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 3. The name "Solution Engineering" must not be used to endorse or
* promote products derived from this software without prior
* written permission. For written permission, please contact
* admin@seisw.com.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 SOLUTION ENGINEERING, INC. OR
* ITS 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.
* ====================================================================
*/
package com.seisw.util.geom;
import java.awt.Polygon;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.List;
/**
* PolySimple is a simple polygon - contains only one inner polygon.
*
* WARNING: This type of Poly cannot be used for an
* inner polygon that is a hole.
*
* @author Dan Bridenbecker, Solution Engineering, Inc.
*/
public class PolySimple implements Poly
{
// -----------------
// --- Constants ---
// -----------------
// ------------------------
// --- Member Variables ---
// ------------------------
/**
* The list of Point2D objects in the polygon.
*/
protected List m_List = new ArrayList();
/** Flag used by the Clip algorithm */
private boolean m_Contributes = true ;
// --------------------
// --- Constructors ---
// --------------------
/** Creates a new instance of PolySimple */
public PolySimple()
{
}
// ----------------------
// --- Object Methods ---
// ----------------------
/**
* Return true if the given object is equal to this one.
*
* WARNING: This method failse if the first point
* appears more than once in the list.
*/
public boolean equals( Object obj )
{
if( !(obj instanceof PolySimple) )
{
return false;
}
PolySimple that = (PolySimple)obj;
int this_num = this.m_List.size();
int that_num = that.m_List.size();
if( this_num != that_num ) return false ;
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// !!! WARNING: This is not the greatest algorithm. It fails if !!!
// !!! the first point in "this" poly appears more than once. !!!
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
if( this_num > 0 )
{
double this_x = this.getX(0);
double this_y = this.getY(0);
int that_first_index = -1 ;
for( int that_index = 0 ; (that_first_index == -1) && (that_index < that_num) ; that_index++ )
{
double that_x = that.getX(that_index);
double that_y = that.getY(that_index);
if( (this_x == that_x) && (this_y == that_y) )
{
that_first_index = that_index ;
}
}
if( that_first_index == -1 ) return false ;
int that_index = that_first_index ;
for( int this_index = 0 ; this_index < this_num ; this_index++ )
{
this_x = this.getX(this_index);
this_y = this.getY(this_index);
double that_x = that.getX(that_index);
double that_y = that.getY(that_index);
if( (this_x != that_x) || (this_y != that_y) ) return false;
that_index++ ;
if( that_index >= that_num )
{
that_index = 0 ;
}
}
}
return true ;
}
/**
* Return the hashCode of the object.
*
* WARNING:Hash and Equals break contract.
*
* @return an integer value that is the same for two objects
* whenever their internal representation is the same (equals() is true)
*/
public int hashCode()
{
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// !!! WARNING: This hash and equals break the contract. !!!
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
int result = 17 ;
result = 37*result + m_List.hashCode();
return result;
}
/**
* Return a string briefly describing the polygon.
*/
public String toString()
{
return "PolySimple: num_points="+getNumPoints();
}
// --------------------
// --- Poly Methods ---
// --------------------
/**
* Remove all of the points. Creates an empty polygon.
*/
public void clear()
{
m_List.clear();
}
/**
* Add a point to the first inner polygon.
*/
public void add(double x, double y)
{
add( new Point2D.Double( x, y ) );
}
/**
* Add a point to the first inner polygon.
*/
public void add(Point2D p)
{
m_List.add( p );
}
/**
* Throws IllegalStateexception if called
*/
public void add(Poly p)
{
throw new IllegalStateException("Cannot add poly to a simple poly.");
}
/**
* Return true if the polygon is empty
*/
public boolean isEmpty()
{
return m_List.isEmpty();
}
/**
* Returns the bounding rectangle of this polygon.
*/
public Rectangle2D getBounds()
{
double xmin = Double.MAX_VALUE ;
double ymin = Double.MAX_VALUE ;
double xmax = -Double.MAX_VALUE ;
double ymax = -Double.MAX_VALUE ;
for( int i = 0 ; i < m_List.size() ; i++ )
{
double x = getX(i);
double y = getY(i);
if( x < xmin ) xmin = x;
if( x > xmax ) xmax = x;
if( y < ymin ) ymin = y;
if( y > ymax ) ymax = y;
}
return new Rectangle2D.Double( xmin, ymin, (xmax-xmin), (ymax-ymin) );
}
/**
* Returns this if polyIndex = 0, else it throws
* IllegalStateException.
*/
public Poly getInnerPoly(int polyIndex)
{
if( polyIndex != 0 )
{
throw new IllegalStateException("PolySimple only has one poly");
}
return this ;
}
/**
* Always returns 1.
*/
public int getNumInnerPoly()
{
return 1 ;
}
/**
* Return the number points of the first inner polygon
*/
public int getNumPoints()
{
return m_List.size();
}
/**
* Return the X value of the point at the index in the first inner polygon
*/
public double getX(int index)
{
return ((Point2D)m_List.get(index)).getX();
}
/**
* Return the Y value of the point at the index in the first inner polygon
*/
public double getY(int index)
{
return ((Point2D)m_List.get(index)).getY();
}
/**
* Always returns false since PolySimples cannot be holes.
*/
public boolean isHole()
{
return false ;
}
/**
* Throws IllegalStateException if called.
*/
public void setIsHole(boolean isHole)
{
throw new IllegalStateException("PolySimple cannot be a hole");
}
/**
* Return true if the given inner polygon is contributing to the set operation.
* This method should NOT be used outside the Clip algorithm.
*
* @throws IllegalStateException if polyIndex != 0
*/
public boolean isContributing( int polyIndex )
{
if( polyIndex != 0 )
{
throw new IllegalStateException("PolySimple only has one poly");
}
return m_Contributes ;
}
/**
* Set whether or not this inner polygon is constributing to the set operation.
* This method should NOT be used outside the Clip algorithm.
*
* @throws IllegalStateException if polyIndex != 0
*/
public void setContributing( int polyIndex, boolean contributes )
{
if( polyIndex != 0 )
{
throw new IllegalStateException("PolySimple only has one poly");
}
m_Contributes = contributes ;
}
/**
* Return a Poly that is the intersection of this polygon with the given polygon.
* The returned polygon is simple.
*
* @return The returned Poly is of type PolySimple
*/
public Poly intersection(Poly p)
{
return Clip.intersection( this, p, this.getClass() );
}
/**
* Return a Poly that is the union of this polygon with the given polygon.
* The returned polygon is simple.
*
* @return The returned Poly is of type PolySimple
*/
public Poly union(Poly p)
{
return Clip.union( this, p, this.getClass() );
}
/**
* Return a Poly that is the exclusive-or of this polygon with the given polygon.
* The returned polygon is simple.
*
* @return The returned Poly is of type PolySimple
*/
public Poly xor(Poly p)
{
return Clip.xor( p, this, this.getClass() );
}
/**
* Returns the area of the polygon.
*
* The algorithm for the area of a complex polygon was take from
* code by Joseph O'Rourke author of " Computational Geometry in C".
*/
public double getArea()
{
if( getNumPoints() < 3 )
{
return 0.0 ;
}
double ax = getX(0);
double ay = getY(0);
double area = 0.0 ;
for( int i = 1 ; i < (getNumPoints()-1) ; i++ )
{
double bx = getX(i);
double by = getY(i);
double cx = getX(i+1);
double cy = getY(i+1);
double tarea = ((cx - bx)*(ay - by)) - ((ax - bx)*(cy - by));
area += tarea ;
}
area = 0.5*Math.abs(area);
return area ;
}
public Poly subtract(Poly p){
return Clip.diff(this, p,getClass());
}
public Polygon getPolygon() {
Polygon jp = new Polygon();
for( int i = 0 ; i < getNumPoints(); i++ )
{
jp.addPoint( (int)getX(i), (int)getY(i) );
}
return jp;
}
// -----------------------
// --- Package Methods ---
// -----------------------
}
Ads help maintain this website.