PolyLinepublic class PolyLine extends Object implements Shape, Cloneable, ExternalizableThis Shape implementation represents a series of connected line segments.
It is like a Polygon, but is not closed. This class is used by the
ScribblePane class of the GUI chapter. It implements the Cloneable and
Externalizable interfaces so it can be used in the Drag-and-Drop examples
in the Data Transfer chapter. |
Fields Summary |
---|
float | x0 | float | y0 | float[] | coords | int | numsegs | float | xmin | float | xmax | float | ymin | float | ymax |
Constructors Summary |
---|
public PolyLine()
// No arg constructor assumes an origin of (0,0)
// A no-arg constructor is required for the Externalizable interface
this(0f, 0f);
| public PolyLine(float x0, float y0)
setOrigin(x0,y0); // Record the starting point.
numsegs = 0; // Note that we have no line segments, so far
|
Methods Summary |
---|
public void | addSegment(float x, float y)Add a line segment to the PolyLine. Note that x and y are absolute
coordinates, even though the implementation stores them relative to
x0, y0;
// Allocate or reallocate the coords[] array when necessary
if (coords == null) coords = new float[32];
if (numsegs*2 >= coords.length) {
float[] newcoords = new float[coords.length * 2];
System.arraycopy(coords, 0, newcoords, 0, coords.length);
coords = newcoords;
}
// Convert from absolute to relative coordinates
x = x - x0;
y = y - y0;
// Store the data
coords[numsegs*2] = x;
coords[numsegs*2+1] = y;
numsegs++;
// Enlarge the bounding box, if necessary
if (x > xmax) xmax = x;
else if (x < xmin) xmin = x;
if (y > ymax) ymax = y;
else if (y < ymin) ymin = y;
| public java.lang.Object | clone()Override the Object.clone() method so that the array gets cloned, too.
try {
PolyLine copy = (PolyLine) super.clone();
if (coords != null) copy.coords = (float[]) this.coords.clone();
return copy;
}
catch(CloneNotSupportedException e) {
throw new AssertionError(); // This should never happen
}
| public boolean | contains(double x, double y) return false;
| public boolean | contains(double x, double y, double w, double h)
return false;
| public boolean | contains(java.awt.geom.Point2D p) return false;
| public boolean | contains(java.awt.geom.Rectangle2D r) return false;
| public java.awt.Rectangle | getBounds()
return new Rectangle((int)(x0 + xmin - 0.5f), // x0
(int)(y0 + ymin - 0.5f), // y0
(int)(xmax - xmin + 0.5f), // width
(int)(ymax - ymin + 0.5f)); // height
| public java.awt.geom.Rectangle2D | getBounds2D()
return new Rectangle2D.Float(x0 + xmin, y0 + ymin,
xmax-xmin, ymax-ymin);
| public java.awt.geom.PathIterator | getPathIterator(java.awt.geom.AffineTransform transform)
return new PathIterator() {
int curseg = -1; // current segment
// Copy the current segment for thread-safety, so we don't
// mess up of a segment is added while we're iterating
int numsegs = PolyLine.this.numsegs;
public boolean isDone() { return curseg >= numsegs; }
public void next() { curseg++; }
// Get coordinates and type of current segment as floats
public int currentSegment(float[] data) {
int segtype;
if (curseg == -1) { // First time we're called
data[0] = x0; // Data is the origin point
data[1] = y0;
segtype = SEG_MOVETO; // Returned as a moveto segment
}
else { // Otherwise, the data is a segment endpoint
data[0] = x0 + coords[curseg*2];
data[1] = y0 + coords[curseg*2 + 1];
segtype = SEG_LINETO; // Returned as a lineto segment
}
// If a tranform was specified, transform point in place
if (transform != null)
transform.transform(data, 0, data, 0, 1);
return segtype;
}
// Same as last method, but use doubles
public int currentSegment(double[] data) {
int segtype;
if (curseg == -1) {
data[0] = x0;
data[1] = y0;
segtype = SEG_MOVETO;
}
else {
data[0] = x0 + coords[curseg*2];
data[1] = y0 + coords[curseg*2 + 1];
segtype = SEG_LINETO;
}
if (transform != null)
transform.transform(data, 0, data, 0, 1);
return segtype;
}
// This only matters for closed shapes
public int getWindingRule() { return WIND_NON_ZERO; }
};
| public java.awt.geom.PathIterator | getPathIterator(java.awt.geom.AffineTransform at, double flatness)
return getPathIterator(at);
| public boolean | intersects(java.awt.geom.Rectangle2D r)
if (numsegs < 1) return false;
float lastx = x0, lasty = y0;
for(int i = 0; i < numsegs; i++) { // loop through the segments
float x = coords[i*2] + x0;
float y = coords[i*2+1] + y0;
// See if this line segment intersects the rectangle
if (r.intersectsLine(x, y, lastx, lasty)) return true;
// Otherwise move on to the next segment
lastx = x;
lasty = y;
}
return false; // No line segment intersected the rectangle
| public boolean | intersects(double x, double y, double w, double h)
return intersects(new Rectangle2D.Double(x,y,w,h));
| public void | readExternal(java.io.ObjectInput in)
this.x0 = in.readFloat();
this.y0 = in.readFloat();
this.numsegs = in.readInt();
this.coords = new float[numsegs*2];
for(int i=0; i < numsegs*2; i++) coords[i] = in.readFloat();
| public void | setOrigin(float x0, float y0)Set the origin of the PolyLine. Useful when moving it
this.x0 = x0;
this.y0 = y0;
| public void | translate(float dx, float dy)Add dx and dy to the origin
this.x0 += dx;
this.y0 += dy;
| public void | writeExternal(java.io.ObjectOutput out)The following two methods implement the Externalizable interface.
We use Externalizable instead of Seralizable so we have full control
over the data format, and only write out the defined coordinates
out.writeFloat(x0);
out.writeFloat(y0);
out.writeInt(numsegs);
for(int i=0; i < numsegs*2; i++) out.writeFloat(coords[i]);
|
|