/* Area.java -- represents a shape built by constructive area geometry
   Copyright (C) 2002, 2004 Free Software Foundation

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */

package java.awt.geom;

import java.awt.Rectangle;
import java.awt.Shape;
import java.util.Vector;


/**
 * The Area class represents any area for the purpose of
 * Constructive Area Geometry (CAG) manipulations. CAG manipulations
 * work as an area-wise form of boolean logic, where the basic operations are:
 * <P><li>Add (in boolean algebra: A <B>or</B> B)<BR>
 * <li>Subtract (in boolean algebra: A <B>and</B> (<B>not</B> B) )<BR>
 * <li>Intersect (in boolean algebra: A <B>and</B> B)<BR>
 * <li>Exclusive Or <BR>
 * <img src="doc-files/Area-1.png" width="342" height="302"
 * alt="Illustration of CAG operations" /><BR>
 * Above is an illustration of the CAG operations on two ring shapes.<P>
 *
 * The contains and intersects() methods are also more accurate than the
 * specification of #Shape requires.<P>
 *
 * Please note that constructing an Area can be slow
 * (Self-intersection resolving is proportional to the square of
 * the number of segments).<P>
 * @see #add(Area)
 * @see #subtract(Area)
 * @see #intersect(Area)
 * @see #exclusiveOr(Area)
 *
 * @author Sven de Marothy (sven@physto.se)
 *
 * @since 1.2
 * @status Works, but could be faster and more reliable.
 */
public class Area implements Shape, Cloneable
{
  /**
   * General numerical precision
   */
  private static final double EPSILON = 1E-11;

  /**
   * recursive subdivision epsilon - (see getRecursionDepth)
   */
  private static final double RS_EPSILON = 1E-13;

  /**
   * Snap distance - points within this distance are considered equal
   */
  private static final double PE_EPSILON = 1E-11;

  /**
   * Segment vectors containing solid areas and holes
   * This is package-private to avoid an accessor method.
   */
  Vector solids;

  /**
   * Segment vectors containing solid areas and holes
   * This is package-private to avoid an accessor method.
   */
  Vector holes;

  /**
   * Vector (temporary) storing curve-curve intersections
   */
  private Vector cc_intersections;

  /**
   * Winding rule WIND_NON_ZERO used, after construction,
   * this is irrelevant.
   */
  private int windingRule;

  /**
   * Constructs an empty Area
   */
  public Area()
  {
    solids = new Vector();
    holes = new Vector();
  }

  /**
   * Constructs an Area from any given Shape. <P>
   *
   * If the Shape is self-intersecting, the created Area will consist
   * of non-self-intersecting subpaths, and any inner paths which
   * are found redundant in accordance with the Shape's winding rule
   * will not be included.
   *
   * @param s  the shape (<code>null</code> not permitted).
   *
   * @throws NullPointerException if <code>s</code> is <code>null</code>.
   */
  public Area(Shape s)
  {
    this();

    Vector p = makeSegment(s);

    // empty path
    if (p == null)
      return;

    // delete empty paths
    for (int i = 0; i < p.size(); i++)
      if (((Segment) p.elementAt(i)).getSignedArea() == 0.0)
        p.remove(i--);

    /*
     * Resolve self intersecting paths into non-intersecting
     * solids and holes.
     * Algorithm is as follows:
     * 1: Create nodes at all self intersections
     * 2: Put all segments into a list
     * 3: Grab a segment, follow it, change direction at each node,
     *    removing segments from the list in the process
     * 4: Repeat (3) until no segments remain in the list
     * 5: Remove redundant paths and sort into solids and holes
     */
    Vector paths = new Vector();
    Segment v;

    for (int i = 0; i < p.size(); i++)
      {
        Segment path = (Segment) p.elementAt(i);
        createNodesSelf(path);
      }

    if (p.size() > 1)
      {
        for (int i = 0; i < p.size() - 1; i++)
          for (int j = i + 1; j < p.size(); j++)
            {
              Segment path1 = (Segment) p.elementAt(i);
              Segment path2 = (Segment) p.elementAt(j);
              createNodes(path1, path2);
            }
      }

    // we have intersecting points.
    Vector segments = new Vector();

    for (int i = 0; i < p.size(); i++)
      {
        Segment path = v = (Segment) p.elementAt(i);
        do
          {
            segments.add(v);
            v = v.next;
          }
        while (v != path);
      }

    paths = weilerAtherton(segments);
    deleteRedundantPaths(paths);
  }

  /**
   * Performs an add (union) operation on this area with another Area.<BR>
   * @param area - the area to be unioned with this one
   */
  public void add(Area area)
  {
    if (equals(area))
      return;
    if (area.isEmpty())
      return;

    Area B = (Area) area.clone();

    Vector pathA = new Vector();
    Vector pathB = new Vector();
    pathA.addAll(solids);
    pathA.addAll(holes);
    pathB.addAll(B.solids);
    pathB.addAll(B.holes);

    int nNodes = 0;

    for (int i = 0; i < pathA.size(); i++)
      {
        Segment a = (Segment) pathA.elementAt(i);
        for (int j = 0; j < pathB.size(); j++)
          {
            Segment b = (Segment) pathB.elementAt(j);
            nNodes += createNodes(a, b);
          }
      }

    Vector paths = new Vector();
    Segment v;

    // we have intersecting points.
    Vector segments = new Vector();

    // In a union operation, we keep all
    // segments of A oustide B and all B outside A
    for (int i = 0; i < pathA.size(); i++)
      {
        v = (Segment) pathA.elementAt(i);
        Segment path = v;
        do
          {
            if (v.isSegmentOutside(area))
              segments.add(v);
            v = v.next;
          }
        while (v != path);
      }

    for (int i = 0; i < pathB.size(); i++)
      {
        v = (Segment) pathB.elementAt(i);
        Segment path = v;
        do
          {
            if (v.isSegmentOutside(this))
              segments.add(v);
            v = v.next;
          }
        while (v != path);
      }

    paths = weilerAtherton(segments);
    deleteRedundantPaths(paths);
  }

  /**
   * Performs a subtraction operation on this Area.<BR>
   * @param area the area to be subtracted from this area.
   * @throws NullPointerException if <code>area</code> is <code>null</code>.
   */
  public void subtract(Area area)
  {
    if (isEmpty() || area.isEmpty())
      return;

    if (equals(area))
      {
        reset();
        return;
      }

    Vector pathA = new Vector();
    Area B = (Area) area.clone();
    pathA.addAll(solids);
    pathA.addAll(holes);

    // reverse the directions of B paths.
    setDirection(B.holes, true);
    setDirection(B.solids, false);

    Vector pathB = new Vector();
    pathB.addAll(B.solids);
    pathB.addAll(B.holes);

    int nNodes = 0;

    // create nodes
    for (int i = 0; i < pathA.size(); i++)
      {
        Segment a = (Segment) pathA.elementAt(i);
        for (int j = 0; j < pathB.size(); j++)
          {
            Segment b = (Segment) pathB.elementAt(j);
            nNodes += createNodes(a, b);
          }
      }

    Vector paths = new Vector();

    // we have intersecting points.
    Vector segments = new Vector();

    // In a subtraction operation, we keep all
    // segments of A oustide B and all B within A
    // We outsideness-test only one segment in each path
    // and the segments before and after any node
    for (int i = 0; i < pathA.size(); i++)
      {
        Segment v = (Segment) pathA.elementAt(i);
        Segment path = v;
        if (v.isSegmentOutside(area) && v.node == null)
          segments.add(v);
        boolean node = false;
        do
          {
            if ((v.node != null || node))
              {
                node = (v.node != null);
                if (v.isSegmentOutside(area))
                  segments.add(v);
              }
            v = v.next;
          }
        while (v != path);
      }

    for (int i = 0; i < pathB.size(); i++)
      {
        Segment v = (Segment) pathB.elementAt(i);
        Segment path = v;
        if (! v.isSegmentOutside(this) && v.node == null)
          segments.add(v);
        v = v.next;
        boolean node = false;
        do
          {
            if ((v.node != null || node))
              {
                node = (v.node != null);
                if (! v.isSegmentOutside(this))
                  segments.add(v);
              }
            v = v.next;
          }
        while (v != path);
      }

    paths = weilerAtherton(segments);
    deleteRedundantPaths(paths);
  }

  /**
   * Performs an intersection operation on this Area.<BR>
   * @param area - the area to be intersected with this area.
   * @throws NullPointerException if <code>area</code> is <code>null</code>.
   */
  public void intersect(Area area)
  {
    if (isEmpty() || area.isEmpty())
      {
        reset();
        return;
      }
    if (equals(area))
      return;

    Vector pathA = new Vector();
    Area B = (Area) area.clone();
    pathA.addAll(solids);
    pathA.addAll(holes);

    Vector pathB = new Vector();
    pathB.addAll(B.solids);
    pathB.addAll(B.holes);

    int nNodes = 0;

    // create nodes
    for (int i = 0; i < pathA.size(); i++)
      {
        Segment a = (Segment) pathA.elementAt(i);
        for (int j = 0; j < pathB.size(); j++)
          {
            Segment b = (Segment) pathB.elementAt(j);
            nNodes += createNodes(a, b);
          }
      }

    Vector paths = new Vector();

    // we have intersecting points.
    Vector segments = new Vector();

    // In an intersection operation, we keep all
    // segments of A within B and all B within A
    // (The rest must be redundant)
    // We outsideness-test only one segment in each path
    // and the segments before and after any node
    for (int i = 0; i < pathA.size(); i++)
      {
        Segment v = (Segment) pathA.elementAt(i);
        Segment path = v;
        if (! v.isSegmentOutside(area) && v.node == null)
          segments.add(v);
        boolean node = false;
        do
          {
            if ((v.node != null || node))
              {
                node = (v.node != null);
                if (! v.isSegmentOutside(area))
                  segments.add(v);
              }
            v = v.next;
          }
        while (v != path);
      }

    for (int i = 0; i < pathB.size(); i++)
      {
        Segment v = (Segment) pathB.elementAt(i);
        Segment path = v;
        if (! v.isSegmentOutside(this) && v.node == null)
          segments.add(v);
        v = v.next;
        boolean node = false;
        do
          {
            if ((v.node != null || node))
              {
                node = (v.node != null);
                if (! v.isSegmentOutside(this))
                  segments.add(v);
              }
            v = v.next;
          }
        while (v != path);
      }

    paths = weilerAtherton(segments);
    deleteRedundantPaths(paths);
  }

