package ika.geo;
/**
* An iterator that provides access to the points and the drawing
* instructions of a GeoPathModel.
*/
public class GeoPathIterator {
/**
* The path to iterate over. Initialized by the constructor.
*/
private final GeoPathModel path;
/**
* The current drawing instruction. A call to next() moves this index
* to the next instruction.
*/
private int instructionID = 0;
/**
* The current point. A call to next() moves this index to the next
* point for the current drawing instruction.
*/
private int pointID = 0;
/**
* Construct a new iterator.
* @param path The GeoPathModel which will be iterated.
*/
protected GeoPathIterator(GeoPathModel path) {
this.path = path;
}
/**
* Move to the next drawing instruction.
* @return True if there exists a next drawing instruction, false
* otherwise.
*/
public boolean next() {
if (instructionID + 1 >= path.instructions.length) {
return false;
}
switch (path.instructions[instructionID]) {
case GeoPathModel.CLOSE:
break;
case GeoPathModel.MOVETO:
case GeoPathModel.LINETO:
pointID += 2;
break;
case GeoPathModel.QUADCURVETO:
pointID += 4;
break;
case GeoPathModel.CURVETO:
pointID += 6;
break;
}
++instructionID;
return true;
}
/**
* Returns the current drawing instruction.
* @return The current drawing instruction.
*/
public byte getInstruction() {
if (path.instructions.length == 0) {
return GeoPathModel.NONE;
}
return path.instructions[instructionID];
}
/**
* Returns whether the current instruction is the first instruction.
* @return True if a call to getInstruction() will return the first instruction.
*/
public boolean atFirstInstruction() {
return instructionID == 0;
}
/**
* Returns the horizontal x coordinate for the current drawing
* instruction. An exception will be thrown if the current instruction
* is a close instruction or if there are no drawing instructions.
* @return The x coordinate for the current drawing instruction.
*/
public double getX() {
final int instruction = path.instructions[instructionID];
if (instruction == GeoPathModel.CLOSE) {
throw new IllegalStateException();
}
return path.points[pointID];
}
/**
* Returns the vertical y coordinate for the current drawing
* instruction. An exception will be thrown if the current instruction
* is a close instruction or if there are no drawing instructions.
* @return The y coordinate for the current drawing instruction.
*/
public double getY() {
final int instruction = path.instructions[instructionID];
if (instruction == GeoPathModel.CLOSE) {
throw new IllegalStateException();
}
return path.points[pointID + 1];
}
/**
* Returns the horizontal x coordinate of the second control point of
* a cubic bezier curve or the final point of a quadratic bezier curve.
* An exception will be thrown if the current instruction is not a cubic
* or quadratic bezier curve.
* @return The x coordinate of the first control point.
*/
public double getX2() {
final int instruction = path.instructions[instructionID];
if (instruction == GeoPathModel.CURVETO || instruction == GeoPathModel.QUADCURVETO) {
return path.points[pointID + 2];
} else {
throw new IllegalStateException();
}
}
/**
* Returns the vertical y coordinate of the second control point of
* a cubic bezier curve or the final point of a quadratic bezier curve.
* An exception will be thrown if the current instruction is not a cubic
* or quadratic bezier curve.
* @return The y coordinate of the first control point.
*/
public double getY2() {
final int instruction = path.instructions[instructionID];
if (instruction == GeoPathModel.CURVETO || instruction == GeoPathModel.QUADCURVETO) {
return path.points[pointID + 3];
} else {
throw new IllegalStateException();
}
}
/**
* Returns the horizontal x coordinate of the final point of
* a cubic bezier curve. An exception will be thrown if the current
* instruction is not a cubic bezier curve.
* @return The x coordinate of the second control point.
*/
public double getX3() {
final int instruction = path.instructions[instructionID];
if (instruction == GeoPathModel.CURVETO) {
return path.points[pointID + 4];
} else {
throw new IllegalStateException();
}
}
/**
* Returns the vertical y coordinate of the final control point of
* a cubic bezier curve. An exception will be thrown if the current
* instruction is not a cubic bezier curve.
* @return The y coordinate of the second control point.
*/
public double getY3() {
final int instruction = path.instructions[instructionID];
if (instruction == GeoPathModel.CURVETO) {
return path.points[pointID + 5];
} else {
throw new IllegalStateException();
}
}
}