// ************************************** // Edge // ************************************** Edge::Edge(ifstream &in, NodeSetPtr validNodes, EdgeSetPtr edges) throw(Error) { equatedTo = NULL; segments = new LineSegmentSet; LoadName(in); CheckNameForDuplication(edges); // load nodes NodePtr S, F; if (!GetAndDiscard(in, '(')) { Error e("Missing Paranthesis in edge definition"); throw(e); } S = LoadNode(in, validNodes); // also checks to see if nodes are valid if (!GetAndDiscard(in, ',')) { Error e("Missing Comma in edge definition"); throw(e); } F = LoadNode(in, validNodes); // also checks to see if nodes are valid if (!GetAndDiscard(in, ')')) { Error e("Missing Paranthesis in edge definition"); throw(e); } start = S; finish = F; segments->push_back(new LineSegment(S, F)); CheckForIdenticalEdges(edges); // check to see if this edge has a length (if not, cannot intersect or have nodes on it) if (S != F) { CheckForIntersections(validNodes, edges); CheckForNodesOnThisEdge(validNodes); } edges->push_back(this); #ifdef _tdebug cout << "created edge " << name << endl; #endif }; bool Edge::CheckForIdenticalEdges(EdgeSetPtr edges) { // check to see that this is not the same as an existing edge for (unsigned int i=0; isize(); i++) { if ((((*edges)[i]->Start() == start) && ((*edges)[i]->Finish() == finish)) || (((*edges)[i]->Start() == finish) && ((*edges)[i]->Finish() == start))) { // equate if ((*edges)[i]->equatedTo != NULL) equatedTo = (*edges)[i]->equatedTo; // try to avoid chains else equatedTo = (*edges)[i]; return true; } } return false; } bool Edge::CheckForNodesOnThisEdge(NodeSetPtr nodes) { // check to see if any nodes lie on this edge bool returnVal = false; for (unsigned int i=0; isize(); i++) { if ((*nodes)[i] == Start()) continue; // obviously our start node will lie on this edge! if ((*nodes)[i] == Finish()) continue; // obviously our finish node will lie on this edge! LineSegmentPtr me; if (LiesOnMe((*nodes)[i], me)) { SplitAt((*nodes)[i], me); returnVal = true; } } return returnVal; } bool Edge::Intersects(const EdgePtr otherEdge, float &x, float &y, LineSegmentPtr &S, bool &overlaps, float &x2, float &y2, NodeSetPtr validNodes) { // check each pair of line segments within these two edges to see if they intersect for (unsigned int i=0; i<(*Segments()).size(); i++) { for (unsigned int j=0; j<(*(otherEdge->Segments())).size(); j++) { if ((*Segments())[i]->Intersects((*(otherEdge->Segments()))[j], x, y, overlaps, x2, y2, validNodes)) { S = (*(otherEdge->Segments()))[j]; return true; } } } return false; } bool Edge::CheckForIntersections(NodeSetPtr validNodes, EdgeSetPtr edges) { // check to see if this edge intersects any other edge bool returnVal = false; for (unsigned int i=0; isize(); i++) { float x, y, x2, y2; bool twoIntersects; LineSegmentPtr intersectedSegment; if (Intersects((*edges)[i], x, y, intersectedSegment, twoIntersects, x2, y2, validNodes)) { returnVal = true; NodePtr N = new Node(x, y, validNodes); if (twoIntersects) { // these two lines overlap each other (what a pain) NodePtr N2 = new Node(x2, y2, validNodes); LineSegmentPtr temp2; temp2 = (*edges)[i]->SplitAt(N, intersectedSegment); (*edges)[i]->SplitAt(N2, temp2); } else (*edges)[i]->SplitAt(N, intersectedSegment); } } return returnVal; } bool Edge::LiesOnMe(const NodePtr someNode, LineSegmentPtr &S) { for (unsigned int i=0; i<(*Segments()).size(); i++) { if ((*Segments())[i]->Includes(someNode)) { S = (*Segments())[i]; return true; } } return false; } LineSegmentPtr Edge::SplitAt(const NodePtr someNode, LineSegmentPtr &S, const NodePtr returnNode = NULL) { // create the two new segments to replace the existing one LineSegmentPtr left = new LineSegment(S->Start(), someNode); LineSegmentPtr right = new LineSegment(someNode, S->Finish()); // update the references to the line segments for (unsigned int i=0; i<(*Segments()).size(); i++) { if ((*Segments())[i] == S) { (*Segments())[i] = left; // there should only be one! } } (*Segments()).push_back(right); // delete the old line segment delete S; if (returnNode == NULL) return NULL; // we want to return a pointer to the new line segment that contains node returnNode if (left->Includes(returnNode)) return left; return right; } NodePtr Edge::LoadNode(ifstream &in, NodeSetPtr validNodes) throw (Error){ string nodeName; LoadAlphaString(in, nodeName); for (unsigned int i=0; isize(); i++) { if ((*validNodes)[i]->IsCalled(nodeName)) return (*validNodes)[i]; } // error, can't find node Error e("Edge description includes unknown nodes\n"); throw(e); } bool Edge::CheckNameForDuplication(EdgeSetPtr edges) throw (Error) { for (unsigned int i=0; isize(); i++) { if ((*edges)[i]->IsCalled(name)) { // error, name duplication Error e("Name duplication in edges\n"); throw(e); return true; } } return false; } /*void Edge::ResolveEquatedNodes(NodeSetPtr NS) { // if this edge is equated to another one, don't bother if (equatedTo == NULL) return; for (unsigned int i=0; i<(*Segments()).size(); i++) { (*Segments())[i]->ResolveStartNode(NS); } bool del; NodePtr oldFinish = finish; finish = finish->ResolveEquatedNodes(NS, del); if (del) delete oldFinish; } */ LineSegmentSetPtr Edge::Segments() { if (equatedTo == NULL) return segments; return equatedTo->Segments(); } NodePtr Edge::Start() { if (equatedTo == NULL) return start; return equatedTo->Start(); } NodePtr Edge::Finish() { if (equatedTo == NULL) return finish; return equatedTo->Finish(); }