#include "segment.h" Segment::Segment() { verts[0] = verts[1] = NULL; slope = 0; slope_inf = 0; neighbor = NULL; } Segment::Segment(Vertex *v1, Vertex *v2) { verts[0] = v1; verts[1] = v2; neighbor = NULL; compute_slope(); } Segment::Segment(Vertex *v1, Vertex *v2, Polygon *p) { verts[0] = v1; verts[1] = v2; neighbor = p; compute_slope(); } void Segment::do_copy(Segment *s_copy) { verts[0] = new Vertex(); verts[0]->do_copy(s_copy->GetVertex(0)); verts[1] = new Vertex(); verts[1]->do_copy(s_copy->GetVertex(1)); slope = s_copy->slope; slope_inf = s_copy->slope_inf; y_intercept = s_copy->y_intercept; neighbor = s_copy->neighbor; } Segment::~Segment() { } void Segment::SetVertex(Vertex *v, int num) { if (num < 0 || num > 1) return; verts[num] = v; if (verts[0] && verts[1]) { compute_slope(); } } Vertex *Segment::GetVertex(int num) { if (num < 0 || num > 1) return NULL; return verts[num]; } void Segment::compute_slope() { REGISTER("Segment::compute_slope"); if (verts[0]->x != verts[1]->x) { slope = FDIV(FSUB(verts[1]->y,verts[0]->y),FSUB(verts[1]->x,verts[0]->x)); slope_inf = 0; y_intercept = FSUB(verts[1]->y,FMUL(slope,verts[1]->x)); } else { if (FSUB(verts[1]->y,verts[0]->y) > 0) { slope_inf = 1; } else { slope_inf = -1; } } line_x = (verts[0]->y) - (verts[1]->y); line_y = (verts[1]->x) - (verts[0]->x); line_w = (verts[0]->x * verts[1]->y) - (verts[1]->x * verts[0]->y); UNREGISTER(); } /* * Intersection * * This function computes where and if two segments intersect. It must * first find the intersection between two lines, and then determine * if they intersect by checking bounds. * * Whether or not to check bounds is given in the bounds variable. * * If no intersection is found, NULL is returned. */ int Segment::compute_intersection(Segment *other, int bounds, fixedpt *hit_x, fixedpt *hit_y) { Vertex *other_verts[2]; Vertex *hit_vert; int is_hit; other_verts[0] = other->GetVertex(0); other_verts[1] = other->GetVertex(1); // Compute the intersection of the two lines defined by the sets of // vertices. fixedpt result_x, result_y, result_w; // There is one special case, where the intersection of the two // segments occurs at both of the segments' vertices. if (other_verts[0]->Equals(verts[0]) || other_verts[1]->Equals(verts[1]) || other_verts[1]->Equals(verts[1]) || other_verts[1]->Equals(verts[0])) { if (bounds == 3 || bounds == 1) return 0; else return 1; } result_x = (line_y * other->line_w) - (other->line_y * line_w); result_y = (other->line_x * line_w) - (line_x * other->line_w); result_w = (line_x * other->line_y) - (other->line_x * line_y); if (result_w == 0) // Point at infinity --> no intersection. return 0; *hit_x = (result_x / result_w); *hit_y = (result_y / result_w); hit_vert = new Vertex(*hit_x, *hit_y); // Do bounds check on the other segment. Note that this is always // done, since I'm checking for intersection with a segment, // not a line. is_hit = 0; if ((hit_vert->Distance(other_verts[0]) < 0.01) || (hit_vert->Distance(other_verts[1]) < 0.01)) { if (bounds == 3) { delete hit_vert; return 0; } is_hit = 1; } if (!((*hit_x <= other_verts[0]->x && *hit_x >= other_verts[1]->x) || (*hit_x >= other_verts[0]->x && *hit_x <= other_verts[1]->x) || is_hit)) { return 0; } if (!((*hit_y <= other_verts[0]->y && *hit_y >= other_verts[1]->y) || (*hit_y >= other_verts[0]->y && *hit_y <= other_verts[1]->y) || is_hit)) { return 0; } // Now do bounds check on my segment if requested. is_hit = 0; if ((hit_vert->Distance(verts[0]) < 0.01) || (hit_vert->Distance(verts[1]) < 0.01)) { if (bounds == 1) { delete hit_vert; return 0; } is_hit = 1; } if (bounds) { if (!((*hit_x <= verts[0]->x && *hit_x >= verts[1]->x) || (*hit_x >= verts[0]->x && *hit_x <= verts[1]->x) || is_hit)) { return 0; } if (!((*hit_y <= verts[0]->y && *hit_y >= verts[1]->y) || (*hit_y >= verts[0]->y && *hit_y <= verts[1]->y) || is_hit)) { return 0; } } return 1; } Vertex *Segment::Intersection(Segment *other, int bounds) { fixedpt hit_x, hit_y; Vertex *hit_vertex; if (!compute_intersection(other, bounds, &hit_x, &hit_y)) return NULL; hit_vertex = new Vertex(hit_x, hit_y); return hit_vertex; } int Segment::IsIntersection(Segment *other, int bounds) { fixedpt hit_x, hit_y; return compute_intersection(other, bounds, &hit_x, &hit_y); } int Segment::Contains(Vertex *v) { if (verts[0]->Equals(v) || verts[1]->Equals(v)) return 1; return 0; } int Segment::Equals(Segment *other) { if (verts[0]->Equals(other->GetVertex(0)) && verts[1]->Equals(other->GetVertex(1))) return 1; if (verts[0]->Equals(other->GetVertex(1)) && verts[1]->Equals(other->GetVertex(0))) return 1; return 0; } void Segment::Flip() { Vertex *temp; temp = verts[0]; verts[0] = verts[1]; verts[1] = temp; } void Segment::print() { printf("(%.3f, %.3f) - (%.3f, %.3f), y-int: %.3f, slope: %.3f, neighbor: %d\n", verts[0]->x, verts[0]->y, verts[1]->x, verts[1]->y, y_intercept, slope, (int) neighbor); fflush(stdout); } /*** INCOMPLETE FUNCTION! ***/ int Segment::VertexOnSegment(Vertex *v) { // If my slope is infinite, then the vertex must have the same x-coord // as me. if (slope_inf) { if (v->x == verts[0]->x) { // Now do bounds check to make sure. if ((v->y <= verts[0]->y && v->y >= verts[1]->y) || (v->y <= verts[1]->y && v->y >= verts[0]->y)) return 1; else return 0; } else { return 0; } } return 1; }