import java.awt.Graphics; import java.awt.Polygon; import java.awt.Color; public class Segment { public Vertex p; public Vertex q; public HalfSpace h; private Polygon poly; // to draw a fat line private Polygon poly_front; // to see which side is front public Segment(Vertex p, Vertex q) { // creates an oriented segment p->q with the associated half-space this.p = p; this.q = q; this.h = new HalfSpace(this); this.computePolygon(); } public void draw(Graphics g, boolean colored) { if (colored) { g.setColor(Color.green.darker().darker()); g.fillPolygon(poly); g.setColor(Color.green.darker()); g.fillPolygon(poly_front); } else g.fillPolygon(poly); } public Segment clip(HalfSpace H) { // clips this segment to half-space // returns the part of that lies in front of int e = H.eval(this); if (e == Parameters.IN_FRONT || e == Parameters.COINCIDENT) return new Segment(p, q); else if (e == Parameters.IN_BACK) return null; else { // one of the vertices is in front, and the other in back // intersect with half-space line Vertex r = this.intersect(H); if (H.eval(p) == Parameters.IN_FRONT) return new Segment(p, r); else return new Segment(r, q); } } public Segment[] cutWith(HalfSpace H) { // returns 2 segments // segments[0] = in front // segments[1] = in back Segment [] segments = new Segment[2]; int e = H.eval(this); if (e == Parameters.IN_FRONT || e == Parameters.SPANNING) segments[0] = new Segment(p, q); else if (e == Parameters.IN_BACK) segments[1] = new Segment(p, q); else { // one of the vertices is in front, and the other in back // intersect with half-space line Vertex r = this.intersect(H); if (H.eval(p) == Parameters.IN_FRONT) { segments[0] = new Segment(p, r); segments[1] = new Segment(r, q); } else { segments[1] = new Segment(p, r); segments[0] = new Segment(r, q); } } return segments; } public Vertex intersect(Segment s) { // intersect with return this.intersect(s.h); } public double length() { return Math.sqrt((q.x-p.x)*(q.x-p.x) + (q.y-p.y)*(q.y-p.y)); } public int pick(Vertex v) { // for the point v, return whether it is in the neighborhood // of p, q, middle of the segment, or away from the segment if (!poly.contains((int)v.x, (int)v.y)) return Parameters.NIL; double t = this.project(v);// / this.length(); System.out.println(t); if (t < 0.15) return Parameters.P; else if (t > 0.85) return Parameters.Q; else return Parameters.S; } private double project(Vertex v) { // project onto this segment // return t, the distance such that v_projected = p + t*(q-p) double lpq = this.length(); return ((v.x-p.x)*(q.x-p.x) + (v.y-p.y)*(q.y-p.y)) / lpq / lpq; } private Vertex intersect(HalfSpace H) { // intersect with // boils down to intersecting 2 lines double d = h.a*H.b - h.b*H.a; double intersect_x = (h.b*H.c - h.c*H.b) / d; double intersect_y = (h.c*H.a - h.a*H.c) / d; return new Vertex(intersect_x, intersect_y); } private void computePolygon() { // for a fat line, i draw a polygon double dx = q.x - p.x; double dy = q.y - p.y; double l = Math.sqrt(dx*dx+dy*dy); // get normal double nx = dy/l; double ny = -dx/l; // create the polygon poly = new Polygon(); poly.addPoint((int)(p.x+3*nx), (int)(p.y+3*ny)); poly.addPoint((int)(p.x-3*nx), (int)(p.y-3*ny)); poly.addPoint((int)(q.x-3*nx), (int)(q.y-3*ny)); poly.addPoint((int)(q.x+3*nx), (int)(q.y+3*ny)); poly_front = new Polygon(); poly_front.addPoint((int)(p.x), (int)(p.y)); poly_front.addPoint((int)(p.x+3*nx), (int)(p.y+3*ny)); poly_front.addPoint((int)(q.x+3*nx), (int)(q.y+3*ny)); poly_front.addPoint((int)(q.x), (int)(q.y)); } }