import java.awt.*; /** * Title: Bresenham's line algorithm * Description: Implements Bresenham's line drawing algorithm * using code described in Chapter 1 * Copyright: Copyright (c) 2000 * Company: * @author Glenn Rowe * @version 1.0 */ public class LineCanvas extends Canvas { static int START_POINT = 0; static int END_POINT = 1; Point m_startPoint = null, m_endPoint = null, m_tempEnd = null; int m_x0, m_y0, m_x1, m_y1; int m_slopeSign; boolean m_slopeLT1; int m_param; int m_twoDeltaY, m_twoDYDX, m_twoDeltaX, m_twoDXDY; /** * Constructs the canvas */ public LineCanvas() { setBackground(Color.white); } /** * Called by mouse event handlers to define the * endpoints of the line */ public void setPoint(int type, Point point) { if (type == LineCanvas.START_POINT) { m_startPoint = point; m_tempEnd = point; m_endPoint = point; repaint(); } else if (type == LineCanvas.END_POINT) { m_endPoint = point; } } /** * Draws a single pixel */ void drawPixel(Graphics g, int x, int y) { g.drawLine(x,y,x,y); } /** * Sorts out endpoints so that m_x0 is smallest x value if * the slope is less than 1; otherwise ensures that m_y0 is * the smallest y value */ boolean selectEndPoints(Point point0, Point point1) { m_x0 = point0.x; m_y0 = point0.y; m_x1 = point1.x; m_y1 = point1.y; // Find slope of line int deltaY = m_y1 - m_y0, deltaX = m_x1 - m_x0; // Check sign of slope m_slopeSign = 1; // Check if slope < 1 m_slopeLT1 = true; if (Math.abs(deltaY) > Math.abs(deltaX)) { m_slopeLT1 = false; } if (m_slopeLT1) { // Ensure m_x0 is smallest x value if slope < 1 if (m_x1 < m_x0) { int temp = m_x0; m_x0 = m_x1; m_x1 = temp; temp = m_y0; m_y0 = m_y1; m_y1 = temp; deltaX = -deltaX; deltaY = -deltaY; } if (deltaY < 0) { m_slopeSign = -1; deltaY = -deltaY; } m_twoDeltaY = 2 * deltaY; m_twoDYDX = 2 * (deltaY - deltaX); m_param = m_twoDeltaY - deltaX; } else { // Ensure m_y0 is smallest y value if slope >= 1 if (m_y1 < m_y0) { int temp = m_x0; m_x0 = m_x1; m_x1 = temp; temp = m_y0; m_y0 = m_y1; m_y1 = temp; deltaX = -deltaX; deltaY = -deltaY; } if (deltaX < 0) { m_slopeSign = -1; deltaX = -deltaX; } m_twoDeltaX = 2 * deltaX; m_twoDXDY = 2 * (deltaX - deltaY); m_param = m_twoDeltaX - deltaY; } return m_slopeLT1; } /** * Implements Bresenham's algorithm to draw a line * from startRef to endRef */ void drawBresenhamLine(Graphics g, Point startRef, Point endRef) { Graphics2D gg = (Graphics2D)g; Point start = new Point(startRef); Point end = new Point(endRef); m_slopeLT1 = selectEndPoints(start, end); int x, y; // Implements algorithm in Chapter 1 for slope < 1 if (m_slopeLT1) { x = m_x0 + 1; y = m_y0; while (x < m_x1) { if (m_param < 0) { m_param += m_twoDeltaY; } else { m_param += m_twoDYDX; y += m_slopeSign; } drawPixel(g, x, y); x++; } // Implements algorithm for slope >= 1 } else { x = m_x0; y = m_y0 + 1; while (y < m_y1) { if (m_param < 0) { m_param += m_twoDeltaX; } else { m_param += m_twoDXDY; x += m_slopeSign; } drawPixel(g, x, y); y++; } } } /** * Draws a dashed red "rubber band" connecting the start point * of the line with the current mouse position as mouse is dragged */ public void rubberBand(Point endPoint) { Graphics2D g = (Graphics2D)getGraphics(); // Specify a dashed line pattern for rubber band/box float[] dashPattern = {10.0f, 10.0f}; g.setStroke(new BasicStroke(1, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER, 10.0f, dashPattern, 0.0f)); // Erase the old rubber band g.setColor(getBackground()); g.drawLine(m_startPoint.x, m_startPoint.y, m_tempEnd.x, m_tempEnd.y); // Draw the new rubber band g.setColor(Color.red); g.drawLine(m_startPoint.x, m_startPoint.y, endPoint.x, endPoint.y); // Save the old rubber band's endpoint so it can be erased next time m_tempEnd = endPoint; } /** * Called to refresh the display. If either endpoint * is undefined, paint() clears the screen but draws nothing */ public void paint(Graphics g) { Graphics2D gg = (Graphics2D)g; if (m_startPoint == null || m_endPoint == null) { return; } g.setColor(Color.black); drawBresenhamLine(g, m_startPoint, m_endPoint); } }