Package net.phys2d.raw.shapes

Source Code of net.phys2d.raw.shapes.Polygon

/*
* Phys2D - a 2D physics engine based on the work of Erin Catto.
*
* This source is provided under the terms of the BSD License.
*
* Copyright (c) 2006, Phys2D
* 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 the Phys2D/New Dawn Software 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.
*/
package net.phys2d.raw.shapes;

import net.phys2d.math.ROVector2f;
import net.phys2d.math.Vector2f;

/**
* A polygon represented by a list of its vertices in counterclockwise
* ordering. Note that the term 'counterclockwise' depends on the
* orientation of the axes: if x points to the right and y points up,
* the vertices are counter clockwise.
* This means that on many displays the ordering of vertices will be
* clockwise because the y axis is pointing down.
*
* TODO: the polygon is immutable but that could be changed
*
* @author Gideon Smeding
*
*/
public class Polygon extends AbstractShape implements DynamicShape {

  /** The vertices of this polygon in counterclockwise order */
  protected Vector2f[] vertices;
  /** The total area of this polygon */
  protected float area;
  /** The center of mass of this polygon */
  protected Vector2f centroid;
 
  /** Construct the polygon with a list of vertices
   * sorted in counterclockwise order.
   * Note that all the vector values will be copied.
   *
   * Throws an exception when too few vertices (<3) are supplied.
   * TODO: throw an exception when the vertices arent counterclockwise?
   *
   * @param vertices Vertices sorted in counterclockwise order
   */
  public Polygon(ROVector2f[] vertices) { 
    if ( vertices.length < 3 )
      throw new IllegalArgumentException("A polygon can not have fewer than 3 edges!");
   
    this.vertices = new Vector2f[vertices.length];
   
    for ( int i = 0; i < vertices.length; i++ ) {
      this.vertices[i] = new Vector2f(vertices[i]);
    }
   
   
    float r = computeBoundingCircleRadius();
    this.bounds = new AABox(r*2,r*2);
    this.area = computeArea();
    this.centroid = computeCentroid();
  }
 
  /**
   * A constructor that allows for overloading without using
   * the public constructor. Does absolutely nothing.
   */
  protected Polygon() {}
 
  /**
   * Computes the area as described by Paul Borke.
   * See: http://local.wasp.uwa.edu.au/~pbourke/geometry/polyarea/
   *
   * @return this polygon's computed area
   */
  protected float computeArea() {
    this.area = 0;
   
    Vector2f v1, v2;
   
    for ( int i = 0; i < vertices.length; i++ ) {
      v1 = vertices[i];
      v2 = vertices[(i+1) % vertices.length];
     
      this.area += v1.x * v2.y;
      this.area -= v2.x * v1.y;
    }
   
    return Math.abs(this.area / 2f);
  }
 
  /**
   * Compute the centroid (center of mass) as described by Paul Borke.
   * See: http://local.wasp.uwa.edu.au/~pbourke/geometry/polyarea/
   *
   * Make sure you have computed the area before calling this!
   *
   * @return the computed centroid
   */
  protected Vector2f computeCentroid() {
    float x = 0;
    float y = 0;
   
    Vector2f v1, v2;
   
    for ( int i = 0; i < vertices.length; i++ ) {
      v1 = vertices[i];
      v2 = vertices[(i+1) % vertices.length];
     
      x += (v1.x + v2.x) * (v1.x * v2.y - v2.x * v1.y);
      y += (v1.y + v2.y) * (v1.x * v2.y - v2.x * v1.y);
    }
   
    return new Vector2f(x / (6 * this.area), y / (6 * this.area));
  }
 
  /**
   * Computes the radius of an approximation of a minimal bounding circle
   * which has its origin at (0,0) and sets this.bounds.
   *
   * TODO: this can be done much better
   *
   * @return The
   */
  protected float computeBoundingCircleRadius() {
    float r = 0;
    float l;
   
    for ( int i = 0; i < vertices.length; i++ ) {
      l = vertices[i].x * vertices[i].x + vertices[i].y * vertices[i].y;
      r = l > r ? l : r;
    }
   
    return (float) Math.sqrt(r);
  }