  /**
   * Performs an exclusive-or operation on this Area.<BR>
   * @param area - the area to be XORed with this area.
   * @throws NullPointerException if <code>area</code> is <code>null</code>.
   */
  public void exclusiveOr(Area area)
  {
    if (area.isEmpty())
      return;

    if (isEmpty())
      {
        Area B = (Area) area.clone();
        solids = B.solids;
        holes = B.holes;
        return;
      }
    if (equals(area))
      {
        reset();
        return;
      }

    Vector pathA = new Vector();

    Area B = (Area) area.clone();
    Vector pathB = new Vector();
    pathA.addAll(solids);
    pathA.addAll(holes);

    // reverse the directions of B paths.
    setDirection(B.holes, true);
    setDirection(B.solids, false);
    pathB.addAll(B.solids);
    pathB.addAll(B.holes);

    int nNodes = 0;

    for (int i = 0; i < pathA.size(); i++)
      {
        Segment a = (Segment) pathA.elementAt(i);
        for (int j = 0; j < pathB.size(); j++)
          {
            Segment b = (Segment) pathB.elementAt(j);
            nNodes += createNodes(a, b);
          }
      }

    Vector paths = new Vector();
    Segment v;

    // we have intersecting points.
    Vector segments = new Vector();

    // In an XOR operation, we operate on all segments
    for (int i = 0; i < pathA.size(); i++)
      {
        v = (Segment) pathA.elementAt(i);
        Segment path = v;
        do
          {
            segments.add(v);
            v = v.next;
          }
        while (v != path);
      }

    for (int i = 0; i < pathB.size(); i++)
      {
        v = (Segment) pathB.elementAt(i);
        Segment path = v;
        do
          {
            segments.add(v);
            v = v.next;
          }
        while (v != path);
      }

    paths = weilerAtherton(segments);
    deleteRedundantPaths(paths);
  }

  /**
   * Clears the Area object, creating an empty area.
   */
  public void reset()
  {
    solids = new Vector();
    holes = new Vector();
  }

  /**
   * Returns whether this area encloses any area.
   * @return true if the object encloses any area.
   */
  public boolean isEmpty()
  {
    if (solids.size() == 0)
      return true;

    double totalArea = 0;
    for (int i = 0; i < solids.size(); i++)
      totalArea += Math.abs(((Segment) solids.elementAt(i)).getSignedArea());
    for (int i = 0; i < holes.size(); i++)
      totalArea -= Math.abs(((Segment) holes.elementAt(i)).getSignedArea());
    if (totalArea <= EPSILON)
      return true;

    return false;
  }

  /**
   * Determines whether the Area consists entirely of line segments
   * @return true if the Area lines-only, false otherwise
   */
  public boolean isPolygonal()
  {
    for (int i = 0; i < holes.size(); i++)
      if (! ((Segment) holes.elementAt(i)).isPolygonal())
        return false;
    for (int i = 0; i < solids.size(); i++)
      if (! ((Segment) solids.elementAt(i)).isPolygonal())
        return false;
    return true;
  }

  /**
   * Determines if the Area is rectangular.<P>
   *
   * This is strictly qualified. An area is considered rectangular if:<BR>
   * <li>It consists of a single polygonal path.<BR>
   * <li>It is oriented parallel/perpendicular to the xy axis<BR>
   * <li>It must be exactly rectangular, i.e. small errors induced by
   * transformations may cause a false result, although the area is
   * visibly rectangular.<P>
   * @return true if the above criteria are met, false otherwise
   */
  public boolean isRectangular()
  {
    if (isEmpty())
      return true;

    if (holes.size() != 0 || solids.size() != 1)
      return false;

    Segment path = (Segment) solids.elementAt(0);
    if (! path.isPolygonal())
      return false;

    int nCorners = 0;
    Segment s = path;
    do
      {
        Segment s2 = s.next;
        double d1 = (s.P2.getX() - s.P1.getX())*(s2.P2.getX() - s2.P1.getX())/
            ((s.P1.distance(s.P2)) * (s2.P1.distance(s2.P2)));
        double d2 = (s.P2.getY() - s.P1.getY())*(s2.P2.getY() - s2.P1.getY())/
            ((s.P1.distance(s.P2)) * (s2.P1.distance(s2.P2)));
        double dotproduct = d1 + d2;

        // For some reason, only rectangles on the XY axis count.
        if (d1 != 0 && d2 != 0)
          return false;

        if (Math.abs(dotproduct) == 0) // 90 degree angle
          nCorners++;
        else if ((Math.abs(1.0 - dotproduct) > 0)) // 0 degree angle?
          return false; // if not, return false

        s = s.next;
      }
    while (s != path);

    return nCorners == 4;
  }

  /**
   * Returns whether the Area consists of more than one simple
   * (non self-intersecting) subpath.
   *
   * @return true if the Area consists of none or one simple subpath,
   * false otherwise.
   */
  public boolean isSingular()
  {
    return (holes.size() == 0 && solids.size() <= 1);
  }

  /**
   * Returns the bounding box of the Area.<P> Unlike the CubicCurve2D and
   * QuadraticCurve2D classes, this method will return the tightest possible
   * bounding box, evaluating the extreme points of each curved segment.<P>
   * @return the bounding box
   */
  public Rectangle2D getBounds2D()
  {
    if (solids.size() == 0)
      return new Rectangle2D.Double(0.0, 0.0, 0.0, 0.0);

    double xmin;
    double xmax;
    double ymin;
    double ymax;
    xmin = xmax = ((Segment) solids.elementAt(0)).P1.getX();
    ymin = ymax = ((Segment) solids.elementAt(0)).P1.getY();

    for (int path = 0; path < solids.size(); path++)
      {
        Rectangle2D r = ((Segment) solids.elementAt(path)).getPathBounds();
        xmin = Math.min(r.getMinX(), xmin);
        ymin = Math.min(r.getMinY(), ymin);
        xmax = Math.max(r.getMaxX(), xmax);
        ymax = Math.max(r.getMaxY(), ymax);
      }

    return (new Rectangle2D.Double(xmin, ymin, (xmax - xmin), (ymax - ymin)));
  }

  /**
   * Returns the bounds of this object in Rectangle format.
   * Please note that this may lead to loss of precision.
   *
   * @return The bounds.
   * @see #getBounds2D()
   */
  public Rectangle getBounds()
  {
    return getBounds2D().getBounds();
  }

  /**
   * Create a new area of the same run-time type with the same contents as
   * this one.
   *
   * @return the clone
   */
  public Object clone()
  {
    try
      {
        Area clone = new Area();
        for (int i = 0; i < solids.size(); i++)
          clone.solids.add(((Segment) solids.elementAt(i)).cloneSegmentList());
        for (int i = 0; i < holes.size(); i++)
          clone.holes.add(((Segment) holes.elementAt(i)).cloneSegmentList());
        return clone;
      }
    catch (CloneNotSupportedException e)
      {
        throw (Error) new InternalError().initCause(e); // Impossible
      }
  }

  /**
   * Compares two Areas.
   *
   * @param area  the area to compare against this area (<code>null</code>
   *              permitted).
   * @return <code>true</code> if the areas are equal, and <code>false</code>
   *         otherwise.
   */
  public boolean equals(Area area)
  {
    if (area == null)
      return false;

    if (! getBounds2D().equals(area.getBounds2D()))
      return false;

    if (solids.size() != area.solids.size()
        || holes.size() != area.holes.size())
      return false;

    Vector pathA = new Vector();
    pathA.addAll(solids);
    pathA.addAll(holes);
    Vector pathB = new Vector();
    pathB.addAll(area.solids);
    pathB.addAll(area.holes);

    int nPaths = pathA.size();
    boolean[][] match = new boolean[2][nPaths];

    for (int i = 0; i < nPaths; i++)
      {
        for (int j = 0; j < nPaths; j++)
          {
            Segment p1 = (Segment) pathA.elementAt(i);
            Segment p2 = (Segment) pathB.elementAt(j);
            if (! match[0][i] && ! match[1][j])
              if (p1.pathEquals(p2))
                match[0][i] = match[1][j] = true;
          }
      }

    boolean result = true;
    for (int i = 0; i < nPaths; i++)
      result = result && match[0][i] && match[1][i];
    return result;
  }

  /**
   * Transforms this area by the AffineTransform at.
   *
   * @param at  the transform.
   */
  public void transform(AffineTransform at)
  {
    for (int i = 0; i < solids.size(); i++)
      ((Segment) solids.elementAt(i)).transformSegmentList(at);
    for (int i = 0; i < holes.size(); i++)
      ((Segment) holes.elementAt(i)).transformSegmentList(at);

    // Note that the orientation is not invariant under inversion
    if ((at.getType() & AffineTransform.TYPE_FLIP) != 0)
      {
        setDirection(holes, false);
        setDirection(solids, true);
      }
  }

  /**
   * Returns a new Area equal to this one, transformed
   * by the AffineTransform at.
   * @param at  the transform.
   * @return the transformed area
   * @throws NullPointerException if <code>at</code> is <code>null</code>.
   */
  public Area createTransformedArea(AffineTransform at)
  {
    Area a = (Area) clone();
    a.transform(at);
    return a;
  }

  /**
   * Determines if the point (x,y) is contained within this Area.
   *
   * @param x the x-coordinate of the point.
   * @param y the y-coordinate of the point.
   * @return true if the point is contained, false otherwise.
   */
  public boolean contains(double x, double y)
  {
    int n = 0;
    for (int i = 0; i < solids.size(); i++)
      if (((Segment) solids.elementAt(i)).contains(x, y))
        n++;

    for (int i = 0; i < holes.size(); i++)
      if (((Segment) holes.elementAt(i)).contains(x, y))
        n--;

    return (n != 0);
  }

  /**
   * Determines if the Point2D p is contained within this Area.
   *
   * @param p the point.
   * @return <code>true</code> if the point is contained, <code>false</code>
   *         otherwise.
   * @throws NullPointerException if <code>p</code> is <code>null</code>.
   */
  public boolean contains(Point2D p)
  {
    return contains(p.getX(), p.getY());
  }

  /**
   * Determines if the rectangle specified by (x,y) as the upper-left
   * and with width w and height h is completely contained within this Area,
   * returns false otherwise.<P>
   *
   * This method should always produce the correct results, unlike for other
   * classes in geom.
   *
   * @param x the x-coordinate of the rectangle.
   * @param y the y-coordinate of the rectangle.
   * @param w the width of the the rectangle.
   * @param h the height of the rectangle.
   * @return <code>true</code> if the rectangle is considered contained
   */
  public boolean contains(double x, double y, double w, double h)
  {
    LineSegment[] l = new LineSegment[4];
    l[0] = new LineSegment(x, y, x + w, y);
    l[1] = new LineSegment(x, y + h, x + w, y + h);
    l[2] = new LineSegment(x, y, x, y + h);
    l[3] = new LineSegment(x + w, y, x + w, y + h);

    // Since every segment in the area must a contour
    // between inside/outside segments, ANY intersection
    // will mean the rectangle is not entirely contained.
    for (int i = 0; i < 4; i++)
      {
        for (int path = 0; path < solids.size(); path++)
          {
            Segment v;
            Segment start;
            start = v = (Segment) solids.elementAt(path);
            do
              {
                if (l[i].hasIntersections(v))
                  return false;
                v = v.next;
              }
            while (v != start);
          }
        for (int path = 0; path < holes.size(); path++)
          {
            Segment v;
            Segment start;
            start = v = (Segment) holes.elementAt(path);
            do
              {
                if (l[i].hasIntersections(v))
                  return false;
                v = v.next;
              }
            while (v != start);
          }
      }

    // Is any point inside?
    if (! contains(x, y))
      return false;

    // Final hoop: Is the rectangle non-intersecting and inside,
    // but encloses a hole?
    Rectangle2D r = new Rectangle2D.Double(x, y, w, h);
    for (int path = 0; path < holes.size(); path++)
      if (! ((Segment) holes.elementAt(path)).isSegmentOutside(r))
        return false;

    return true;
  }

