/* ---- This file is part of SECONDO. Copyright (C) 2004, University in Hagen, Department of Computer Science, Database Systems for New Applications. SECONDO is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. SECONDO is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with SECONDO; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ---- //paragraph [1] Title: [{\Large \bf \begin {center}] [\end {center}}] //[TOC] [\tableofcontents] [1] Source File of the Transportation Mode Algebra March, 2010 Jianqiu Xu [TOC] 1 Overview This source file essentially contains the necessary implementations for partitioning space. */ #include "Partition.h" /* ~Shift~ Operator for ~ownertype~ */ using namespace std; using namespace network; ostream& myavlseg::operator<<(ostream& o, const myavlseg::ownertype& owner){ switch(owner){ case myavlseg::none : o << "none" ; break; case myavlseg::first : o << "first"; break; case myavlseg::second : o << "second"; break; case myavlseg::both : o << "both"; break; default : assert(false); } return o; } /* 3.1 Constructors ~Standard Constructor~ */ myavlseg::MyAVLSegment::MyAVLSegment() { x1 = 0; x2 = 0; y1 = 0; y2 = 0; owner = none; insideAbove_first = false; insideAbove_second = false; con_below = 0; con_above = 0; } /* ~Constructor~ This constructor creates a new segment from the given HalfSegment. As owner only __first__ and __second__ are the allowed values. */ myavlseg::MyAVLSegment::MyAVLSegment(const HalfSegment& hs, ownertype owner){ x1 = hs.GetLeftPoint().GetX(); y1 = hs.GetLeftPoint().GetY(); x2 = hs.GetRightPoint().GetX(); y2 = hs.GetRightPoint().GetY(); // if( (MyAlmostEqual(x1,x2) && (y2owner = owner; switch(owner){ case first: { insideAbove_first = hs.GetAttr().insideAbove; insideAbove_second = false; break; } case second: { insideAbove_second = hs.GetAttr().insideAbove; insideAbove_first = false; break; } default: { assert(false); } } con_below = 0; con_above = 0; } /* ~Constructor~ Create a Segment only consisting of a single point. */ myavlseg::MyAVLSegment::MyAVLSegment(const Point& p, ownertype owner) { x1 = p.GetX(); x2 = x1; y1 = p.GetY(); y2 = y1; this->owner = owner; insideAbove_first = false; insideAbove_second = false; con_below = 0; con_above = 0; } /* ~Copy Constructor~ */ myavlseg::MyAVLSegment::MyAVLSegment(const MyAVLSegment& src){ Equalize(src); } /* 3.3 Operators */ myavlseg::MyAVLSegment& myavlseg::MyAVLSegment::operator=( const myavlseg::MyAVLSegment& src){ Equalize(src); return *this; } bool myavlseg::MyAVLSegment::operator==(const myavlseg::MyAVLSegment& s)const{ return compareTo(s)==0; } bool myavlseg::MyAVLSegment::operator<(const myavlseg::MyAVLSegment& s) const{ return compareTo(s)<0; } bool myavlseg::MyAVLSegment::operator>(const myavlseg::MyAVLSegment& s) const{ return compareTo(s)>0; } /* 3.3 Further Needful Functions ~Print~ This function writes this segment to __out__. */ void myavlseg::MyAVLSegment::Print(ostream& out)const{ out << "Segment("< (" << x2 << ", " << y2 <<") " << owner << " [ " << insideAbove_first << ", " << insideAbove_second << "] con(" << con_below << ", " << con_above << ")"; } /* ~Equalize~ The value of this segment is taken from the argument. */ void myavlseg::MyAVLSegment::Equalize( const myavlseg::MyAVLSegment& src){ x1 = src.x1; x2 = src.x2; y1 = src.y1; y2 = src.y2; owner = src.owner; insideAbove_first = src.insideAbove_first; insideAbove_second = src.insideAbove_second; con_below = src.con_below; con_above = src.con_above; } /* 3.5 Geometric Functions ~crosses~ Checks whether this segment and __s__ have an intersection point of their interiors. */ bool myavlseg::MyAVLSegment::crosses(const myavlseg::MyAVLSegment& s) const{ double x,y; return crosses(s,x,y); } /* ~crosses~ This function checks whether the interiors of the related segments are crossing. If this function returns true, the parameters ~x~ and ~y~ are set to the intersection point. */ bool myavlseg::MyAVLSegment::crosses(const myavlseg::MyAVLSegment& s, double& x, double& y) const{ if(isPoint() || s.isPoint()){ return false; } if(!xOverlaps(s)){ return false; } if(overlaps(s)){ // a common line return false; } if(compareSlopes(s)==0){ // parallel or disjoint lines return false; } if(isVertical()){ x = x1; // compute y for s y = s.y1 + ((x-s.x1)/(s.x2-s.x1))*(s.y2 - s.y1); return !MyAlmostEqual(y1,y) && !MyAlmostEqual(y2,y) && (y>y1) && (ys.y1) && (y x2){ // (X,Y) right of this return false; } if(isVertical()){ return (!MyAlmostEqual(y,y1) && (y>y1) && !MyAlmostEqual(y,y2) && (y=y1) && (y <= y2); } // check if (x,y) is located on the line double res1 = (x-x1)*(y2-y1); double res2 = (y-y1)*(x2-x1); if(!MyAlmostEqual(res1,res2)){ return false; } return ((x>x1) && (xowner==first || this->owner==second); assert( owner==both || owner==first || owner==second); bool insideAbove; if(owner==both){ insideAbove = this->owner==first?insideAbove_first :insideAbove_second; } else { insideAbove = owner==first?insideAbove_first :insideAbove_second; } Point p1(true,x1,y1); Point p2(true,x2,y2); HalfSegment hs(lpd, p1, p2); hs.attr.insideAbove = insideAbove; return hs; } /* ~pointequal~ This function checks if the points defined by (x1, y1) and (x2,y2) are equals using the ~MyAlmostEqual~ function. */ bool myavlseg::MyAVLSegment::pointEqual(const double x1, const double y1, const double x2, const double y2){ return MyAlmostEqual(x1,x2) && MyAlmostEqual(y1,y2); } /* ~pointSmaller~ This function checks if the point defined by (x1, y1) is smaller than the point defined by (x2, y2). */ bool myavlseg::MyAVLSegment::pointSmaller(const double x1, const double y1, const double x2, const double y2){ return comparePoints(x1,y1,x2,y2) < 0; } /* ~comparePoints~ */ int myavlseg::MyAVLSegment::comparePoints(const double x1,const double y1, const double x2,const double y2){ if(MyAlmostEqual(x1,x2)){ if(MyAlmostEqual(y1,y2)){ return 0; } else if(y1res2 result = 1; } return result; } /* ~XOverlaps~ Checks whether the x interval of this segment overlaps the x interval of ~s~. */ bool myavlseg::MyAVLSegment::xOverlaps(const myavlseg::MyAVLSegment& s) const{ if(!MyAlmostEqual(x1,s.x2) && x1 > s.x2){ // left of s return false; } if(!MyAlmostEqual(x2,s.x1) && x2 < s.x1){ // right of s return false; } return true; } /* ~XContains~ Checks if the x coordinate provided by the parameter __x__ is contained in the x interval of this segment; */ bool myavlseg::MyAVLSegment::xContains(const double x) const{ if(!MyAlmostEqual(x1,x) && x1>x){ return false; } if(!MyAlmostEqual(x2,x) && x2diff2?diff1:diff2); cerr << "difference to x is " << diff << endl; cerr << "The segment is " << *this << endl; //assert(diff < 1.0); } if(isVertical()){ return y1; } double d = (x-x1)/(x2-x1); return y1 + d*(y2-y1); } /* 3.12 Shift Operator */ ostream& myavlseg::operator<<(ostream& o, const myavlseg::MyAVLSegment& s){ s.Print(o); return o; } /* ~selectNext~ Selects the minimum halfsegment from ~v~1, ~v~2, ~q~1, and ~q~2. If no values are available, the return value will be __none__. In this case, __result__ remains unchanged. Otherwise, __result__ is set to the minimum value found. In this case, the return value will be ~first~ or ~second~. If some halfsegments are equal, the one from ~v~1 is selected. Note: ~pos~1 and ~pos~2 are increased automatically. In the same way, the topmost element of the selected queue is deleted. The template parameter can be instantiated with ~Region~ or ~Line~ */ template myavlseg::ownertype myselectNext(const T1& v1, int& pos1, const T2& v2, int& pos2, priority_queue, greater >& q1, priority_queue, greater >& q2, HalfSegment& result, int& src ){ const HalfSegment* values[4]; HalfSegment hs0, hs1, hs2, hs3; int number = 0; // number of available values // read the available elements if(pos1 *values[i])){ result = *values[i]; index = i; } } } src = index + 1; switch(index){ case 0: pos1++; return myavlseg::first; case 1: q1.pop(); return myavlseg::first; case 2: pos2++; return myavlseg::second; case 3: q2.pop(); return myavlseg::second; default: assert(false); } return myavlseg::none; } /* Instantiation of the ~selectNext~ Function. */ myavlseg::ownertype myselectNext(const Region& reg1, int& pos1, const Region& reg2, int& pos2, priority_queue, greater >& q1, priority_queue, greater >& q2, HalfSegment& result, int& src // for debugging only ){ return myselectNext(reg1,pos1,reg2,pos2,q1,q2,result,src); } /* ~insertEvents~ Creates events for the ~AVLSegment~ and insert them into ~q1~ and/ or ~q1~. The target queue(s) is (are) determined by the owner of ~seg~. The flags ~createLeft~ and ~createRight~ determine whether the left and / or the right events should be created. */ void myinsertEvents(const myavlseg::MyAVLSegment& seg, const bool createLeft, const bool createRight, priority_queue, greater >& q1, priority_queue, greater >& q2){ if(seg.isPoint()){ return; } switch(seg.getOwner()){ case myavlseg::first: { if(createLeft){ q1.push(seg.convertToHs(true, myavlseg::first)); } if(createRight){ q1.push(seg.convertToHs(false, myavlseg::first)); } break; } case myavlseg::second:{ if(createLeft){ q2.push(seg.convertToHs(true, myavlseg::second)); } if(createRight){ q2.push(seg.convertToHs(false, myavlseg::second)); } break; } case myavlseg::both : { if(createLeft){ q1.push(seg.convertToHs(true, myavlseg::first)); q2.push(seg.convertToHs(true, myavlseg::second)); } if(createRight){ q1.push(seg.convertToHs(false, myavlseg::first)); q2.push(seg.convertToHs(false, myavlseg::second)); } break; } default: { assert(false); } } } /* ~splitByNeighbour~ ~neighbour~ has to be an neighbour from ~current~ within ~sss~. The return value is true, if current was changed. */ bool MysplitByNeighbour(avltree::AVLTree& sss, myavlseg::MyAVLSegment& current, myavlseg::MyAVLSegment*& neighbour, priority_queue, greater >& q1, priority_queue, greater >& q2){ myavlseg::MyAVLSegment left1, right1, left2, right2; if(neighbour && !neighbour->innerDisjoint(current)){ if(neighbour->ininterior(current.getX1(),current.getY1())){ neighbour->splitAt(current.getX1(),current.getY1(),left1,right1); sss.remove(*neighbour); if(!left1.isPoint()){ neighbour = sss.insert2(left1); myinsertEvents(left1,false,true,q1,q2); } myinsertEvents(right1,true,true,q1,q2); return false; } else if(neighbour->ininterior(current.getX2(),current.getY2())){ neighbour->splitAt(current.getX2(),current.getY2(),left1,right1); sss.remove(*neighbour); if(!left1.isPoint()){ neighbour = sss.insert2(left1); myinsertEvents(left1,false,true,q1,q2); } myinsertEvents(right1,true,true,q1,q2); return false; } else if(current.ininterior(neighbour->getX2(),neighbour->getY2())){ current.splitAt(neighbour->getX2(),neighbour->getY2(),left1,right1); current = left1; myinsertEvents(left1,false,true,q1,q2); myinsertEvents(right1,true,true,q1,q2); return true; } else if(current.crosses(*neighbour)){ neighbour->splitCross(current,left1,right1,left2,right2); sss.remove(*neighbour); if(!left1.isPoint()){ neighbour = sss.insert2(left1); } current = left2; myinsertEvents(left1,false,true,q1,q2); myinsertEvents(right1,true,true,q1,q2); myinsertEvents(left2,false,true,q1,q2); myinsertEvents(right2,true,true,q1,q2); return true; } else { // forgotten case or wrong order of halfsegments cerr.precision(16); cerr << "Warning wrong order in halfsegment array detected" << endl; cerr << "current" << current << endl << "neighbour " << (*neighbour) << endl; if(current.overlaps(*neighbour)){ // a common line cerr << "1 : The segments overlaps" << endl; } if(neighbour->ininterior(current.getX1(),current.getY1())){ cerr << "2 : neighbour->ininterior(current.x1,current.y1)" << endl; } if(neighbour->ininterior(current.getX2(),current.getY2())){ cerr << "3 : neighbour->ininterior(current.getX2()" << ",current.getY2()" << endl; } if(current.ininterior(neighbour->getX1(),neighbour->getY1())){ cerr << " case 4 : current.ininterior(neighbour->getX1()," << "neighbour.getY1()" << endl; cerr << "may be an effect of rounding errors" << endl; cerr << "remove left part from current" << endl; current.splitAt(neighbour->getX1(),neighbour->getY1(), left1,right1); cerr << "removed part is " << left1 << endl; current = right1; myinsertEvents(current,false,true,q1,q2); return true; } if(current.ininterior(neighbour->getX2(),neighbour->getY2())){ cerr << " 5 : current.ininterior(neighbour->getX2()," << "neighbour->getY2())" << endl; } if(current.crosses(*neighbour)){ cerr << "6 : crosses" << endl; } assert(false); return true; } } else { return false; } } /* ~splitNeighbours~ Checks if the left and the right neighbour are intersecting in their interiors and performs the required actions. */ void MysplitNeighbours(avltree::AVLTree& sss, myavlseg::MyAVLSegment *& leftN, myavlseg::MyAVLSegment *& rightN, priority_queue, greater >& q1, priority_queue, greater >& q2){ if(leftN && rightN && !leftN->innerDisjoint(*rightN)){ myavlseg::MyAVLSegment left1, right1, left2, right2; if(leftN->ininterior(rightN->getX2(),rightN->getY2())){ leftN->splitAt(rightN->getX2(),rightN->getY2(),left1,right1); sss.remove(*leftN); if(!left1.isPoint()){ leftN = sss.insert2(left1); myinsertEvents(left1,false,true,q1,q2); } myinsertEvents(right1,true,true,q1,q2); } else if(rightN->ininterior(leftN->getX2(),leftN->getY2())){ rightN->splitAt(leftN->getX2(),leftN->getY2(),left1,right1); sss.remove(*rightN); if(!left1.isPoint()){ rightN = sss.insert2(left1); myinsertEvents(left1,false,true,q1,q2); } myinsertEvents(right1,true,true,q1,q2); } else if (rightN->crosses(*leftN)){ leftN->splitCross(*rightN,left1,right1,left2,right2); sss.remove(*leftN); sss.remove(*rightN); if(!left1.isPoint()) { leftN = sss.insert2(left1); } if(!left2.isPoint()){ rightN = sss.insert2(left2); } myinsertEvents(left1,false,true,q1,q2); myinsertEvents(left2,false,true,q1,q2); myinsertEvents(right1,true,true,q1,q2); myinsertEvents(right2,true,true,q1,q2); } else { // forgotten case or overlapping segments (rounding errors) if(leftN->overlaps(*rightN)){ cerr << "Overlapping neighbours found" << endl; cerr << "leftN = " << *leftN << endl; cerr << "rightN = " << *rightN << endl; myavlseg::MyAVLSegment left; myavlseg::MyAVLSegment common; myavlseg::MyAVLSegment right; int parts = leftN->split(*rightN, left,common,right,false); sss.remove(*leftN); sss.remove(*rightN); if(parts & avlseg::LEFT){ if(!left.isPoint()){ cerr << "insert left part" << left << endl; leftN = sss.insert2(left); myinsertEvents(left,false,true,q1,q2); } } if(parts & avlseg::COMMON){ if(!common.isPoint()){ cerr << "insert common part" << common << endl; rightN = sss.insert2(common); myinsertEvents(common,false,true,q1,q2); } } if(parts & avlseg::RIGHT){ if(!right.isPoint()){ cerr << "insert events for the right part" << right << endl;; myinsertEvents(right,true,true,q1,q2); } } } else { assert(false); } } } // intersecting neighbours } void MyIntersection(const Line& line, const Region& reg, Line& result) { MySetOp(line, reg, result, myavlseg::intersection_op); } /* Intersection, union and minus between a line and a region */ void MySetOp(const Line& line, const Region& region, Line& result, myavlseg::SetOperation op){ assert(op==myavlseg::intersection_op || op == myavlseg::difference_op); result.Clear(); if(!line.IsDefined() || !region.IsDefined()){ result.SetDefined(false); return; } result.SetDefined(true); if(line.Size()==0){ // empty line -> empty result switch(op){ case myavlseg::intersection_op : return; // empty region case myavlseg::difference_op : return; // empty region default : assert(false); } } if(region.Size()==0){ switch(op){ case myavlseg::intersection_op: return; case myavlseg::difference_op: result = line; return; default : assert(false); } } priority_queue, greater > q1; priority_queue, greater > q2; avltree::AVLTree sss; myavlseg::ownertype owner; int pos1 = 0; int pos2 = 0; int size1= line.Size(); HalfSegment nextHs; int src = 0; myavlseg::MyAVLSegment* member=0; myavlseg::MyAVLSegment* leftN = 0; myavlseg::MyAVLSegment* rightN = 0; myavlseg::MyAVLSegment left1,right1,common1, left2,right2; int edgeno =0; myavlseg::MyAVLSegment tmpL,tmpR; bool done = false; result.StartBulkLoad(); // perform a planesweeo while( ((owner=myselectNext(line,pos1, region,pos2, q1,q2,nextHs,src))!= myavlseg::none) && ! done){ myavlseg::MyAVLSegment current(nextHs,owner); member = sss.getMember(current,leftN,rightN); if(leftN){ tmpL = *leftN; leftN = &tmpL; } if(rightN){ tmpR = *rightN; rightN = &tmpR; } if(nextHs.IsLeftDomPoint()){ if(member){ // there is an overlapping segment in sss if(member->getOwner()==owner || member->getOwner()==myavlseg::both ){ if(current.ininterior(member->getX2(),member->getY2())){ current.splitAt(member->getX2(),member->getY2(),left1,right1); myinsertEvents(right1,true,true,q1,q2); } } else { // member and source come from difference sources int parts = member->split(current,left1,common1,right1); sss.remove(*member); member = &common1; if(parts & myavlseg::LEFT){ if(!left1.isPoint()){ sss.insert(left1); myinsertEvents(left1,false,true,q1,q2); } } assert(parts & myavlseg::COMMON); if(owner==myavlseg::second) { // the region if(current.getInsideAbove()){ common1.con_above++; } else { common1.con_above--; } } // for a line is nothing to do if(!common1.isPoint()){ sss.insert(common1); myinsertEvents(common1,false,true,q1,q2); } if(parts & myavlseg::RIGHT){ myinsertEvents(right1,true,true,q1,q2); } } } else { // no overlapping segment in sss found MysplitByNeighbour(sss,current,leftN,q1,q2); MysplitByNeighbour(sss,current,rightN,q1,q2); // update coverage numbers if(owner==myavlseg::second){ // the region bool iac = current.getInsideAbove(); if(leftN && current.extends(*leftN)){ current.con_below = leftN->con_below; current.con_above = leftN->con_above; }else{ if(leftN && leftN->isVertical()){ current.con_below = leftN->con_below; } else if(leftN){ current.con_below = leftN->con_above; } else { current.con_below = 0; } if(iac){ current.con_above = current.con_below+1; } else { current.con_above = current.con_below-1; } } } else { // the line if(leftN){ if(leftN->isVertical()){ current.con_below = leftN->con_below; } else { current.con_below = leftN->con_above; } } current.con_above = current.con_below; } // insert element if(!current.isPoint()){ sss.insert(current); myinsertEvents(current,false,true,q1,q2); } } } else { // nextHs.IsRightDomPoint() if(member && member->exactEqualsTo(current)){ switch(op){ case myavlseg::intersection_op: { if( (member->getOwner()==myavlseg::both) || (member->getOwner()==myavlseg::first && member->con_above>0)){ HalfSegment hs1 = member->convertToHs(true,myavlseg::first); hs1.attr.edgeno = edgeno; result += hs1; hs1.SetLeftDomPoint(false); result += hs1; edgeno++; } break; } case myavlseg::difference_op: { if( (member->getOwner()==myavlseg::first) && (member->con_above==0)){ HalfSegment hs1 = member->convertToHs(true,myavlseg::first); hs1.attr.edgeno = edgeno; result += hs1; hs1.SetLeftDomPoint(false); result += hs1; edgeno++; } break; } default : assert(false); } sss.remove(*member); MysplitNeighbours(sss,leftN,rightN,q1,q2); } if(pos1>=size1 && q1.empty()){ // line is processed done = true; } } } result.EndBulkLoad(); } // setOP(line x region -> line) void MyIntersection(const Line& l1, const Line& l2, Line& result) { MySetOp(l1, l2, result, myavlseg::intersection_op); } /* Intersection, union and minus between two lines */ void MySetOp(const Line& line1, const Line& line2, Line& result, myavlseg::SetOperation op){ result.Clear(); if(!line1.IsDefined() || !line2.IsDefined()){ result.SetDefined(false); return; } result.SetDefined(true); if(line1.Size()==0){ switch(op){ case myavlseg::union_op : result = line2; return; case myavlseg::intersection_op : return; // empty line case myavlseg::difference_op : return; // empty line default : assert(false); } } if(line2.Size()==0){ switch(op){ case myavlseg::union_op: result = line1; return; case myavlseg::intersection_op: return; case myavlseg::difference_op: result = line1; return; default : assert(false); } } priority_queue, greater > q1; priority_queue, greater > q2; avltree::AVLTree sss; myavlseg::ownertype owner; int pos1 = 0; int pos2 = 0; HalfSegment nextHs; int src = 0; myavlseg::MyAVLSegment* member=0; myavlseg::MyAVLSegment* leftN = 0; myavlseg::MyAVLSegment* rightN = 0; myavlseg::MyAVLSegment left1,right1,common1, left2,right2; int edgeno =0; myavlseg::MyAVLSegment tmpL,tmpR; result.StartBulkLoad(); while( (owner=myselectNext(line1,pos1, line2,pos2, q1,q2,nextHs,src))!= myavlseg::none){ myavlseg::MyAVLSegment current(nextHs,owner); member = sss.getMember(current,leftN,rightN); if(leftN){ tmpL = *leftN; leftN = &tmpL; } if(rightN){ tmpR = *rightN; rightN = &tmpR; } if(nextHs.IsLeftDomPoint()){ if(member){ // found an overlapping segment if(member->getOwner()==current.getOwner() || member->getOwner()== myavlseg::both){ // same source double xm = member->getX2(); double xc = current.getX2(); if(!AlmostEqual(xm,xc) && (xmgetY2(),left1,right1); myinsertEvents(right1,true,true,q1,q2); } } else { // member and current come from different sources int parts = member->split(current,left1,common1,right1); sss.remove(*member); member = &common1; if(parts & myavlseg::LEFT){ if(!left1.isPoint()){ sss.insert(left1); myinsertEvents(left1,false,true,q1,q2); } } assert(parts & myavlseg::COMMON); if(!common1.isPoint()){ sss.insert(common1); myinsertEvents(common1,false,true,q1,q2); } if(parts & myavlseg::RIGHT){ myinsertEvents(right1,true,true,q1,q2); } } } else { // no overlapping segment found MysplitByNeighbour(sss,current,leftN,q1,q2); MysplitByNeighbour(sss,current,rightN,q1,q2); if(!current.isPoint()){ sss.insert(current); myinsertEvents(current,false,true,q1,q2); } } } else { // nextHS rightDomPoint if(member && member->exactEqualsTo(current)){ // insert the segments into the result switch(op){ case myavlseg::union_op : { HalfSegment hs1 = member->convertToHs(true,myavlseg::first); hs1.attr.edgeno = edgeno; result += hs1; hs1.SetLeftDomPoint(false); result += hs1; edgeno++; break; } case myavlseg::intersection_op : { if(member->getOwner()== myavlseg::both){ HalfSegment hs1 = member->convertToHs(true, myavlseg::first); hs1.attr.edgeno = edgeno; result += hs1; hs1.SetLeftDomPoint(false); result += hs1; edgeno++; } break; } case myavlseg::difference_op :{ if(member->getOwner()== myavlseg::first){ HalfSegment hs1 = member->convertToHs(true, myavlseg::first); hs1.attr.edgeno = edgeno; result += hs1; hs1.SetLeftDomPoint(false); result += hs1; edgeno++; } break; } default : { assert(false); } } sss.remove(*member); MysplitNeighbours(sss,leftN,rightN,q1,q2); } } } result.EndBulkLoad(true,false); } // setop line x line -> line /* correct version of detecting the intersects of two halfsegments */ bool MyHSIntersects(const HalfSegment* hs1, const HalfSegment* hs2) { double k, a, K, A; if( !hs1->BoundingBox().Intersects( hs2->BoundingBox() ) ) return false; Coord xl = hs1->GetLeftPoint().GetX(), yl = hs1->GetLeftPoint().GetY(), xr = hs1->GetRightPoint().GetX(), yr = hs1->GetRightPoint().GetY(), Xl = hs2->GetLeftPoint().GetX(), Yl = hs2->GetLeftPoint().GetY(), Xr = hs2->GetRightPoint().GetX(), Yr = hs2->GetRightPoint().GetY(); if( AlmostEqual( xl, xr ) && AlmostEqual( Xl, Xr ) ) // both segments are vertical { if( AlmostEqual( xl, Xl ) && ( AlmostEqual( yl, Yl ) || AlmostEqual( yl, Yr ) || AlmostEqual( yr, Yl ) || AlmostEqual( yr, Yr ) || ( yl > Yl && yl < Yr ) || ( yr > Yl && yr < Yr ) || ( Yl > yl && Yl < yr ) || ( Yr > yl && Yr < yr ) ) ) return true; return false; } if( !AlmostEqual( xl, xr ) ) // this segment is not vertical { k = (yr - yl) / (xr - xl); a = yl - k * xl; } if( !AlmostEqual( Xl, Xr ) ) // hs is not vertical { K = (Yr - Yl) / (Xr - Xl); A = Yl - K * Xl; } if( AlmostEqual( Xl, Xr ) ) //only hs is vertical { Coord y0 = k * Xl + a; if( ( Xl > xl || AlmostEqual( Xl, xl ) ) && ( Xl < xr || AlmostEqual( Xl, xr ) ) ) { if( ( ( y0 > Yl || AlmostEqual( y0, Yl ) ) && ( y0 < Yr || AlmostEqual( y0, Yr ) ) ) || ( ( y0 > Yr || AlmostEqual( y0, Yr ) ) && ( y0 < Yl || AlmostEqual( y0, Yl ) ) ) ) // (Xl, y0) is the intersection point return true; } return false; } if( AlmostEqual( xl, xr ) ) // only this segment is vertical { Coord Y0 = K * xl + A; if( ( xl > Xl || AlmostEqual( xl, Xl ) ) && ( xl < Xr || AlmostEqual( xl, Xr ) ) ) { if( ( ( Y0 > yl || AlmostEqual( Y0, yl ) ) && ( Y0 < yr || AlmostEqual( Y0, yr ) ) ) || ( ( Y0 > yr || AlmostEqual( Y0, yr ) ) && ( Y0 < yl || AlmostEqual( Y0, yl ) ) ) ) // (xl, Y0) is the intersection point return true; } return false; } // both segments are non-vertical if( AlmostEqual( k, K ) ) // both segments have the same inclination { /*the original halfsegment::intersects function has a small bug, see if( AlmostEqual( A, a ) && ( ( xl > Xl || AlmostEqual( xl, Xl ) ) && ( xl < Xr || AlmostEqual( xl, Xr ) ) ) || ( ( Xl > xl || AlmostEqual( xl, Xl ) ) && ( Xl < xr || AlmostEqual( xr, Xl ) ) ) ){ return true; } it should be if( AlmostEqual( A, a ) && (( ( xl > Xl || AlmostEqual( xl, Xl ) ) && ( xl < Xr || AlmostEqual( xl, Xr ) ) ) || ( ( Xl > xl || AlmostEqual( xl, Xl ) ) && ( Xl < xr || AlmostEqual( xr, Xl ) ) )) ){ return true; }*/ if( AlmostEqual( A, a ) && (( ( xl > Xl || AlmostEqual( xl, Xl ) ) && ( xl < Xr || AlmostEqual( xl, Xr ) ) ) || ( ( Xl > xl || AlmostEqual( xl, Xl ) ) && ( Xl < xr || AlmostEqual( xr, Xl ) ) )) ) // the segments are in the same straight line return true; } else { Coord x0 = (A - a) / (k - K); // y0 = x0 * k + a; if( ( x0 > xl || AlmostEqual( x0, xl ) ) && ( x0 < xr || AlmostEqual( x0, xr ) ) && ( x0 > Xl || AlmostEqual( x0, Xl ) ) && ( x0 < Xr || AlmostEqual( x0, Xr ) ) ) // the segments intersect at (x0, y0) return true; } return false; } /* detect whether two regions intersect, by the correct intersection function between two halfsegments */ bool MyRegIntersects(const Region* reg1, const Region* reg2) { assert( reg1->IsDefined() ); assert( reg2->IsDefined() ); if( reg1->IsEmpty() || reg2->IsEmpty() ) return false; if( !reg1->BoundingBox().Intersects( reg2->BoundingBox() ) ) return false; assert( reg1->IsOrdered() ); assert( reg2->IsOrdered() ); if( reg1->Inside( *reg2 ) || reg2->Inside( *reg1 ) ) return true; HalfSegment hs1, hs2; for( int i = 0; i < reg1->Size(); i++ ) { reg1->Get( i, hs1 ); if( hs1.IsLeftDomPoint() ) { for( int j = 0; j < reg2->Size(); j++ ) { reg2->Get( j, hs2 ); if( hs2.IsLeftDomPoint() && MyHSIntersects(&hs1, &hs2)) return true; } } } return false; } /* It checks wheter the region contains the halfsegment. for the intersection point which is not the endpoint of the halfsegment, it should also check the middle point. */ bool RegContainHS(Region* r, HalfSegment hs) { BBox<2> bbox = r->BoundingBox(); if( !hs.GetLeftPoint().Inside(bbox) || !hs.GetRightPoint().Inside(bbox) ) return false; if( !r->Contains(hs.GetLeftPoint()) || !r->Contains(hs.GetRightPoint()) ) return false; HalfSegment auxhs; bool checkMidPoint = false; vector intersection_points; //now we know that both endpoints of hs is inside region for( int i = 0; i < r->Size(); i++ ){ r->Get(i, auxhs); if( auxhs.IsLeftDomPoint() ){ if( hs.Crosses(auxhs) ){ return false; } else if( hs.Inside(auxhs) ) //hs is part of the border return true; else if( hs.Intersects(auxhs)){ if(auxhs.Contains(hs.GetLeftPoint()) || auxhs.Contains(hs.GetRightPoint()) || hs.Contains(auxhs.GetLeftPoint()) || hs.Contains(auxhs.GetRightPoint())){ checkMidPoint = true; //the intersection point that is not the endpoint Point temp_p; if(hs.Intersection(auxhs,temp_p)) intersection_points.push_back(temp_p); HalfSegment temp_hs; if(hs.Intersection(auxhs, temp_hs)){ intersection_points.push_back(temp_hs.GetLeftPoint()); intersection_points.push_back(temp_hs.GetRightPoint()); } } } } } if( checkMidPoint ) { Point midp( true, ( hs.GetLeftPoint().GetX() + hs.GetRightPoint().GetX() ) / 2, ( hs.GetLeftPoint().GetY() + hs.GetRightPoint().GetY() ) / 2 ); if( !r->Contains( midp ) ) return false; } // cout<<"hs "<Contains(midp1)) return false; if(!r->Contains(midp2)) return false; } return true; } /* it checks whether a line is inside a region */ bool MyInside(Line* l, Region* r) { if(l->IsEmpty()) return false; if(r->IsEmpty()) return false; if(!r->BoundingBox().Contains(l->BoundingBox())) return false; assert(l->IsOrdered()); assert(r->IsOrdered()); for(int i = 0;i < l->Size();i++){ HalfSegment hs; l->Get(i, hs); if(!hs.IsLeftDomPoint()) continue; if(!RegContainHS(r, hs)) return false; } return true; } /* The following is the implementation of structure for space partition */ /* Default constructor function */ SpacePartition::SpacePartition() { l = NULL; resulttype = NULL; count = 0; } SpacePartition::SpacePartition(Relation* in_line):l(in_line),count(0){} /* take the input point as the center and delta as the radius a line function represented by a and b it returns the intersection point (only x value) for the circle and line function */ void SpacePartition::GetDeviation(Point center, double a, double b,double& x1, double& x2, int delta) { double x0 = center.GetX(); double y0 = center.GetY(); double A = 1 + a*a; double B = 2*a*(b-y0)-2*x0; // double C = x0*x0 + (b-y0)*(b-y0) - 1; double C = x0*x0 + (b-y0)*(b-y0) - delta*delta; x1 = (-B - sqrt(B*B-4*A*C))/(2*A); x2 = (-B + sqrt(B*B-4*A*C))/(2*A); } /* It checks whether the rotation from segment (p1-p0) to segment (p2-p0) is counterclockwise or clockwise TRUE--clockwise false--couterclockwise we define if three points are collinear, it is counter-clockwise */ bool SpacePartition::GetClockwise(Point& p0,Point& p1, Point& p2) { double x0 = p0.GetX(); double y0 = p0.GetY(); double x1 = p1.GetX(); double y1 = p1.GetY(); double x2 = p2.GetX(); double y2 = p2.GetY(); bool result; if(AlmostEqual(x0,x1)){ if(y1 >= y0){ // if(x2 < x0) result = false; if(x2 < x0 || AlmostEqual(x2,x0)) result = false; else result = true; }else{ if(x2 < x0) result = true; else result = false; } }else{ double slope = (y1-y0)/(x1-x0); /* if(AlmostEqual(y1,y0)) slope = 0; else slope = (y1-y0)/(x1-x0);*/ double intercept = y1-slope*x1; if(x1 < x0){ if(y2 < (slope*x2 + intercept)) result = false; else result = true; }else{ if(y2 < (slope*x2 + intercept)) result = true; else result = false; } } // if(result) cout<<"clockwise "<& boundary, int delta, bool clock_flag) { Point from = mhs.GetLeftPoint(); Point to = mhs.GetRightPoint(); Point next_from1; Point next_to1; Point p1,p2,p3,p4; if(AlmostEqual(from.GetX(),to.GetX())){ p1.Set(from.GetX() - delta,from.GetY()); p2.Set(from.GetX() + delta,from.GetY()); p3.Set(to.GetX() - delta, to.GetY()); p4.Set(to.GetX() + delta, to.GetY()); } else if(AlmostEqual(from.GetY(), to.GetY())){ p1.Set(from.GetX(), from.GetY() - delta); p2.Set(from.GetX(), from.GetY() + delta); p3.Set(to.GetX(), to.GetY() - delta); p4.Set(to.GetX(), to.GetY() + delta); }else{ double k1 = (from.GetY() - to.GetY())/(from.GetX() - to.GetX()); double k2 = -1/k1; double b1 = from.GetY() - k2*from.GetX(); double x1,x2; GetDeviation(from,k2,b1,x1,x2,delta); double y1 = x1*k2 + b1; double y2 = x2*k2 + b1; double x3,x4; double b2 = to.GetY() - k2*to.GetX(); GetDeviation(to,k2,b2,x3,x4,delta); double y3 = x3*k2 + b2; double y4 = x4*k2 + b2; p1.Set(x1,y1); p2.Set(x2,y2); p3.Set(x3,y3); p4.Set(x4,y4); // cout<<"k1: "< clock_wise; vector counterclock_wise; if(GetClockwise(from,to,p1)) clock_wise.push_back(p1); else counterclock_wise.push_back(p1); if(GetClockwise(from,to,p2)) clock_wise.push_back(p2); else counterclock_wise.push_back(p2); if(GetClockwise(from,to,p3)) clock_wise.push_back(p3); else counterclock_wise.push_back(p3); if(GetClockwise(from,to,p4)) clock_wise.push_back(p4); else counterclock_wise.push_back(p4); // cout<<"clock size "<(GetCloser(a1)); y1 = static_cast(GetCloser(b1)); x2 = static_cast(GetCloser(a2)); y2 = static_cast(GetCloser(b2)); HalfSegment hs2; Point p1,p2; p1.Set(x1,y1); p2.Set(x2,y2); if(p1.Distance(p2) > delta_dist){//////////////final check hs2.Set(true,p1,p2); hs2.attr.edgeno = edgeno++; *res += hs2; hs2.SetLeftDomPoint(!hs2.IsLeftDomPoint()); *res += hs2; } } /* for the given line stored in segs, it gets its left or right side line after transfer by a deviation given by delta */ void SpacePartition::Gettheboundary(vector& segs, vector& boundary, int delta, bool clock_wise) { const double delta_dist = 0.1; for(unsigned int i = 0;i < segs.size();i++){ TransferSegment(segs[i], boundary, delta, clock_wise); } //////// connect the new boundary //////////////////////// for(unsigned int i = 0;i < boundary.size() - 1; i++){ Point p1_1 = boundary[i].GetLeftPoint(); Point p1_2 = boundary[i].GetRightPoint(); Point p2_1 = boundary[i+1].GetLeftPoint(); Point p2_2 = boundary[i+1].GetRightPoint(); // cout< 5*delta){//reason: two roads points (y) too close // cout<<"special case: (needs to be processed)"<& segs,int delta, bool clock_wise, vector& outer, vector& outer_half) { const double delta_dist = 0.1; for(unsigned int i = 0;i < segs.size();i++){ // cout<<"start "< boundary; Gettheboundary(segs, boundary, delta, clock_wise); ///////////////////////add two more segments /////////////////////// Point old_start = segs[0].GetLeftPoint(); Point old_end = segs[segs.size() - 1].GetRightPoint(); Point new_start = boundary[0].GetLeftPoint(); Point new_end = boundary[boundary.size() - 1].GetRightPoint(); MyHalfSegment* mhs = new MyHalfSegment(true, old_start, new_start); boundary.push_back(*mhs); for(int i = boundary.size() - 2; i >= 0;i --) boundary[i+1] = boundary[i]; boundary[0] = *mhs; delete mhs; mhs = new MyHalfSegment(true,new_end,old_end); boundary.push_back(*mhs); delete mhs; if(clock_wise){ for(unsigned int i = 0;i < boundary.size();i++){ ///////////////outer segments//////////////////////////////// Point p = boundary[i].GetLeftPoint(); ModifyPoint(p); if(i == 0){ outer.push_back(boundary[i].GetLeftPoint()); outer_half.push_back(boundary[i].GetLeftPoint()); } else{ outer.push_back(p); outer_half.push_back(p); } } for(int i = segs.size() - 1; i >= 0; i--) outer_half.push_back(segs[i].GetRightPoint()); }else{ for(unsigned int i = 0; i < segs.size(); i++) outer_half.push_back(segs[i].GetLeftPoint()); for(int i = boundary.size() - 1;i >= 0;i--){ ///////////////////////////////////////////////////////////// Point p = boundary[i].GetRightPoint(); ModifyPoint(p); ///////////////////////////////////////////////////////////// if((unsigned)i == boundary.size() - 1){ outer.push_back(boundary[i].GetRightPoint()); outer_half.push_back(boundary[i].GetRightPoint()); }else{ outer.push_back(p); outer_half.push_back(p); } } } } /* For the given line, it gets all the points forming its boundary where delta defines the deviation of the left or right side line for transfer. It is to create the region covering both road and pavement so that the original road line is not used. This region is larger than the one created by function ExtendSeg1 because it contains pavements. */ void SpacePartition::ExtendSeg2(vector& segs,int delta, bool clock_wise, vector& outer) { const double delta_dist = 0.1; for(unsigned int i = 0;i < segs.size();i++){ // cout<<"start "< boundary; Gettheboundary(segs, boundary, delta, clock_wise); ///////////////////////add two more segments /////////////////////// Point old_start = segs[0].GetLeftPoint(); Point old_end = segs[segs.size() - 1].GetRightPoint(); Point new_start = boundary[0].GetLeftPoint(); Point new_end = boundary[boundary.size() - 1].GetRightPoint(); MyHalfSegment* mhs = new MyHalfSegment(true,old_start,new_start); boundary.push_back(*mhs); for(int i = boundary.size() - 2; i >= 0;i --) boundary[i+1] = boundary[i]; boundary[0] = *mhs; delete mhs; mhs = new MyHalfSegment(true,new_end,old_end); boundary.push_back(*mhs); delete mhs; if(clock_wise){ for(unsigned int i = 0;i < boundary.size();i++){ ///////////////outer segments//////////////////////////////// Point p = boundary[i].GetLeftPoint(); ModifyPoint(p); ///////////////////////////////////////////////////////// if(i == 0){ outer.push_back(boundary[i].GetLeftPoint()); } else{ outer.push_back(p); } } }else{ for(int i = boundary.size() - 1;i >= 0;i--){ ///////////////////////////////////////////////////////////// Point p = boundary[i].GetRightPoint(); ModifyPoint(p); ///////////////////////////////////////////////////////////// if((unsigned)i == boundary.size() - 1){ outer.push_back(boundary[i].GetRightPoint()); }else{ outer.push_back(p); } } } } /* For the given line, it gets all the points forming its boundary where delta defines the deviation of the left or right side line for transfer. */ void SpacePartition::ExtendSeg3(vector& segs,int delta, bool clock_wise, vector& outer) { const double delta_dist = 0.1; for(unsigned int i = 0;i < segs.size();i++){ // cout<<"start "< boundary; Gettheboundary(segs, boundary, delta, clock_wise); // cout<<"boundary size "<, with higher precision */ void SpacePartition::ReorderLine(SimpleLine* sline, vector& seq_halfseg) { if(!(sline->Size() > 0)){ cout<<__FILE__<<" "<<__LINE__<<" line empty "<AtPosition(0.0,true,sp)); vector copyline; for(int i = 0;i < sline->Size();i++){ HalfSegment hs; sline->Get(i,hs); if(hs.IsLeftDomPoint()){ Point lp = hs.GetLeftPoint(); Point rp = hs.GetRightPoint(); MyHalfSegment* mhs = new MyHalfSegment(true,lp,rp); copyline.push_back(*mhs); delete mhs; } } ////////////////reorder ///////////////////////////////////// /*for(unsigned i = 0;i < copyline.size();i++) copyline[i].Print();*/ const double delta_dist = 0.00001; unsigned int count = 0; while(count < copyline.size()){ vector pos; vector dist; for(unsigned int index = 0;index < copyline.size();index++){ if(copyline[index].def == false)continue; Point lp = copyline[index].GetLeftPoint(); Point rp = copyline[index].GetRightPoint(); double d1 = lp.Distance(sp); double d2 = rp.Distance(sp); if(d1 > delta_dist && d2 > delta_dist) continue; if(d1 < delta_dist){ pos.push_back(index); dist.push_back(d1); } if(d2 < delta_dist){ pos.push_back(index); dist.push_back(d2); } } assert(pos.size() > 0 && dist.size() > 0); double threshold_dist = numeric_limits::max(); int pos_index = -1; for(unsigned int i = 0;i < dist.size();i++){ if(dist[i] < threshold_dist){ pos_index = i; threshold_dist = dist[i]; } } assert(pos_index != -1); int find_pos = pos[pos_index]; Point from = copyline[find_pos].GetLeftPoint(); Point to = copyline[find_pos].GetRightPoint(); double dist1 = from.Distance(sp); double dist2 = to.Distance(sp); assert(dist1 < delta_dist || dist2 < delta_dist); if(dist1 < dist2){ sp = to; count++; copyline[find_pos].def = false; MyHalfSegment* mhs = new MyHalfSegment(true,from,to); seq_halfseg.push_back(*mhs); delete mhs; continue; }else{ sp = from; count++; copyline[find_pos].def = false; MyHalfSegment* mhs = new MyHalfSegment(true,to,from); seq_halfseg.push_back(*mhs); delete mhs; continue; } assert(false); } } /* for the given set of ordered points, it creates a region */ bool SpacePartition::CheckRegionPS(vector& outer_region) { ////////////whether two points are equal or segments overlapping //// if(outer_region.size() < 3){ return false; } //assert(outer_region.size() >= 3); vector flag_list; vector ps_list; for(unsigned int i = 0;i < outer_region.size();i++){ flag_list.push_back(true); ps_list.push_back(outer_region[i]); } for(unsigned int i = 0;i < outer_region.size() - 2;i++){ unsigned int j = i + 1; unsigned int k = j + 1; Point p1 = outer_region[i]; Point p2 = outer_region[j]; Point p3 = outer_region[k]; // cout<<"p1 "< 0.0) // cout<<"wrong overlapping segment"< 0.0){ // cout<<"wrong overlapping segments"< mhs; for(unsigned int i = 0;i < outer_region.size() - 1;i++){ Point from = outer_region[i]; unsigned int j = i + 1; while(j < outer_region.size()){ Point to = outer_region[j]; if(!AlmostEqual(from, to)){ MyHalfSegment my_hs(true, from, to); mhs.push_back(my_hs); break; }else j++; } } // cout<<"mhs size "< temp_mhs; // for(unsigned int i = 0;i < mhs.size() - 1;i++){ // unsigned int j = i + 1; // if(j == mhs.size()) break; // if(AlmostEqual(mhs[i].from, mhs[j].from) && // AlmostEqual(mhs[i].to, mhs[j].to)){ // cout<<"wrong"<= 3); if(outer_region.size() >= 3) return true; else return false; } /* this function is called by operator segment2region. It is to create the region for the road and pavement for each input route w is defined as the deviation */ void SpacePartition::ExtendRoad(int attr_pos, int w) { if(w < 3){ cout<<"road width should be larger than 2"<GetNoTuples();i++){ // Tuple* t = l->GetTuple(i); Tuple* t = l->GetTuple(i,false); SimpleLine* sline = (SimpleLine*)t->GetAttribute(attr_pos); vector seq_halfseg; //reorder it from start to end ReorderLine(sline, seq_halfseg); int delta1;//width of road on each side, depend on the road length int delta2; delta1 = w; int delta = w/2; if(delta < 2) delta = 2; delta2 = delta1 + delta; vector outer_s; vector outer1; vector outer2; vector outer4; vector outer_l; vector outer5; assert(delta1 != delta2); // cout<<"i "< 0;j--) outer_l[j] = outer_l[j-1]; outer_l[1] = outer_s[1]; outer_l.push_back(outer_s[outer_s.size() - 1]); int point_count1 = outer_s.size(); int point_count2 = outer_l.size(); //////////////////paveroad--larger///////////////////////////////// for(unsigned int j = 0;j < outer_l.size();j++) outer4.push_back(outer_l[j]); for(int j = seq_halfseg.size() - 1; j >= 0; j--) outer4.push_back(seq_halfseg[j].GetRightPoint()); ////////////////////////////////////////////////////////// ExtendSeg1(seq_halfseg, delta1, false, outer_s, outer2); ExtendSeg2(seq_halfseg, delta2, false,outer_l); //////////////////////////////////////////////////////////// outer_l.push_back(outer_s[point_count1+1]); for(int j = outer_l.size() - 1;j > point_count2;j--) outer_l[j] = outer_l[j-1]; outer_l[point_count2 + 1] = outer_s[point_count1 + 1]; outer_l.push_back(outer_s[outer_s.size() - 1]); //////////////////paveroad---larger//////////////////////////// for(unsigned int j = 0; j < seq_halfseg.size(); j++) outer5.push_back(seq_halfseg[j].GetLeftPoint()); for(unsigned int j = point_count2; j < outer_l.size();j++) outer5.push_back(outer_l[j]); ///////////////////////////////////////////////////////////// t->DeleteIfAllowed(); /////////////get the boundary////////////////// ComputeRegion(outer_s, outer_regions_s); assert(outer_regions_s.size() > 0); ComputeRegion(outer1, outer_regions1); assert(outer_regions1.size() > 0); ComputeRegion(outer2, outer_regions2); assert(outer_regions2.size() > 0); ComputeRegion(outer_l, outer_regions_l); assert(outer_regions_l.size() > 0); ComputeRegion(outer4, outer_regions4); assert(outer_regions4.size() > 0); ComputeRegion(outer5, outer_regions5); assert(outer_regions5.size() > 0); //////////////////////////////////////////////////////////////// ///////////////////////debuging//////////////////////////////// /////////////////////////////////////////////////////////////// // Region* res1 = new Region(0); // Region* res2 = new Region(0); // int reg_id = outer_regions_s.size() - 1; // outer_regions4[reg_id].Minus(outer_regions1[reg_id],*res1); // outer_regions5[reg_id].Minus(outer_regions2[reg_id],*res2); // // delete res1; // delete res2; } } /* cut the intersection region between pavement and road, especailly at junction */ void SpacePartition::ClipPaveRegion(Region& reg, vector& paves,int rid, Region* inborder) { Region* comm_reg = new Region(0); // reg.Intersection(*inborder,*comm_reg); MyIntersection(reg,*inborder,*comm_reg); Region* result = new Region(0); // reg.Minus(*comm_reg,*result); MyMinus(reg,*comm_reg,*result); paves[rid - 1] = *result; result->DeleteIfAllowed(); comm_reg->DeleteIfAllowed(); } /* fill the gap between two pavements at some junction positions */ void SpacePartition::FillPave(Network* n, vector& pavements1, vector& pavements2, vector& routes_length, vector& paves1, vector& paves2) { Relation* routes = n->GetRoutes(); Relation* juns = n->GetJunctions(); vector myjuns; for(int i = 1;i <= n->GetNoJunctions();i++){ Tuple* jun_tuple = juns->GetTuple(i,false); CcInt* rid1 = (CcInt*)jun_tuple->GetAttribute(JUNCTION_ROUTE1_ID); CcInt* rid2 = (CcInt*)jun_tuple->GetAttribute(JUNCTION_ROUTE2_ID); int id1 = rid1->GetIntval(); int id2 = rid2->GetIntval(); Point* junp = (Point*)jun_tuple->GetAttribute(JUNCTION_POS); CcReal* meas1 = (CcReal*)jun_tuple->GetAttribute(JUNCTION_ROUTE1_MEAS); CcReal* meas2 = (CcReal*)jun_tuple->GetAttribute(JUNCTION_ROUTE2_MEAS); double len1 = meas1->GetRealval(); double len2 = meas2->GetRealval(); MyJun mj(*junp, id1, id2, len1, len2); myjuns.push_back(mj); jun_tuple->DeleteIfAllowed(); } juns->Delete(); sort(myjuns.begin(), myjuns.end()); bool global_flag = false; const double delta_dist = 0.1; for(unsigned int i = 0 ;i < myjuns.size();i++){ Point loc = myjuns[i].loc; int rid1 = myjuns[i].rid1; int rid2 = myjuns[i].rid2; // cout<<"rid1 "< rids; int j1 = i - 1; while(j1 >= 0 && loc.Distance(myjuns[j1].loc) < delta_dist){ rids.push_back(myjuns[j1].rid1); rids.push_back(myjuns[j1].rid2); j1--; } unsigned int j2 = i; while(j2 < myjuns.size() && loc.Distance(myjuns[j2].loc)< delta_dist){ rids.push_back(myjuns[j2].rid1); rids.push_back(myjuns[j2].rid2); j2++; } if(rids.size() == 2){ NewFillPavement3(routes, rid1, rid2, &loc, pavements1, pavements2, rids, paves1, paves2); } if(rids.size() == 6){ NewFillPavement4(routes, rid1, rid2, &loc, pavements1, pavements2, rids, paves1, paves2); } ////////a special case for junction rid 2549--2550 /////////////////// //////////////////for Berlin Network //////////////////////////////// /////////////not so good, but it does not have to check every case//// if(rids.size() == 12 && global_flag == false){ bool flag1 = false; bool flag2 = false; for(unsigned int k1 = 0;k1 < rids.size();k1++){ if(rids[k1] == 2549) flag1 = true; if(rids[k1] == 2550) flag2 = true; } if(flag1 && flag2){ /* for(unsigned int k1= 0; k1 < rids.size();k1++) cout<& regs, Region* reg) { vector subregions; int no_faces = reg->NoComponents(); // cout<<"no_faces "<DeleteIfAllowed(); subregions[i].StartBulkLoad(); } for(int i = 0;i < reg->Size();i++){ HalfSegment hs; reg->Get(i,hs); int face = hs.attr.faceno; subregions[face] += hs; } for(int i = 0;i < no_faces;i++) subregions[i].EndBulkLoad(false,false,false,false); //////////////////////////new method////////////////////////////// Region* result = new Region(0); int count = 0; for(unsigned int i = 0;i < subregions.size();i++){ // if(subregions[i].Size() <= 6 || subregions[i].Area() < 3.0)continue; if(subregions[i].Size() <= 6 || fabs(subregions[i].Area()) < 3.0)continue; Region* temp = new Region(0); subregions[i].Union(*result, *temp); *result = *temp; temp->DeleteIfAllowed(); count++; } // cout<<"count "<SetNoComponents(count); regs.push_back(*result); result->DeleteIfAllowed(); } /* Create the pavement beside each road */ void SpacePartition::Getpavement(Network* n, Relation* rel1, int attr_pos, Relation* rel2, int attr_pos1, int attr_pos2, int w) { //cut the pavement for each junction vector pavements1; vector pavements2; Relation* routes = n->GetRoutes(); vector routes_length; for(int i = 1;i <= rel2->GetNoTuples();i++){ Tuple* tuple = rel2->GetTuple(i, false); Region* reg1 = (Region*)tuple->GetAttribute(attr_pos1); Region* reg2 = (Region*)tuple->GetAttribute(attr_pos2); pavements1.push_back(Region(*reg1,false)); pavements2.push_back(Region(*reg2,false)); tuple->DeleteIfAllowed(); Tuple* route_tuple = routes->GetTuple(i, false); CcReal* len = (CcReal*)route_tuple->GetAttribute(ROUTE_LENGTH); double length = len->GetRealval(); route_tuple->DeleteIfAllowed(); routes_length.push_back(length); } ////////////////////////////////////////////////////////////// Relation* juns = n->GetJunctions(); for(int i = 1;i <= n->GetNoJunctions();i++){ Tuple* jun_tuple = juns->GetTuple(i, false); CcInt* rid1 = (CcInt*)jun_tuple->GetAttribute(JUNCTION_ROUTE1_ID); CcInt* rid2 = (CcInt*)jun_tuple->GetAttribute(JUNCTION_ROUTE2_ID); int id1 = rid1->GetIntval(); int id2 = rid2->GetIntval(); // Point* junp = (Point*)jun_tuple->GetAttribute(JUNCTION_POS); // if(!(id1 == 2043 || id2 == 2043)) { // jun_tuple->DeleteIfAllowed(); // continue; // } // cout<<"rid1 "<GetAttribute(JUNCTION_ROUTE1_MEAS); // CcReal* meas2 = (CcReal*)jun_tuple->GetAttribute(JUNCTION_ROUTE2_MEAS); // double len1 = meas1->GetRealval(); // double len2 = meas2->GetRealval(); Region rid1_pave1 = pavements1[id1 - 1]; Region rid1_pave2 = pavements2[id1 - 1]; Region rid2_pave1 = pavements1[id2 - 1]; Region rid2_pave2 = pavements2[id2 - 1]; Tuple* inborder_tuple1 = rel1->GetTuple(id1, false); Tuple* inborder_tuple2 = rel1->GetTuple(id2, false); Region* reg1 = (Region*)inborder_tuple1->GetAttribute(attr_pos); Region* reg2 = (Region*)inborder_tuple2->GetAttribute(attr_pos); ClipPaveRegion(rid1_pave1,pavements1,id1,reg2); ClipPaveRegion(rid1_pave2,pavements2,id1,reg2); ClipPaveRegion(rid2_pave1,pavements1,id2,reg1); ClipPaveRegion(rid2_pave2,pavements2,id2,reg1); inborder_tuple1->DeleteIfAllowed(); inborder_tuple2->DeleteIfAllowed(); jun_tuple->DeleteIfAllowed(); } juns->Delete(); //////////////fill the hole of pavement///////////////////// vector newpave1; vector newpave2; for(unsigned int i = 0;i < pavements1.size();i++){ Region* reg = new Region(0); newpave1.push_back(*reg); newpave2.push_back(*reg); reg->DeleteIfAllowed(); } FillPave(n, pavements1, pavements2, routes_length, newpave1, newpave2); for(unsigned int i = 0;i < pavements1.size();i++){ Region* reg1 = new Region(0); MyUnion(pavements1[i], newpave1[i], *reg1); pavements1[i] = *reg1; reg1->DeleteIfAllowed(); Region* reg2 = new Region(0); MyUnion(pavements2[i], newpave2[i], *reg2); pavements2[i] = *reg2; reg2->DeleteIfAllowed(); } ///////////////////////////////////////////////////////////// for(unsigned int i = 0;i < pavements1.size();i++){ // outer_regions1.push_back(pavements1[i]); // outer_regions2.push_back(pavements2[i]); // cout<<"id "<StartBulkLoad(); // for(int i = 0; i < curve->Size();i++){ // HalfSegment hs; // curve->Get(i,hs); // // cout<<"old "<EndBulkLoad(); // } template< template class Array1, template class Array2> void SpacePartition::GetSubCurve( SimpleLineT* curve, LineT* newcurve, int roadwidth, bool clock) { newcurve->StartBulkLoad(); int edgeno = 0; for(int i = 0; i < curve->Size();i++){ HalfSegment hs; curve->Get(i, hs); if(hs.IsLeftDomPoint() == false) continue; // cout<<"old "<EndBulkLoad(); } /* build the zebracrossing at the junction position. The main determined input parameters are endpoints1 and endpoints2. If the four points can construct a zebra, returns true, otherwise return false */ template< template class Array1, template class Array2, template class Array3, template class Array4, template class Array5> bool SpacePartition::BuildZebraCrossing( vector& endpoints1, vector& endpoints2, RegionT* reg_pave1, RegionT* reg_pave2, LineT* pave1, RegionT* crossregion, Point& junp, RegionT* last_zc) { if(endpoints1.size() > 0 && endpoints2.size() > 0){ MyPoint lp = endpoints1[0]; MyPoint rp = endpoints2[0]; MMLine* pave = new MMLine(0); pave->StartBulkLoad(); HalfSegment hs; hs.Set(true,lp.loc,rp.loc); int edgeno = 0; hs.attr.edgeno = edgeno++; *pave += hs; hs.SetLeftDomPoint(!hs.IsLeftDomPoint()); *pave += hs; pave->EndBulkLoad(); //////////////extend it to a region///////////////////////////// HalfSegment hs1 = hs; HalfSegment hs2 = hs; TransferHalfSegment(hs1, 2, true); TransferHalfSegment(hs2, 2, false); vector outer_ps; vector result; Point lp1 = hs1.GetLeftPoint(); Point rp1 = hs1.GetRightPoint(); Point lp2 = hs2.GetLeftPoint(); Point rp2 = hs2.GetRightPoint(); Point mp1, mp2; mp1.Set((lp1.GetX() + rp1.GetX())/2, (lp1.GetY() + rp1.GetY())/2); mp2.Set((lp2.GetX() + rp2.GetX())/2, (lp2.GetY() + rp2.GetY())/2); if(mp1.Distance(junp) > mp2.Distance(junp)){ lp1 = hs.GetLeftPoint(); rp1 = hs.GetRightPoint(); lp2 = hs1.GetLeftPoint(); rp2 = hs1.GetRightPoint(); }else{ lp1 = hs.GetLeftPoint(); rp1 = hs.GetRightPoint(); lp2 = hs2.GetLeftPoint(); rp2 = hs2.GetRightPoint(); } /* if((lp2.Inside(*reg_pave1) && rp2.Inside(*reg_pave2)) || (lp2.Inside(*reg_pave2) && rp2.Inside(*reg_pave1)) ){ if(GetClockwise(lp2, lp1, rp2)){ outer_ps.push_back(lp2); outer_ps.push_back(rp2); outer_ps.push_back(rp1); outer_ps.push_back(lp1); }else{ outer_ps.push_back(lp1); outer_ps.push_back(rp1); outer_ps.push_back(rp2); outer_ps.push_back(lp2); } ComputeRegion(outer_ps, result); *crossregion = result[0]; *pave1 = *pave; delete pave; return true; }*/ // cout<<"lp2 "< outer_ps1; int index = (j + 1) % outer_ps.size(); for(unsigned int i = 0 ; i < outer_ps.size() ;i++){ Point p = outer_ps[index]; outer_ps1.push_back(p); index = (index + 1) % outer_ps.size(); ////////////////////2012.3.9//////////////////// if(outer_ps1.size() >= 2){ if(p.Distance(outer_ps1[outer_ps1.size() - 2]) < 0.001){ outer_ps1.clear(); break; } } /////////////////////////////////////////////////// } vector result1; // ComputeRegion(outer_ps1, result1); if(outer_ps1.size() >= 3)/////////2012.3.9 ComputeRegion(outer_ps1, result1); // if(result1[0].GetCycleDirection() && if(result1.size() > 0 && result1[0].GetCycleDirection() && result1[0].Intersects(*last_zc) == false){ *crossregion = result1[0]; *pave1 = *pave; pave->DeleteIfAllowed(); return true; } } } pave->DeleteIfAllowed(); /////////////////////////////////////////////////////////////// } endpoints1.clear(); endpoints2.clear(); return false; } /* for the road line around the junction position, it creates the zebra crossing */ template< template class Array1, template class Array2, template class Array3, template class Array4, template class Array5, template class Array6> void SpacePartition::GetZebraCrossing( SimpleLineT* subcurve, RegionT* reg_pave1, RegionT* reg_pave2, int roadwidth, LineT* pave1, double delta_l, Point p1, RegionT* crossregion, RegionT* last_zc) { vector endpoints1; vector endpoints2; double delta = 1.0; MMLine* subline1 = new MMLine(0); MMLine* subline2 = new MMLine(0); Point junp = p1; GetSubCurve(subcurve, subline1, roadwidth + 1, true); GetSubCurve(subcurve, subline2, roadwidth + 1, false); // *pave1 = *subline1; Point p2; double l; /* if(flag) l = delta; else l = subcurve->Length() - delta;*/ ////////////////////////////////////////////////////// Point startp, endp; assert(subcurve->AtPosition(0.0, true, startp)); assert(subcurve->AtPosition(subcurve->Length(), true, endp)); bool flag1; if(startp.Distance(p1) < endp.Distance(p1)){ flag1 = true; l = delta; } else{ l = subcurve->Length() - delta; flag1 = false; } // cout<<"flag1 "<Length()< subcurve->Length() || AlmostEqual(l, subcurve->Length())) break; } else{ l = l - delta; if(l < 0.0 || AlmostEqual(l, 0.0)) break; } assert(subcurve->AtPosition(l,true,p2)); if(MyAlmostEqual(p1.GetX(), p2.GetX())){ double y = p2.GetY(); double x1 = p2.GetX() - (roadwidth + 2); double x2 = p2.GetX() + (roadwidth + 2); MMLine* line1 = new MMLine(0); line1->StartBulkLoad(); HalfSegment hs; Point lp,rp; lp.Set(x1, y); rp.Set(x2, y); hs.Set(true,lp,rp); int edgeno = 0; hs.attr.edgeno = edgeno++; *line1 += hs; hs.SetLeftDomPoint(!hs.IsLeftDomPoint()); *line1 += hs; line1->EndBulkLoad(); MMPoints* ps1 = new MMPoints(0); MMPoints* ps2 = new MMPoints(0); subline1->Crossings(*line1, *ps1); subline2->Crossings(*line1, *ps2); if(ps1->Size() > 0 && ps2->Size() > 0 && ((ps1->Inside(*reg_pave1) && ps2->Inside(*reg_pave2)) || (ps1->Inside(*reg_pave2) && ps2->Inside(*reg_pave1)))){ // if(ps1->Size() > 0 && ps2->Size() > 0){ // cout<<"1 "<Size();i++){ Point p; ps1->Get(i,p); MyPoint mp(p,p.Distance(p2)); endpoints1.push_back(mp); } for(int i = 0;i < ps2->Size();i++){ Point p; ps2->Get(i,p); MyPoint mp(p, p.Distance(p2)); endpoints2.push_back(mp); } sort(endpoints1.begin(),endpoints1.end()); sort(endpoints2.begin(),endpoints2.end()); // find = true; find=BuildZebraCrossing(endpoints1, endpoints2, reg_pave1, reg_pave2, pave1, crossregion, junp,last_zc); } p1 = p2; ps1->DeleteIfAllowed(); ps2->DeleteIfAllowed(); line1->DeleteIfAllowed(); }else if(MyAlmostEqual(p1.GetY(), p2.GetY())){ double y1 = p2.GetY() - (roadwidth + 2); double y2 = p2.GetY() + (roadwidth + 2); double x = p2.GetX(); MMLine* line1 = new MMLine(0); line1->StartBulkLoad(); HalfSegment hs; Point lp,rp; lp.Set(x, y1); rp.Set(x, y2); hs.Set(true,lp,rp); int edgeno = 0; hs.attr.edgeno = edgeno++; *line1 += hs; hs.SetLeftDomPoint(!hs.IsLeftDomPoint()); *line1 += hs; line1->EndBulkLoad(); MMPoints* ps1 = new MMPoints(0); MMPoints* ps2 = new MMPoints(0); subline1->Crossings(*line1,*ps1); subline2->Crossings(*line1,*ps2); if(ps1->Size() > 0 && ps2->Size() > 0 && ((ps1->Inside(*reg_pave1) && ps2->Inside(*reg_pave2)) || (ps1->Inside(*reg_pave2) && ps2->Inside(*reg_pave1)))){ // if(ps1->Size() > 0 && ps2->Size() > 0){ // cout<<"2 "<Size();i++){ Point p; ps1->Get(i,p); MyPoint mp(p,p.Distance(p2)); endpoints1.push_back(mp); } for(int i = 0;i < ps2->Size();i++){ Point p; ps2->Get(i,p); MyPoint mp(p, p.Distance(p2)); endpoints2.push_back(mp); } sort(endpoints1.begin(),endpoints1.end()); sort(endpoints2.begin(),endpoints2.end()); // find = true; find=BuildZebraCrossing(endpoints1, endpoints2, reg_pave1, reg_pave2, pave1, crossregion, junp,last_zc); } p1 = p2; ps1->DeleteIfAllowed(); ps2->DeleteIfAllowed(); line1->DeleteIfAllowed(); }else{//not vertical double k1 = (p2.GetY() - p1.GetY())/(p2.GetX() - p1.GetX()); double k2 = -1/k1; double c2 = p2.GetY() - p2.GetX()*k2; double x1 = p2.GetX() - (roadwidth + 2); double x2 = p2.GetX() + (roadwidth + 2); MMLine* line1 = new MMLine(0); line1->StartBulkLoad(); HalfSegment hs; Point lp,rp; lp.Set(x1, x1*k2 + c2); rp.Set(x2, x2*k2 + c2); hs.Set(true,lp,rp); int edgeno = 0; hs.attr.edgeno = edgeno++; *line1 += hs; hs.SetLeftDomPoint(!hs.IsLeftDomPoint()); *line1 += hs; line1->EndBulkLoad(); MMPoints* ps1 = new MMPoints(0); MMPoints* ps2 = new MMPoints(0); subline1->Crossings(*line1,*ps1); subline2->Crossings(*line1,*ps2); if(ps1->Size() > 0 && ps2->Size() > 0 && ((ps1->Inside(*reg_pave1) && ps2->Inside(*reg_pave2)) || (ps1->Inside(*reg_pave2) && ps2->Inside(*reg_pave1)))){ // if(ps1->Size() > 0 && ps2->Size() > 0){ // cout<<"3 "<Size();i++){ Point p; ps1->Get(i,p); MyPoint mp(p, p.Distance(p2)); endpoints1.push_back(mp); } for(int i = 0;i < ps2->Size();i++){ Point p; ps2->Get(i,p); MyPoint mp(p, p.Distance(p2)); endpoints2.push_back(mp); } sort(endpoints1.begin(),endpoints1.end()); sort(endpoints2.begin(),endpoints2.end()); // find = true; find=BuildZebraCrossing(endpoints1, endpoints2, reg_pave1, reg_pave2, pave1, crossregion, junp,last_zc); } p1 = p2; ps1->DeleteIfAllowed(); ps2->DeleteIfAllowed(); line1->DeleteIfAllowed(); } } subline1->DeleteIfAllowed(); subline2->DeleteIfAllowed(); } /* Extend the line in decreasing direction */ template< template class Array1, template class Array2, template class Array3, template class Array4, template class Array5, template class Array6> void SpacePartition::Decrease( SimpleLineT* curve, RegionT* reg_pave1, RegionT* reg_pave2, double len, LineT* pave, int roadwidth, RegionT* crossregion, RegionT* last_zc) { double l = len; double delta_l = 20.0; Point p1; assert(curve->AtPosition(l, true, p1)); while(1){ MMSimpleLine* subcurve = new MMSimpleLine(0); if(l - delta_l > 0.0) curve->SubLine(l - delta_l, l, true, *subcurve); else curve->SubLine(0.0, l, true, *subcurve); GetZebraCrossing(subcurve, reg_pave1, reg_pave2, roadwidth, pave, delta_l, p1, crossregion, last_zc); subcurve->DeleteIfAllowed(); if(pave->Size() > 0 || delta_l >= curve->Length()) break; delta_l += delta_l; } } /* Extend the line in increasing direction */ template< template class Array1, template class Array2, template class Array3, template class Array4, template class Array5, template class Array6> void SpacePartition::Increase( SimpleLineT* curve, RegionT* reg_pave1, RegionT* reg_pave2, double len, LineT* pave, int roadwidth, RegionT* crossregion, RegionT* last_zc) { double route_length = curve->Length(); double l = len; double delta_l = 20.0; Point p1; assert(curve->AtPosition(l, true, p1)); // cout<<"increase p1 "<SubLine(l, l+delta_l, true, *subcurve); else curve->SubLine(l, route_length, true, *subcurve); // cout<<*subcurve<DeleteIfAllowed(); if(pave->Size() > 0 || delta_l >= route_length) break; delta_l += delta_l; } // cout<<"increase "<<*crossregion< class Array1, template class Array2, template class Array3, template class Array4, template class Array5, template class Array6> void SpacePartition::CreatePavement( SimpleLineT* curve, RegionT* reg_pave1, RegionT* reg_pave2, double len, int roadwidth, RegionT* cross1, RegionT* cross2, RegionT* last_zc) { MMLine* pave1 = new MMLine(0); MMLine* pave2 = new MMLine(0); if(MyAlmostEqual(curve->Length(), len)) Decrease(curve, reg_pave1, reg_pave2, len, pave2, roadwidth, cross2, last_zc);//-- else if(MyAlmostEqual(len, 0.0)) Increase(curve, reg_pave1, reg_pave2, len, pave1, roadwidth, cross1, last_zc);//++ else{ Increase(curve, reg_pave1, reg_pave2, len, pave1, roadwidth, cross1, last_zc); ///////////////////////////////////////////////// MMRegion* temp = new MMRegion(0); cross1->Union(*last_zc, *temp); *last_zc = *temp; temp->DeleteIfAllowed(); ///////////////////////////////////////////////// Decrease(curve, reg_pave1, reg_pave2, len, pave2, roadwidth, cross2, last_zc); } pave1->DeleteIfAllowed(); pave2->DeleteIfAllowed(); } /* check the existence of a road network position */ bool SpacePartition::RidPosExist(int rid, float pos, vector >& rid_pos_list) { if(rid_pos_list[rid - 1].size() == 0){ rid_pos_list[rid - 1].push_back(pos); return false; } for(unsigned int i = 0;i < rid_pos_list[rid - 1].size();i++){ if(fabs(rid_pos_list[rid - 1][i] - pos) < EPSDIST)return true; } rid_pos_list[rid - 1].push_back(pos); return false; } /* called by operator junregion */ void SpacePartition::Junpavement(Network* n, Relation* rel, int attr_pos1, int attr_pos2, int width, Relation* rel_road, int attr_pos3) { Flob::resetStatistics(); //get the pavement for each junction Relation* routes = n->GetRoutes(); vector zc_reg; vector > rid_pos_list; MMRegion* temp = new MMRegion(0); MMRegion* crossregion1 = new MMRegion(0); MMRegion* crossregion2 = new MMRegion(0); MMRegion* temp_reg = new MMRegion(0); MMRegion* crossregion3 = new MMRegion(0); MMRegion* crossregion4 = new MMRegion(0); MMRegion* cross12 = new MMRegion(0); for(int i = 0;i < routes->GetNoTuples();i++){ MMRegion* reg = new MMRegion(0); zc_reg.push_back(reg); vector real_list; rid_pos_list.push_back(real_list); } Relation* juns = n->GetJunctions(); for(int i = 1;i <= n->GetNoJunctions();i++){ Tuple* jun_tuple = juns->GetTuple(i, false); CcInt* rid1 = (CcInt*)jun_tuple->GetAttribute(JUNCTION_ROUTE1_ID); CcInt* rid2 = (CcInt*)jun_tuple->GetAttribute(JUNCTION_ROUTE2_ID); int id1 = rid1->GetIntval(); int id2 = rid2->GetIntval(); CcReal* meas1 = (CcReal*)jun_tuple->GetAttribute(JUNCTION_ROUTE1_MEAS); CcReal* meas2 = (CcReal*)jun_tuple->GetAttribute(JUNCTION_ROUTE2_MEAS); double len1 = meas1->GetRealval(); double len2 = meas2->GetRealval(); // cout<<"len1 "<GetTuple(id1, false); Tuple* inborder_tuple2 = rel->GetTuple(id2, false); Region* reg1_in = (Region*)inborder_tuple1->GetAttribute(attr_pos1); Region* reg1_out = (Region*)inborder_tuple1->GetAttribute(attr_pos2); Region* reg2_in = (Region*)inborder_tuple2->GetAttribute(attr_pos1); Region* reg2_out = (Region*)inborder_tuple2->GetAttribute(attr_pos2); //////////////////////////////////////////////////////// Tuple* route_tuple1 = routes->GetTuple(id1, false); SimpleLine* curve1 = (SimpleLine*)route_tuple1->GetAttribute(ROUTE_CURVE); if(RidPosExist(id1, len1, rid_pos_list) == false){//not expand yet CreatePavement(curve1, reg1_in, reg1_out, len1, width, crossregion1, crossregion2, temp_reg); if(zc_reg[id1 - 1]->Intersects(*crossregion1) == false){ zc_reg[id1 - 1]->Union(*crossregion1, *temp); MMRegion* rp = zc_reg[id1-1]; zc_reg[id1 - 1] = temp; temp = rp; } if(zc_reg[id1 - 1]->Intersects(*crossregion2) == false){ zc_reg[id1 - 1]->Union(*crossregion2, *temp); MMRegion* rp = zc_reg[id1 - 1]; zc_reg[id1 - 1] = temp; temp = rp; } } temp_reg->Clear(); Tuple* route_tuple2 = routes->GetTuple(id2, false); SimpleLine* curve2 = (SimpleLine*)route_tuple2->GetAttribute(ROUTE_CURVE); crossregion1->Union(*crossregion2, *cross12); /////////////////a special case, for the triangle area//////////////// if(id1 == 1402 && id2 == 1406){ *cross12 = *crossregion3; } if(RidPosExist(id2, len2, rid_pos_list) == false){//not expand yet. CreatePavement(curve2, reg2_in, reg2_out, len2, width, crossregion3, crossregion4, cross12); if(zc_reg[id2 - 1]->Intersects(*crossregion3) == false){ zc_reg[id2 - 1]->Union(*crossregion3, *temp); MMRegion* rp = zc_reg[id2 - 1]; zc_reg[id2 - 1] = temp; temp = rp; } if(zc_reg[id2 - 1]->Intersects(*crossregion4) == false){ zc_reg[id2 - 1]->Union(*crossregion4, *temp); MMRegion* rp = zc_reg[id2 - 1]; zc_reg[id2 - 1] = temp; temp = rp; } } cross12->Clear(); crossregion1->Clear(); crossregion2->Clear(); crossregion3->Clear(); crossregion4->Clear(); route_tuple1->DeleteIfAllowed(); route_tuple2->DeleteIfAllowed(); inborder_tuple1->DeleteIfAllowed(); inborder_tuple2->DeleteIfAllowed(); jun_tuple->DeleteIfAllowed(); } juns->Delete(); cout << "before copying regions, the statistic is " << endl; Flob::printStatistics(cout); cout << "----------------------" << endl << endl; size_t sum=0; for(unsigned int i = 0;i < zc_reg.size();i++){ junid1.push_back(i + 1); outer_regions1.push_back(*zc_reg[i]); cout << "region " << i << " has a size of " << zc_reg[i]->Size() << endl; sum += zc_reg[i]->Size(); zc_reg[i]->DeleteIfAllowed(); } cout << "result's size summarized is " << sum << endl; cout << "temporarly data has sizes " << endl; cout << "temp : " << temp->Size() << endl; cout << "crossregion1: " << crossregion1->Size() << endl; cout << "crossregion2: " << crossregion2->Size() << endl; cout << "crossregion3: " << crossregion3->Size() << endl; cout << "crossregion4: " << crossregion4->Size() << endl; cout << "temp_reg: " << temp_reg->Size() << endl; cout << "cross12: " << cross12->Size() << endl; temp->DeleteIfAllowed(); crossregion1->DeleteIfAllowed(); crossregion2->DeleteIfAllowed(); temp_reg->DeleteIfAllowed(); crossregion3->DeleteIfAllowed(); crossregion4->DeleteIfAllowed(); cross12->DeleteIfAllowed(); Flob::printStatistics(cout); } /* Detect whether three points collineation */ bool SpacePartition::Collineation(Point& p1, Point& p2, Point& p3) { if(MyAlmostEqual(p1.GetX(), p2.GetX())){ if(MyAlmostEqual(p2.GetX(), p3.GetX())) return true; } if(MyAlmostEqual(p1.GetY(), p2.GetY())){ if(MyAlmostEqual(p2.GetY(), p3.GetY())) return true; } double k1 = (p1.GetY() - p2.GetY())/(p1.GetX() - p2.GetX()); double k2 = (p2.GetY() - p3.GetY())/(p2.GetX() - p3.GetX()); if(MyAlmostEqual(k1, k2)) return true; return false; } /* check the junction position rids.size() != 2 rids.size() != 6 */ void SpacePartition::NewFillPavementDebug(Relation* rel, Relation* routes, int id1, int id2, Point* junp, int attr_pos1, int attr_pos2, vector rids) { Line* r1r2 = new Line(0); int edgeno = 0; double delta_dist = 0.1; r1r2->StartBulkLoad(); for(unsigned int i = 0;i < rids.size();i++){ // Tuple* route_tuple = routes->GetTuple(rids[i]); Tuple* route_tuple = routes->GetTuple(rids[i], false); SimpleLine* route = (SimpleLine*)route_tuple->GetAttribute(ROUTE_CURVE); for(int j = 0;j < route->Size();j++){ HalfSegment hs; route->Get(j,hs); if(hs.IsLeftDomPoint()){ Point lp = hs.GetLeftPoint(); Point rp = hs.GetRightPoint(); if(lp.Distance(*junp) < delta_dist || rp.Distance(*junp) < delta_dist){ HalfSegment newhs; newhs.Set(true,lp,rp); newhs.attr.edgeno = edgeno++; *r1r2 += newhs; newhs.SetLeftDomPoint(!newhs.IsLeftDomPoint()); *r1r2 += newhs; } } } route_tuple->DeleteIfAllowed(); } r1r2->EndBulkLoad(); // Tuple* pave_tuple1 = rel->GetTuple(id1); // Tuple* pave_tuple2 = rel->GetTuple(id2); Tuple* pave_tuple1 = rel->GetTuple(id1, false); Tuple* pave_tuple2 = rel->GetTuple(id2, false); Region* reg1_pave1 = (Region*)pave_tuple1->GetAttribute(attr_pos1); Region* reg1_pave2 = (Region*)pave_tuple1->GetAttribute(attr_pos2); Region* reg2_pave1 = (Region*)pave_tuple2->GetAttribute(attr_pos1); Region* reg2_pave2 = (Region*)pave_tuple2->GetAttribute(attr_pos2); if(reg1_pave1->Intersects(*reg2_pave1) == false){ junid1.push_back(id1); junid2.push_back(id2); pave_line1.push_back(*r1r2); outer_fillgap1.push_back(*reg1_pave1); outer_fillgap2.push_back(*reg2_pave1); Region* result1 = new Region(0); assert(reg1_pave1->GetCycleDirection()); assert(reg2_pave1->GetCycleDirection()); outer_fillgap.push_back(*result1); result1->DeleteIfAllowed(); } if(reg1_pave1->Intersects(*reg2_pave2) == false){ junid1.push_back(id1); junid2.push_back(id2); pave_line1.push_back(*r1r2); outer_fillgap1.push_back(*reg1_pave1); outer_fillgap2.push_back(*reg2_pave2); assert(reg1_pave1->GetCycleDirection()); assert(reg2_pave2->GetCycleDirection()); Region* result1 = new Region(0); outer_fillgap.push_back(*result1); result1->DeleteIfAllowed(); } if(reg1_pave2->Intersects(*reg2_pave1) == false ){ junid1.push_back(id1); junid2.push_back(id2); pave_line1.push_back(*r1r2); outer_fillgap1.push_back(*reg1_pave2); outer_fillgap2.push_back(*reg2_pave1); assert(reg1_pave2->GetCycleDirection()); assert(reg2_pave1->GetCycleDirection()); Region* result1 = new Region(0); outer_fillgap.push_back(*result1); result1->DeleteIfAllowed(); } if(reg1_pave2->Intersects(*reg2_pave2) == false){ junid1.push_back(id1); junid2.push_back(id2); pave_line1.push_back(*r1r2); outer_fillgap1.push_back(*reg1_pave2); outer_fillgap2.push_back(*reg2_pave2); assert(reg1_pave2->GetCycleDirection()); assert(reg2_pave2->GetCycleDirection()); Region* result1 = new Region(0); outer_fillgap.push_back(*result1); result1->DeleteIfAllowed(); } pave_tuple1->DeleteIfAllowed(); pave_tuple2->DeleteIfAllowed(); r1r2->DeleteIfAllowed(); } /* check for the junction where two road intersect rids.size() == 2, used by operator fillgap */ void SpacePartition::NewFillPavement1(Relation* rel, Relation* routes, int id1, int id2, Point* junp, int attr_pos1, int attr_pos2, vector rids) { Line* r1r2 = new Line(0); int edgeno = 0; double delta_dist = 0.1; r1r2->StartBulkLoad(); for(unsigned int i = 0;i < rids.size();i++){ // Tuple* route_tuple = routes->GetTuple(rids[i]); Tuple* route_tuple = routes->GetTuple(rids[i], false); SimpleLine* route = (SimpleLine*)route_tuple->GetAttribute(ROUTE_CURVE); for(int j = 0;j < route->Size();j++){ HalfSegment hs; route->Get(j,hs); if(hs.IsLeftDomPoint()){ Point lp = hs.GetLeftPoint(); Point rp = hs.GetRightPoint(); if(lp.Distance(*junp) < delta_dist || rp.Distance(*junp) < delta_dist){ HalfSegment newhs; newhs.Set(true,lp,rp); newhs.attr.edgeno = edgeno++; *r1r2 += newhs; newhs.SetLeftDomPoint(!newhs.IsLeftDomPoint()); *r1r2 += newhs; } } } route_tuple->DeleteIfAllowed(); } r1r2->EndBulkLoad(); // Tuple* pave_tuple1 = rel->GetTuple(id1); // Tuple* pave_tuple2 = rel->GetTuple(id2); Tuple* pave_tuple1 = rel->GetTuple(id1, false); Tuple* pave_tuple2 = rel->GetTuple(id2, false); Region* reg1_pave1 = (Region*)pave_tuple1->GetAttribute(attr_pos1); Region* reg1_pave2 = (Region*)pave_tuple1->GetAttribute(attr_pos2); Region* reg2_pave1 = (Region*)pave_tuple2->GetAttribute(attr_pos1); Region* reg2_pave2 = (Region*)pave_tuple2->GetAttribute(attr_pos2); // if(reg1_pave1->Intersects(*reg2_pave1) == false && if(PavementIntersection(reg1_pave1, reg2_pave1) == false && SameSide1(reg1_pave1, reg2_pave1, r1r2, junp)){ junid1.push_back(id1); junid2.push_back(id2); pave_line1.push_back(*r1r2); outer_fillgap1.push_back(*reg1_pave1); outer_fillgap2.push_back(*reg2_pave1); Region* result1 = new Region(0); assert(reg1_pave1->GetCycleDirection()); assert(reg2_pave1->GetCycleDirection()); // cout<DeleteIfAllowed(); } // if(reg1_pave1->Intersects(*reg2_pave2) == false && if(PavementIntersection(reg1_pave1, reg2_pave2) == false && SameSide1(reg1_pave1, reg2_pave2, r1r2, junp)){ junid1.push_back(id1); junid2.push_back(id2); pave_line1.push_back(*r1r2); outer_fillgap1.push_back(*reg1_pave1); outer_fillgap2.push_back(*reg2_pave2); assert(reg1_pave1->GetCycleDirection()); assert(reg2_pave2->GetCycleDirection()); Region* result1 = new Region(0); MyUnion(*reg1_pave1, outer_fillgap[outer_fillgap.size() - 1], *result1); // outer_fillgap1.push_back(*result1); // outer_fillgap2.push_back(*reg2_pave1); result1->DeleteIfAllowed(); } // if(reg1_pave2->Intersects(*reg2_pave1) == false && if(PavementIntersection(reg1_pave2, reg2_pave1) == false && SameSide1(reg1_pave2, reg2_pave1, r1r2, junp)){ junid1.push_back(id1); junid2.push_back(id2); pave_line1.push_back(*r1r2); outer_fillgap1.push_back(*reg1_pave2); outer_fillgap2.push_back(*reg2_pave1); assert(reg1_pave2->GetCycleDirection()); assert(reg2_pave1->GetCycleDirection()); Region* result1 = new Region(0); MyUnion(*reg1_pave2, outer_fillgap[outer_fillgap.size() - 1], *result1); // outer_fillgap1.push_back(*result1); // outer_fillgap2.push_back(*reg2_pave1); result1->DeleteIfAllowed(); } // if(reg1_pave2->Intersects(*reg2_pave2) == false && if(PavementIntersection(reg1_pave2, reg2_pave2) == false && SameSide1(reg1_pave2, reg2_pave2, r1r2, junp)){ junid1.push_back(id1); junid2.push_back(id2); pave_line1.push_back(*r1r2); outer_fillgap1.push_back(*reg1_pave2); outer_fillgap2.push_back(*reg2_pave2); assert(reg1_pave2->GetCycleDirection()); assert(reg2_pave2->GetCycleDirection()); Region* result1 = new Region(0); MyUnion(*reg1_pave2, outer_fillgap[outer_fillgap.size() - 1], *result1); // outer_fillgap1.push_back(*result1); // outer_fillgap2.push_back(*reg2_pave1); result1->DeleteIfAllowed(); } pave_tuple1->DeleteIfAllowed(); pave_tuple2->DeleteIfAllowed(); r1r2->DeleteIfAllowed(); } /* check for the junction where three roads intersect called by operator fillgap */ void SpacePartition:: NewFillPavement2(Relation* rel, Relation* routes, int id1, int id2, Point* junp, int attr_pos1, int attr_pos2, vector rids) { Line* r1r2 = new Line(0); int edgeno = 0; double delta_dist = 0.1; r1r2->StartBulkLoad(); MyHalfSegment firstseg; MyHalfSegment secondseg; MyHalfSegment thirdseg; int third_seg = 0; for(unsigned int i = 0;i < rids.size();i++){ // Tuple* route_tuple = routes->GetTuple(rids[i]); Tuple* route_tuple = routes->GetTuple(rids[i], false); SimpleLine* route = (SimpleLine*)route_tuple->GetAttribute(ROUTE_CURVE); for(int j = 0;j < route->Size();j++){ HalfSegment hs; route->Get(j,hs); if(hs.IsLeftDomPoint()){ Point lp = hs.GetLeftPoint(); Point rp = hs.GetRightPoint(); if(lp.Distance(*junp) < delta_dist || rp.Distance(*junp) < delta_dist){ HalfSegment newhs; newhs.Set(true,lp,rp); newhs.attr.edgeno = edgeno++; *r1r2 += newhs; newhs.SetLeftDomPoint(!newhs.IsLeftDomPoint()); *r1r2 += newhs; if(rids[i] != id1 && rids[i] != id2){ third_seg++; if(lp.Distance(*junp) < delta_dist){ thirdseg.def = true; thirdseg.from = lp; thirdseg.to = rp; }else{ thirdseg.def = true; thirdseg.from = rp; thirdseg.to = lp; } } if(rids[i] == id1){ if(lp.Distance(*junp) < delta_dist){ firstseg.def = true; firstseg.from = lp; firstseg.to = rp; }else{ firstseg.def = true; firstseg.from = rp; firstseg.to = lp; } } if(rids[i] == id2){ if(lp.Distance(*junp) < delta_dist){ secondseg.def = true; secondseg.from = lp; secondseg.to = rp; }else{ secondseg.def = true; secondseg.from = rp; secondseg.to = lp; } } } } } route_tuple->DeleteIfAllowed(); } r1r2->EndBulkLoad(); if(third_seg > 2){ r1r2->DeleteIfAllowed(); return; } //////////////////////////////// double angle1 = GetAngle(firstseg.from, firstseg.to, thirdseg.to); double angle2 = GetAngle(firstseg.from, firstseg.to, secondseg.to); bool clock1 = GetClockwise(firstseg.from, firstseg.to, thirdseg.to); bool clock2 = GetClockwise(firstseg.from, firstseg.to, secondseg.to); if(clock2){ if(clock1){ if(angle1 > angle2){ r1r2->DeleteIfAllowed(); return; } }else{ r1r2->DeleteIfAllowed(); return; } }else{ if(clock1 == false){ if(angle1 > angle2){ r1r2->DeleteIfAllowed(); return; } }else{ r1r2->DeleteIfAllowed(); return; } } ////////////////////////////// vector ps; vector smallreg; ps.push_back(firstseg.from); ps.push_back(firstseg.to); ps.push_back(thirdseg.to); ps.push_back(secondseg.to); ComputeRegion(ps, smallreg); assert(smallreg.size() > 0); ////////////////////////////// Tuple* pave_tuple1 = rel->GetTuple(id1, false); Tuple* pave_tuple2 = rel->GetTuple(id2, false); Region* reg1_pave1 = (Region*)pave_tuple1->GetAttribute(attr_pos1); Region* reg1_pave2 = (Region*)pave_tuple1->GetAttribute(attr_pos2); Region* reg2_pave1 = (Region*)pave_tuple2->GetAttribute(attr_pos1); Region* reg2_pave2 = (Region*)pave_tuple2->GetAttribute(attr_pos2); if(PavementIntersection(reg1_pave1, reg2_pave2) == false && SameSide2(reg1_pave1, reg2_pave1, r1r2, junp, thirdseg, smallreg[0])){ /* if(third_seg > 2){ cout<<"1"<GetCycleDirection()); assert(reg2_pave1->GetCycleDirection()); MyUnion(*reg1_pave1, outer_fillgap[outer_fillgap.size() - 1], *result1); result1->DeleteIfAllowed(); } if(PavementIntersection(reg1_pave1, reg2_pave2) == false && SameSide2(reg1_pave1, reg2_pave2, r1r2, junp, thirdseg, smallreg[0])){ // if(third_seg > 2){ // cout<<"2"<GetCycleDirection()); assert(reg2_pave2->GetCycleDirection()); Region* result1 = new Region(0); MyUnion(*reg1_pave1, outer_fillgap[outer_fillgap.size() - 1], *result1); result1->DeleteIfAllowed(); } if(PavementIntersection(reg1_pave2, reg2_pave1) == false && SameSide2(reg1_pave2, reg2_pave1, r1r2, junp, thirdseg, smallreg[0])){ // if(third_seg > 2){ // cout<<"3"<GetCycleDirection()); assert(reg2_pave1->GetCycleDirection()); Region* result1 = new Region(0); MyUnion(*reg1_pave2, outer_fillgap[outer_fillgap.size() - 1], *result1); result1->DeleteIfAllowed(); } if(PavementIntersection(reg1_pave2, reg2_pave2) == false && SameSide2(reg1_pave2, reg2_pave2, r1r2, junp, thirdseg, smallreg[0])){ // if(third_seg > 2){ // cout<<"4"<GetCycleDirection()); assert(reg2_pave2->GetCycleDirection()); Region* result1 = new Region(0); MyUnion(*reg1_pave2, outer_fillgap[outer_fillgap.size() - 1], *result1); result1->DeleteIfAllowed(); } pave_tuple1->DeleteIfAllowed(); pave_tuple2->DeleteIfAllowed(); r1r2->DeleteIfAllowed(); } /* the same function as in NewFillPavement2, but with different input parameters called by function FillPave() */ void SpacePartition::NewFillPavement3(Relation* routes, int id1, int id2, Point* junp, vector& paves1, vector& paves2, vector rids, vector& newpaves1, vector& newpaves2) { Line* r1r2 = new Line(0); int edgeno = 0; double delta_dist = 0.1; r1r2->StartBulkLoad(); for(unsigned int i = 0;i < rids.size();i++){ // Tuple* route_tuple = routes->GetTuple(rids[i]); Tuple* route_tuple = routes->GetTuple(rids[i], false); SimpleLine* route = (SimpleLine*)route_tuple->GetAttribute(ROUTE_CURVE); for(int j = 0;j < route->Size();j++){ HalfSegment hs; route->Get(j,hs); if(hs.IsLeftDomPoint()){ Point lp = hs.GetLeftPoint(); Point rp = hs.GetRightPoint(); if(lp.Distance(*junp) < delta_dist || rp.Distance(*junp) < delta_dist){ HalfSegment newhs; newhs.Set(true,lp,rp); newhs.attr.edgeno = edgeno++; *r1r2 += newhs; newhs.SetLeftDomPoint(!newhs.IsLeftDomPoint()); *r1r2 += newhs; } } } route_tuple->DeleteIfAllowed(); } r1r2->EndBulkLoad(); Region* reg1_pave1 = &paves1[id1 - 1]; Region* reg1_pave2 = &paves2[id1 - 1]; Region* reg2_pave1 = &paves1[id2 - 1]; Region* reg2_pave2 = &paves2[id2 - 1]; if(PavementIntersection(reg1_pave1, reg2_pave1) == false && SameSide1(reg1_pave1, reg2_pave1, r1r2, junp)){ Region* result = new Region(0); assert(reg1_pave1->GetCycleDirection()); assert(reg2_pave1->GetCycleDirection()); MyUnion(newpaves1[id1 - 1], outer_fillgap[outer_fillgap.size() - 1], *result); newpaves1[id1 - 1] = *result; result->DeleteIfAllowed(); } if(PavementIntersection(reg1_pave1, reg2_pave2) == false && SameSide1(reg1_pave1, reg2_pave2, r1r2, junp)){ assert(reg1_pave1->GetCycleDirection()); assert(reg2_pave2->GetCycleDirection()); Region* result = new Region(0); MyUnion(newpaves1[id1 - 1], outer_fillgap[outer_fillgap.size() - 1], *result); newpaves1[id1 - 1] = *result; result->DeleteIfAllowed(); } if(PavementIntersection(reg1_pave2, reg2_pave1) == false && SameSide1(reg1_pave2, reg2_pave1, r1r2, junp)){ assert(reg1_pave2->GetCycleDirection()); assert(reg2_pave1->GetCycleDirection()); Region* result = new Region(0); MyUnion(newpaves2[id1 - 1], outer_fillgap[outer_fillgap.size() - 1], *result); newpaves2[id1 - 1] = *result; result->DeleteIfAllowed(); } if(PavementIntersection(reg1_pave2, reg2_pave2) == false && SameSide1(reg1_pave2, reg2_pave2, r1r2, junp)){ assert(reg1_pave2->GetCycleDirection()); assert(reg2_pave2->GetCycleDirection()); Region* result = new Region(0); MyUnion(newpaves2[id1 - 1], outer_fillgap[outer_fillgap.size() - 1], *result); newpaves2[id1 - 1] = *result; result->DeleteIfAllowed(); } r1r2->DeleteIfAllowed(); } /* the same function as NewFillPavement2, but with different input parameters called by function FillPave() */ void SpacePartition::NewFillPavement4(Relation* routes, int id1, int id2, Point* junp, vector& paves1, vector& paves2, vector rids, vector& newpaves1, vector& newpaves2) { Line* r1r2 = new Line(0); int edgeno = 0; double delta_dist = 0.1; r1r2->StartBulkLoad(); MyHalfSegment firstseg; MyHalfSegment secondseg; MyHalfSegment thirdseg; int third_seg = 0; for(unsigned int i = 0;i < rids.size();i++){ // Tuple* route_tuple = routes->GetTuple(rids[i]); Tuple* route_tuple = routes->GetTuple(rids[i], false); SimpleLine* route = (SimpleLine*)route_tuple->GetAttribute(ROUTE_CURVE); for(int j = 0;j < route->Size();j++){ HalfSegment hs; route->Get(j,hs); if(hs.IsLeftDomPoint()){ Point lp = hs.GetLeftPoint(); Point rp = hs.GetRightPoint(); if(lp.Distance(*junp) < delta_dist || rp.Distance(*junp) < delta_dist){ HalfSegment newhs; newhs.Set(true,lp,rp); newhs.attr.edgeno = edgeno++; *r1r2 += newhs; newhs.SetLeftDomPoint(!newhs.IsLeftDomPoint()); *r1r2 += newhs; if(rids[i] != id1 && rids[i] != id2){ third_seg++; if(lp.Distance(*junp) < delta_dist){ thirdseg.def = true; thirdseg.from = lp; thirdseg.to = rp; }else{ thirdseg.def = true; thirdseg.from = rp; thirdseg.to = lp; } } if(rids[i] == id1){ if(lp.Distance(*junp) < delta_dist){ firstseg.def = true; firstseg.from = lp; firstseg.to = rp; }else{ firstseg.def = true; firstseg.from = rp; firstseg.to = lp; } } if(rids[i] == id2){ if(lp.Distance(*junp) < delta_dist){ secondseg.def = true; secondseg.from = lp; secondseg.to = rp; }else{ secondseg.def = true; secondseg.from = rp; secondseg.to = lp; } } } } } route_tuple->DeleteIfAllowed(); } r1r2->EndBulkLoad(); if(third_seg > 2){ r1r2->DeleteIfAllowed(); return; } //////////////////////////////// double angle1 = GetAngle(firstseg.from, firstseg.to, thirdseg.to); double angle2 = GetAngle(firstseg.from, firstseg.to, secondseg.to); bool clock1 = GetClockwise(firstseg.from, firstseg.to, thirdseg.to); bool clock2 = GetClockwise(firstseg.from, firstseg.to, secondseg.to); if(clock2){ if(clock1){ if(angle1 > angle2){ r1r2->DeleteIfAllowed(); return; } }else{ r1r2->DeleteIfAllowed(); return; } }else{ if(clock1 == false){ if(angle1 > angle2){ r1r2->DeleteIfAllowed(); return; } }else{ r1r2->DeleteIfAllowed(); return; } } ////////////////////////////// vector ps; vector smallreg; ps.push_back(firstseg.from); ps.push_back(firstseg.to); ps.push_back(thirdseg.to); ps.push_back(secondseg.to); ComputeRegion(ps, smallreg); assert(smallreg.size() > 0); ////////////////////////////// Region* reg1_pave1 = &paves1[id1 - 1]; Region* reg1_pave2 = &paves2[id1 - 1]; Region* reg2_pave1 = &paves1[id2 - 1]; Region* reg2_pave2 = &paves2[id2 - 1]; // if(PavementIntersection(reg1_pave1, reg2_pave2) == false && if(PavementIntersection(reg1_pave1, reg2_pave1) == false && SameSide2(reg1_pave1, reg2_pave1, r1r2, junp, thirdseg, smallreg[0])){ Region* result = new Region(0); assert(reg1_pave1->GetCycleDirection()); assert(reg2_pave1->GetCycleDirection()); MyUnion(newpaves1[id1 - 1], outer_fillgap[outer_fillgap.size() - 1], *result); newpaves1[id1 - 1] = *result; result->DeleteIfAllowed(); } if(PavementIntersection(reg1_pave1, reg2_pave2) == false && SameSide2(reg1_pave1, reg2_pave2, r1r2, junp, thirdseg, smallreg[0])){ assert(reg1_pave1->GetCycleDirection()); assert(reg2_pave2->GetCycleDirection()); Region* result = new Region(0); MyUnion(newpaves1[id1 - 1], outer_fillgap[outer_fillgap.size() - 1], *result); newpaves1[id1 - 1] = *result; result->DeleteIfAllowed(); } if(PavementIntersection(reg1_pave2, reg2_pave1) == false && SameSide2(reg1_pave2, reg2_pave1, r1r2, junp, thirdseg, smallreg[0])){ assert(reg1_pave2->GetCycleDirection()); assert(reg2_pave1->GetCycleDirection()); Region* result = new Region(0); MyUnion(newpaves2[id1 - 1], outer_fillgap[outer_fillgap.size() - 1], *result); newpaves2[id1 - 1] = *result; result->DeleteIfAllowed(); } if(PavementIntersection(reg1_pave2, reg2_pave2) == false && SameSide2(reg1_pave2, reg2_pave2, r1r2, junp, thirdseg, smallreg[0])){ assert(reg1_pave2->GetCycleDirection()); assert(reg2_pave2->GetCycleDirection()); Region* result = new Region(0); MyUnion(newpaves2[id1 - 1], outer_fillgap[outer_fillgap.size() - 1], *result); newpaves2[id1 - 1] = *result; result->DeleteIfAllowed(); } r1r2->DeleteIfAllowed(); } /* a special function for junction- rid 2549 and 2550 */ void SpacePartition::NewFillPavement5(Relation* routes, int id1, int id2, Point* junp, vector& paves1, vector& paves2, vector rids, vector& newpaves1, vector& newpaves2) { Line* r1r2 = new Line(0); int edgeno = 0; double delta_dist = 0.1; r1r2->StartBulkLoad(); for(unsigned int i = 0;i < rids.size();i++){ // Tuple* route_tuple = routes->GetTuple(rids[i]); Tuple* route_tuple = routes->GetTuple(rids[i], false); SimpleLine* route = (SimpleLine*)route_tuple->GetAttribute(ROUTE_CURVE); for(int j = 0;j < route->Size();j++){ HalfSegment hs; route->Get(j,hs); if(hs.IsLeftDomPoint()){ Point lp = hs.GetLeftPoint(); Point rp = hs.GetRightPoint(); if(lp.Distance(*junp) < delta_dist || rp.Distance(*junp) < delta_dist){ HalfSegment newhs; newhs.Set(true,lp,rp); newhs.attr.edgeno = edgeno++; *r1r2 += newhs; newhs.SetLeftDomPoint(!newhs.IsLeftDomPoint()); *r1r2 += newhs; } } } route_tuple->DeleteIfAllowed(); } r1r2->EndBulkLoad(); Region* reg1_pave1 = &paves1[id1 - 1]; Region* reg2_pave1 = &paves1[id2 - 1]; if(PavementIntersection(reg1_pave1, reg2_pave1) == false && SameSide1(reg1_pave1, reg2_pave1, r1r2, junp)){ Region* result = new Region(0); assert(reg1_pave1->GetCycleDirection()); assert(reg2_pave1->GetCycleDirection()); MyUnion(newpaves1[id1 - 1], outer_fillgap[outer_fillgap.size() - 1], *result); newpaves1[id1 - 1] = *result; result->DeleteIfAllowed(); } r1r2->DeleteIfAllowed(); } /* for operator fillgap */ void SpacePartition::FillHoleOfPave(Network* n, Relation* rel, int attr_pos1, int attr_pos2, int width) { Relation* routes = n->GetRoutes(); Relation* juns = n->GetJunctions(); vector routes_length; double min_length = numeric_limits::max(); double max_length = numeric_limits::min(); for(int i = 1;i <= routes->GetNoTuples();i++){ Tuple* route_tuple = routes->GetTuple(i, false); CcReal* len = (CcReal*)route_tuple->GetAttribute(ROUTE_LENGTH); double length = len->GetRealval(); if(length < min_length) min_length = length; if(length > max_length) max_length = length; route_tuple->DeleteIfAllowed(); routes_length.push_back(length); } ////////////////////////////////////////////////////////////////// // vector pavements1; // vector pavements2; // for(int i = 1;i <= rel->GetNoTuples();i++){ // Tuple* pave_tuple = rel->GetTuple(i, false); // Region* reg1 = (Region*)pave_tuple->GetAttribute(attr_pos1); // Region* reg2 = (Region*)pave_tuple->GetAttribute(attr_pos2); // pavements1.push_back(*reg1); // pavements2.push_back(*reg2); // pave_tuple->DeleteIfAllowed(); // } // // vector newpave1; // vector newpave2; // for(unsigned int i = 0;i < pavements1.size();i++){ // Region* reg = new Region(0); // newpave1.push_back(*reg); // newpave2.push_back(*reg); // delete reg; // } // FillPave(n, pavements1, pavements2, routes_length, newpave1, newpave2); // for(unsigned int i = 0;i < pavements1.size();i++){ // // cout<<"i "< myjuns; for(int i = 1;i <= n->GetNoJunctions();i++){ Tuple* jun_tuple = juns->GetTuple(i, false); CcInt* rid1 = (CcInt*)jun_tuple->GetAttribute(JUNCTION_ROUTE1_ID); CcInt* rid2 = (CcInt*)jun_tuple->GetAttribute(JUNCTION_ROUTE2_ID); int id1 = rid1->GetIntval(); int id2 = rid2->GetIntval(); Point* junp = (Point*)jun_tuple->GetAttribute(JUNCTION_POS); // cout<<"rid1 "<GetAttribute(JUNCTION_ROUTE1_MEAS); CcReal* meas2 = (CcReal*)jun_tuple->GetAttribute(JUNCTION_ROUTE2_MEAS); double len1 = meas1->GetRealval(); double len2 = meas2->GetRealval(); MyJun mj(*junp, id1, id2, len1, len2); myjuns.push_back(mj); jun_tuple->DeleteIfAllowed(); } juns->Delete(); sort(myjuns.begin(), myjuns.end()); // for(unsigned int i = 0;i < myjuns.size();i++) // myjuns[i].Print(); const double delta_dist = 0.1; for(unsigned int i = 0 ;i < myjuns.size();i++){ Point loc = myjuns[i].loc; int rid1 = myjuns[i].rid1; int rid2 = myjuns[i].rid2; // cout<<"rid1 "< rids; int j1 = i - 1; while(j1 >= 0 && loc.Distance(myjuns[j1].loc) < delta_dist){ rids.push_back(myjuns[j1].rid1); rids.push_back(myjuns[j1].rid2); j1--; } unsigned int j2 = i; while(j2 < myjuns.size() && loc.Distance(myjuns[j2].loc) < delta_dist){ rids.push_back(myjuns[j2].rid1); rids.push_back(myjuns[j2].rid2); j2++; } // cout<<" rids size "<DeleteIfAllowed(); } StrRS::StrRS(Network* net,Relation* rel1, Relation* rel2):n(net), r1(rel1), r2(rel2), count(0),resulttype(NULL) { } /* for each route, it creates a set of sections from that route where the intersecting places can locate. It is according to the position of each junction. The sections should not intersect the junction area (zebra crossing). For each junction position, w meters before it and w meters after it, these places are available. */ void StrRS::GetSections(int attr_pos1, int attr_pos2, int attr_pos3) { const double dist_delta = 10.0; for(int i = 1;i <= r2->GetNoTuples();i++){ Tuple* cross_tuple = r2->GetTuple(i, false); CcInt* rid = (CcInt*)cross_tuple->GetAttribute(attr_pos2); Region* cross_reg = (Region*)cross_tuple->GetAttribute(attr_pos3); // cout<<"rid "<GetIntval()<GetTuple(rid->GetIntval(), false); SimpleLine* sl = (SimpleLine*)route_tuple->GetAttribute(attr_pos1); vector xjuns; n->GetJunctionsOnRoute(rid, xjuns); // cout<<*l< cross_pos; ////////////collect intersection points and the position/////// for(unsigned int j = 0;j < xjuns.size();j++){ double meas = xjuns[j].GetRouteMeas(); // cout<<"meas "<Length() - dist_delta; while(pos1 < pos2){ SimpleLine* sub_sl = new SimpleLine(0); sl->SubLine(pos1, pos2, true, *sub_sl); Line* l = new Line(0); sub_sl->toLine(*l); if(l->Intersects(*cross_reg) == false){ rids.push_back(rid->GetIntval()); lines.push_back(*l); l->DeleteIfAllowed(); sub_sl->DeleteIfAllowed(); break; }else{ pos1 += dist_delta; pos2 -= dist_delta; } l->DeleteIfAllowed(); sub_sl->DeleteIfAllowed(); } }else{ double pos1 = cross_pos[j]; double pos2 = cross_pos[j + 1] - dist_delta; while(pos1 < pos2){ SimpleLine* sub_sl = new SimpleLine(0); sl->SubLine(pos1, pos2, true, *sub_sl); Line* l = new Line(0); sub_sl->toLine(*l); if(l->Intersects(*cross_reg) == false){ rids.push_back(rid->GetIntval()); lines.push_back(*l); l->DeleteIfAllowed(); sub_sl->DeleteIfAllowed(); break; }else{ pos1 += dist_delta; pos2 -= dist_delta; } l->DeleteIfAllowed(); sub_sl->DeleteIfAllowed(); } } }else{ double pos1 = cross_pos[j - 1] + dist_delta; double pos2 = cross_pos[j] - dist_delta; while(pos1 < pos2){ SimpleLine* sub_sl = new SimpleLine(0); sl->SubLine(pos1, pos2, true, *sub_sl); Line* l = new Line(0); sub_sl->toLine(*l); if(l->Intersects(*cross_reg) == false){ rids.push_back(rid->GetIntval()); lines.push_back(*l); l->DeleteIfAllowed(); sub_sl->DeleteIfAllowed(); break; }else{ pos1 += dist_delta; pos2 -= dist_delta; } l->DeleteIfAllowed(); sub_sl->DeleteIfAllowed(); } /////////////process the last part///////////////// if(j == cross_pos.size() - 1){ double pos1 = cross_pos[j] + dist_delta; double pos2 = sl->Length() - dist_delta; while(pos1 < pos2){ SimpleLine* sub_sl = new SimpleLine(0); sl->SubLine(pos1, pos2, true, *sub_sl); Line* l = new Line(0); sub_sl->toLine(*l); if(l->Intersects(*cross_reg) == false){ rids.push_back(rid->GetIntval()); lines.push_back(*l); l->DeleteIfAllowed(); sub_sl->DeleteIfAllowed(); break; }else{ pos1 += dist_delta; pos2 -= dist_delta; } l->DeleteIfAllowed(); sub_sl->DeleteIfAllowed(); } } } } ////////////////////////////////////////////////////////////////////// cross_tuple->DeleteIfAllowed(); route_tuple->DeleteIfAllowed(); } } /* get the interesting points locate on both sides of a road region */ void StrRS::GetInterestingPoints(HalfSegment hs, Point ip, vector& intersect_ps, Region* reg1, Region* reg2) { Point p1 = hs.GetLeftPoint(); Point p2 = hs.GetRightPoint(); const double delta_dist = 10.0; Line* line1 = new Line(0); if(MyAlmostEqual(p1.GetX(), p2.GetX())){ double y = ip.GetY(); double x1 = ip.GetX() - delta_dist; double x2 = ip.GetX() + delta_dist; line1->StartBulkLoad(); HalfSegment hs; Point lp,rp; lp.Set(x1, y); rp.Set(x2, y); hs.Set(true,lp,rp); int edgeno = 0; hs.attr.edgeno = edgeno++; *line1 += hs; hs.SetLeftDomPoint(!hs.IsLeftDomPoint()); *line1 += hs; line1->EndBulkLoad(); }else if(MyAlmostEqual(p1.GetY(), p2.GetY())){ double y1 = ip.GetY() - delta_dist; double y2 = ip.GetY() + delta_dist; double x = ip.GetX(); line1->StartBulkLoad(); HalfSegment hs; Point lp,rp; lp.Set(x, y1); rp.Set(x, y2); hs.Set(true,lp,rp); int edgeno = 0; hs.attr.edgeno = edgeno++; *line1 += hs; hs.SetLeftDomPoint(!hs.IsLeftDomPoint()); *line1 += hs; line1->EndBulkLoad(); }else{//not vertical double k1 = (p2.GetY() - p1.GetY())/(p2.GetX() - p1.GetX()); double k2 = -1/k1; double c2 = ip.GetY() - ip.GetX()*k2; double x1 = ip.GetX() - delta_dist; double x2 = ip.GetX() + delta_dist; line1->StartBulkLoad(); HalfSegment hs; Point lp,rp; lp.Set(x1, x1*k2 + c2); rp.Set(x2, x2*k2 + c2); hs.Set(true,lp,rp); int edgeno = 0; hs.attr.edgeno = edgeno++; *line1 += hs; hs.SetLeftDomPoint(!hs.IsLeftDomPoint()); *line1 += hs; line1->EndBulkLoad(); } vector temp; // cout<<"ip "<Intersection(*reg1, *l1); line1->Intersection(*reg2, *l2); // cout<Size()<<" "<Size()<Size() >= 2 && l2->Size() >= 2){ Point lp, rp; for(int i = 0;i < l1->Size();i++){ HalfSegment hs; l1->Get(i, hs); if(!hs.IsLeftDomPoint())continue; lp = hs.GetLeftPoint(); rp = hs.GetRightPoint(); // cout<<"lp1 "<Size();i++){ HalfSegment hs; l2->Get(i, hs); if(!hs.IsLeftDomPoint())continue; lp = hs.GetLeftPoint(); rp = hs.GetRightPoint(); // cout<<"lp2 "<= 4); for(unsigned int i = 0;i < 4;i++){ intersect_ps.push_back(temp[i]); } l1->DeleteIfAllowed(); l2->DeleteIfAllowed(); line1->DeleteIfAllowed(); } } /* Generate Interesting points on pavement */ void StrRS::GenPoints1(int attr_pos1, int attr_pos2, int attr_pos3, int attr_pos4, int no_ps) { const double dist_deta = 2.0; // cout<<"generating no_ps points "<GetNoTuples(); struct timeval tval; struct timezone tzone; gettimeofday(&tval, &tzone); srand48(tval.tv_sec); while(no_ps > 0){ //randomly selects a section // int m = lrand48() % no_sub_sec + 1; int m = GetRandom() % no_sub_sec + 1; Tuple* tuple_sec = r1->GetTuple(m, false); int rid = ((CcInt*)tuple_sec->GetAttribute(attr_pos1))->GetIntval(); Line* l = (Line*)tuple_sec->GetAttribute(attr_pos2); //randomly selects a halfsegment in the section int no_hs = l->Size(); // int hs_index = lrand48()% no_hs; int hs_index = GetRandom()% no_hs; HalfSegment hs; l->Get(hs_index, hs); double length = hs.Length(); if(length > dist_deta){ // int pos = lrand48()% ((int)floor(length)); int pos = GetRandom() % ((int)floor(length)); assert(0 <= pos && pos <= length); // cout<<"rid "< intersect_ps; Tuple* tuple_pave = r2->GetTuple(rid, false); Region* pave_reg1 = (Region*)tuple_pave->GetAttribute(attr_pos3); Region* pave_reg2 = (Region*)tuple_pave->GetAttribute(attr_pos4); GetInterestingPoints(hs, ip, intersect_ps, pave_reg1, pave_reg2); tuple_pave->DeleteIfAllowed(); for(unsigned int i = 0;i < intersect_ps.size();i++){ rids.push_back(rid); ps.push_back(ip); if(i == 0 || i == 1) ps_type.push_back(false); else ps_type.push_back(true); interestps.push_back(intersect_ps[i].loc); } no_ps -= intersect_ps.size(); } tuple_sec->DeleteIfAllowed(); } } /* traverse the Rtree to find which triangle contains the point */ void StrRS::DFTraverse(R_Tree<2,TupleId>* rtree, SmiRecordId adr, Point* p, int attr_pos) { R_TreeNode<2,TupleId>* node = rtree->GetMyNode(adr,false, rtree->MinEntries(0), rtree->MaxEntries(0)); for(int j = 0;j < node->EntryCount();j++){ if(node->IsLeaf()){ R_TreeLeafEntry<2,TupleId> e = (R_TreeLeafEntry<2,TupleId>&)(*node)[j]; Tuple* dg_tuple2 = r2->GetTuple(e.info, false); Region* candi_reg = (Region*)dg_tuple2->GetAttribute(attr_pos); if(candi_reg->Contains(*p)){ for(int i = 0;i < candi_reg->Size();i++){ HalfSegment hs; candi_reg->Get(i, hs); if(!hs.IsLeftDomPoint())continue; if(hs.Contains(*p)){ rids.push_back(e.info); BBox<2> bbox = candi_reg->BoundingBox(); Coord x = p->GetX() - bbox.MinD(0); Coord y = p->GetY() - bbox.MinD(1); Point new_p(true, x, y); interestps.push_back(new_p); ps.push_back(*p); break; } } } dg_tuple2->DeleteIfAllowed(); }else{ R_TreeInternalEntry<2> e = (R_TreeInternalEntry<2>&)(*node)[j]; if(p->Inside(e.box)){ DFTraverse(rtree, e.pointer, p, attr_pos); } } } delete node; } /* mapping the point into a triangle */ void StrRS::GenPoints2(R_Tree<2,TupleId>* rtree, int attr_pos1, int attr_pos2, unsigned int no_ps) { SmiRecordId adr = rtree->RootRecordId(); for(int i = 1;i <= r1->GetNoTuples();i++){ Tuple* point_tuple = r1->GetTuple(i, false); Point* p1 = (Point*)point_tuple->GetAttribute(attr_pos1); DFTraverse(rtree, adr, p1, attr_pos2); point_tuple->DeleteIfAllowed(); if(rids.size() == no_ps)break; } if(rids.size() < no_ps){ cout<<"WARNING!!! not enough points found"<Clear(); out->StartBulkLoad(); int edgeno = 0; static int line_id = 1; const double delta_dist = 0.001; for(int i = 0;i < in->Size();i++){ HalfSegment hs1; in->Get(i, hs1); if(!hs1.IsLeftDomPoint()) continue; Point lp = hs1.GetLeftPoint(); Point rp = hs1.GetRightPoint(); // Modify_Point2(lp); // Modify_Point2(rp); HalfSegment hs2(true, lp, rp); hs2.attr.edgeno = edgeno++; *out += hs2; hs2.SetLeftDomPoint(!hs2.IsLeftDomPoint()); *out += hs2; if(lp.Distance(rp) < delta_dist){ cout<EndBulkLoad(); } /* check the coordinates; data clean for roads data it checks whether two roads have overlapping. if it is, then delete the two old roads, and create a new one by doing union on them using traverse rtree to improve efficiency much faster than navie algorithm (two loops) */ void DataClean::CheckRoads(Relation* rel, R_Tree<2,TupleId>* rtree) { /*vector new_line_list; for(unsigned int i = 0;i < line_list.size();i++){ Line* l1 = &(line_list[i]); //////////////////////naive method/////////////////////////// for(unsigned int j = i + 1;j < line_list.size();j++){ Line* l2 = &line_list[j]; Line* res = new Line(0); l1->Intersection(*l2, *res); if(res->IsDefined() && res->Length() > 0.0){ flag_list[i] = false; flag_list[j] = false; cout<<"len "<Length() <<" l1 "<Union(*l2, *res2); new_line_list.push_back(*res2); delete res2; } delete res; } } for(unsigned int i = 0;i < flag_list.size();i++){ if(flag_list[i] == false) continue; SimpleLine* sl = new SimpleLine(0); sl->fromLine(line_list[i]); sl_list.push_back(*sl); delete sl; } //////new generated line///// for(unsigned int i = 0;i < new_line_list.size();i++){ SimpleLine* sl = new SimpleLine(0); sl->fromLine(new_line_list[i]); sl_list.push_back(*sl); delete sl; }*/ /* vector flag_list; vector line_list; vector sline_list; vector line_id_list; for(int i = 1;i <= rel->GetNoTuples();i++){ flag_list.push_back(true); Tuple* road_tuple = rel->GetTuple(i, false); SimpleLine* sl = (SimpleLine*)road_tuple->GetAttribute(ROUTE_CURVE); line_id_list.push_back(i); Line* l = new Line(0); sl->toLine(*l); line_list.push_back(*l); sline_list.push_back(*sl); delete l; road_tuple->DeleteIfAllowed(); }*/ // const double delta_len = 0.001; // // for(unsigned int i = 0;i < line_list.size();i++){ // Line* l1 = &(line_list[i]); // // vector oid_list; // DFTraverse(rel,rtree,rtree->RootRecordId(),l1, oid_list, i + 1); // for(unsigned int j = 0;j < oid_list.size();j++){ // int index = oid_list[j] - 1; // Line* l2 = &line_list[index]; // // if(flag_list[index] == false) continue; // // if(l1->Inside(*l2)){ // flag_list[i] = false;//delete this line // break; // } // if(l2->Inside(*l1)){ // flag_list[index] = false; // }else { // // Line* res1 = new Line(0); // l1->Intersection(*l2, *res1); // if(res1->IsDefined() && res1->Length() > 0.0){ // double len1 = l1->Length(); // double len2 = l2->Length(); // cout<<"id1 "<Length()<Length() > delta_len); // assert(len1 - res1->Length() > delta_len); // assert(len2 - res1->Length() > delta_len); // // if(len1 > len2){ // Line* res = new Line(0); // l1->Minus(*res1,*res); // line_list[i] = *res; // delete res; // l1 = &(line_list[i]); // }else{ // Line* res = new Line(0); // l2->Minus(*res1,*res); // line_list[index] = *res; // delete res; // } // } // delete res1; // } // // } // // } // // // for(unsigned int i = 0;i < flag_list.size();i++){ // if(flag_list[i] == false) continue; // // SimpleLine* sl = new SimpleLine(0); // sl->fromLine(line_list[i]); // if(sl->IsDefined() && sl->Length() > 0.0) // sl_list.push_back(*sl); // else // cout<<"id "<GetNoTuples();i++){ // Tuple* road_tuple = rel->GetTuple(i, false); // SimpleLine* sl = (SimpleLine*)road_tuple->GetAttribute(ROUTE_CURVE); // if(sl->IsCycle() == false) // sl_list.push_back(*sl); // else{ // SpacePartition* sp = new SpacePartition(); // vector seq_halfseg; //reorder it from start to end // sp->ReorderLine(sl, seq_halfseg); // // // // double sum = 0; // // for(int j = 0;j < seq_halfseg.size();j++){ // // Point p1 = seq_halfseg[j].from; // // Point p2 = seq_halfseg[j].to; // // sum += p1.Distance(p2); // // } // // cout<Length()<<" "<StartBulkLoad(); // sl2->StartBulkLoad(); // int half = seq_halfseg.size()/2; // int edgeno = 0; // for(int j = 0;j < half;j++){ // Point p1 = seq_halfseg[j].from; // Point p2 = seq_halfseg[j].to; // HalfSegment hs(true, p1, p2); // hs.attr.edgeno = edgeno++; // *sl1 += hs; // hs.SetLeftDomPoint(!hs.IsLeftDomPoint()); // *sl1 += hs; // // } // edgeno = 0; // for(int j = half; j < seq_halfseg.size();j++){ // Point p1 = seq_halfseg[j].from; // Point p2 = seq_halfseg[j].to; // HalfSegment hs(true, p1, p2); // hs.attr.edgeno = edgeno++; // *sl2 += hs; // hs.SetLeftDomPoint(!hs.IsLeftDomPoint()); // *sl2 += hs; // } // // // sl1->EndBulkLoad(); // sl2->EndBulkLoad(); // // // sl_list.push_back(*sl1); // sl_list.push_back(*sl2); // // delete sl2; // delete sl1; // // delete sp; // } // // // road_tuple->DeleteIfAllowed(); // } // return; //////////////////////////////////////////////////////////////////////////// /* for(int i = 1;i <= rel->GetNoTuples();i++){ Tuple* road_tuple1 = rel->GetTuple(i, false); int id1 = ((CcInt*)road_tuple1->GetAttribute(ROUTE_ID))->GetIntval(); SimpleLine* sl1 = (SimpleLine*)road_tuple1->GetAttribute(ROUTE_CURVE); bool s1 = ((CcBool*)road_tuple1->GetAttribute(ROUTE_STARTSSMALLER))->GetBoolval(); Line* l1 = new Line(0); sl1->toLine(*l1); vector oid_list; // DFTraverse(rel,rtree,rtree->RootRecordId(), l1, oid_list, i); DFTraverse(rel,rtree,rtree->RootRecordId(), l1, oid_list, id1); delete l1; for(unsigned int index = 0;index < oid_list.size();index++){ int j = oid_list[index]; Tuple* road_tuple2 = rel->GetTuple(j, false); int id2 = ((CcInt*)road_tuple2->GetAttribute(ROUTE_ID))->GetIntval(); SimpleLine* sl2 = (SimpleLine*)road_tuple2->GetAttribute(ROUTE_CURVE); bool s2 = ((CcBool*)road_tuple2->GetAttribute(ROUTE_STARTSSMALLER))->GetBoolval(); Points* ps = new Points(0); sl1->Crossings( *sl2, *ps); if(ps->Size() == 0){ delete ps; road_tuple2->DeleteIfAllowed(); continue; } // cout<Size()<Size() >= 3){ cout<<"id1 "<Size()<Size();k++){ Point loc; ps->Get(k, loc); double pos1, pos2; // cout<<"loc "<AtPoint(loc, s1, pos1) == false){ cout<<"not find on simpleline1 "<AtPoint(loc, s2, pos2) == false){ cout<<"not find on simpleline2 "<DeleteIfAllowed(); } road_tuple1->DeleteIfAllowed(); } */ for(int i = 1;i <= rel->GetNoTuples();i++){ Tuple* road_tuple = rel->GetTuple(i, false); int id = ((CcInt*)road_tuple->GetAttribute(ROUTE_ID))->GetIntval(); SimpleLine* sl = (SimpleLine*)road_tuple->GetAttribute(ROUTE_CURVE); Line* l = new Line(0); sl->toLine(*l); vector oid_list; DFTraverse2(rel,rtree,rtree->RootRecordId(), l, oid_list, id); l->DeleteIfAllowed(); road_tuple->DeleteIfAllowed(); if(oid_list.size() == 0){ cout<<"rid "<* rtree, SmiRecordId adr, Line* sl, vector& id_list, unsigned int id) { R_TreeNode<2,TupleId>* node = rtree->GetMyNode(adr,false, rtree->MinEntries(0), rtree->MaxEntries(0)); for(int j = 0;j < node->EntryCount();j++){ if(node->IsLeaf()){ R_TreeLeafEntry<2,TupleId> e = (R_TreeLeafEntry<2,TupleId>&)(*node)[j]; Tuple* dg_tuple = rel->GetTuple(e.info, false); SimpleLine* sline = (SimpleLine*)dg_tuple->GetAttribute(ROUTE_CURVE); unsigned int r_id = ((CcInt*)dg_tuple->GetAttribute(ROUTE_ID))->GetIntval(); if(r_id == id){ dg_tuple->DeleteIfAllowed(); continue; } if(sl->BoundingBox().Intersects(sline->BoundingBox())){ if(e.info != id) id_list.push_back(e.info); } dg_tuple->DeleteIfAllowed(); }else{ R_TreeInternalEntry<2> e = (R_TreeInternalEntry<2>&)(*node)[j]; if(sl->BoundingBox().Intersects(e.box)){ DFTraverse(rel,rtree, e.pointer, sl, id_list, id); } } } delete node; } void DataClean::DFTraverse2(Relation* rel, R_Tree<2,TupleId>* rtree, SmiRecordId adr, Line* sl, vector& id_list, unsigned int id) { R_TreeNode<2,TupleId>* node = rtree->GetMyNode(adr,false, rtree->MinEntries(0), rtree->MaxEntries(0)); for(int j = 0;j < node->EntryCount();j++){ if(node->IsLeaf()){ R_TreeLeafEntry<2,TupleId> e = (R_TreeLeafEntry<2,TupleId>&)(*node)[j]; Tuple* dg_tuple = rel->GetTuple(e.info, false); SimpleLine* sline = (SimpleLine*)dg_tuple->GetAttribute(ROUTE_CURVE); if(sl->BoundingBox().Intersects(sline->BoundingBox())){ Line* temp_l = new Line(0); sline->toLine(*temp_l); if(e.info != id && sl->Intersects(*temp_l)){ id_list.push_back(e.info); } temp_l->DeleteIfAllowed(); } dg_tuple->DeleteIfAllowed(); }else{ R_TreeInternalEntry<2> e = (R_TreeInternalEntry<2>&)(*node)[j]; if(sl->BoundingBox().Intersects(e.box)){ DFTraverse2(rel,rtree, e.pointer, sl, id_list, id); } } } delete node; } ///////////////////////////////////////////////////////////////////// ////////a robust method to get the position of a point on a sline/// ///////////////////////////////////////////////////////////////////// double PointOnSline(SimpleLine* sl, Point* loc, bool b) { double res = -1.0; double min_dist = 0.001; SpacePartition* sp = new SpacePartition(); vector mhs_temp; sp->ReorderLine(sl, mhs_temp); delete sp; Point start; sl->AtPosition(0.0, b, start); vector mhs; if(mhs_temp[0].from.Distance(start) < min_dist){ for(unsigned int i = 0;i < mhs_temp.size();i++) mhs.push_back(mhs_temp[i]); }else{ for(int i = mhs_temp.size() - 1;i >= 0;i--){ MyHalfSegment seg = mhs_temp[i]; seg.Print(); seg.Exchange(); seg.Print(); mhs.push_back(seg); } } double l = 0.0; for(unsigned int i = 0;i < mhs.size();i++){ HalfSegment hs(true, mhs[i].from, mhs[i].to); if(hs.Contains(*loc)){ l += loc->Distance(mhs[i].from); res = l; break; }else l += hs.Length(); } if(fabs(res) < 0.000001) res = 0.0; if(fabs(res - sl->Length()) < 0.000001) res = sl->Length(); double result; if(sl->AtPoint(*loc, b, result) == false){ cout<<"error"< 0.001){ cout<<"too large deviation "<