  /**
   * Get the area of this polygon
   * @return the area of this polygon
   */
  public float getArea() {
    return area;
  }

  /**
   * Get the center of mass (aka centroid) for this polygon.
   * @return the center of mass
   */
  public Vector2f getCentroid() {
    return centroid;
  }
 
  /**
   * Returns a copy of the list of vertices. The vertices are sorted
   * counterclockwise.
   *
   * @return this polygons vertices
   */
  public ROVector2f[] getVertices() {
    ROVector2f[] roVertices = new ROVector2f[vertices.length];
   
    for ( int i = 0; i < vertices.length; i++ )
      roVertices[i] = vertices[i];
   
    return roVertices;
  }
 
  /**
   * Check wether or not the polygon is convex.
   *
   * @return true iff this polygon is convex
   */
  public boolean isConvex() {
    // check if all angles are smaller or equal to 180 degrees
    int l = vertices.length;
   
    for ( int i = 0; i < vertices.length; i++ ) {
      Vector2f x = vertices[i];
      Vector2f y = vertices[(i+1)%l];
      Vector2f z = vertices[(i+2)%l];
     
      // does the 3d cross product point up or down?
      if ( (z.x-x.x)*(y.y-x.y)-(y.x-x.x)*(z.y-x.y) >= 0 )
        return false;
    }
   
    return true;
  }
 
  /**
   * Returns a translated and rotated copy of this poly's vertices.
   * The vertices are rotated before they are translated, i.e. they
   * are rotated around the origin (0,0).
   * The vertices are sorted counterclockwise.
   *
   * This function is typically used to get the vertices for a
   * specific body, for example to collide it with another body
   * or draw it.
   *
   * @param displacement The displacement with wich all the
   * @param rotation
   * @return this polygon's vertices translated and rotated
   */
  public Vector2f[] getVertices(ROVector2f displacement, float rotation) {
    Vector2f[] retVertices = new Vector2f[vertices.length];
   
    float cos = (float) Math.cos(rotation);
    float sin = (float) Math.sin(rotation);
   
    for ( int i = 0; i < vertices.length; i++ ) {
      float x = vertices[i].x * cos - vertices[i].y * sin;
      float y = vertices[i].y * cos + vertices[i].x * sin;
      x += displacement.getX();
      y += displacement.getY();
     
      retVertices[i] = new Vector2f(x, y);
    }
   
    return retVertices;
  }
 
  /**
   * Returns a translated and rotated copy of this poly's centroid.
   * The centroid is rotated before it is translated, i.e. it
   * is rotated around the origin (0,0).
   *
   * @param displacement The displacement with wich all the
   * @param rotation
   * @return this polygon's vertices translated and rotated
   */
  public Vector2f getCentroid(ROVector2f displacement, float rotation) {
    float cos = (float) Math.cos(rotation);
    float sin = (float) Math.sin(rotation);
   
    return new Vector2f(
        centroid.x * cos - centroid.y * sin + displacement.getX(),
        centroid.y * cos + centroid.x * sin + displacement.getY());
  }
 
  /**
   * Test whether or not the point p is in this polygon in O(n),
   * where n is the number of vertices in this polygon.
   * 
   * @param p The point to be tested for inclusion in this polygon
   * @return true iff the p is in this polygon (not on a border)
   */
  public boolean contains(ROVector2f p) {
    // TODO: implement this
   
    return false;
  }
 
  /**
   * Get point on this polygon's hull that is closest to p.
   *
   * TODO: make this thing return a negative value when it is contained in the polygon
   *
   * @param p The point to search the closest point for
   * @return the nearest point on this vertex' hull
   */
  public ROVector2f getNearestPoint(ROVector2f p) {
    // TODO: implement this
   
    return null;
  }

  /**
   * @see net.phys2d.raw.shapes.Shape#getSurfaceFactor()
   */
  public float getSurfaceFactor() {
    // TODO: return the real surface factor
    return getArea();
  }

}
TOP

Related Classes of net.phys2d.raw.shapes.Polygon

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.