home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1997 May / Pcwk0597.iso / sybase / starbuck / java.z / Polygon.java < prev    next >
Text File  |  1996-05-03  |  5KB  |  186 lines

  1. /*
  2.  * @(#)Polygon.java    1.8 95/12/14 Sami Shaio
  3.  *
  4.  * Copyright (c) 1995 Sun Microsystems, Inc. All Rights Reserved.
  5.  *
  6.  * Permission to use, copy, modify, and distribute this software
  7.  * and its documentation for NON-COMMERCIAL purposes and without
  8.  * fee is hereby granted provided that this copyright notice
  9.  * appears in all copies. Please refer to the file "copyright.html"
  10.  * for further important copyright and licensing information.
  11.  *
  12.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
  13.  * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
  14.  * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  15.  * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
  16.  * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
  17.  * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
  18.  */
  19. package java.awt;
  20.  
  21. /**
  22.  * A polygon consists of a list of x and y coordinates.
  23.  *
  24.  * @version     1.8, 14 Dec 1995
  25.  * @author     Sami Shaio
  26.  * @author      Herb Jellinek
  27.  */
  28. public class Polygon {
  29.     /**
  30.      * The total number of points.
  31.      */
  32.     public int npoints = 0;
  33.  
  34.     /**
  35.      * The array of x coordinates.
  36.      */
  37.     public int xpoints[] = new int[4];
  38.  
  39.     /**
  40.      * The array of y coordinates.
  41.      */
  42.     public int ypoints[] = new int[4];
  43.     
  44.     /*
  45.      * Bounds of the polygon.
  46.      */
  47.     Rectangle bounds = null;
  48.     
  49.     /**
  50.      * Creates an empty polygon.
  51.      */
  52.     public Polygon() {
  53.     }
  54.  
  55.     /**
  56.      * Constructs and initializes a Polygon from the specified parameters.
  57.      * @param xpoints the array of x coordinates
  58.      * @param ypoints the array of y coordinates
  59.      * @param npoints the total number of points in the Polygon
  60.      */
  61.     public Polygon(int xpoints[], int ypoints[], int npoints) {
  62.     this.npoints = npoints;
  63.     this.xpoints = new int[npoints];
  64.     this.ypoints = new int[npoints];
  65.     System.arraycopy(xpoints, 0, this.xpoints, 0, npoints);
  66.     System.arraycopy(ypoints, 0, this.ypoints, 0, npoints);    
  67.     }
  68.     
  69.     /*
  70.      * Calculate the bounding box of the points passed to the constructor.
  71.      * Sets 'bounds' to the result.
  72.      */
  73.     void calculateBounds(int xpoints[], int ypoints[], int npoints) {
  74.     int boundsMinX = Integer.MAX_VALUE;
  75.     int boundsMinY = Integer.MAX_VALUE;
  76.     int boundsMaxX = Integer.MIN_VALUE;
  77.     int boundsMaxY = Integer.MIN_VALUE;
  78.     
  79.     for (int i = 0; i < npoints; i++) {
  80.         int x = xpoints[i];
  81.         boundsMinX = Math.min(boundsMinX, x);
  82.         boundsMaxX = Math.max(boundsMaxX, x);
  83.         int y = ypoints[i];
  84.         boundsMinY = Math.min(boundsMinY, y);
  85.         boundsMaxY = Math.max(boundsMaxY, y);
  86.     }
  87.     bounds = new Rectangle(boundsMinX, boundsMinY,
  88.                    boundsMaxX - boundsMinX,
  89.                    boundsMaxY - boundsMinY);
  90.     }
  91.  
  92.     /*
  93.      * Update the bounding box to fit the point x, y.
  94.      */
  95.     void updateBounds(int x, int y) {
  96.     bounds.x = Math.min(bounds.x, x);
  97.     bounds.width = Math.max(bounds.width, x - bounds.x);
  98.     bounds.y = Math.min(bounds.y, y);
  99.     bounds.height = Math.max(bounds.height, y - bounds.y);
  100.     }    
  101.  
  102.     /**
  103.      * Appends a point to a polygon.  If inside(x, y) or another
  104.      * operation that calculates the bounding box has already been
  105.      * performed, this method updates the bounds accordingly.
  106.  
  107.      * @param x the x coordinate of the point
  108.      * @param y the y coordinate of the point
  109.      */
  110.     public void addPoint(int x, int y) {
  111.     if (npoints == xpoints.length) {
  112.         int tmp[];
  113.  
  114.         tmp = new int[npoints * 2];
  115.         System.arraycopy(xpoints, 0, tmp, 0, npoints);
  116.         xpoints = tmp;
  117.  
  118.         tmp = new int[npoints * 2];
  119.         System.arraycopy(ypoints, 0, tmp, 0, npoints);
  120.         ypoints = tmp;
  121.     }
  122.     xpoints[npoints] = x;
  123.     ypoints[npoints] = y;
  124.     npoints++;
  125.     if (bounds != null) {
  126.         updateBounds(x, y);
  127.     }
  128.     }
  129.  
  130.     /**
  131.      * Determines the area spanned by this Polygon.
  132.      * @return a Rectangle defining the bounds of the Polygon.
  133.      */
  134.     public Rectangle getBoundingBox() {
  135.     if (bounds == null) {
  136.         calculateBounds(xpoints, ypoints, npoints);
  137.     }
  138.     return bounds;
  139.     }
  140.     
  141.     /**
  142.      * Determines whether the point (x,y) is inside the Polygon. Uses
  143.      * an even-odd insideness rule (also known as an alternating
  144.      * rule).
  145.  
  146.      * @param x the X coordinate of the point to be tested
  147.      * @param y the Y coordinate of the point to be tested
  148.      *
  149.      * <p>Based on code by Hanpeter van Vliet <hvvliet@inter.nl.net>.
  150.      */
  151.     public boolean inside(int x, int y) {
  152.     if (getBoundingBox().inside(x, y)) {
  153.         int hits = 0;
  154.         
  155.         // Walk the edges of the polygon
  156.         for (int i = 0; i < npoints; i++) {
  157.         int j = (i + 1) % npoints;
  158.         
  159.         int dx = xpoints[j] - xpoints[i];
  160.         int dy = ypoints[j] - ypoints[i];
  161.         
  162.         // ignore horizontal edges completely
  163.         if (dy != 0) {
  164.             // Check to see if the edge intersects
  165.             // the horizontal halfline through (x, y)
  166.             int rx = x - xpoints[i];
  167.             int ry = y - ypoints[i];
  168.             
  169.             // Quick and dirty way to deal with vertices
  170.             // that fall exactly on the halfline
  171.             if (ypoints[i] == y) ry--;
  172.             if (ypoints[j] == y) dy++;
  173.             
  174.             float s = (float)ry / (float)dy;
  175.             if (s >= 0.0 && s <= 1.0) {
  176.             if ((int)(s * dx) > rx) hits++;
  177.             }
  178.         }
  179.         }
  180.         
  181.         return (hits % 2) != 0;
  182.     }
  183.     return false;
  184.     }
  185. }
  186.