FileDocCategorySizeDatePackage
PolyLine.javaAPI DocExample8719Sat Jan 24 10:44:36 GMT 2004je3.graphics

PolyLine

public class PolyLine extends Object implements Shape, Cloneable, Externalizable
This 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 voidaddSegment(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.Objectclone()
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 booleancontains(double x, double y)

 return false; 
public booleancontains(double x, double y, double w, double h)

	return false;
    
public booleancontains(java.awt.geom.Point2D p)

 return false; 
public booleancontains(java.awt.geom.Rectangle2D r)

 return false; 
public java.awt.RectanglegetBounds()

	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.Rectangle2DgetBounds2D()

	return new Rectangle2D.Float(x0 + xmin, y0 + ymin, 
				     xmax-xmin, ymax-ymin);
    
public java.awt.geom.PathIteratorgetPathIterator(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.PathIteratorgetPathIterator(java.awt.geom.AffineTransform at, double flatness)

	return getPathIterator(at);
    
public booleanintersects(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 booleanintersects(double x, double y, double w, double h)

	return intersects(new Rectangle2D.Double(x,y,w,h));
    
public voidreadExternal(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 voidsetOrigin(float x0, float y0)
Set the origin of the PolyLine. Useful when moving it

	this.x0 = x0; 
	this.y0 = y0;
    
public voidtranslate(float dx, float dy)
Add dx and dy to the origin

	this.x0 += dx;
	this.y0 += dy;
    
public voidwriteExternal(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]);