001package icy.math;
002
003import java.awt.geom.Line2D;
004import java.awt.geom.Point2D;
005import java.util.Iterator;
006
007/**
008 * Line2D iterator (iterate over Line2D points given a wanted step).
009 * 
010 * @author Stephane Dallongeville
011 */
012public class Line2DIterator implements Iterator<Point2D>
013{
014    final static protected double DEFAULT_STEP = 1d;
015
016    protected boolean done;
017    protected int count;
018    final protected boolean forceLast;
019
020    final protected Point2D pos;
021    final protected Point2D last;
022
023    protected double sx, sy;
024
025    /**
026     * Create the Line2D Iterator.
027     * 
028     * @param line
029     *        the lien we want to iterate points
030     * @param step
031     *        step between each point (default = 1d)
032     * @param forceLastPoint
033     *        set to <i>true</i> if you want the last point to match the end line position
034     */
035    public Line2DIterator(Line2D line, double step, boolean forceLastPoint)
036    {
037        super();
038
039        pos = line.getP1();
040        last = line.getP2();
041        done = false;
042        forceLast = forceLastPoint;
043
044        final double dx = line.getX2() - line.getX1();
045        final double dy = line.getY2() - line.getY1();
046        final double adx = Math.abs(dx);
047        final double ady = Math.abs(dy);
048
049        final double adjStep = (step <= 0d) ? 1d : step;
050
051        // step on X axis
052        if (adx > ady)
053        {
054            count = (int) (adx / adjStep);
055            sx = adjStep;
056            sy = (ady / adx) * adjStep;
057        }
058        // step on Y axis
059        else
060        {
061            if (ady == 0d)
062            {
063                count = 0;
064                sx = 0;
065            }
066            else
067            {
068                count = (int) (ady / adjStep);
069                sx = (adx / ady) * adjStep;
070            }
071            sy = adjStep;
072        }
073        // for initial position
074        count++;
075
076        // reverse step if needed
077        if (dx < 0)
078            sx = -sx;
079        if (dy < 0)
080            sy = -sy;
081    }
082
083    /**
084     * Create the Line2D Iterator.
085     * 
086     * @param line
087     *        the lien we want to iterate points
088     * @param step
089     *        step between each point (default = 1d)
090     */
091    public Line2DIterator(Line2D line, double step)
092    {
093        this(line, step, true);
094    }
095
096    /**
097     * Create the Line2D Iterator.
098     * 
099     * @param line
100     *        the lien we want to iterate points
101     */
102    public Line2DIterator(Line2D line)
103    {
104        this(line, DEFAULT_STEP, true);
105    }
106
107    @Override
108    public boolean hasNext()
109    {
110        return !done;
111    }
112
113    @Override
114    public Point2D next()
115    {
116        final Point2D result = (Point2D) pos.clone();
117
118        // done ?
119        if (--count <= 0)
120        {
121            if (forceLast)
122            {
123                // consider done only if pos is equal to last
124                done = pos.equals(last);
125                // force equality with last position
126                pos.setLocation(last);
127            }
128            else
129                done = true;
130        }
131        else
132            pos.setLocation(pos.getX() + sx, pos.getY() + sy);
133
134        return result;
135    }
136
137    @Override
138    public void remove()
139    {
140        throw new UnsupportedOperationException();
141    }
142}