  /**
   * Determines if the Rectangle2D specified by r is completely contained
   * within this Area, returns false otherwise.<P>
   *
   * This method should always produce the correct results, unlike for other
   * classes in geom.
   *
   * @param r the rectangle.
   * @return <code>true</code> if the rectangle is considered contained
   *
   * @throws NullPointerException if <code>r</code> is <code>null</code>.
   */
  public boolean contains(Rectangle2D r)
  {
    return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight());
  }

  /**
   * Determines if the rectangle specified by (x,y) as the upper-left
   * and with width w and height h intersects any part of this Area.
   *
   * @param x  the x-coordinate for the rectangle.
   * @param y  the y-coordinate for the rectangle.
   * @param w  the width of the rectangle.
   * @param h  the height of the rectangle.
   * @return <code>true</code> if the rectangle intersects the area,
   *         <code>false</code> otherwise.
   */
  public boolean intersects(double x, double y, double w, double h)
  {
    if (solids.size() == 0)
      return false;

    LineSegment[] l = new LineSegment[4];
    l[0] = new LineSegment(x, y, x + w, y);
    l[1] = new LineSegment(x, y + h, x + w, y + h);
    l[2] = new LineSegment(x, y, x, y + h);
    l[3] = new LineSegment(x + w, y, x + w, y + h);

    // Return true on any intersection
    for (int i = 0; i < 4; i++)
      {
        for (int path = 0; path < solids.size(); path++)
          {
            Segment v;
            Segment start;
            start = v = (Segment) solids.elementAt(path);
            do
              {
                if (l[i].hasIntersections(v))
                  return true;
                v = v.next;
              }
            while (v != start);
          }
        for (int path = 0; path < holes.size(); path++)
          {
            Segment v;
            Segment start;
            start = v = (Segment) holes.elementAt(path);
            do
              {
                if (l[i].hasIntersections(v))
                  return true;
                v = v.next;
              }
            while (v != start);
          }
      }

    // Non-intersecting, Is any point inside?
    if (contains(x + w * 0.5, y + h * 0.5))
      return true;

    // What if the rectangle encloses the whole shape?
    Point2D p = ((Segment) solids.elementAt(0)).getMidPoint();
    if ((new Rectangle2D.Double(x, y, w, h)).contains(p))
      return true;
    return false;
  }

  /**
   * Determines if the Rectangle2D specified by r intersects any
   * part of this Area.
   * @param r  the rectangle to test intersection with (<code>null</code>
   *           not permitted).
   * @return <code>true</code> if the rectangle intersects the area,
   *         <code>false</code> otherwise.
   * @throws NullPointerException if <code>r</code> is <code>null</code>.
   */
  public boolean intersects(Rectangle2D r)
  {
    return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight());
  }

  /**
   * Returns a PathIterator object defining the contour of this Area,
   * transformed by at.
   *
   * @param at  the transform.
   * @return A path iterator.
   */
  public PathIterator getPathIterator(AffineTransform at)
  {
    return (new AreaIterator(at));
  }

  /**
   * Returns a flattened PathIterator object defining the contour of this
   * Area, transformed by at and with a defined flatness.
   *
   * @param at  the transform.
   * @param flatness the flatness.
   * @return A path iterator.
   */
  public PathIterator getPathIterator(AffineTransform at, double flatness)
  {
    return new FlatteningPathIterator(getPathIterator(at), flatness);
  }

  //---------------------------------------------------------------------
  // Non-public methods and classes

  /**
   * Private pathiterator object.
   */
  private class AreaIterator implements PathIterator
  {
    private Vector segments;
    private int index;
    private AffineTransform at;

    // Simple compound type for segments
    class IteratorSegment
    {
      int type;
      double[] coords;

      IteratorSegment()
      {
        coords = new double[6];
      }
    }

    /**
     * The contructor here does most of the work,
     * creates a vector of IteratorSegments, which can
     * readily be returned
     */
    public AreaIterator(AffineTransform at)
    {
      this.at = at;
      index = 0;
      segments = new Vector();
      Vector allpaths = new Vector();
      allpaths.addAll(solids);
      allpaths.addAll(holes);

      for (int i = 0; i < allpaths.size(); i++)
        {
          Segment v = (Segment) allpaths.elementAt(i);
          Segment start = v;

          IteratorSegment is = new IteratorSegment();
          is.type = SEG_MOVETO;
          is.coords[0] = start.P1.getX();
          is.coords[1] = start.P1.getY();
          segments.add(is);

          do
            {
              is = new IteratorSegment();
              is.type = v.pathIteratorFormat(is.coords);
              segments.add(is);
              v = v.next;
            }
          while (v != start);

          is = new IteratorSegment();
          is.type = SEG_CLOSE;
          segments.add(is);
        }
    }

    public int currentSegment(double[] coords)
    {
      IteratorSegment s = (IteratorSegment) segments.elementAt(index);
      if (at != null)
        at.transform(s.coords, 0, coords, 0, 3);
      else
        for (int i = 0; i < 6; i++)
          coords[i] = s.coords[i];
      return (s.type);
    }

    public int currentSegment(float[] coords)
    {
      IteratorSegment s = (IteratorSegment) segments.elementAt(index);
      double[] d = new double[6];
      if (at != null)
        {
          at.transform(s.coords, 0, d, 0, 3);
          for (int i = 0; i < 6; i++)
            coords[i] = (float) d[i];
        }
      else
        for (int i = 0; i < 6; i++)
          coords[i] = (float) s.coords[i];
      return (s.type);
    }

    // Note that the winding rule should not matter here,
    // EVEN_ODD is chosen because it renders faster.
    public int getWindingRule()
    {
      return (PathIterator.WIND_EVEN_ODD);
    }

    public boolean isDone()
    {
      return (index >= segments.size());
    }

    public void next()
    {
      index++;
    }
  }

  /**
   * Performs the fundamental task of the Weiler-Atherton algorithm,
   * traverse a list of segments, for each segment:
   * Follow it, removing segments from the list and switching paths
   * at each node. Do so until the starting segment is reached.
   *
   * Returns a Vector of the resulting paths.
   */
  private Vector weilerAtherton(Vector segments)
  {
    Vector paths = new Vector();
    while (segments.size() > 0)
      {
        // Iterate over the path
        Segment start = (Segment) segments.elementAt(0);
        Segment s = start;
        do
          {
            segments.remove(s);
            if (s.node != null)
              { // switch over
                s.next = s.node;
                s.node = null;
              }
            s = s.next; // continue
          }
        while (s != start);

        paths.add(start);
      }
    return paths;
  }

  /**
   * A small wrapper class to store intersection points
   */
  private class Intersection
  {
    Point2D p; // the 2D point of intersection
    double ta; // the parametric value on a
    double tb; // the parametric value on b
    Segment seg; // segment placeholder for node setting

    public Intersection(Point2D p, double ta, double tb)
    {
      this.p = p;
      this.ta = ta;
      this.tb = tb;
    }
  }

  /**
   * Returns the recursion depth necessary to approximate the
   * curve by line segments within the error RS_EPSILON.
   *
   * This is done with Wang's formula:
   * L0 = max{0<=i<=N-2}(|xi - 2xi+1 + xi+2|,|yi - 2yi+1 + yi+2|)
   * r0 = log4(sqrt(2)*N*(N-1)*L0/8e)
   * Where e is the maximum distance error (RS_EPSILON)
   */
  private int getRecursionDepth(CubicSegment curve)
  {
    double x0 = curve.P1.getX();
    double y0 = curve.P1.getY();

    double x1 = curve.cp1.getX();
    double y1 = curve.cp1.getY();

    double x2 = curve.cp2.getX();
    double y2 = curve.cp2.getY();

    double x3 = curve.P2.getX();
    double y3 = curve.P2.getY();

    double L0 = Math.max(Math.max(Math.abs(x0 - 2 * x1 + x2),
                                  Math.abs(x1 - 2 * x2 + x3)),
                         Math.max(Math.abs(y0 - 2 * y1 + y2),
                                  Math.abs(y1 - 2 * y2 + y3)));

    double f = Math.sqrt(2) * 6.0 * L0 / (8.0 * RS_EPSILON);

    int r0 = (int) Math.ceil(Math.log(f) / Math.log(4.0));
    return (r0);
  }

  /**
   * Performs recursive subdivision:
   * @param c1 - curve 1
   * @param c2 - curve 2
   * @param depth1 - recursion depth of curve 1
   * @param depth2 - recursion depth of curve 2
   * @param t1 - global parametric value of the first curve's starting point
   * @param t2 - global parametric value of the second curve's starting point
   * @param w1 - global parametric length of curve 1
   * @param w2 - global parametric length of curve 2
   *
   * The final four parameters are for keeping track of the parametric
   * value of the curve. For a full curve t = 0, w = 1, w is halved with
   * each subdivision.
   */
  private void recursiveSubdivide(CubicCurve2D c1, CubicCurve2D c2,
                                  int depth1, int depth2, double t1,
                                  double t2, double w1, double w2)
  {
    boolean flat1 = depth1 <= 0;
    boolean flat2 = depth2 <= 0;

    if (flat1 && flat2)
      {
        double xlk = c1.getP2().getX() - c1.getP1().getX();
        double ylk = c1.getP2().getY() - c1.getP1().getY();

        double xnm = c2.getP2().getX() - c2.getP1().getX();
        double ynm = c2.getP2().getY() - c2.getP1().getY();

        double xmk = c2.getP1().getX() - c1.getP1().getX();
        double ymk = c2.getP1().getY() - c1.getP1().getY();
        double det = xnm * ylk - ynm * xlk;

        if (det + 1.0 == 1.0)
          return;

        double detinv = 1.0 / det;
        double s = (xnm * ymk - ynm * xmk) * detinv;
        double t = (xlk * ymk - ylk * xmk) * detinv;
        if ((s < 0.0) || (s > 1.0) || (t < 0.0) || (t > 1.0))
          return;

        double[] temp = new double[2];
        temp[0] = t1 + s * w1;
        temp[1] = t2 + t * w1;
        cc_intersections.add(temp);
        return;
      }

    CubicCurve2D.Double c11 = new CubicCurve2D.Double();
    CubicCurve2D.Double c12 = new CubicCurve2D.Double();
    CubicCurve2D.Double c21 = new CubicCurve2D.Double();
    CubicCurve2D.Double c22 = new CubicCurve2D.Double();

    if (! flat1 && ! flat2)
      {
        depth1--;
        depth2--;
        w1 = w1 * 0.5;
        w2 = w2 * 0.5;
        c1.subdivide(c11, c12);
        c2.subdivide(c21, c22);
        if (c11.getBounds2D().intersects(c21.getBounds2D()))
          recursiveSubdivide(c11, c21, depth1, depth2, t1, t2, w1, w2);
        if (c11.getBounds2D().intersects(c22.getBounds2D()))
          recursiveSubdivide(c11, c22, depth1, depth2, t1, t2 + w2, w1, w2);
        if (c12.getBounds2D().intersects(c21.getBounds2D()))
          recursiveSubdivide(c12, c21, depth1, depth2, t1 + w1, t2, w1, w2);
        if (c12.getBounds2D().intersects(c22.getBounds2D()))
          recursiveSubdivide(c12, c22, depth1, depth2, t1 + w1, t2 + w2, w1, w2);
        return;
      }

    if (! flat1)
      {
        depth1--;
        c1.subdivide(c11, c12);
        w1 = w1 * 0.5;
        if (c11.getBounds2D().intersects(c2.getBounds2D()))
          recursiveSubdivide(c11, c2, depth1, depth2, t1, t2, w1, w2);
        if (c12.getBounds2D().intersects(c2.getBounds2D()))
          recursiveSubdivide(c12, c2, depth1, depth2, t1 + w1, t2, w1, w2);
        return;
      }

    depth2--;
    c2.subdivide(c21, c22);
    w2 = w2 * 0.5;
    if (c1.getBounds2D().intersects(c21.getBounds2D()))
      recursiveSubdivide(c1, c21, depth1, depth2, t1, t2, w1, w2);
    if (c1.getBounds2D().intersects(c22.getBounds2D()))
      recursiveSubdivide(c1, c22, depth1, depth2, t1, t2 + w2, w1, w2);
  }

  /**
   * Returns a set of interesections between two Cubic segments
   * Or null if no intersections were found.
   *
   * The method used to find the intersection is recursive midpoint
   * subdivision. Outline description:
   *
   * 1) Check if the bounding boxes of the curves intersect,
   * 2) If so, divide the curves in the middle and test the bounding
   * boxes again,
   * 3) Repeat until a maximum recursion depth has been reached, where
   * the intersecting curves can be approximated by line segments.
   *
   * This is a reasonably accurate method, although the recursion depth
   * is typically around 20, the bounding-box tests allow for significant
   * pruning of the subdivision tree.
   *
   * This is package-private to avoid an accessor method.
   */
  Intersection[] cubicCubicIntersect(CubicSegment curve1, CubicSegment curve2)
  {
    Rectangle2D r1 = curve1.getBounds();
    Rectangle2D r2 = curve2.getBounds();

    if (! r1.intersects(r2))
      return null;

    cc_intersections = new Vector();
    recursiveSubdivide(curve1.getCubicCurve2D(), curve2.getCubicCurve2D(),
                       getRecursionDepth(curve1), getRecursionDepth(curve2),
                       0.0, 0.0, 1.0, 1.0);

    if (cc_intersections.size() == 0)
      return null;

    Intersection[] results = new Intersection[cc_intersections.size()];
    for (int i = 0; i < cc_intersections.size(); i++)
      {
        double[] temp = (double[]) cc_intersections.elementAt(i);
        results[i] = new Intersection(curve1.evaluatePoint(temp[0]), temp[0],
                                      temp[1]);
      }
    cc_intersections = null;
    return (results);
  }

  /**
   * Returns the intersections between a line and a quadratic bezier
   * Or null if no intersections are found1
   * This is done through combining the line's equation with the
   * parametric form of the Bezier and solving the resulting quadratic.
   * This is package-private to avoid an accessor method.
   */
  Intersection[] lineQuadIntersect(LineSegment l, QuadSegment c)
  {
    double[] y = new double[3];
    double[] x = new double[3];
    double[] r = new double[3];
    int nRoots;
    double x0 = c.P1.getX();
    double y0 = c.P1.getY();
    double x1 = c.cp.getX();
    double y1 = c.cp.getY();
    double x2 = c.P2.getX();
    double y2 = c.P2.getY();

    double lx0 = l.P1.getX();
    double ly0 = l.P1.getY();
    double lx1 = l.P2.getX();
    double ly1 = l.P2.getY();
    double dx = lx1 - lx0;
    double dy = ly1 - ly0;

    // form r(t) = y(t) - x(t) for the bezier
    y[0] = y0;
    y[1] = 2 * (y1 - y0);
    y[2] = (y2 - 2 * y1 + y0);

    x[0] = x0;
    x[1] = 2 * (x1 - x0);
    x[2] = (x2 - 2 * x1 + x0);

    // a point, not a line
    if (dy == 0 && dx == 0)
      return null;

    // line on y axis
    if (dx == 0 || (dy / dx) > 1.0)
      {
        double k = dx / dy;
        x[0] -= lx0;
        y[0] -= ly0;
        y[0] *= k;
        y[1] *= k;
        y[2] *= k;
      }
    else
      {
        double k = dy / dx;
        x[0] -= lx0;
        y[0] -= ly0;
        x[0] *= k;
        x[1] *= k;
        x[2] *= k;
      }

    for (int i = 0; i < 3; i++)
      r[i] = y[i] - x[i];

    if ((nRoots = QuadCurve2D.solveQuadratic(r)) > 0)
      {
        Intersection[] temp = new Intersection[nRoots];
        int intersections = 0;
        for (int i = 0; i < nRoots; i++)
          {
            double t = r[i];
            if (t >= 0.0 && t <= 1.0)
              {
                Point2D p = c.evaluatePoint(t);

                // if the line is on an axis, snap the point to that axis.
                if (dx == 0)
                  p.setLocation(lx0, p.getY());
                if (dy == 0)
                  p.setLocation(p.getX(), ly0);

                if (p.getX() <= Math.max(lx0, lx1)
                    && p.getX() >= Math.min(lx0, lx1)
                    && p.getY() <= Math.max(ly0, ly1)
                    && p.getY() >= Math.min(ly0, ly1))
                  {
                    double lineparameter = p.distance(l.P1) / l.P2.distance(l.P1);
                    temp[i] = new Intersection(p, lineparameter, t);
                    intersections++;
                  }
              }
            else
              temp[i] = null;
          }
        if (intersections == 0)
          return null;

        Intersection[] rValues = new Intersection[intersections];

        for (int i = 0; i < nRoots; i++)
          if (temp[i] != null)
            rValues[--intersections] = temp[i];
        return (rValues);
      }
    return null;
  }

  /**
   * Returns the intersections between a line and a cubic segment
   * This is done through combining the line's equation with the
   * parametric form of the Bezier and solving the resulting quadratic.
   * This is package-private to avoid an accessor method.
   */
  Intersection[] lineCubicIntersect(LineSegment l, CubicSegment c)
  {
    double[] y = new double[4];
    double[] x = new double[4];
    double[] r = new double[4];
    int nRoots;
    double x0 = c.P1.getX();
    double y0 = c.P1.getY();
    double x1 = c.cp1.getX();
    double y1 = c.cp1.getY();
    double x2 = c.cp2.getX();
    double y2 = c.cp2.getY();
    double x3 = c.P2.getX();
    double y3 = c.P2.getY();

    double lx0 = l.P1.getX();
    double ly0 = l.P1.getY();
    double lx1 = l.P2.getX();
    double ly1 = l.P2.getY();
    double dx = lx1 - lx0;
    double dy = ly1 - ly0;

    // form r(t) = y(t) - x(t) for the bezier
    y[0] = y0;
    y[1] = 3 * (y1 - y0);
    y[2] = 3 * (y2 + y0 - 2 * y1);
    y[3] = y3 - 3 * y2 + 3 * y1 - y0;

    x[0] = x0;
    x[1] = 3 * (x1 - x0);
    x[2] = 3 * (x2 + x0 - 2 * x1);
    x[3] = x3 - 3 * x2 + 3 * x1 - x0;

    // a point, not a line
    if (dy == 0 && dx == 0)
      return null;

    // line on y axis
    if (dx == 0 || (dy / dx) > 1.0)
      {
        double k = dx / dy;
        x[0] -= lx0;
        y[0] -= ly0;
        y[0] *= k;
        y[1] *= k;
        y[2] *= k;
        y[3] *= k;
      }
    else
      {
        double k = dy / dx;
        x[0] -= lx0;
        y[0] -= ly0;
        x[0] *= k;
        x[1] *= k;
        x[2] *= k;
        x[3] *= k;
      }
    for (int i = 0; i < 4; i++)
      r[i] = y[i] - x[i];

    if ((nRoots = CubicCurve2D.solveCubic(r)) > 0)
      {
        Intersection[] temp = new Intersection[nRoots];
        int intersections = 0;
        for (int i = 0; i < nRoots; i++)
          {
            double t = r[i];
            if (t >= 0.0 && t <= 1.0)
              {
                // if the line is on an axis, snap the point to that axis.
                Point2D p = c.evaluatePoint(t);
                if (dx == 0)
                  p.setLocation(lx0, p.getY());
                if (dy == 0)
                  p.setLocation(p.getX(), ly0);

                if (p.getX() <= Math.max(lx0, lx1)
                    && p.getX() >= Math.min(lx0, lx1)
                    && p.getY() <= Math.max(ly0, ly1)
                    && p.getY() >= Math.min(ly0, ly1))
                  {
                    double lineparameter = p.distance(l.P1) / l.P2.distance(l.P1);
                    temp[i] = new Intersection(p, lineparameter, t);
                    intersections++;
                  }
              }
            else
              temp[i] = null;
          }

        if (intersections == 0)
          return null;

        Intersection[] rValues = new Intersection[intersections];
        for (int i = 0; i < nRoots; i++)
          if (temp[i] != null)
            rValues[--intersections] = temp[i];
        return (rValues);
      }
    return null;
  }

  /**
   * Returns the intersection between two lines, or null if there is no
   * intersection.
   * This is package-private to avoid an accessor method.
   */
  Intersection linesIntersect(LineSegment a, LineSegment b)
  {
    Point2D P1 = a.P1;
    Point2D P2 = a.P2;
    Point2D P3 = b.P1;
    Point2D P4 = b.P2;

    if (! Line2D.linesIntersect(P1.getX(), P1.getY(), P2.getX(), P2.getY(),
                                P3.getX(), P3.getY(), P4.getX(), P4.getY()))
      return null;

    double x1 = P1.getX();
    double y1 = P1.getY();
    double rx = P2.getX() - x1;
    double ry = P2.getY() - y1;

    double x2 = P3.getX();
    double y2 = P3.getY();
    double sx = P4.getX() - x2;
    double sy = P4.getY() - y2;

    double determinant = sx * ry - sy * rx;
    double nom = (sx * (y2 - y1) + sy * (x1 - x2));

    // Parallel lines don't intersect. At least we pretend they don't.
    if (Math.abs(determinant) < EPSILON)
      return null;

    nom = nom / determinant;

    if (nom == 0.0)
      return null;
    if (nom == 1.0)
      return null;

    Point2D p = new Point2D.Double(x1 + nom * rx, y1 + nom * ry);

    return new Intersection(p, p.distance(P1) / P1.distance(P2),
                            p.distance(P3) / P3.distance(P4));
  }

  /**
   * Determines if two points are equal, within an error margin
   * 'snap distance'
   * This is package-private to avoid an accessor method.
   */
  boolean pointEquals(Point2D a, Point2D b)
  {
    return (a.equals(b) || a.distance(b) < PE_EPSILON);
  }

  /**
   * Helper method
   * Turns a shape into a Vector of Segments
   */
  private Vector makeSegment(Shape s)
  {
    Vector paths = new Vector();
    PathIterator pi = s.getPathIterator(null);
    double[] coords = new double[6];
    Segment subpath = null;
    Segment current = null;
    double cx;
    double cy;
    double subpathx;
    double subpathy;
    cx = cy = subpathx = subpathy = 0.0;

    this.windingRule = pi.getWindingRule();

    while (! pi.isDone())
      {
        Segment v;
        switch (pi.currentSegment(coords))
          {
          case PathIterator.SEG_MOVETO:
            if (subpath != null)
              { // close existing open path
                current.next = new LineSegment(cx, cy, subpathx, subpathy);
                current = current.next;
                current.next = subpath;
              }
            subpath = null;
            subpathx = cx = coords[0];
            subpathy = cy = coords[1];
            break;

          // replace 'close' with a line-to.
          case PathIterator.SEG_CLOSE:
            if (subpath != null && (subpathx != cx || subpathy != cy))
              {
                current.next = new LineSegment(cx, cy, subpathx, subpathy);
                current = current.next;
                current.next = subpath;
                cx = subpathx;
                cy = subpathy;
                subpath = null;
              }
            else if (subpath != null)
              {
                current.next = subpath;
                subpath = null;
              }
            break;
          case PathIterator.SEG_LINETO:
            if (cx != coords[0] || cy != coords[1])
              {
                v = new LineSegment(cx, cy, coords[0], coords[1]);
                if (subpath == null)
                  {
                    subpath = current = v;
                    paths.add(subpath);
                  }
                else
                  {
                    current.next = v;
                    current = current.next;
                  }
                cx = coords[0];
                cy = coords[1];
              }
            break;
          case PathIterator.SEG_QUADTO:
            v = new QuadSegment(cx, cy, coords[0], coords[1], coords[2],
                                coords[3]);
            if (subpath == null)
              {
                subpath = current = v;
                paths.add(subpath);
              }
            else
              {
                current.next = v;
                current = current.next;
              }
            cx = coords[2];
            cy = coords[3];
            break;
          case PathIterator.SEG_CUBICTO:
            v = new CubicSegment(cx, cy, coords[0], coords[1], coords[2],
                                 coords[3], coords[4], coords[5]);
            if (subpath == null)
              {
                subpath = current = v;
                paths.add(subpath);
              }
            else
              {
                current.next = v;
                current = current.next;
              }

            // check if the cubic is self-intersecting
            double[] lpts = ((CubicSegment) v).getLoop();
            if (lpts != null)
              {
                // if it is, break off the loop into its own path.
                v.subdivideInsert(lpts[0]);
                v.next.subdivideInsert((lpts[1] - lpts[0]) / (1.0 - lpts[0]));

                CubicSegment loop = (CubicSegment) v.next;
                v.next = loop.next;
                loop.next = loop;

                v.P2 = v.next.P1 = loop.P2 = loop.P1; // snap points
                paths.add(loop);
                current = v.next;
              }

            cx = coords[4];
            cy = coords[5];
            break;
          }
        pi.next();
      }

    if (subpath != null)
      { // close any open path
        if (subpathx != cx || subpathy != cy)
          {
            current.next = new LineSegment(cx, cy, subpathx, subpathy);
            current = current.next;
            current.next = subpath;
          }
        else
          current.next = subpath;
      }

    if (paths.size() == 0)
      return (null);

    return (paths);
  }

  /**
   * Find the intersections of two separate closed paths,
   * A and B, split the segments at the intersection points,
   * and create nodes pointing from one to the other
   */
  private int createNodes(Segment A, Segment B)
  {
    int nNodes = 0;

    Segment a = A;
    Segment b = B;

    do
      {
        do
          {
            nNodes += a.splitIntersections(b);
            b = b.next;
          }
        while (b != B);

        a = a.next; // move to the next segment
      }
    while (a != A); // until one wrap.

    return (nNodes);
  }

  /**
   * Find the intersections of a path with itself.
   * Splits the segments at the intersection points,
   * and create nodes pointing from one to the other.
   */
  private int createNodesSelf(Segment A)
  {
    int nNodes = 0;
    Segment a = A;

    if (A.next == A)
      return 0;

    do
      {
        Segment b = a.next;
        do
          {
            if (b != a) // necessary
              nNodes += a.splitIntersections(b);
            b = b.next;
          }
        while (b != A);
        a = a.next; // move to the next segment
      }
    while (a != A); // until one wrap.

    return (nNodes);
  }

  /**
   * Deletes paths which are redundant from a list, (i.e. solid areas within
   * solid areas) Clears any nodes. Sorts the remaining paths into solids
   * and holes, sets their orientation and sets the solids and holes lists.
   */
  private void deleteRedundantPaths(Vector paths)
  {
    int npaths = paths.size();

    int[][] contains = new int[npaths][npaths];
    int[][] windingNumbers = new int[npaths][2];
    int neg;
    Rectangle2D[] bb = new Rectangle2D[npaths]; // path bounding boxes

    neg = ((windingRule == PathIterator.WIND_NON_ZERO) ? -1 : 1);

    for (int i = 0; i < npaths; i++)
      bb[i] = ((Segment) paths.elementAt(i)).getPathBounds();

    // Find which path contains which, assign winding numbers
    for (int i = 0; i < npaths; i++)
      {
        Segment pathA = (Segment) paths.elementAt(i);
        pathA.nullNodes(); // remove any now-redundant nodes, in case.
        int windingA = pathA.hasClockwiseOrientation() ? 1 : neg;

        for (int j = 0; j < npaths; j++)
          if (i != j)
            {
              Segment pathB = (Segment) paths.elementAt(j);

              // A contains B
              if (bb[i].intersects(bb[j]))
                {
                  Segment s = pathB.next;
                  while (s.P1.getY() == s.P2.getY() && s != pathB)
                    s = s.next;
                  Point2D p = s.getMidPoint();
                  if (pathA.contains(p.getX(), p.getY()))
                    contains[i][j] = windingA;
                }
              else
                // A does not contain B
                contains[i][j] = 0;
            }
          else
            contains[i][j] = windingA; // i == j
      }

    for (int i = 0; i < npaths; i++)
      {
        windingNumbers[i][0] = 0;
        for (int j = 0; j < npaths; j++)
          windingNumbers[i][0] += contains[j][i];
        windingNumbers[i][1] = contains[i][i];
      }

    Vector solids = new Vector();
    Vector holes = new Vector();

    if (windingRule == PathIterator.WIND_NON_ZERO)
      {
        for (int i = 0; i < npaths; i++)
          {
            if (windingNumbers[i][0] == 0)
              holes.add(paths.elementAt(i));
            else if (windingNumbers[i][0] - windingNumbers[i][1] == 0
                     && Math.abs(windingNumbers[i][0]) == 1)
              solids.add(paths.elementAt(i));
          }
      }
    else
      {
        windingRule = PathIterator.WIND_NON_ZERO;
        for (int i = 0; i < npaths; i++)
          {
            if ((windingNumbers[i][0] & 1) == 0)
              holes.add(paths.elementAt(i));
            else if ((windingNumbers[i][0] & 1) == 1)
              solids.add(paths.elementAt(i));
          }
      }

    setDirection(holes, false);
    setDirection(solids, true);
    this.holes = holes;
    this.solids = solids;
  }

  /**
   * Sets the winding direction of a Vector of paths
   * @param clockwise gives the direction,
   * true = clockwise, false = counter-clockwise
   */
  private void setDirection(Vector paths, boolean clockwise)
  {
    Segment v;
    for (int i = 0; i < paths.size(); i++)
      {
        v = (Segment) paths.elementAt(i);
        if (clockwise != v.hasClockwiseOrientation())
          v.reverseAll();
      }
  }

  /**
   * Class representing a linked-list of vertices forming a closed polygon,
   * convex or concave, without holes.
   */
  private abstract class Segment implements Cloneable
  {
    // segment type, PathIterator segment types are used.
    Point2D P1;
    Point2D P2;
    Segment next;
    Segment node;

    Segment()
    {
      P1 = P2 = null;
      node = next = null;
    }

    /**
     * Reverses the direction of a single segment
     */
    abstract void reverseCoords();

    /**
     * Returns the segment's midpoint
     */
    abstract Point2D getMidPoint();

    /**
     * Returns the bounding box of this segment
     */
    abstract Rectangle2D getBounds();

    /**
     * Transforms a single segment
     */
    abstract void transform(AffineTransform at);

    /**
     * Returns the PathIterator type of a segment
     */
    abstract int getType();

    /**
     */
    abstract int splitIntersections(Segment b);

    /**
     * Returns the PathIterator coords of a segment
     */
    abstract int pathIteratorFormat(double[] coords);

    /**
     * Returns the number of intersections on the positive X axis,
     * with the origin at (x,y), used for contains()-testing
     *
     * (Although that could be done by the line-intersect methods,
     * a dedicated method is better to guarantee consitent handling
     * of endpoint-special-cases)
     */
    abstract int rayCrossing(double x, double y);

    /**
     * Subdivides the segment at parametric value t, inserting
     * the new segment into the linked list after this,
     * such that this becomes [0,t] and this.next becomes [t,1]
     */
    abstract void subdivideInsert(double t);

    /**
     * Returns twice the area of a curve, relative the P1-P2 line
     * Used for area calculations.
     */
    abstract double curveArea();

    /**
     * Compare two segments.
     */
    abstract boolean equals(Segment b);

    /**
     * Determines if this path of segments contains the point (x,y)
     */
    boolean contains(double x, double y)
    {
      Segment v = this;
      int crossings = 0;
      do
        {
          int n = v.rayCrossing(x, y);
          crossings += n;
          v = v.next;
        }
      while (v != this);
      return ((crossings & 1) == 1);
    }

    /**
     * Nulls all nodes of the path. Clean up any 'hairs'.
     */
    void nullNodes()
    {
      Segment v = this;
      do
        {
          v.node = null;
          v = v.next;
        }
      while (v != this);
    }

    /**
     * Transforms each segment in the closed path
     */
    void transformSegmentList(AffineTransform at)
    {
      Segment v = this;
      do
        {
          v.transform(at);
          v = v.next;
        }
      while (v != this);
    }

    /**
     * Determines the winding direction of the path
     * By the sign of the area.
     */
    boolean hasClockwiseOrientation()
    {
      return (getSignedArea() > 0.0);
    }

    /**
     * Returns the bounds of this path
     */
    public Rectangle2D getPathBounds()
    {
      double xmin;
      double xmax;
      double ymin;
      double ymax;
      xmin = xmax = P1.getX();
      ymin = ymax = P1.getY();

      Segment v = this;
      do
        {
          Rectangle2D r = v.getBounds();
          xmin = Math.min(r.getMinX(), xmin);
          ymin = Math.min(r.getMinY(), ymin);
          xmax = Math.max(r.getMaxX(), xmax);
          ymax = Math.max(r.getMaxY(), ymax);
          v = v.next;
        }
      while (v != this);

      return (new Rectangle2D.Double(xmin, ymin, (xmax - xmin), (ymax - ymin)));
    }

    /**
     * Calculates twice the signed area of the path;
     */
    double getSignedArea()
    {
      Segment s;
      double area = 0.0;

      s = this;
      do
        {
          area += s.curveArea();

          area += s.P1.getX() * s.next.P1.getY()
          - s.P1.getY() * s.next.P1.getX();
          s = s.next;
        }
      while (s != this);

      return area;
    }

    /**
     * Reverses the orientation of the whole polygon
     */
    void reverseAll()
    {
      reverseCoords();
      Segment v = next;
      Segment former = this;
      while (v != this)
        {
          v.reverseCoords();
          Segment vnext = v.next;
          v.next = former;
          former = v;
          v = vnext;
        }
      next = former;
    }

    /**
     * Inserts a Segment after this one
     */
    void insert(Segment v)
    {
      Segment n = next;
      next = v;
      v.next = n;
    }

    /**
     * Returns if this segment path is polygonal
     */
    boolean isPolygonal()
    {
      Segment v = this;
      do
        {
          if (! (v instanceof LineSegment))
            return false;
          v = v.next;
        }
      while (v != this);
      return true;
    }

    /**
     * Clones this path
     */
    Segment cloneSegmentList() throws CloneNotSupportedException
    {
      Vector list = new Vector();
      Segment v = next;

      while (v != this)
        {
          list.add(v);
          v = v.next;
        }

      Segment clone = (Segment) this.clone();
      v = clone;
      for (int i = 0; i < list.size(); i++)
        {
          clone.next = (Segment) ((Segment) list.elementAt(i)).clone();
          clone = clone.next;
        }
      clone.next = v;
      return v;
    }

    /**
     * Creates a node between this segment and segment b
     * at the given intersection
     * @return the number of nodes created (0 or 1)
     */
    int createNode(Segment b, Intersection i)
    {
      Point2D p = i.p;
      if ((pointEquals(P1, p) || pointEquals(P2, p))
          && (pointEquals(b.P1, p) || pointEquals(b.P2, p)))
        return 0;

      subdivideInsert(i.ta);
      b.subdivideInsert(i.tb);

      // snap points
      b.P2 = b.next.P1 = P2 = next.P1 = i.p;

      node = b.next;
      b.node = next;
      return 1;
    }

    /**
     * Creates multiple nodes from a list of intersections,
     * This must be done in the order of ascending parameters,
     * and the parameters must be recalculated in accordance
     * with each split.
     * @return the number of nodes created
     */
    protected int createNodes(Segment b, Intersection[] x)
    {
      Vector v = new Vector();
      for (int i = 0; i < x.length; i++)
        {
          Point2D p = x[i].p;
          if (! ((pointEquals(P1, p) || pointEquals(P2, p))
              && (pointEquals(b.P1, p) || pointEquals(b.P2, p))))
            v.add(x[i]);
        }

      int nNodes = v.size();
      Intersection[] A = new Intersection[nNodes];
      Intersection[] B = new Intersection[nNodes];
      for (int i = 0; i < nNodes; i++)
        A[i] = B[i] = (Intersection) v.elementAt(i);

      // Create two lists sorted by the parameter
      // Bubble sort, OK I suppose, since the number of intersections
      // cannot be larger than 9 (cubic-cubic worst case) anyway
      for (int i = 0; i < nNodes - 1; i++)
        {
          for (int j = i + 1; j < nNodes; j++)
            {
              if (A[i].ta > A[j].ta)
                {
                  Intersection swap = A[i];
                  A[i] = A[j];
                  A[j] = swap;
                }
              if (B[i].tb > B[j].tb)
                {
                  Intersection swap = B[i];
                  B[i] = B[j];
                  B[j] = swap;
                }
            }
        }
      // subdivide a
      Segment s = this;
      for (int i = 0; i < nNodes; i++)
        {
          s.subdivideInsert(A[i].ta);

          // renormalize the parameters
          for (int j = i + 1; j < nNodes; j++)
            A[j].ta = (A[j].ta - A[i].ta) / (1.0 - A[i].ta);

          A[i].seg = s;
          s = s.next;
        }

      // subdivide b, set nodes
      s = b;
      for (int i = 0; i < nNodes; i++)
        {
          s.subdivideInsert(B[i].tb);

          for (int j = i + 1; j < nNodes; j++)
            B[j].tb = (B[j].tb - B[i].tb) / (1.0 - B[i].tb);

          // set nodes
          B[i].seg.node = s.next; // node a -> b
          s.node = B[i].seg.next; // node b -> a

          // snap points
          B[i].seg.P2 = B[i].seg.next.P1 = s.P2 = s.next.P1 = B[i].p;
          s = s.next;
        }
      return nNodes;
    }

    /**
     * Determines if two paths are equal.
     * Colinear line segments are ignored in the comparison.
     */
    boolean pathEquals(Segment B)
    {
      if (! getPathBounds().equals(B.getPathBounds()))
        return false;

      Segment startA = getTopLeft();
      Segment startB = B.getTopLeft();
      Segment a = startA;
      Segment b = startB;
      do
        {
          if (! a.equals(b))
            return false;

          if (a instanceof LineSegment)
            a = ((LineSegment) a).lastCoLinear();
          if (b instanceof LineSegment)
            b = ((LineSegment) b).lastCoLinear();

          a = a.next;
          b = b.next;
        }
      while (a != startA && b != startB);
      return true;
    }

    /**
     * Return the segment with the top-leftmost first point
     */
    Segment getTopLeft()
    {
      Segment v = this;
      Segment tl = this;
      do
        {
          if (v.P1.getY() < tl.P1.getY())
            tl = v;
          else if (v.P1.getY() == tl.P1.getY())
            {
              if (v.P1.getX() < tl.P1.getX())
                tl = v;
            }
          v = v.next;
        }
      while (v != this);
      return tl;
    }

    /**
     * Returns if the path has a segment outside a shape
     */
    boolean isSegmentOutside(Shape shape)
    {
      return ! shape.contains(getMidPoint());
    }
  } // class Segment

  private class LineSegment extends Segment
  {
    public LineSegment(double x1, double y1, double x2, double y2)
    {
      super();
      P1 = new Point2D.Double(x1, y1);
      P2 = new Point2D.Double(x2, y2);
    }

    public LineSegment(Point2D p1, Point2D p2)
    {
      super();
      P1 = (Point2D) p1.clone();
      P2 = (Point2D) p2.clone();
    }

    /**
     * Clones this segment
     */
    public Object clone()
    {
      return new LineSegment(P1, P2);
    }

    /**
     * Transforms the segment
     */
    void transform(AffineTransform at)
    {
      P1 = at.transform(P1, null);
      P2 = at.transform(P2, null);
    }

    /**
     * Swap start and end points
     */
    void reverseCoords()
    {
      Point2D p = P1;
      P1 = P2;
      P2 = p;
    }

    /**
     * Returns the segment's midpoint
     */
    Point2D getMidPoint()
    {
      return (new Point2D.Double(0.5 * (P1.getX() + P2.getX()),
                                 0.5 * (P1.getY() + P2.getY())));
    }

    /**
     * Returns twice the area of a curve, relative the P1-P2 line
     * Obviously, a line does not enclose any area besides the line
     */
    double curveArea()
    {
      return 0;
    }

    /**
     * Returns the PathIterator type of a segment
     */
    int getType()
    {
      return (PathIterator.SEG_LINETO);
    }

    /**
     * Subdivides the segment at parametric value t, inserting
     * the new segment into the linked list after this,
     * such that this becomes [0,t] and this.next becomes [t,1]
     */
    void subdivideInsert(double t)
    {
      Point2D p = new Point2D.Double((P2.getX() - P1.getX()) * t + P1.getX(),
                                     (P2.getY() - P1.getY()) * t + P1.getY());
      insert(new LineSegment(p, P2));
      P2 = p;
      next.node = node;
      node = null;
    }

    /**
     * Determines if two line segments are strictly colinear
     */
    boolean isCoLinear(LineSegment b)
    {
      double x1 = P1.getX();
      double y1 = P1.getY();
      double x2 = P2.getX();
      double y2 = P2.getY();
      double x3 = b.P1.getX();
      double y3 = b.P1.getY();
      double x4 = b.P2.getX();
      double y4 = b.P2.getY();

      if ((y1 - y3) * (x4 - x3) - (x1 - x3) * (y4 - y3) != 0.0)
        return false;

      return ((x2 - x1) * (y4 - y3) - (y2 - y1) * (x4 - x3) == 0.0);
    }

    /**
     * Return the last segment colinear with this one.
     * Used in comparing paths.
     */
    Segment lastCoLinear()
    {
      Segment prev = this;
      Segment v = next;

      while (v instanceof LineSegment)
        {
          if (isCoLinear((LineSegment) v))
            {
              prev = v;
              v = v.next;
            }
          else
            return prev;
        }
      return prev;
    }

    /**
     * Compare two segments.
     * We must take into account that the lines may be broken into colinear
     * subsegments and ignore them.
     */
    boolean equals(Segment b)
    {
      if (! (b instanceof LineSegment))
        return false;
      Point2D p1 = P1;
      Point2D p3 = b.P1;

      if (! p1.equals(p3))
        return false;

      Point2D p2 = lastCoLinear().P2;
      Point2D p4 = ((LineSegment) b).lastCoLinear().P2;
      return (p2.equals(p4));
    }

    /**
     * Returns a line segment
     */
    int pathIteratorFormat(double[] coords)
    {
      coords[0] = P2.getX();
      coords[1] = P2.getY();
      return (PathIterator.SEG_LINETO);
    }

    /**
     * Returns if the line has intersections.
     */
    boolean hasIntersections(Segment b)
    {
      if (b instanceof LineSegment)
        return (linesIntersect(this, (LineSegment) b) != null);

      if (b instanceof QuadSegment)
        return (lineQuadIntersect(this, (QuadSegment) b) != null);

      if (b instanceof CubicSegment)
        return (lineCubicIntersect(this, (CubicSegment) b) != null);

      return false;
    }

    /**
     * Splits intersections into nodes,
     * This one handles line-line, line-quadratic, line-cubic
     */
    int splitIntersections(Segment b)
    {
      if (b instanceof LineSegment)
        {
          Intersection i = linesIntersect(this, (LineSegment) b);

          if (i == null)
            return 0;

          return createNode(b, i);
        }

      Intersection[] x = null;

      if (b instanceof QuadSegment)
        x = lineQuadIntersect(this, (QuadSegment) b);

      if (b instanceof CubicSegment)
        x = lineCubicIntersect(this, (CubicSegment) b);

      if (x == null)
        return 0;

      if (x.length == 1)
        return createNode(b, (Intersection) x[0]);

      return createNodes(b, x);
    }

    /**
     * Returns the bounding box of this segment
     */
    Rectangle2D getBounds()
    {
      return (new Rectangle2D.Double(Math.min(P1.getX(), P2.getX()),
                                     Math.min(P1.getY(), P2.getY()),
                                     Math.abs(P1.getX() - P2.getX()),
                                     Math.abs(P1.getY() - P2.getY())));
    }

    /**
     * Returns the number of intersections on the positive X axis,
     * with the origin at (x,y), used for contains()-testing
     */
    int rayCrossing(double x, double y)
    {
      double x0 = P1.getX() - x;
      double y0 = P1.getY() - y;
      double x1 = P2.getX() - x;
      double y1 = P2.getY() - y;

      if (y0 * y1 > 0)
        return 0;

      if (x0 < 0 && x1 < 0)
        return 0;

      if (y0 == 0.0)
        y0 -= EPSILON;

      if (y1 == 0.0)
        y1 -= EPSILON;

      if (Line2D.linesIntersect(x0, y0, x1, y1,
                                EPSILON, 0.0, Double.MAX_VALUE, 0.0))
        return 1;
      return 0;
    }
  } // class LineSegment

  /**
   * Quadratic Bezier curve segment
   *
   * Note: Most peers don't support quadratics directly, so it might make
   * sense to represent them as cubics internally and just be done with it.
   * I think we should be peer-agnostic, however, and stay faithful to the
   * input geometry types as far as possible.
   */
  private class QuadSegment extends Segment
  {
    Point2D cp; // control point

    /**
     * Constructor, takes the coordinates of the start, control,
     * and end point, respectively.
     */
    QuadSegment(double x1, double y1, double cx, double cy, double x2,
                double y2)
    {
      super();
      P1 = new Point2D.Double(x1, y1);
      P2 = new Point2D.Double(x2, y2);
      cp = new Point2D.Double(cx, cy);
    }

    /**
     * Clones this segment
     */
    public Object clone()
    {
      return new QuadSegment(P1.getX(), P1.getY(), cp.getX(), cp.getY(),
                             P2.getX(), P2.getY());
    }

    /**
     * Returns twice the area of a curve, relative the P1-P2 line
     *
     * The area formula can be derived by using Green's formula in the
     * plane on the parametric form of the bezier.
     */
    double curveArea()
    {
      double x0 = P1.getX();
      double y0 = P1.getY();
      double x1 = cp.getX();
      double y1 = cp.getY();
      double x2 = P2.getX();
      double y2 = P2.getY();

      double P = (y2 - 2 * y1 + y0);
      double Q = 2 * (y1 - y0);

      double A = (x2 - 2 * x1 + x0);
      double B = 2 * (x1 - x0);

      double area = (B * P - A * Q) / 3.0;
      return (area);
    }

    /**
     * Compare two segments.
     */
    boolean equals(Segment b)
    {
      if (! (b instanceof QuadSegment))
        return false;

      return (P1.equals(b.P1) && cp.equals(((QuadSegment) b).cp)
             && P2.equals(b.P2));
    }

    /**
     * Returns a Point2D corresponding to the parametric value t
     * of the curve
     */
    Point2D evaluatePoint(double t)
    {
      double x0 = P1.getX();
      double y0 = P1.getY();
      double x1 = cp.getX();
      double y1 = cp.getY();
      double x2 = P2.getX();
      double y2 = P2.getY();

      return new Point2D.Double(t * t * (x2 - 2 * x1 + x0) + 2 * t * (x1 - x0)
                                + x0,
                                t * t * (y2 - 2 * y1 + y0) + 2 * t * (y1 - y0)
                                + y0);
    }

    /**
     * Returns the bounding box of this segment
     */
    Rectangle2D getBounds()
    {
      double x0 = P1.getX();
      double y0 = P1.getY();
      double x1 = cp.getX();
      double y1 = cp.getY();
      double x2 = P2.getX();
      double y2 = P2.getY();
      double r0;
      double r1;

      double xmax = Math.max(x0, x2);
      double ymax = Math.max(y0, y2);
      double xmin = Math.min(x0, x2);
      double ymin = Math.min(y0, y2);

      r0 = 2 * (y1 - y0);
      r1 = 2 * (y2 - 2 * y1 + y0);
      if (r1 != 0.0)
        {
          double t = -r0 / r1;
          if (t > 0.0 && t < 1.0)
            {
              double y = evaluatePoint(t).getY();
              ymax = Math.max(y, ymax);
              ymin = Math.min(y, ymin);
            }
        }
      r0 = 2 * (x1 - x0);
      r1 = 2 * (x2 - 2 * x1 + x0);
      if (r1 != 0.0)
        {
          double t = -r0 / r1;
          if (t > 0.0 && t < 1.0)
            {
              double x = evaluatePoint(t).getY();
              xmax = Math.max(x, xmax);
              xmin = Math.min(x, xmin);
            }
        }

      return (new Rectangle2D.Double(xmin, ymin, xmax - xmin, ymax - ymin));
    }

    /**
     * Returns a cubic segment corresponding to this curve
     */
    CubicSegment getCubicSegment()
    {
      double x1 = P1.getX() + 2.0 * (cp.getX() - P1.getX()) / 3.0;
      double y1 = P1.getY() + 2.0 * (cp.getY() - P1.getY()) / 3.0;
      double x2 = cp.getX() + (P2.getX() - cp.getX()) / 3.0;
      double y2 = cp.getY() + (P2.getY() - cp.getY()) / 3.0;

      return new CubicSegment(P1.getX(), P1.getY(), x1, y1, x2, y2, P2.getX(),
                              P2.getY());
    }

    /**
     * Returns the segment's midpoint
     */
    Point2D getMidPoint()
    {
      return evaluatePoint(0.5);
    }

    /**
     * Returns the PathIterator type of a segment
     */
    int getType()
    {
      return (PathIterator.SEG_QUADTO);
    }

    /**
     * Returns the PathIterator coords of a segment
     */
    int pathIteratorFormat(double[] coords)
    {
      coords[0] = cp.getX();
      coords[1] = cp.getY();
      coords[2] = P2.getX();
      coords[3] = P2.getY();
      return (PathIterator.SEG_QUADTO);
    }

    /**
     * Returns the number of intersections on the positive X axis,
     * with the origin at (x,y), used for contains()-testing
     */
    int rayCrossing(double x, double y)
    {
      double x0 = P1.getX() - x;
      double y0 = P1.getY() - y;
      double x1 = cp.getX() - x;
      double y1 = cp.getY() - y;
      double x2 = P2.getX() - x;
      double y2 = P2.getY() - y;
      double[] r = new double[3];
      int nRoots;
      int nCrossings = 0;

      /* check if curve may intersect X+ axis. */
      if ((x0 > 0.0 || x1 > 0.0 || x2 > 0.0) && (y0 * y1 <= 0 || y1 * y2 <= 0))
        {
          if (y0 == 0.0)
            y0 -= EPSILON;
          if (y2 == 0.0)
            y2 -= EPSILON;

          r[0] = y0;
          r[1] = 2 * (y1 - y0);
          r[2] = (y2 - 2 * y1 + y0);

          nRoots = QuadCurve2D.solveQuadratic(r);
          for (int i = 0; i < nRoots; i++)
            if (r[i] > 0.0f && r[i] < 1.0f)
              {
                double t = r[i];
                if (t * t * (x2 - 2 * x1 + x0) + 2 * t * (x1 - x0) + x0 > 0.0)
                  nCrossings++;
              }
        }
      return nCrossings;
    }

    /**
     * Swap start and end points
     */
    void reverseCoords()
    {
      Point2D temp = P1;
      P1 = P2;
      P2 = temp;
    }

    /**
     * Splits intersections into nodes,
     * This one handles quadratic-quadratic only,
     * Quadratic-line is passed on to the LineSegment class,
     * Quadratic-cubic is passed on to the CubicSegment class
     */
    int splitIntersections(Segment b)
    {
      if (b instanceof LineSegment)
        return (b.splitIntersections(this));

      if (b instanceof CubicSegment)
        return (b.splitIntersections(this));

      if (b instanceof QuadSegment)
        {
          // Use the cubic-cubic intersection routine for quads as well,
          // Since a quadratic can be exactly described as a cubic, this
          // should not be a problem;
          // The recursion depth will be the same in any case.
          Intersection[] x = cubicCubicIntersect(getCubicSegment(),
                                                 ((QuadSegment) b)
                                                 .getCubicSegment());
          if (x == null)
            return 0;

          if (x.length == 1)
            return createNode(b, (Intersection) x[0]);

          return createNodes(b, x);
        }
      return 0;
    }

    /**
     * Subdivides the segment at parametric value t, inserting
     * the new segment into the linked list after this,
     * such that this becomes [0,t] and this.next becomes [t,1]
     */
    void subdivideInsert(double t)
    {
      double x0 = P1.getX();
      double y0 = P1.getY();
      double x1 = cp.getX();
      double y1 = cp.getY();
      double x2 = P2.getX();
      double y2 = P2.getY();

      double p10x = x0 + t * (x1 - x0);
      double p10y = y0 + t * (y1 - y0);
      double p11x = x1 + t * (x2 - x1);
      double p11y = y1 + t * (y2 - y1);
      double p20x = p10x + t * (p11x - p10x);
      double p20y = p10y + t * (p11y - p10y);

      insert(new QuadSegment(p20x, p20y, p11x, p11y, x2, y2));
      P2 = next.P1;
      cp.setLocation(p10x, p10y);

      next.node = node;
      node = null;
    }

    /**
     * Transforms the segment
     */
    void transform(AffineTransform at)
    {
      P1 = at.transform(P1, null);
      P2 = at.transform(P2, null);
      cp = at.transform(cp, null);
    }
  } // class QuadSegment

  /**
   * Cubic Bezier curve segment
   */
  private class CubicSegment extends Segment
  {
    Point2D cp1; // control points
    Point2D cp2; // control points

    /**
     * Constructor - takes coordinates of the starting point,
     * first control point, second control point and end point,
     * respecively.
     */
    public CubicSegment(double x1, double y1, double c1x, double c1y,
                        double c2x, double c2y, double x2, double y2)
    {
      super();
      P1 = new Point2D.Double(x1, y1);
      P2 = new Point2D.Double(x2, y2);
      cp1 = new Point2D.Double(c1x, c1y);
      cp2 = new Point2D.Double(c2x, c2y);
    }

    /**
     * Clones this segment
     */
    public Object clone()
    {
      return new CubicSegment(P1.getX(), P1.getY(), cp1.getX(), cp1.getY(),
                              cp2.getX(), cp2.getY(), P2.getX(), P2.getY());
    }

    /**
     * Returns twice the area of a curve, relative the P1-P2 line
     *
     * The area formula can be derived by using Green's formula in the
     * plane on the parametric form of the bezier.
     */
    double curveArea()
    {
      double x0 = P1.getX();
      double y0 = P1.getY();
      double x1 = cp1.getX();
      double y1 = cp1.getY();
      double x2 = cp2.getX();
      double y2 = cp2.getY();
      double x3 = P2.getX();
      double y3 = P2.getY();

      double P = y3 - 3 * y2 + 3 * y1 - y0;
      double Q = 3 * (y2 + y0 - 2 * y1);
      double R = 3 * (y1 - y0);

      double A = x3 - 3 * x2 + 3 * x1 - x0;
      double B = 3 * (x2 + x0 - 2 * x1);
      double C = 3 * (x1 - x0);

      double area = (B * P - A * Q) / 5.0 + (C * P - A * R) / 2.0
                    + (C * Q - B * R) / 3.0;

      return (area);
    }

    /**
     * Compare two segments.
     */
    boolean equals(Segment b)
    {
      if (! (b instanceof CubicSegment))
        return false;

      return (P1.equals(b.P1) && cp1.equals(((CubicSegment) b).cp1)
             && cp2.equals(((CubicSegment) b).cp2) && P2.equals(b.P2));
    }

    /**
     * Returns a Point2D corresponding to the parametric value t
     * of the curve
     */
    Point2D evaluatePoint(double t)
    {
      double x0 = P1.getX();
      double y0 = P1.getY();
      double x1 = cp1.getX();
      double y1 = cp1.getY();
      double x2 = cp2.getX();
      double y2 = cp2.getY();
      double x3 = P2.getX();
      double y3 = P2.getY();

      return new Point2D.Double(-(t * t * t) * (x0 - 3 * x1 + 3 * x2 - x3)
                                + 3 * t * t * (x0 - 2 * x1 + x2)
                                + 3 * t * (x1 - x0) + x0,
                                -(t * t * t) * (y0 - 3 * y1 + 3 * y2 - y3)
                                + 3 * t * t * (y0 - 2 * y1 + y2)
                                + 3 * t * (y1 - y0) + y0);
    }

    /**
     * Returns the bounding box of this segment
     */
    Rectangle2D getBounds()
    {
      double x0 = P1.getX();
      double y0 = P1.getY();
      double x1 = cp1.getX();
      double y1 = cp1.getY();
      double x2 = cp2.getX();
      double y2 = cp2.getY();
      double x3 = P2.getX();
      double y3 = P2.getY();
      double[] r = new double[3];

      double xmax = Math.max(x0, x3);
      double ymax = Math.max(y0, y3);
      double xmin = Math.min(x0, x3);
      double ymin = Math.min(y0, y3);

      r[0] = 3 * (y1 - y0);
      r[1] = 6.0 * (y2 + y0 - 2 * y1);
      r[2] = 3.0 * (y3 - 3 * y2 + 3 * y1 - y0);

      int n = QuadCurve2D.solveQuadratic(r);
      for (int i = 0; i < n; i++)
        {
          double t = r[i];
          if (t > 0 && t < 1.0)
            {
              double y = evaluatePoint(t).getY();
              ymax = Math.max(y, ymax);
              ymin = Math.min(y, ymin);
            }
        }

      r[0] = 3 * (x1 - x0);
      r[1] = 6.0 * (x2 + x0 - 2 * x1);
      r[2] = 3.0 * (x3 - 3 * x2 + 3 * x1 - x0);
      n = QuadCurve2D.solveQuadratic(r);
      for (int i = 0; i < n; i++)
        {
          double t = r[i];
          if (t > 0 && t < 1.0)
            {
              double x = evaluatePoint(t).getX();
              xmax = Math.max(x, xmax);
              xmin = Math.min(x, xmin);
            }
        }
      return (new Rectangle2D.Double(xmin, ymin, (xmax - xmin), (ymax - ymin)));
    }

    /**
     * Returns a CubicCurve2D object corresponding to this segment.
     */
    CubicCurve2D getCubicCurve2D()
    {
      return new CubicCurve2D.Double(P1.getX(), P1.getY(), cp1.getX(),
                                     cp1.getY(), cp2.getX(), cp2.getY(),
                                     P2.getX(), P2.getY());
    }

    /**
     * Returns the parametric points of self-intersection if the cubic
     * is self-intersecting, null otherwise.
     */
    double[] getLoop()
    {
      double x0 = P1.getX();
      double y0 = P1.getY();
      double x1 = cp1.getX();
      double y1 = cp1.getY();
      double x2 = cp2.getX();
      double y2 = cp2.getY();
      double x3 = P2.getX();
      double y3 = P2.getY();
      double[] r = new double[4];
      double k;
      double R;
      double T;
      double A;
      double B;
      double[] results = new double[2];

      R = x3 - 3 * x2 + 3 * x1 - x0;
      T = y3 - 3 * y2 + 3 * y1 - y0;

      // A qudratic
      if (R == 0.0 && T == 0.0)
        return null;

      // true cubic
      if (R != 0.0 && T != 0.0)
        {
          A = 3 * (x2 + x0 - 2 * x1) / R;
          B = 3 * (x1 - x0) / R;

          double P = 3 * (y2 + y0 - 2 * y1) / T;
          double Q = 3 * (y1 - y0) / T;

          if (A == P || Q == B)
            return null;

          k = (Q - B) / (A - P);
        }
      else
        {
          if (R == 0.0)
            {
              // quadratic in x
              k = -(3 * (x1 - x0)) / (3 * (x2 + x0 - 2 * x1));
              A = 3 * (y2 + y0 - 2 * y1) / T;
              B = 3 * (y1 - y0) / T;
            }
          else
            {
              // quadratic in y
              k = -(3 * (y1 - y0)) / (3 * (y2 + y0 - 2 * y1));
              A = 3 * (x2 + x0 - 2 * x1) / R;
              B = 3 * (x1 - x0) / R;
            }
        }

      r[0] = -k * k * k - A * k * k - B * k;
      r[1] = 3 * k * k + 2 * k * A + 2 * B;
      r[2] = -3 * k;
      r[3] = 2;

      int n = CubicCurve2D.solveCubic(r);
      if (n != 3)
        return null;

      // sort r
      double t;
      for (int i = 0; i < 2; i++)
        for (int j = i + 1; j < 3; j++)
          if (r[j] < r[i])
            {
              t = r[i];
              r[i] = r[j];
              r[j] = t;
            }

      if (Math.abs(r[0] + r[2] - k) < 1E-13)
        if (r[0] >= 0.0 && r[0] <= 1.0 && r[2] >= 0.0 && r[2] <= 1.0)
          if (evaluatePoint(r[0]).distance(evaluatePoint(r[2])) < PE_EPSILON * 10)
            { // we snap the points anyway
              results[0] = r[0];
              results[1] = r[2];
              return (results);
            }
      return null;
    }

    /**
     * Returns the segment's midpoint
     */
    Point2D getMidPoint()
    {
      return evaluatePoint(0.5);
    }

    /**
     * Returns the PathIterator type of a segment
     */
    int getType()
    {
      return (PathIterator.SEG_CUBICTO);
    }

    /**
     * Returns the PathIterator coords of a segment
     */
    int pathIteratorFormat(double[] coords)
    {
      coords[0] = cp1.getX();
      coords[1] = cp1.getY();
      coords[2] = cp2.getX();
      coords[3] = cp2.getY();
      coords[4] = P2.getX();
      coords[5] = P2.getY();
      return (PathIterator.SEG_CUBICTO);
    }

    /**
     * Returns the number of intersections on the positive X axis,
     * with the origin at (x,y), used for contains()-testing
     */
    int rayCrossing(double x, double y)
    {
      double x0 = P1.getX() - x;
      double y0 = P1.getY() - y;
      double x1 = cp1.getX() - x;
      double y1 = cp1.getY() - y;
      double x2 = cp2.getX() - x;
      double y2 = cp2.getY() - y;
      double x3 = P2.getX() - x;
      double y3 = P2.getY() - y;
      double[] r = new double[4];
      int nRoots;
      int nCrossings = 0;

      /* check if curve may intersect X+ axis. */
      if ((x0 > 0.0 || x1 > 0.0 || x2 > 0.0 || x3 > 0.0)
          && (y0 * y1 <= 0 || y1 * y2 <= 0 || y2 * y3 <= 0))
        {
          if (y0 == 0.0)
            y0 -= EPSILON;
          if (y3 == 0.0)
            y3 -= EPSILON;

          r[0] = y0;
          r[1] = 3 * (y1 - y0);
          r[2] = 3 * (y2 + y0 - 2 * y1);
          r[3] = y3 - 3 * y2 + 3 * y1 - y0;

          if ((nRoots = CubicCurve2D.solveCubic(r)) > 0)
            for (int i = 0; i < nRoots; i++)
              {
                if (r[i] > 0.0 && r[i] < 1.0)
                  {
                    double t = r[i];
                    if (-(t * t * t) * (x0 - 3 * x1 + 3 * x2 - x3)
                        + 3 * t * t * (x0 - 2 * x1 + x2) + 3 * t * (x1 - x0)
                        + x0 > 0.0)
                      nCrossings++;
                  }
              }
        }
      return nCrossings;
    }

    /**
     * Swap start and end points
     */
    void reverseCoords()
    {
      Point2D p = P1;
      P1 = P2;
      P2 = p;
      p = cp1; // swap control points
      cp1 = cp2;
      cp2 = p;
    }

    /**
     * Splits intersections into nodes,
     * This one handles cubic-cubic and cubic-quadratic intersections
     */
    int splitIntersections(Segment b)
    {
      if (b instanceof LineSegment)
        return (b.splitIntersections(this));

      Intersection[] x = null;

      if (b instanceof QuadSegment)
        x = cubicCubicIntersect(this, ((QuadSegment) b).getCubicSegment());

      if (b instanceof CubicSegment)
        x = cubicCubicIntersect(this, (CubicSegment) b);

      if (x == null)
        return 0;

      if (x.length == 1)
        return createNode(b, x[0]);

      return createNodes(b, x);
    }

    /**
     * Subdivides the segment at parametric value t, inserting
     * the new segment into the linked list after this,
     * such that this becomes [0,t] and this.next becomes [t,1]
     */
    void subdivideInsert(double t)
    {
      CubicSegment s = (CubicSegment) clone();
      double p1x = (s.cp1.getX() - s.P1.getX()) * t + s.P1.getX();
      double p1y = (s.cp1.getY() - s.P1.getY()) * t + s.P1.getY();

      double px = (s.cp2.getX() - s.cp1.getX()) * t + s.cp1.getX();
      double py = (s.cp2.getY() - s.cp1.getY()) * t + s.cp1.getY();

      s.cp2.setLocation((s.P2.getX() - s.cp2.getX()) * t + s.cp2.getX(),
                        (s.P2.getY() - s.cp2.getY()) * t + s.cp2.getY());

      s.cp1.setLocation((s.cp2.getX() - px) * t + px,
                        (s.cp2.getY() - py) * t + py);

      double p2x = (px - p1x) * t + p1x;
      double p2y = (py - p1y) * t + p1y;

      double p3x = (s.cp1.getX() - p2x) * t + p2x;
      double p3y = (s.cp1.getY() - p2y) * t + p2y;
      s.P1.setLocation(p3x, p3y);

      // insert new curve
      insert(s);

      // set this curve
      cp1.setLocation(p1x, p1y);
      cp2.setLocation(p2x, p2y);
      P2 = s.P1;
      next.node = node;
      node = null;
    }

    /**
     * Transforms the segment
     */
    void transform(AffineTransform at)
    {
      P1 = at.transform(P1, null);
      P2 = at.transform(P2, null);
      cp1 = at.transform(cp1, null);
      cp2 = at.transform(cp2, null);
    }
  } // class CubicSegment
} // class Area
