/[classpath]/classpath/java/awt/Polygon.java
ViewVC logotype

Diff of /classpath/java/awt/Polygon.java

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.4 by mark, Tue Jan 22 22:26:58 2002 UTC revision 1.5 by ericb, Wed Mar 20 04:56:08 2002 UTC
# Line 1  Line 1 
1  /* Polygon.java -- Class representing a polygon  /* Polygon.java -- class representing a polygon
2     Copyright (C) 1999 Free Software Foundation, Inc.     Copyright (C) 1999, 2002 Free Software Foundation, Inc.
3    
4  This file is part of GNU Classpath.  This file is part of GNU Classpath.
5    
# Line 38  exception statement from your version. * Line 38  exception statement from your version. *
38    
39  package java.awt;  package java.awt;
40    
41  /**  import java.awt.geom.AffineTransform;
42    * This class represents a polygon  import java.awt.geom.PathIterator;
43    *  import java.awt.geom.Point2D;
44    * @author Aaron M. Renn (arenn@urbanophile.com)  import java.awt.geom.Rectangle2D;
45    */  import java.io.Serializable;
46  public class Polygon implements Shape, java.io.Serializable  
47  {  /**
48     * This class represents a polygon, a closed, two-dimensional region in a
49  /*   * coordinate space. The region is bounded by an arbitrary number of line
50   * Instance Variables   * segments, between (x,y) coordinate vertices. The polygon has even-odd
51   */   * winding, meaning that a point is inside the shape if it crosses the
52     * boundary an odd number of times on the way to infinity.
53  /**   *
54    * This total number of endpoints   * <p>There are some public fields; if you mess with them in an inconsistent
55    */   * manner, it is your own fault when you get NullPointerException,
56  public int npoints;   * ArrayIndexOutOfBoundsException, or invalid results. Also, this class is
57     * not threadsafe.
58  /**   *
59    * The array of X coordinates of endpoints.   * @author Aaron M. Renn <arenn@urbanophile.com>
60    */   * @author Eric Blake <ebb9@email.byu.edu>
61  public int xpoints[];   * @since 1.0
62     * @status updated to 1.4
 /**  
   * The array of Y coordinates of endpoints.  
   */  
 public int ypoints[];  
   
 /**  
   * The bounding box of this polygon  
   */  
 protected Rectangle bounds;  
   
 /*************************************************************************/  
   
 /*  
  * Constructors  
63   */   */
64    public class Polygon implements Shape, Serializable
 /**  
   * Initializes a new instance of <code>Polygon</code> that is empty.  
   */  
 public  
 Polygon()  
 {  
   xpoints = new int[0];  
   ypoints = new int[0];  
   
   bounds = new Rectangle(0,0,0,0);  
 }  
   
 /*************************************************************************/  
   
 /**  
   * Initializes a new instance of <code>Polygon</code> that has the  
   * specified endpoints.  
   *  
   * @param xpoints The array of X coordinates for this polygon.  
   * @param ypoints The array of Y coordinates for this polygon.  
   * @param npoints The total number of endpoints in this polygon.  
   *  
   * @exception NegativeArraySizeException If <code>npoints</code> is negative.  
   */  
 public  
 Polygon(int[] xpoints, int[] ypoints, int npoints)  
 {  
   if (npoints < 0)  
     throw new NegativeArraySizeException();  
   
   this.xpoints = xpoints;  
   this.ypoints = ypoints;  
   this.npoints = npoints;  
   
   calculateBounds();  
 }  
   
 /*************************************************************************/  
   
 /*  
  * Instance Methods  
  */  
   
 /**  
   * Calculates the bounding rectangle of this polygon.  
   */  
 public void  
 calculateBounds()  
 {  
   int minx = xpoints[0], maxx = xpoints[0];  
   int miny = ypoints[0], maxy = ypoints[0];  
   
   for (int i = 0; i < npoints; i++)  
     {  
       if (xpoints[i] < minx)  
         minx = xpoints[i];  
   
       if (xpoints[i] > maxx)  
         maxx = xpoints[i];  
   
       if (ypoints[i] < miny)  
         miny = ypoints[i];  
   
       if (ypoints[i] > maxy)  
         maxy = ypoints[i];  
     }  
   
   bounds = new Rectangle(minx, maxy, maxx-minx, maxy-miny);  
 }  
   
 /*************************************************************************/  
   
 /**  
   * Translates the polygon by adding the specified values to all X and Y  
   * coordinates.  
   *  
   * @param dx The amount to add to all X coordinates.  
   * @param dy The amount to add to all Y coordinates.  
   */  
 public void  
 translate(int dx, int dy)  
65  {  {
66    for (int i = 0; i < npoints; i++)    /**
67       * Compatible with JDK 1.0+.
68       */
69      private static final long serialVersionUID = -6460061437900069969L;
70    
71      /**
72       * This total number of endpoints.
73       *
74       * @serial the number of endpoints, possibly less than the array sizes
75       */
76      public int npoints;
77    
78      /**
79       * The array of X coordinates of endpoints. This should not be null.
80       *
81       * @see #addPoint(int, int)
82       * @serial the x coordinates
83       */
84      public int[] xpoints;
85    
86      /**
87       * The array of Y coordinates of endpoints. This should not be null.
88       *
89       * @see #addPoint(int, int)
90       * @serial the y coordinates
91       */
92      public int[] ypoints;
93    
94      /**
95       * The bounding box of this polygon. This is lazily created and cached, so
96       * it must be invalidated after changing points.
97       *
98       * @see #getBounds()
99       * @serial the bounding box, or null
100       */
101      protected Rectangle bounds;
102    
103      /**
104       * Cached flattened version - condense points and parallel lines, so the
105       * result has area if there are >= 3 condensed vertices. flat[0] is the
106       * number of condensed points, and (flat[odd], flat[odd+1]) form the
107       * condensed points.
108       *
109       * @see #condense()
110       * @see #contains(double, double)
111       * @see #contains(double, double, double, double)
112       */
113      private transient int[] condensed;
114    
115      /**
116       * Initializes an empty polygon.
117       */
118      public Polygon()
119      {
120        // Leave room for growth.
121        xpoints = new int[4];
122        ypoints = new int[4];
123      }
124    
125      /**
126       * Create a new polygon with the specified endpoints.
127       *
128       * @param xpoints the array of X coordinates for this polygon
129       * @param ypoints the array of Y coordinates for this polygon
130       * @param npoints the total number of endpoints in this polygon
131       * @throws NegativeArraySizeException if npoints is negative
132       * @throws IndexOutOfBoundsException if npoints exceeds either array
133       * @throws NullPointerException if xpoints or ypoints is null
134       */
135      public Polygon(int[] xpoints, int[] ypoints, int npoints)
136      {
137        if (npoints < 0)
138          throw new NegativeArraySizeException();
139        if (npoints > xpoints.length || npoints > ypoints.length)
140          throw new IndexOutOfBoundsException();
141        this.xpoints = xpoints;
142        this.ypoints = ypoints;
143        this.npoints = npoints;
144      }
145    
146      /**
147       * Reset the polygon to be empty. The arrays are left alone, to avoid object
148       * allocation, but the number of points is set to 0, and all cached data
149       * is discarded. If you are discarding a huge number of points, it may be
150       * more efficient to just create a new Polygon.
151       *
152       * @see #invalidate()
153       * @since 1.4
154       */
155      public void reset()
156      {
157        npoints = 0;
158        invalidate();
159      }
160    
161      /**
162       * Invalidate or flush all cached data. After direct manipulation of the
163       * public member fields, this is necessary to avoid inconsistent results
164       * in methods like <code>contains</code>.
165       *
166       * @see #getBounds()
167       * @since 1.4
168       */
169      public void invalidate()
170      {
171        bounds = null;
172        condensed = null;
173      }
174    
175      /**
176       * Translates the polygon by adding the specified values to all X and Y
177       * coordinates. This updates the bounding box, if it has been calculated.
178       *
179       * @param dx the amount to add to all X coordinates
180       * @param dy the amount to add to all Y coordinates
181       * @since 1.1
182       */
183      public void translate(int dx, int dy)
184      {
185        int i = npoints;
186        while (--i >= 0)
187          {
188            xpoints[i] += dx;
189            xpoints[i] += dy;
190          }
191        if (bounds != null)
192          {
193            bounds.x += dx;
194            bounds.y += dy;
195          }
196        condensed = null;
197      }
198    
199      /**
200       * Adds the specified endpoint to the polygon. This updates the bounding
201       * box, if it has been created.
202       *
203       * @param x the X coordinate of the point to add
204       * @param y the Y coordiante of the point to add
205       */
206      public void addPoint(int x, int y)
207      {
208        if (npoints + 1 > xpoints.length)
209          {
210            int[] newx = new int[npoints + 1];
211            System.arraycopy(xpoints, 0, newx, 0, npoints);
212            xpoints = newx;
213          }
214        if (npoints + 1 > ypoints.length)
215          {
216            int[] newy = new int[npoints + 1];
217            System.arraycopy(ypoints, 0, newy, 0, npoints);
218            ypoints = newy;
219          }
220        xpoints[npoints] = x;
221        ypoints[npoints] = y;
222        npoints++;
223        if (bounds != null)
224          {
225            if (npoints == 1)
226              {
227                bounds.x = x;
228                bounds.y = y;
229              }
230            else
231              {
232                if (x < bounds.x)
233                  {
234                    bounds.width += bounds.x - x;
235                    bounds.x = x;
236                  }
237                else if (x > bounds.x + bounds.width)
238                  bounds.width = x - bounds.x;
239                if (y < bounds.y)
240                  {
241                    bounds.height += bounds.y - y;
242                    bounds.y = y;
243                  }
244                else if (y > bounds.y + bounds.height)
245                  bounds.height = y - bounds.y;
246              }
247          }
248        condensed = null;
249      }
250    
251      /**
252       * Returns the bounding box of this polygon. This is the smallest
253       * rectangle with sides parallel to the X axis that will contain this
254       * polygon.
255       *
256       * @return the bounding box for this polygon
257       * @see #getBounds2D()
258       * @since 1.1
259       */
260      public Rectangle getBounds()
261      {
262        if (bounds == null)
263          {
264            if (npoints == 0)
265              return bounds = new Rectangle();
266            int i = npoints - 1;
267            int minx = xpoints[i];
268            int maxx = minx;
269            int miny = ypoints[i];
270            int maxy = miny;
271            while (--i >= 0)
272              {
273                int x = xpoints[i];
274                int y = ypoints[i];
275                if (x < minx)
276                  minx = x;
277                else if (x > maxx)
278                  maxx = x;
279                if (y < miny)
280                  miny = y;
281                else if (y > maxy)
282                  maxy = y;
283              }
284            bounds = new Rectangle(minx, maxy, maxx - minx, maxy - miny);
285          }
286        return bounds;
287      }
288    
289      /**
290       * Returns the bounding box of this polygon. This is the smallest
291       * rectangle with sides parallel to the X axis that will contain this
292       * polygon.
293       *
294       * @return the bounding box for this polygon
295       * @see #getBounds2D()
296       * @deprecated use {@link #getBounds()} instead
297       */
298      public Rectangle getBoundingBox()
299      {
300        return getBounds();
301      }
302    
303      /**
304       * Tests whether or not the specified point is inside this polygon.
305       *
306       * @param p the point to test
307       * @return true if the point is inside this polygon
308       * @throws NullPointerException if p is null
309       * @see #contains(double, double)
310       */
311      public boolean contains(Point p)
312      {
313        return contains(p.getX(), p.getY());
314      }
315    
316      /**
317       * Tests whether or not the specified point is inside this polygon.
318       *
319       * @param x the X coordinate of the point to test
320       * @param y the Y coordinate of the point to test
321       * @return true if the point is inside this polygon
322       * @see #contains(double, double)
323       * @since 1.1
324       */
325      public boolean contains(int x, int y)
326      {
327        return contains((double) x, (double) y);
328      }
329    
330      /**
331       * Tests whether or not the specified point is inside this polygon.
332       *
333       * @param x the X coordinate of the point to test
334       * @param y the Y coordinate of the point to test
335       * @return true if the point is inside this polygon
336       * @see #contains(double, double)
337       * @deprecated use {@link #contains(int, int)} instead
338       */
339      public boolean inside(int x, int y)
340      {
341        return contains((double) x, (double) y);
342      }
343    
344      /**
345       * Returns a high-precision bounding box of this polygon. This is the
346       * smallest rectangle with sides parallel to the X axis that will contain
347       * this polygon.
348       *
349       * @return the bounding box for this polygon
350       * @see #getBounds()
351       * @since 1.2
352       */
353      public Rectangle2D getBounds2D()
354      {
355        // For polygons, the integer version is exact!
356        return getBounds();
357      }
358    
359      /**
360       * Tests whether or not the specified point is inside this polygon.
361       *
362       * @param x the X coordinate of the point to test
363       * @param y the Y coordinate of the point to test
364       * @return true if the point is inside this polygon
365       * @since 1.2
366       */
367      public boolean contains(double x, double y)
368      {
369        // First, the obvious bounds checks.
370        if (! condense() || ! getBounds().contains(x, y))
371          return false;
372        // A point is contained if a ray to (-inf, y) crosses an odd number
373        // of segments. This must obey the semantics of Shape when the point is
374        // exactly on a segment or vertex. Note that we are guaranteed that the
375        // condensed polygon has area, and no two segments with identical slope.
376        int intersections = 0;
377        int limit = condensed[0];
378        int curx = condensed[(limit << 1) - 1];
379        int cury = condensed[limit << 1];
380        for (int i = 1; i <= limit; i++)
381          {
382            int priorx = curx;
383            int priory = cury;
384            curx = condensed[(i << 1) - 1];
385            cury = condensed[i << 1];
386            if ((priorx > x && curx > x) // Left of segment, or NaN.
387                || (priory > y && cury > y) // Below segment, or NaN.
388                || (priory < y && cury < y)) // Above segment.
389              continue;
390            if (priory == cury) // Horizontal segment, y == cury == priory
391              {
392                if (priorx < x && curx < x) // Right of segment.
393                  {
394                    intersections++;
395                    continue;
396                  }
397                // Did we approach this segment from above or below?
398                // This mess is necessary to obey rules of Shape.
399                priory = condensed[((limit + i - 2) % limit) << 1];
400                boolean above = priory > cury;
401                if ((curx == x && (curx > priorx || above))
402                    || (priorx == x && (curx < priorx || ! above))
403                    || (curx > priorx && ! above) || above)
404                  intersections++;
405                continue;
406              }
407            if (priorx == x && priory == y) // On prior vertex.
408              continue;
409            if (priorx == curx // Vertical segment.
410                || (priorx < x && curx < x)) // Right of segment.
411              {
412                intersections++;
413                continue;
414              }
415            // The point is inside the segment's bounding box, compare slopes.
416            double slopeseg = (double) (cury - priory) / (curx - priorx);
417            double slopepoint = (double) (y - priory) / (x - priorx);
418            if ((slopeseg > 0 && slopeseg > slopepoint)
419                || slopeseg < slopepoint)
420              intersections++;
421          }
422        return (intersections & 1) != 0;
423      }
424    
425      /**
426       * Tests whether or not the specified point is inside this polygon.
427       *
428       * @param p the point to test
429       * @return true if the point is inside this polygon
430       * @throws NullPointerException if p is null
431       * @see #contains(double, double)
432       * @since 1.2
433       */
434      public boolean contains(Point2D p)
435      {
436        return contains(p.getX(), p.getY());
437      }
438    
439      /**
440       * Test if a high-precision rectangle intersects the shape. This is true
441       * if any point in the rectangle is in the shape. This implementation is
442       * precise.
443       *
444       * @param x the x coordinate of the rectangle
445       * @param y the y coordinate of the rectangle
446       * @param w the width of the rectangle, treated as point if negative
447       * @param h the height of the rectangle, treated as point if negative
448       * @return true if the rectangle intersects this shape
449       * @since 1.2
450       */
451      public boolean intersects(double x, double y, double w, double h)
452      {
453        // First, the obvious bounds checks.
454        if (w <= 0 || h <= 0 || npoints == 0 ||
455            ! getBounds().intersects(x, y, w, h))
456          return false; // Disjoint bounds.
457        if ((x <= bounds.x && x + w >= bounds.x + bounds.width
458             && y <= bounds.y && y + h >= bounds.y + bounds.height)
459            || contains(x, y))
460          return true; // Rectangle contains the polygon, or one point matches.
461        // If any vertex is in the rectangle, the two might intersect.
462        int curx = 0;
463        int cury = 0;
464        for (int i = 0; i < npoints; i++)
465          {
466            curx = xpoints[i];
467            cury = ypoints[i];
468            if (curx >= x && curx < x + w && cury >= y && cury < y + h
469                && contains(curx, cury)) // Boundary check necessary.
470              return true;
471          }
472        // Finally, if at least one of the four bounding lines intersect any
473        // segment of the polygon, return true. Be careful of the semantics of
474        // Shape; coinciding lines do not necessarily return true.
475        for (int i = 0; i < npoints; i++)
476          {
477            int priorx = curx;
478            int priory = cury;
479            curx = xpoints[i];
480            cury = ypoints[i];
481            if (priorx == curx) // Vertical segment.
482              {
483                if (curx < x || curx >= x + w) // Outside rectangle.
484                  continue;
485                if ((cury >= y + h && priory <= y)
486                    || (cury <= y && priory >= y + h))
487                  return true; // Bisects rectangle.
488                continue;
489              }
490            if (priory == cury) // Horizontal segment.
491              {
492                if (cury < y || cury >= y + h) // Outside rectangle.
493                  continue;
494                if ((curx >= x + w && priorx <= x)
495                    || (curx <= x && priorx >= x + w))
496                  return true; // Bisects rectangle.
497                continue;
498              }
499            // Slanted segment.
500            double slope = (double) (cury - priory) / (curx - priorx);
501            double intersect = slope * (x - curx) + cury;
502            if (intersect > y && intersect < y + h) // Intersects left edge.
503              return true;
504            intersect = slope * (x + w - curx) + cury;
505            if (intersect > y && intersect < y + h) // Intersects right edge.
506              return true;
507            intersect = (y - cury) / slope + curx;
508            if (intersect > x && intersect < x + w) // Intersects bottom edge.
509              return true;
510            intersect = (y + h - cury) / slope + cury;
511            if (intersect > x && intersect < x + w) // Intersects top edge.
512              return true;
513          }
514        return false;
515      }
516    
517      /**
518       * Test if a high-precision rectangle intersects the shape. This is true
519       * if any point in the rectangle is in the shape. This implementation is
520       * precise.
521       *
522       * @param r the rectangle
523       * @return true if the rectangle intersects this shape
524       * @throws NullPointerException if r is null
525       * @see #intersects(double, double, double, double)
526       * @since 1.2
527       */
528      public boolean intersects(Rectangle2D r)
529      {
530        return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight());
531      }
532    
533      /**
534       * Test if a high-precision rectangle lies completely in the shape. This is
535       * true if all points in the rectangle are in the shape. This implementation
536       * is precise.
537       *
538       * @param x the x coordinate of the rectangle
539       * @param y the y coordinate of the rectangle
540       * @param w the width of the rectangle, treated as point if negative
541       * @param h the height of the rectangle, treated as point if negative
542       * @return true if the rectangle is contained in this shape
543       * @since 1.2
544       */
545      public boolean contains(double x, double y, double w, double h)
546      {
547        // First, the obvious bounds checks.
548        if (w <= 0 || h <= 0 || ! contains(x, y)
549            || ! bounds.contains(x, y, w, h))
550          return false;
551        // Now, if any of the four bounding lines intersects a polygon segment,
552        // return false. The previous check had the side effect of setting
553        // the condensed array, which we use. Be careful of the semantics of
554        // Shape; coinciding lines do not necessarily return false.
555        int limit = condensed[0];
556        int curx = condensed[(limit << 1) - 1];
557        int cury = condensed[limit << 1];
558        for (int i = 1; i <= limit; i++)
559          {
560            int priorx = curx;
561            int priory = cury;
562            curx = condensed[(i << 1) - 1];
563            cury = condensed[i << 1];
564            if (curx > x && curx < x + w && cury > y && cury < y + h)
565              return false; // Vertex is in rectangle.
566            if (priorx == curx) // Vertical segment.
567              {
568                if (curx < x || curx > x + w) // Outside rectangle.
569                  continue;
570                if ((cury >= y + h && priory <= y)
571                    || (cury <= y && priory >= y + h))
572                  return false; // Bisects rectangle.
573                continue;
574              }
575            if (priory == cury) // Horizontal segment.
576              {
577                if (cury < y || cury > y + h) // Outside rectangle.
578                  continue;
579                if ((curx >= x + w && priorx <= x)
580                    || (curx <= x && priorx >= x + w))
581                  return false; // Bisects rectangle.
582                continue;
583              }
584            // Slanted segment.
585            double slope = (double) (cury - priory) / (curx - priorx);
586            double intersect = slope * (x - curx) + cury;
587            if (intersect > y && intersect < y + h) // Intersects left edge.
588              return false;
589            intersect = slope * (x + w - curx) + cury;
590            if (intersect > y && intersect < y + h) // Intersects right edge.
591              return false;
592            intersect = (y - cury) / slope + curx;
593            if (intersect > x && intersect < x + w) // Intersects bottom edge.
594              return false;
595            intersect = (y + h - cury) / slope + cury;
596            if (intersect > x && intersect < x + w) // Intersects top edge.
597              return false;
598          }
599        return true;
600      }
601    
602      /**
603       * Test if a high-precision rectangle lies completely in the shape. This is
604       * true if all points in the rectangle are in the shape. This implementation
605       * is precise.
606       *
607       * @param r the rectangle
608       * @return true if the rectangle is contained in this shape
609       * @throws NullPointerException if r is null
610       * @see #contains(double, double, double, double)
611       * @since 1.2
612       */
613      public boolean contains(Rectangle2D r)
614      {
615        return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight());
616      }
617    
618      /**
619       * Return an iterator along the shape boundary. If the optional transform
620       * is provided, the iterator is transformed accordingly. Each call returns
621       * a new object, independent from others in use. This class is not
622       * threadsafe to begin with, so the path iterator is not either.
623       *
624       * @param transform an optional transform to apply to the iterator
625       * @return a new iterator over the boundary
626       * @since 1.2
627       */
628      public PathIterator getPathIterator(final AffineTransform transform)
629      {
630        return new PathIterator()
631      {      {
632        xpoints[i] += dx;        /** The current vertex of iteration. */
633        xpoints[i] += dy;        private int vertex;
     }  
   
   calculateBounds();  
 }  
   
 /*************************************************************************/  
   
 /**  
   * Adds the specified endpoint to the polygon.  
   *  
   * @param x The X coordinate of the point to add.  
   * @param y The Y coordiante of the point to add.  
   */  
 public void  
 addPoint(int x, int y)  
 {  
   int newxpoints[] = new int[npoints + 1];  
   int newypoints[] = new int[npoints + 1];  
   
   System.arraycopy(xpoints, 0, newxpoints, 0, npoints);  
   System.arraycopy(ypoints, 0, newypoints, 0, npoints);  
   
   newxpoints[npoints] = x;  
   newypoints[npoints] = y;  
   
   xpoints = newxpoints;  
   ypoints = newypoints;  
   ++npoints;  
 }  
   
 /*************************************************************************/  
   
 /**  
   * Returns the bounding box of this polygon.  This is the smallest  
   * rectangle with sides parallel to the X axis that will contain this  
   * polygon.  
   *  
   * @return The bounding box for this polygon.  
   */  
 public Rectangle  
 getBounds()  
 {  
   return(bounds);  
 }  
   
 /*************************************************************************/  
   
 /**  
   * Returns the bounding box of this polygon.  This is the smallest  
   * rectangle with sides parallel to the X axis that will contain this  
   * polygon.  
   *  
   * @return The bounding box for this polygon.  
   *  
   * @deprecated This method has been replaced by <code>getBounds()</code>.  
   */  
 public Rectangle  
 getBoundingBox()  
 {  
   return(bounds);  
 }  
   
 /*************************************************************************/  
   
 /**  
   * Tests whether or not the specified point is inside this polygon.  
   *  
   * @param x The X coordinate of the point to test.  
   * @param y the Y coordinate of the point to test.  
   *  
   * @return <code>true</code> if the point is inside this polygon,  
   * <code>false</code> otherwise.  
   */  
 public boolean  
 contains(int x, int y)  
 {  
   // Is inside bounding box.  
   if (!bounds.contains(x, y))  
     return(false);  
   
   int sign = 0;  
   for (int i = 0; i < npoints; i ++)  
     {  
       int nx = xpoints[(i + 1) % npoints] - xpoints[i];  
       int ny = ypoints[(i + 1) % npoints] - ypoints[i];  
   
       int dx = x - xpoints[i];  
       int dy = y - ypoints[i];  
   
       int val = (dx*nx) + (dy*nx);  
   
       if (sign == 0)  
         {  
           if (val < 1)  
             sign = -1;  
           else if (val > 1)  
             sign = 1;  
         }  
   
       if ((val > 1) && (sign < 1))  
         return(false);  
       if ((val < 1) && (sign > 1))  
         return(false);  
     }  
   
   return(true);  
 }  
   
 /*************************************************************************/  
   
 /**  
   * Tests whether or not the specified point is inside this polygon.  
   *  
   * @param x The X coordinate of the point to test.  
   * @param y the Y coordinate of the point to test.  
   *  
   * @return <code>true</code> if the point is inside this polygon,  
   * <code>false</code> otherwise.  
   *  
   * @deprecated This method has been replaced by <code>contains()</code>.  
   */  
 public boolean  
 inside(int x, int y)  
 {  
   return(contains(x, y));  
 }  
   
 } // class Polygon  
634    
635          public int getWindingRule()
636          {
637            return WIND_EVEN_ODD;
638          }
639    
640          public boolean isDone()
641          {
642            return vertex >= npoints;
643          }
644    
645          public void next()
646          {
647            vertex++;
648          }
649    
650          public int currentSegment(float[] coords)
651          {
652            if (vertex >= npoints)
653              return SEG_CLOSE;
654            coords[0] = xpoints[vertex];
655            coords[1] = ypoints[vertex];
656            if (transform != null)
657              transform.transform(coords, 0, coords, 0, 1);
658            return SEG_LINETO;
659          }
660    
661          public int currentSegment(double[] coords)
662          {
663            if (vertex >= npoints)
664              return SEG_CLOSE;
665            coords[0] = xpoints[vertex];
666            coords[1] = ypoints[vertex];
667            if (transform != null)
668              transform.transform(coords, 0, coords, 0, 1);
669            return SEG_LINETO;
670          }
671        };
672      }
673    
674      /**
675       * Return an iterator along the flattened version of the shape boundary.
676       * Since rectangles are already flat, the flatness parameter is ignored, and
677       * the resulting iterator only has SEG_LINETO and SEG_CLOSE points. If the
678       * optional transform is provided, the iterator is transformed accordingly.
679       * Each call returns a new object, independent from others in use. This
680       * class is not threadsafe to begin with, so the path iterator is not either.
681       *
682       * @param transform an optional transform to apply to the iterator
683       * @param double the maximum distance for deviation from the real boundary
684       * @return a new iterator over the boundary
685       * @since 1.2
686       */
687      public PathIterator getPathIterator(AffineTransform transform,
688                                          double flatness)
689      {
690        return getPathIterator(transform);
691      }
692    
693      /**
694       * Helper for contains, which caches a condensed version of the polygon.
695       * This condenses all colinear points, so that consecutive segments in
696       * the condensed version always have different slope.
697       *
698       * @return true if the condensed polygon has area
699       * @see #condensed
700       * @see #contains(double, double)
701       */
702      private boolean condense()
703      {
704        if (npoints <= 2)
705          return false;
706        if (condensed != null)
707          return condensed[0] > 2;
708        condensed = new int[npoints * 2 + 1];
709        int curx = xpoints[npoints - 1];
710        int cury = ypoints[npoints - 1];
711        double curslope = Double.NaN;
712        int count = 0;
713      outer:
714        for (int i = 0; i < npoints; i++)
715          {
716            int priorx = curx;
717            int priory = cury;
718            double priorslope = curslope;
719            curx = xpoints[i];
720            cury = ypoints[i];
721            while (curx == priorx && cury == priory)
722              {
723                if (++i == npoints)
724                  break outer;
725                curx = xpoints[i];
726                cury = ypoints[i];
727              }
728            curslope = (curx == priorx ? Double.POSITIVE_INFINITY
729                        : (double) (cury - priory) / (curx - priorx));
730            if (priorslope == curslope)
731              {
732                if (count > 1 && condensed[(count << 1) - 3] == curx
733                    && condensed[(count << 1) - 2] == cury)
734                  {
735                    count--;
736                    continue;
737                  }
738              }
739            else
740              count++;
741            condensed[(count << 1) - 1] = curx;
742            condensed[count << 1] = cury;
743          }
744        condensed[0] = count;
745        return count > 2;
746      }
747    } // class Polygon

Legend:
Removed from v.1.4  
changed lines
  Added in v.1.5

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26