#include "polygon.h" Polygon::Polygon() { seg_list = new List(); num_segments = 0; internal_segments = new List(); center = NULL; visible_segments = new List(); visible_polygons = new List(); } void Polygon::do_copy(Polygon *p_copy) { Segment *s, *new_seg; seg_list = new List(); num_segments = 0; internal_segments = new List(); s = (Segment *)p_copy->SegList()->Last(); while(s) { new_seg = new Segment(); new_seg->do_copy(s); seg_list->Append(new_seg); s = (Segment *)p_copy->SegList()->Prev(s); } s = (Segment *)p_copy->internal_segments->Last(); while(s) { new_seg = new Segment(); new_seg->do_copy(s); internal_segments->Append(new_seg); s = (Segment *)p_copy->SegList()->Prev(s); } num_segments = seg_list->Size(); } Polygon::~Polygon() { if (seg_list) delete seg_list; if (internal_segments) delete internal_segments; if (visible_segments) delete visible_segments; if (visible_polygons) delete visible_polygons; } void Polygon::AddSegment(Segment *s, Segment *where) { seg_list->InsertAfter(s, where); num_segments++; } void Polygon::AddSegment(Segment *s) { seg_list->Append(s); num_segments++; } void Polygon::DeleteSegment(Segment *s) { seg_list->Delete(s); num_segments--; } int Polygon::NumSegments() { return num_segments; } Segment *Polygon::SegmentNum(int segment_num) { return (Segment *)seg_list->Number(segment_num); } /* This function returns 1 if the polygon contains a segment with * these two vertices. */ int Polygon::Contains(Vertex *v1, Vertex *v2) { Segment *temp_seg; int found = 0; temp_seg = (Segment *)seg_list->First(); while(temp_seg) { if((temp_seg->GetVertex(0)->Equals(v1) && temp_seg->GetVertex(1)->Equals(v2)) || (temp_seg->GetVertex(0)->Equals(v2) && temp_seg->GetVertex(1)->Equals(v1))) { found = 1; break; } temp_seg = (Segment *)seg_list->Next(temp_seg); } return found; } int Polygon::Contains(Vertex *v) { Segment *temp_seg; int found = 0; temp_seg = (Segment *)seg_list->First(); while(temp_seg) { if(temp_seg->Contains(v)) { found = 1; break; } temp_seg = (Segment *)seg_list->Next(temp_seg); } return found; } /* * segment_in_triangle * * This function forms a triangle using the vertex v and its two * neighboring vertices. It then determines if the extension of s * goes through the triangle. It does this by detecting if there's * an intersection between that extension and the edge of the triangle * diametrically opposite to v. * * It returns 1 or 0 depending on whether it finds the segment in the * triangle. * * Note also that it assumes that the extension of s goes through v. */ int Polygon::segment_in_triangle(Vertex *v, Segment *s) { REGISTER("Polygon::segment_in_triangle"); int i; Segment *seg[2], *temp_seg; Vertex *temp_vert[2]; Vertex *return_vert; int curr_seg = 0; // Find the two segments which contain v. temp_seg = (Segment *)seg_list->First(); while(temp_seg) { if(temp_seg->Contains(v)) { seg[curr_seg] = temp_seg; curr_seg++; if (curr_seg > 1) break; } temp_seg = (Segment *)seg_list->Next(temp_seg); } if (curr_seg < 2) { UNREGISTER(); return 0; } if (seg[0]->slope == s->slope || (seg[0]->slope_inf && s->slope_inf)) { UNREGISTER(); return 0; } else if (seg[1]->slope == s->slope || (seg[1]->slope_inf && s->slope_inf)) { UNREGISTER(); return 0; } for (i = 0; i < 2; i++) { if (seg[i]->GetVertex(0)->Equals(v)) { temp_vert[i] = seg[i]->GetVertex(1); } else { temp_vert[i] = seg[i]->GetVertex(0); } } temp_seg = new Segment(temp_vert[0], temp_vert[1]); return_vert = s->Intersection(temp_seg, 0); UNREGISTER(); delete temp_seg; if (return_vert) { delete return_vert; return 1; } else { return 0; } } Segment *Polygon::Next(Segment *s) { Segment *temp; temp = (Segment *)seg_list->CircularNext(s); while(1) { if (!s->Equals(temp)) { if (temp->GetVertex(0)->Equals(s->GetVertex(1))) return temp; } temp = (Segment *)seg_list->CircularNext(temp); } } void Polygon::compute_centroid(Vertex *v1, Vertex *v2, Vertex *v3, Vertex *result) { result->x = v1->x + v2->x + v3->x; result->y = v1->y + v2->y + v3->y; } fixedpt Polygon::compute_area(Vertex *v1, Vertex *v2, Vertex *v3) { return (v2->x - v1->x) * (v3->y - v1->y) - (v3->x - v1->x) * (v2->y - v1->y); } void Polygon::ComputeCenter() { int i; Vertex Cent; center = new Vertex; fixedpt area; fixedpt areasum = 0; center->x = 0; center->y = 0; num_segments = seg_list->Size(); for (i = 1; i < num_segments-1; i++) { compute_centroid(((Segment *)seg_list->Number(0))->GetVertex(0), ((Segment *)seg_list->Number(i))->GetVertex(0), ((Segment *)seg_list->Number(i+1))->GetVertex(0), &Cent ); area = compute_area(((Segment *)seg_list->Number(0))->GetVertex(0), ((Segment *)seg_list->Number(i))->GetVertex(0), ((Segment *)seg_list->Number(i+1))->GetVertex(0)); center->x += area * Cent.x; center->y += area * Cent.y; areasum += area; } center->x /= 3 * areasum; center->y /= 3 * areasum; } /* * print * * This function generates a textual output giving information about a * polygon. */ void Polygon::print() { Segment *temp_seg; REGISTER("Polygon::print"); printf("Polygon Information: %d\n", (int) this); temp_seg = (Segment *)seg_list->First(); while(temp_seg) { temp_seg->print(); temp_seg = (Segment *)seg_list->Next(temp_seg); } if (center) { printf("Center: (%.3f, %.3f)\n", FLOAT(center->x), FLOAT(center->y) ); } printf("\n"); fflush(stdout); UNREGISTER(); }