// Segment.java // Class for a line segment. // Written by THC for CS 5 Lab Assignment 3. import java.awt.*; public class Segment extends Shape { private static final double TOLERANCE = 3; // how close is "close enough" private int x1, y1, x2, y2; // Line segment's endpoints // Constructor just saves the parameters in the instance variables. public Segment(int x1, int y1, int x2, int y2, Color color) { super(color); this.x1 = x1; this.y1 = y1; this.x2 = x2; this.y2 = y2; } // Have the Segment draw itself. public void drawShape(Graphics page) { page.drawLine(x1, y1, x2, y2); } // Return true if Point p is within a small distance of the Segment, false // otherwise. public boolean containsPoint(Point p) { // If p is within TOLERANCE of being within the Segment's bounding box // AND p is within 3 pixels of the line containing the Segment, then we'll // say that p is close enough. return almostContainsPoint(p, Math.min(x1, x2), Math.min(y1, y2), Math.max(x1, x2), Math.max(y1, y2), TOLERANCE) && distanceToPoint(p, x1, y1, x2, y2) <= TOLERANCE; } // Helper method that returns true if Point p is within a tolerance of a // given bounding box. Here, the bounding box is given by the coordinates of // its left, top, right, and bottom. private static boolean almostContainsPoint(Point p, int left, int top, int right, int bottom, double tolerance) { return p.x >= left - tolerance && p.y >= top - tolerance && p.x <= right + tolerance && p.y <= bottom + tolerance; } // Helper method that returns the distance from Point p to the line // containing a line segment whose endpoints are given. private static double distanceToPoint(Point p, int x1, int y1, int x2, int y2) { if (x1 == x2) // vertical segment? return (double) (Math.abs(p.x - x1)); // yes, use horizontal distance else if (y1 == y2) // horizontal segment? return (double) (Math.abs(p.y - y1)); // yes, use vertical distance else { // Here, we know that the segment is neither vertical nor // horizontal. // Compute m, the slope of the line containing the segment. double m = ((double) (y1 - y2)) / ((double) (x1 - x2)); // Compute mperp, the slope of the line perpendicular to the // segment. double mperp = -1.0 / m; // Compute the (x, y) intersection of the line containing the // segment and the line that is perpendicular to the segment and that // contains Point p. double x = (((double) y1) - ((double) p.y) - (m * x1) + (mperp * p.x)) / (mperp - m); double y = m * (x - x1) + y1; // Return the distance between Point p and (x, y). return Math.sqrt(Math.pow(p.x - x, 2) + Math.pow(p.y - y, 2)); } } // Have the Segment move itself. public void move(int deltaX, int deltaY) { x1 += deltaX; y1 += deltaY; x2 += deltaX; y2 += deltaY; } // Return the Segment's center. public Point getCenter() { return new Point((x1 + x2) / 2, (y1 + y2) / 2); } }