import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.ImageObserver;
import java.awt.Rectangle;

/*
 * This class implements a TurtleGraphics Line graphics operation.
 * A line of a specified width is drawn between two TurtleSpace
 * points.
 * 

* @author Guy Haas */ class TGLineOp implements ImageObserver, TGGraphicsOp { private Color color; private int width; int[] xPoints; int[] yPoints; private TGPoint p1, p2; // // constructor // public TGLineOp( TGPoint point1, TGPoint point2, Color color, int width ) { this.p1 = point1; this.p2 = point2; this.color = color; this.width = width; } // // ImageObserver interface methods // public boolean imageUpdate(Image img, int flags, int x, int y, int wd, int ht) { System.out.println( "TGLineOp.imageUpdate: got here!" ); return true; } private Rectangle drawHorizontalFatLine( Graphics g, int canvasHeight, int canvasWidth ) { float hafWid = ((float) width) / 2.0F; xPoints[0] = xPoints[3] = p1.canvasX( canvasWidth ); xPoints[1] = xPoints[2] = p2.canvasX( canvasWidth ); yPoints[0] = p1.canvasY( hafWid, canvasHeight ); yPoints[1] = p2.canvasY( hafWid, canvasHeight ); yPoints[2] = p2.canvasY( -hafWid, canvasHeight ); yPoints[3] = p1.canvasY( -hafWid, canvasHeight ); int crX = min( xPoints ); int crWidth = Math.abs( crX - max(xPoints) ) + 1; int crY = min( yPoints ); int crHeight = Math.abs( crY - max(yPoints) ) + 1; g.setClip( crX, crY, crWidth, crHeight ); g.fillPolygon( xPoints, yPoints, 4 ); //System.out.print( "drawHorizontalFatLine: xPoints=" ); //System.out.println( xPoints[0]+","+xPoints[1]+","+xPoints[2]+","+xPoints[3] ); //System.out.print( " yPoints=" ); //System.out.println( yPoints[0]+","+yPoints[1]+","+yPoints[2]+","+yPoints[3] ); Rectangle clipRect = new Rectangle( crX, crY, crWidth, crHeight ); return clipRect; } // end drawHorizontalFatLine() private Rectangle drawFatLine( Graphics g, int canvasHeight, int canvasWidth ) { //System.out.println( "drawFatLine: p1="+ p1 +", p2="+ p2 ); if ( xPoints == null ) { xPoints = new int[4]; yPoints = new int[4]; } double deltaX = p2.xFloatValue() - p1.xFloatValue(); if ( Math.abs(deltaX) < .5/canvasWidth ) return drawVerticalFatLine( g, canvasHeight, canvasWidth ); double deltaY = p2.yFloatValue() - p1.yFloatValue(); if ( Math.abs(deltaY) < .5/canvasHeight ) return drawHorizontalFatLine( g, canvasHeight, canvasWidth ); double slope = deltaY / deltaX; double radians = Math.atan( slope ); // add 90 degrees to get end points of one parallel line double hafWid = ((double) width) / 2.0; double heading = radians + (Math.PI / 2.0); if ( heading > 2.0 * Math.PI ) heading -= 2.0 * Math.PI; TGPoint point = p1.otherEndPoint( heading, hafWid ); xPoints[0] = point.canvasX( canvasWidth ); yPoints[0] = point.canvasY( canvasHeight ); point = p2.otherEndPoint( heading, hafWid ); xPoints[1] = point.canvasX( canvasWidth ); yPoints[1] = point.canvasY( canvasHeight ); // subtract 90 degrees to get end points of other parallel line heading = radians - (Math.PI / 2.0); if ( heading < 0.0 ) heading += 2.0 * Math.PI; point = p2.otherEndPoint( heading, hafWid ); xPoints[2] = point.canvasX( canvasWidth ); yPoints[2] = point.canvasY( canvasHeight ); point = p1.otherEndPoint( heading, hafWid ); xPoints[3] = point.canvasX( canvasWidth ); yPoints[3] = point.canvasY( canvasHeight ); int crX = min( xPoints ); int crWidth = Math.abs( crX - max(xPoints) ) + 1; int crY = min( yPoints ); int crHeight = Math.abs( crY - max(yPoints) ) + 1; g.setClip( crX, crY, crWidth, crHeight ); g.fillPolygon( xPoints, yPoints, 4 ); //System.out.println(" xC="+xCenter+", yC="+yCenter); //System.out.println(" x0="+xPoints[0]+", y0="+yPoints[0]); //System.out.println(" x1="+xPoints[1]+", y1="+yPoints[1]); //System.out.println(" x2="+xPoints[2]+", y2="+yPoints[2]); //System.out.println(" x3="+xPoints[3]+", y3="+yPoints[3]); Rectangle clipRect = new Rectangle( crX, crY, crWidth, crHeight ); return clipRect; } // end drawFatLine() private Rectangle drawVerticalFatLine( Graphics g, int canvasHeight, int canvasWidth ) { float hafWid = ((float) width) / 2.0F; yPoints[0] = yPoints[3] = p1.canvasY( canvasHeight ); yPoints[1] = yPoints[2] = p2.canvasY( canvasHeight ); xPoints[0] = p1.canvasX( -hafWid, canvasWidth ); xPoints[1] = p2.canvasX( -hafWid, canvasWidth ); xPoints[2] = p2.canvasX( hafWid, canvasWidth ); xPoints[3] = p1.canvasX( hafWid, canvasWidth ); int crX = min( xPoints ); int crWidth = Math.abs( crX - max(xPoints) ) + 1; int crY = min( yPoints ); int crHeight = Math.abs( crY - max(yPoints) ) + 1; g.setClip( crX, crY, crWidth, crHeight ); g.fillPolygon( xPoints, yPoints, 4 ); //System.out.print( "drawVerticalFatLine: xPoints=" ); //System.out.println( xPoints[0]+","+xPoints[1]+","+xPoints[2]+","+xPoints[3] ); //System.out.print( " yPoints=" ); //System.out.println( yPoints[0]+","+yPoints[1]+","+yPoints[2]+","+yPoints[3] ); Rectangle clipRect = new Rectangle( crX, crY, crWidth, crHeight ); return clipRect; } // end drawVerticalFatLine() private int max( int[] ary ) { int num = ary[0]; for ( int i=1; i < ary.length; i++ ) if ( ary[i] > num ) num = ary[i]; return num; } // end max() private int min( int[] ary ) { int num = ary[0]; for ( int i=1; i < ary.length; i++ ) if ( ary[i] < num ) num = ary[i]; return num; } // end min() public Rectangle doIt( Image inMemoryImage ) { int crX, crY, crHeight, crWidth; Rectangle clipRect; int canvasWidth = inMemoryImage.getWidth( this ); if ( canvasWidth < 0 ) return null; int canvasHeight = inMemoryImage.getHeight( this ); if ( canvasHeight < 0 ) return null; Graphics g = inMemoryImage.getGraphics(); g.setColor(color); if ( width == 1 ) { int p1X = p1.canvasX( canvasWidth ); int p1Y = p1.canvasY( canvasHeight ); int p2X = p2.canvasX( canvasWidth ); int p2Y = p2.canvasY( canvasHeight ); crX = p1X < p2X ? p1X : p2X; crWidth = Math.abs( p1X - p2X ) + 1; crY = p1Y < p2Y ? p1Y : p2Y; crHeight = Math.abs( p1Y - p2Y ) + 1; g.setClip( crX, crY, crWidth, crHeight ); g.drawLine( p1X, p1Y, p2X, p2Y ); clipRect = new Rectangle( crX, crY, crWidth, crHeight ); } else clipRect = drawFatLine( g, canvasHeight, canvasWidth ); g.dispose(); return clipRect;; } // end doIt() public Color getColor() { return color; } public String toString() { return "TGLineOp[width="+width+",p1="+p1+",p2="+p2+"]"; } } // end class TGLineOp