/* ---- 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 April, 2010 Jianqiu Xu [TOC] 1 Overview This source file essentially contains the necessary implementations for creating the graph model for walk planning. */ #include "Partition.h" #include "Triangulate.h" #include "PaveGraph.h" #include "GeneralType.h" #include "Indoor.h" #include "Algebras/Spatial/Point.h" #include "Algebras/Spatial/SpatialAlgebra.h" using namespace network; using namespace std; /* Decompose the pavement on one side of the road into a set of subregions */ void SpacePartition::DecomposePave(Region* reg1, Region* reg2, vector& result) { vector temp_result; vector result1; // int no_faces = reg1->NoComponents(); // int no_faces = reg1->Size();//faceno in halfsegment is not recomputed int no_faces = 0; for(int i = 0;i < reg1->Size();i++){ HalfSegment hs; reg1->Get(i, hs); if(hs.attr.faceno >= no_faces) no_faces = hs.attr.faceno + 1; } for(int i = 0;i < no_faces;i++){ Region* temp = new Region(0); result1.push_back(*temp); temp->DeleteIfAllowed(); result1[i].StartBulkLoad(); } for(int index = 0;index < reg1->Size();index++){ HalfSegment temp_hs; reg1->Get(index, temp_hs); int face = temp_hs.attr.faceno; if(temp_hs.attr.cycleno == 0){/////do not need the hole result1[face] += temp_hs; } } for(int i = 0;i < no_faces;i++){ result1[i].SetNoComponents(1); result1[i].EndBulkLoad(false,false,false,false); if(result1[i].Size() >= 6){ temp_result.push_back(result1[i]); } } vector result2; // no_faces = reg2->NoComponents(); // no_faces = reg2->Size(); no_faces = 0; /// original faceno in halfsegment is not recomputed for(int i = 0;i < reg2->Size();i++){ HalfSegment hs; reg2->Get(i, hs); if(hs.attr.faceno >= no_faces) no_faces = hs.attr.faceno + 1; } for(int i = 0;i < no_faces;i++){ Region* temp = new Region(0); result2.push_back(*temp); temp->DeleteIfAllowed(); result2[i].StartBulkLoad(); } for(int i = 0;i < reg2->Size();i++){ HalfSegment hs; reg2->Get(i,hs); int face = hs.attr.faceno; if(hs.attr.cycleno == 0){/////do not need the hole result2[face] += hs; } } for(int i = 0;i < no_faces;i++){ result2[i].SetNoComponents(1); result2[i].EndBulkLoad(false,false,false,false); if(result2[i].Size() >= 6) { temp_result.push_back(result2[i]); } } ////////////////////////////////////////////////////////// for(unsigned int i = 0;i < temp_result.size();i++){ Line* line = new Line(0); temp_result[i].Boundary(line); SimpleLine* sline = new SimpleLine(0); sline->fromLine(*line); vector mhs; ReorderLine(sline, mhs); sline->DeleteIfAllowed(); line->DeleteIfAllowed(); vector ps; for(unsigned int j = 0;j < mhs.size();j++){ Point p = mhs[j].from; // cout<<"before "< newps; const double delta_dist = 0.1; for(unsigned int i = 0;i < ps.size();i++){ if(i == 0){ newps.push_back(ps[i]); continue; } if(i < ps.size() - 1){ Point last_p = ps[i - 1]; if(last_p.Distance(ps[i]) > delta_dist){ newps.push_back(ps[i]); continue; } } if(i == ps.size() - 1){ Point first_p = ps[0]; if(first_p.Distance(ps[i]) > delta_dist){ newps.push_back(ps[i]); continue; } } } /////////////////////////////////// vector regs; // ComputeRegion(ps, regs); ComputeRegion(newps, regs); if(!regs.empty()){ result.push_back(regs[0]); } ////////////////////////////////////////////////////// } /////////////////////////////////////////////////////////// } /* get the closest point in hs to p, and return it in cp it also returns the distance between hs and p */ double SpacePartition::GetClosestPoint(HalfSegment& hs, Point& p, Point& cp) { assert( p.IsDefined() ); Coord xl = hs.GetLeftPoint().GetX(), yl = hs.GetLeftPoint().GetY(), xr = hs.GetRightPoint().GetX(), yr = hs.GetRightPoint().GetY(), X = p.GetX(), Y = p.GetY(); double result, auxresult; if( xl == xr || yl == yr ){ if( xl == xr){ //hs is vertical if( (yl <= Y && Y <= yr) || (yr <= Y && Y <= yl) ){ result = fabs( X - xl ); cp.Set(xl, Y); //store the closest point } else{ result = p.Distance(hs.GetLeftPoint()); auxresult = p.Distance(hs.GetRightPoint()); if( result > auxresult ){ result = auxresult; cp = hs.GetRightPoint(); //store the closest point }else{ cp = hs.GetLeftPoint(); //store the closest point } } }else{ //hs is horizontal line: (yl==yr) if( xl <= X && X <= xr ){ result = fabs( Y - yl ); cp.Set(X,yl);//store the closest point }else{ result = p.Distance(hs.GetLeftPoint()); auxresult = p.Distance(hs.GetRightPoint()); if( result > auxresult ){ result = auxresult; cp = hs.GetRightPoint();//store the closest point }else{ cp = hs.GetLeftPoint();//store the closest point } } } }else { double k = (yr - yl) / (xr - xl), a = yl - k * xl, xx = (k * (Y - a) + X) / (k * k + 1), yy = k * xx + a; Coord XX = xx, YY = yy; Point PP( true, XX, YY ); if( xl <= XX && XX <= xr ){ result = p.Distance( PP ); cp = PP; //store the closest point } else { result = p.Distance( hs.GetLeftPoint() ); auxresult = p.Distance( hs.GetRightPoint()); if( result > auxresult ){ result = auxresult; cp = hs.GetRightPoint(); }else{ cp = hs.GetLeftPoint(); } } } return result; } double SpacePartition::GetClosestPoint_New(HalfSegment& hs, Point& p, Point& cp) { assert( p.IsDefined() ); Coord xl = hs.GetLeftPoint().GetX(), yl = hs.GetLeftPoint().GetY(), xr = hs.GetRightPoint().GetX(), yr = hs.GetRightPoint().GetY(), X = p.GetX(), Y = p.GetY(); double result, auxresult; if( AlmostEqual(xl,xr) || AlmostEqual(yl ,yr) ){ if( AlmostEqual(xl, xr)){ //hs is vertical if(((yl < Y || AlmostEqual(yl,Y)) && (Y < yr || AlmostEqual(Y, yr))) || ((yr < Y || AlmostEqual(yr,Y)) && (Y < yl || AlmostEqual(Y, yl) ))){ result = fabs( X - xl ); cp.Set(xl, Y); //store the closest point } else{ result = p.Distance(hs.GetLeftPoint()); auxresult = p.Distance(hs.GetRightPoint()); if( result > auxresult ){ result = auxresult; cp = hs.GetRightPoint(); //store the closest point }else{ cp = hs.GetLeftPoint(); //store the closest point } } }else{ //hs is horizontal line: (yl==yr) // if( xl <= X && X <= xr ){ if( (xl < X || AlmostEqual(xl,X)) && (X < xr || AlmostEqual(X, xr) ) ){ result = fabs( Y - yl ); cp.Set(X,yl);//store the closest point }else{ result = p.Distance(hs.GetLeftPoint()); auxresult = p.Distance(hs.GetRightPoint()); if( result > auxresult ){ result = auxresult; cp = hs.GetRightPoint();//store the closest point }else{ cp = hs.GetLeftPoint();//store the closest point } } } }else{ double k = (yr - yl) / (xr - xl), a = yl - k * xl, xx = (k * (Y - a) + X) / (k * k + 1), yy = k * xx + a; Coord XX = xx, YY = yy; Point PP( true, XX, YY ); // if( xl <= XX && XX <= xr ){ if( (xl < XX || AlmostEqual(xl, XX)) && (XX < xr || AlmostEqual(XX, xr) ) ){ // cout< auxresult ){ result = auxresult; cp = hs.GetRightPoint(); }else{ cp = hs.GetLeftPoint(); } } } return result; } /* Decompose the pavement of one road into a set of subregions */ void SpacePartition::DecomposePavement1(Network* n, Relation* rel, int attr_pos1, int attr_pos2, int attr_pos3) { vector paves1; vector paves2; vector route_flag; for(int i = 1;i <= rel->GetNoTuples();i++){ Tuple* pave_tuple = rel->GetTuple(i, false); Region* reg1 = (Region*)pave_tuple->GetAttribute(attr_pos2); Region* reg2 = (Region*)pave_tuple->GetAttribute(attr_pos3); paves1.push_back(*reg1); paves2.push_back(*reg2); pave_tuple->DeleteIfAllowed(); route_flag.push_back(false); } vector pavements1; vector pavements2; int oid = 1;//object identifier assert(paves1.size() == paves2.size()); for(int i = 1;i <= rel->GetNoTuples();i++){ Tuple* pave_tuple = rel->GetTuple(i, false); int rid = ((CcInt*)pave_tuple->GetAttribute(attr_pos1))->GetIntval(); // cout<<"rid "<DeleteIfAllowed(); continue; }*/ // cout<<"pave1 "<DeleteIfAllowed(); pavements1.clear(); } ////////////check inside above////////////////////////////// } /* Decompose the zebra crossings into a set of subregions */ void SpacePartition::DecomposePavement2(int start_oid, Relation* rel, int attr_pos1, int attr_pos2) { // cout<<"start_oid "< zc_regs; for(int i = 1;i <= rel->GetNoTuples();i++){ Tuple* zc_tuple = rel->GetTuple(i, false); int rid = ((CcInt*)zc_tuple->GetAttribute(attr_pos1))->GetIntval(); Region* zc_reg = (Region*)zc_tuple->GetAttribute(attr_pos2); Region* temp = new Region(0); // cout<<"rid "< 0); // cout< zc_regs_filter; for(unsigned int j1 = 0;j1 < zc_regs.size();j1++){ unsigned int j2 = 0; for(;j2 < zc_regs_filter.size();j2++){ if(zc_regs_filter[j2].Distance(zc_regs[j1]) < delta_dist) break; } if(j2 == zc_regs_filter.size()) zc_regs_filter.push_back(zc_regs[j2]); // zc_regs_filter.push_back(zc_regs[j1]); } for(unsigned int j = 0;j < zc_regs_filter.size();j++){ junid1.push_back(oid); junid2.push_back(rid); outer_regions1.push_back(Region(zc_regs_filter[j],false)); oid++; } temp->DeleteIfAllowed(); zc_regs.clear(); zc_tuple->DeleteIfAllowed(); } } /* get the commone line between two pavements (node in the graph model) */ void SpacePartition::GetPavementEdge1(Network* n, Relation* rel, BTree* btree_pave, int attr1, int attr2, int attr3) { Relation* juns = n->GetJunctions(); vector regs1; vector regs2; 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(); /* if(!(id1 == 3 && id2 == 6)){ jun_tuple->DeleteIfAllowed(); continue; }*/ // cout<<"rid1 "<ExactMatch(rid1); while(btreeiter1->Next()){ Tuple* pave_tup = rel->GetTuple(btreeiter1->GetId(), false); int oid = ((CcInt*)pave_tup->GetAttribute(attr1))->GetIntval(); Region* pave = (Region*)pave_tup->GetAttribute(attr3); Region_Oid* ro = new Region_Oid(oid, *pave); regs1.push_back(*ro); delete ro; pave_tup->DeleteIfAllowed(); } delete btreeiter1; BTreeIterator* btreeiter2 = btree_pave->ExactMatch(rid2); while(btreeiter2->Next()){ Tuple* pave_tup = rel->GetTuple(btreeiter2->GetId(), false); int oid = ((CcInt*)pave_tup->GetAttribute(attr1))->GetIntval(); Region* pave = (Region*)pave_tup->GetAttribute(attr3); Region_Oid* ro = new Region_Oid(oid, *pave); regs2.push_back(*ro); delete ro; pave_tup->DeleteIfAllowed(); } delete btreeiter2; // cout<DeleteIfAllowed(); } juns->Delete(); } /* get the commone line between zc and pavement (node in the graph model) */ void SpacePartition::GetPavementEdge2(Relation* rel1, Relation* rel2, BTree* btree_pave, int attr1, int attr2, int attr3) { vector reg_pave; for(int i = 1;i <= rel1->GetNoTuples();i++){ Tuple* zc_tuple = rel1->GetTuple(i, false); CcInt* zc_oid = (CcInt*)zc_tuple->GetAttribute(attr1); CcInt* rid = (CcInt*)zc_tuple->GetAttribute(attr2); Region* reg = (Region*)zc_tuple->GetAttribute(attr3); /* if(!(rid->GetIntval() == 476)){ zc_tuple->DeleteIfAllowed(); continue; }*/ // cout<<"oid "<GetIntval()<<"rid "<GetIntval()<ExactMatch(rid); while(btreeiter->Next()){ Tuple* pave_tuple = rel2->GetTuple(btreeiter->GetId(), false); int oid = ((CcInt*)pave_tuple->GetAttribute(attr1))->GetIntval(); Region* pave = (Region*)pave_tuple->GetAttribute(attr3); Region_Oid* ro = new Region_Oid(oid, *pave); reg_pave.push_back(*ro); delete ro; pave_tuple->DeleteIfAllowed(); } delete btreeiter; GetCommPave2(reg, zc_oid->GetIntval(),reg_pave); reg_pave.clear(); zc_tuple->DeleteIfAllowed(); } } /* detect whether two pavements intersect, (pave1, pave2) */ void SpacePartition::GetCommPave1(vector& pave1, vector& pave2, int rid1, int rid2) { // const double delta_dist = 0.01; const double delta_dist = 0.00001; for(unsigned int i = 0;i < pave1.size();i++){ for(unsigned int j = 0;j < pave2.size();j++){ if(pave1[i].reg.Inside(pave2[j].reg)){ continue; } if(pave2[j].reg.Inside(pave1[i].reg)){ continue; } ////////////////////////////////////////////////////////////// if(MyRegIntersects(&pave1[i].reg, &pave2[j].reg)){ vector common_ps; for(int index1 = 0; index1 < pave1[i].reg.Size();index1++){ HalfSegment hs1; pave1[i].reg.Get(index1, hs1); if(!hs1.IsLeftDomPoint())continue; for(int index2 = 0;index2 < pave2[j].reg.Size();index2++){ HalfSegment hs2; pave2[j].reg.Get(index2, hs2); if(!hs2.IsLeftDomPoint())continue; Point cp; if(hs1.Intersection(hs2,cp)){ unsigned int index = 0; for(;index < common_ps.size();index++){ if(cp.Distance(common_ps[index]) < delta_dist) break; } if(index == common_ps.size()) common_ps.push_back(cp); } } } // cout<<"oid1 "< 1); if(common_ps.size() > 1){ junid1.push_back(pave1[i].oid); junid2.push_back(pave2[j].oid); Line* l = new Line(0); pave_line1.push_back(*l); l->DeleteIfAllowed(); } } ///////////////////////////////////////////////////////////// } } } /* detect whether the zebra crossing intersects the pavement */ void SpacePartition::GetCommPave2(Region* reg, int oid, vector& pave2) { for(unsigned int i = 0;i < pave2.size();i++){ if(MyRegIntersects(reg, &pave2[i].reg)){ Line* boundary = new Line(0); pave2[i].reg.Boundary(boundary); Line* result = new Line(0); boundary->Intersection(*reg, *result); if(result->Size() == 0){ cout<<"zc oid1 "<Size() > 0); if(result->Size() > 0){ junid1.push_back(oid); junid2.push_back(pave2[i].oid); Line* l = new Line(0); pave_line1.push_back(*l); l->DeleteIfAllowed(); } result->DeleteIfAllowed(); boundary->DeleteIfAllowed(); } } } /* doing triangulation for a polygon with and without hole */ CompTriangle::CompTriangle() { count = 0; path = NULL; resulttype = NULL; } CompTriangle::CompTriangle(Region* r):reg(r),count(0), path(NULL),resulttype(NULL) { } CompTriangle:: ~CompTriangle() { if(path != NULL) path->DeleteIfAllowed(); if(resulttype != NULL) delete resulttype; } /* get the clockwise value */ bool CompTriangle::GetClockwise(const vector& contour) { float obj_area = Area(contour); if(0.0f < obj_area) return false; else return true; } /* Compute the area of a polygon. It is also used to compute the clockwise value of a list of points. if area > 0.0f, counter-clockwise order else clockwise order */ float CompTriangle::Area(const vector& contour) { int n = contour.size(); float A=0.0f; for(int p=n-1,q=0; q= 0.0f) && (bCROSScp >= 0.0f) && (cCROSSap >= 0.0f)); }; bool CompTriangle::Snip(const vector& contour,int u,int v,int w, int n,int *V) { int p; float Ax, Ay, Bx, By, Cx, Cy, Px, Py; Ax = contour[V[u]].GetX(); Ay = contour[V[u]].GetY(); Bx = contour[V[v]].GetX(); By = contour[V[v]].GetY(); Cx = contour[V[w]].GetX(); Cy = contour[V[w]].GetY(); if ( EPSILON > (((Bx-Ax)*(Cy-Ay)) - ((By-Ay)*(Cx-Ax))) ) return false; for (p=0;p& contour, vector& result) { /* allocate and initialize list of Vertices in polygon */ int n = contour.size(); if ( n < 3 ) return false; int *V = new int[n]; /* we want a counter-clockwise polygon in V */ // cout<<"Area "<2; ) { /* if we loop, it is probably a non-simple polygon */ if (0 >= (count--)) { //** Triangulate: ERROR - probable bad polygon! return false; } /* three consecutive vertices in current polygon, */ int u = v ; if (nv <= u) u = 0; /* previous */ v = u+1; if (nv <= v) v = 0; /* new v */ int w = v+1; if (nv <= w) w = 0; /* next */ if ( Snip(contour,u,v,w,nv,V) ) { int a,b,c,s,t; /* true names of the vertices */ a = V[u]; b = V[v]; c = V[w]; /* output Triangle */ result.push_back( contour[a] ); result.push_back( contour[b] ); result.push_back( contour[c] ); m++; /* remove v from remaining polygon */ for(s=v,t=v+1;tNoComponents() == 0){ cout<<"this is not a region"<NoComponents() > 1){ cout<<"can't handle region with more than one faces"< no_cycles(reg->Size(), -1); for(int i = 0;i < reg->Size();i++){ HalfSegment hs; reg->Get(i, hs); if(!hs.IsLeftDomPoint())continue; int cycleno = hs.attr.cycleno; no_cycles[cycleno] = cycleno; } unsigned int no_cyc = 0; for(unsigned int i = 0;i < no_cycles.size();i++){ if(no_cycles[i] != -1) no_cyc++; else break; } if(no_cyc > 1){ cout<<"polgyon has hole inside, please call NewTriangulation()"<Boundary(boundary); // cout<<"boundary "<<*boundary<fromLine(*boundary); // cout<<"sboundary size "<Size()< mhs; //get all the points of the region SpacePartition* sp = new SpacePartition(); if(sboundary->Size() > 0) sp->ReorderLine(sboundary, mhs); else{ cout<<"can't covert the boundary to a sline"<DeleteIfAllowed(); sboundary->DeleteIfAllowed(); return; } boundary->DeleteIfAllowed(); sboundary->DeleteIfAllowed(); /* for(unsigned int i = 0;i < mhs.size();i++) mhs[i].Print();*/ vector ps; for(unsigned int i = 0;i < mhs.size();i++) ps.push_back(mhs[i].from); /* for(unsigned int i = 0;i < ps.size();i++){ printf("%.8f %.8f\n",ps[i].GetX(), ps[i].GetY()); }*/ vector result; assert(GetTriangles(ps, result)); unsigned int tcount = result.size()/3; for (unsigned int i=0; i (%.5f,%.5f) (%.5f,%.5f) (%.5f,%.5f)\n", i + 1, p1.GetX(), p1.GetY(), p2.GetX(), p2.GetY(), p3.GetX(), p3.GetY());*/ vector reg_ps; reg_ps.push_back(p1); reg_ps.push_back(p2); reg_ps.push_back(p3); sp->ComputeRegion(reg_ps, triangles); } delete sp; } bool CompTriangle::IsConvex(vector ps) { int n = ps.size(); int i,j,k; int flag = 0; double z; if (ps.size() < 3){ cout<<"less than 3 points, it is not a region"< 0) flag |= 2; if (flag == 3) return false; } if (flag != 0) return true; else return false; } /* if the polygon is convex, returns true, otherwise (concave) returns false */ bool CompTriangle::PolygonConvex() { if(reg->NoComponents() == 0){ cout<<"error: this is not a region"<NoComponents() > 1 || NoOfCycles() > 1){ cout<<"error: there is hole inside or several subregions"<Boundary(boundary); // cout<<"boundary "<<*boundary<fromLine(*boundary); // cout<<"sboundary size "<Size()< mhs; //get all the points of the region SpacePartition* sp = new SpacePartition(); if(sboundary->Size() > 0) sp->ReorderLine(sboundary, mhs); else{ cout<<"can't covert the boundary to a sline"<DeleteIfAllowed(); sboundary->DeleteIfAllowed(); delete sp; return false; } boundary->DeleteIfAllowed(); sboundary->DeleteIfAllowed(); delete sp; /* for(unsigned int i = 0;i < mhs.size();i++) mhs[i].Print();*/ vector ps; for(unsigned int i = 0;i < mhs.size();i++) ps.push_back(mhs[i].from); /////////////// convex/concave ///////////////////////////// /* int n = ps.size(); int i,j,k; int flag = 0; double z; if (ps.size() < 3){ cout<<"less than 3 points, it is not a region"< 0) flag |= 2; if (flag == 3) return false; } if (flag != 0) return true; else return false;*/ return IsConvex(ps); ///////////////////////////////////////////////////////////////////////// } bool CompTriangle::PolygonConvex2(int& error) { if(reg->NoComponents() == 0){ cout<<"error: this is not a region"<NoComponents() > 1 || NoOfCycles() > 1){ cout<<"error: there is hole inside or several subregions"<Boundary(boundary); // cout<<"boundary "<<*boundary<fromLine(*boundary); // cout<<"sboundary size "<Size()< mhs; //get all the points of the region SpacePartition* sp = new SpacePartition(); if(sboundary->Size() > 0) sp->ReorderLine(sboundary, mhs); else{ error = 3; cout<<"can't covert the boundary to a sline"<DeleteIfAllowed(); sboundary->DeleteIfAllowed(); return false; } boundary->DeleteIfAllowed(); sboundary->DeleteIfAllowed(); /* for(unsigned int i = 0;i < mhs.size();i++) mhs[i].Print();*/ vector ps; for(unsigned int i = 0;i < mhs.size();i++) ps.push_back(mhs[i].from); /////////////// convex/concave ///////////////////////////// error = 0; return IsConvex(ps); ///////////////////////////////////////////////////////////////////////// } /* number of vertices is larger than 100. it is a concave polgyon with holes inside if it is a complex region, when it needs to compute the shortest path inside. we do not call the simple method, but build the dual graph, visual graph and an auxiliary relation. 1:complex region 0 not complex region -1: error */ int CompTriangle::ComplexRegion() { int nocom = reg->NoComponents(); if(nocom == 0){ cout<<"error: this is not a region"< 1){ cout<<"error: several subregions"<Size() < 80) return 0; if(reg->Size() > 150) return 1;//////////complex region vector no_cycles(reg->Size(), -1); for(int i = 0;i < reg->Size();i++){ HalfSegment hs; reg->Get(i, hs); if(!hs.IsLeftDomPoint())continue; int cycleno = hs.attr.cycleno; no_cycles[cycleno] = cycleno; } unsigned int no_cyc = 0; for(unsigned int i = 0;i < no_cycles.size();i++){ if(no_cycles[i] != -1) no_cyc++; else break; } if(no_cyc < 4) return 0; else return 1; /////////there are many holes inside } /* get a sequence of triangles where the shoretest path should pass through */ void CompTriangle::FindAdj(unsigned int index, vector& flag, vector& adj_list) { vector cur_triangle; for(int i = 0;i < triangles[index].Size();i++){ HalfSegment hs; triangles[index].Get(i, hs); if(!hs.IsLeftDomPoint())continue; cur_triangle.push_back(hs); } assert(cur_triangle.size() == 3); const double delta_dist = 0.00001; for(unsigned int i = 0;i < triangles.size();i++){ if(flag[i] == true) continue; ///////////////////get the edges//////////////////////// vector triangle; for(int j = 0;j < triangles[i].Size();j++){ HalfSegment hs; triangles[i].Get(j, hs); if(!hs.IsLeftDomPoint())continue; triangle.push_back(hs); } assert(triangle.size() == 3); //////////////////////////////////////////////////////////// for(unsigned int k1 = 0;k1 < cur_triangle.size();k1++){ Point p1 = cur_triangle[k1].GetLeftPoint(); Point p2 = cur_triangle[k1].GetRightPoint(); unsigned int k2 = 0; for(;k2 < triangle.size();k2++){ Point p3 = triangle[k2].GetLeftPoint(); Point p4 = triangle[k2].GetRightPoint(); if(p1.Distance(p3) < delta_dist && p2.Distance(p4) < delta_dist){ adj_list.push_back(i); flag[i] = true; break; } if(p1.Distance(p4) < delta_dist && p2.Distance(p3) < delta_dist){ adj_list.push_back(i); flag[i] = true; break; } } if(k2 != triangle.size())break; } } } /* get a sequence of triangles from the start point to the end point */ void CompTriangle::GetChannel(Point* start, Point* end) { ////////// find the start triangle ///////////////////////// int index1 = -1; int index2 = -1; for(unsigned int i = 0;i < triangles.size();i++){ if(start->Inside(triangles[i])){ index1 = i; break; } } ////////// find the end triangle ///////////////////////// for(unsigned int i = 0;i < triangles.size();i++){ if(end->Inside(triangles[i])){ index2 = i; break; } } assert(index1 != -1 && index2 != -1); cout<<"index1 "< triangle_flag; for(unsigned int i = 0;i < triangles.size();i++) triangle_flag.push_back(false); triangle_flag[index1] = true; ////////////////shortest path algorithm/////////////////////// priority_queue path_queue; vector expand_path; path_queue.push(SPath_elem(-1, 0, index1, 1)); expand_path.push_back(SPath_elem(-1,0, index1, 1)); bool find = false; SPath_elem dest;//////////destination while(path_queue.empty() == false){ SPath_elem top = path_queue.top(); path_queue.pop(); // top.Print(); if(top.tri_index == index2){ cout<<"find the path"< adj_list; FindAdj(top.tri_index, triangle_flag, adj_list); // cout<<"adjcency_list size "< path_record; while(dest.prev_index != -1){ // sleeve.push_back(triangles[dest.tri_index]); path_record.push_back(dest.tri_index); dest = expand_path[dest.prev_index]; } // sleeve.push_back(triangles[dest.tri_index]); path_record.push_back(dest.tri_index); for(int i = path_record.size() - 1;i >= 0;i--) sleeve.push_back(triangles[path_record[i]]); } } /* build the channel/funnel */ void CompTriangle::ConstructConvexChannel1(list& funnel_front, list& funnel_back, Point& newvertex, vector& path, bool front_back) { // cout<<"ConstructConvexChannel1 "<Contains(hs)){ funnel_back.pop_back(); mp1 = elem; }else break; } if(funnel_back.empty()){//case 1 // cout<<"funnel_back empty"<::iterator iter = funnel_front.begin(); for(;iter != funnel_front.end();iter++){ Point p = iter->loc; HalfSegment hs; hs.Set(true, p, newvertex); if(reg->Contains(hs))break; } double l2 = newvertex.Distance(iter->loc) + iter->dist; /////////////////////////////// // cout<<"l1 "<Contains(hs))break; funnel_front.pop_front(); if(path[path.size() - 1].Distance(elem.loc) > delta_dist) path.push_back(elem.loc); } assert(funnel_front.empty() == false); MyPoint top = funnel_front.front(); path.push_back(top.loc); //update funnel_back funnel_back.clear(); funnel_back.push_back(top); funnel_back.push_back(MyPoint(newvertex, newvertex.Distance(top.loc) + top.dist)); } }else{//case 1,find a point in funnel_back directly connected to newvertex funnel_back.push_back(mp1); funnel_back.push_back(MyPoint(newvertex, newvertex.Distance(mp1.loc) + mp1.dist)); } } //push newvertex into funnel_front }else{ //back = newvertex, check funnel funnel_front first // cout<<"back "<<"push into front "<Contains(hs)){ funnel_front.pop_back(); mp1 = elem; }else break; } if(funnel_front.empty()){//case 1 // cout<<"funnel_front empty"<::iterator iter = funnel_back.begin(); for(;iter != funnel_back.end();iter++){ Point p = iter->loc; HalfSegment hs; hs.Set(true, p, newvertex); if(reg->Contains(hs))break; } double l2 = newvertex.Distance(iter->loc) + iter->dist; ///////////////////////////////////////////////// // cout<<"l1 "<Contains(hs))break; funnel_back.pop_front(); if(path[path.size() - 1].Distance(elem.loc) > delta_dist) path.push_back(elem.loc); } assert(funnel_back.empty() == false); MyPoint top = funnel_back.front(); path.push_back(top.loc); //update funnel_front funnel_front.clear(); funnel_front.push_back(top); funnel_front.push_back(MyPoint(newvertex, newvertex.Distance(top.loc) + top.dist)); } }else{//case 1,find a point in funnel_back directly connected to newvertex funnel_front.push_back(mp1); funnel_front.push_back(MyPoint(newvertex, newvertex.Distance(mp1.loc) + mp1.dist)); } } } /* list::iterator iter = funnel_front.begin(); cout<<"front "; for(;iter != funnel_front.end();iter++){ Point p = iter->loc; cout<loc; cout< funnel_front, list funnel_back, Point& newvertex, vector& path, bool front_back) { // cout<<"ConstructConvexChannel2 "<Contains(hs)){ funnel_back.pop_back(); mp1 = elem; }else break; } double l1 = newvertex.Distance(mp1.loc) + mp1.dist; //////////////////////////////////////////////// list::iterator iter = funnel_front.begin(); for(;iter != funnel_front.end();iter++){ Point p = iter->loc; HalfSegment hs; if(p.Distance(newvertex) < delta_dist) break; hs.Set(true, p, newvertex); if(reg->Contains(hs))break; } double l2 = newvertex.Distance(iter->loc) + iter->dist; ///////////////////////////////////////////////// // cout<<"l1 "< delta_dist) path.push_back(mp1.loc); }else{ MyPoint top = funnel_front.front(); if(funnel_front.empty() == false) funnel_front.pop_front(); HalfSegment hs; if(top.loc.Distance(newvertex) < delta_dist) return; hs.Set(true, top.loc, newvertex); if(reg->Contains(hs)) return; while(funnel_front.empty() == false){ MyPoint elem = funnel_front.front(); path.push_back(elem.loc); //////////////////////////////////////// HalfSegment hs; if(elem.loc.Distance(newvertex) < delta_dist) break; hs.Set(true, elem.loc, newvertex); if(reg->Contains(hs))break; /////////////////////////////////////// funnel_front.pop_front(); } } //push newvertex into funnel_front }else{ //back = newvertex, check funnel funnel_front first // cout<<"back "<<"push into front "<Contains(hs)){ funnel_front.pop_back(); mp1 = elem; }else break; } double l1 = newvertex.Distance(mp1.loc) + mp1.dist; ///////////////////////////////////////////// list::iterator iter = funnel_back.begin(); for(;iter != funnel_back.end();iter++){ Point p = iter->loc; HalfSegment hs; if(p.Distance(newvertex) < delta_dist){ break; } hs.Set(true, p, newvertex); if(reg->Contains(hs))break; } double l2 = newvertex.Distance(iter->loc) + iter->dist; //////////////////////////////////////////// // cout<<"l1 "< delta_dist) path.push_back(mp1.loc); } else{ MyPoint top = funnel_back.front(); if(funnel_back.empty() == false){ funnel_back.pop_front(); } HalfSegment hs; if(top.loc.Distance(newvertex) < delta_dist)return; hs.Set(true, top.loc, newvertex); if(reg->Contains(hs)) return; while(funnel_back.empty() == false){ MyPoint elem = funnel_back.front(); path.push_back(elem.loc); ///////////////////////////// HalfSegment hs; if(elem.loc.Distance(newvertex) < delta_dist)break; hs.Set(true, elem.loc, newvertex); if(reg->Contains(hs))break; ////////////////////////////// funnel_back.pop_front(); } } } } /* geometrical shortest path in a polygon Apply the Funnel Algorithm, front point---->point The polygon should not have hole inside. !!! If it has hole inside, it has to check every possible path. */ void CompTriangle::GeoShortestPath(Point* start, Point* end) { if(start->Inside(*reg) == false || end->Inside(*reg) == false){ cout<<"points are not inside the polygon"<GetX(), end->GetX()) && AlmostEqual(start->GetY(), end->GetY())){ cout<<"two points are equal"<StartBulkLoad(); HalfSegment hs; hs.Set(true, *start, *end); hs.attr.edgeno = edgeno++; *path += hs; hs.SetLeftDomPoint(!hs.IsLeftDomPoint()); *path += hs; path->EndBulkLoad(); sleeve.push_back(*reg); return; } // Triangulation();//get a set of triangles, does not support hole NewTriangulation(); if(triangles.size() < 3){ cout<<"triangulation is not correct"< diagonals; const double delta_dist = 0.00001; // cout<<"channel size "< cur_triangle; for(int j = 0;j < sleeve[i].Size();j++){ HalfSegment hs; sleeve[i].Get(j, hs); if(!hs.IsLeftDomPoint())continue; cur_triangle.push_back(hs); } vector next_triangle; for(int j = 0;j < sleeve[i + 1].Size();j++){ HalfSegment hs; sleeve[i + 1].Get(j, hs); if(!hs.IsLeftDomPoint())continue; next_triangle.push_back(hs); } for(unsigned int k1 = 0;k1 < cur_triangle.size();k1++){ Point p1 = cur_triangle[k1].GetLeftPoint(); Point p2 = cur_triangle[k1].GetRightPoint(); unsigned int k2 = 0; for(;k2 < next_triangle.size();k2++){ Point p3 = next_triangle[k2].GetLeftPoint(); Point p4 = next_triangle[k2].GetRightPoint(); if(p1.Distance(p3) < delta_dist && p2.Distance(p4) < delta_dist){ HalfSegment hs; hs.Set(true,p1, p2); diagonals.push_back(hs); break; } if(p1.Distance(p4) < delta_dist && p2.Distance(p3) < delta_dist){ HalfSegment hs; hs.Set(true,p1, p2); diagonals.push_back(hs); break; } } if(k2 != next_triangle.size())break; } } // cout<<"diagnoals size "< funnel_front; list funnel_back; Point apex = *start; vector shortest_path; shortest_path.push_back(apex); funnel_front.push_back(MyPoint(apex, 0.0)); funnel_back.push_back(MyPoint(apex, 0.0)); bool funnel_front_flag = true; for(unsigned int i = 0;i < diagonals.size();i++){ Point lp = diagonals[i].GetLeftPoint(); Point rp = diagonals[i].GetRightPoint(); if(i == 0){ funnel_front.push_back(MyPoint(lp, lp.Distance(apex))); funnel_back.push_back(MyPoint(rp, rp.Distance(apex))); continue; } Point last_lp = diagonals[i - 1].GetLeftPoint(); Point last_rp = diagonals[i - 1].GetRightPoint(); Point newvertex; if(lp.Distance(last_lp) < delta_dist || lp.Distance(last_rp) < delta_dist){ newvertex = rp; // cout<<"newvertex rp" <StartBulkLoad(); int edgeno = 0; for(unsigned int i = 0;i < shortest_path.size() - 1;i++){ // cout<<"point1 "<EndBulkLoad(); } /* select the point on segment to compute the shortest path. it goes through the funnel to check the vertex stored and try to find sucn an segment which is contained by the polygon and it consists of the vertex and the closest point to the vertex in the input segement. */ void CompTriangle::SelectPointOnSeg(list funnel_front, list funnel_back, HalfSegment* end, Point& vertex, Point& cp) { SpacePartition* sp = new SpacePartition(); const double delta_dist = 0.00001; MyPoint elem_front = funnel_front.back(); MyPoint elem_back = funnel_back.back(); if(elem_front.loc.Distance(vertex) < delta_dist){ sp->GetClosestPoint(*end, elem_front.loc, cp); funnel_front.pop_back(); while(funnel_front.empty() == false){ MyPoint elem = funnel_front.back(); Point p; sp->GetClosestPoint(*end, elem.loc, p); HalfSegment hs; hs.Set(true, elem.loc, p); if(reg->Contains(hs) == false)break; cp = p; funnel_front.pop_back(); } }else if(elem_back.loc.Distance(vertex) < delta_dist){ sp->GetClosestPoint(*end, elem_back.loc, cp); funnel_back.pop_back(); while(funnel_back.empty() == false){ MyPoint elem = funnel_back.back(); Point p; sp->GetClosestPoint(*end, elem.loc, p); HalfSegment hs; hs.Set(true, elem.loc, p); if(reg->Contains(hs) == false)break; cp = p; funnel_back.pop_back(); } }else assert(false); delete sp; } /* compute the shortest path from start point to the end segment */ void CompTriangle::PtoSegSPath(Point* start, HalfSegment* end, vector& temp_sleeve, Line* res_line) { /////////////////get the channel//////////////////////////// vector diagonals; const double delta_dist = 0.00001; for(unsigned int i = 0;i < temp_sleeve.size() - 1;i++){ vector cur_triangle; for(int j = 0;j < temp_sleeve[i].Size();j++){ HalfSegment hs; temp_sleeve[i].Get(j, hs); if(!hs.IsLeftDomPoint())continue; cur_triangle.push_back(hs); } vector next_triangle; for(int j = 0;j < temp_sleeve[i + 1].Size();j++){ HalfSegment hs; temp_sleeve[i + 1].Get(j, hs); if(!hs.IsLeftDomPoint())continue; next_triangle.push_back(hs); } for(unsigned int k1 = 0;k1 < cur_triangle.size();k1++){ Point p1 = cur_triangle[k1].GetLeftPoint(); Point p2 = cur_triangle[k1].GetRightPoint(); unsigned int k2 = 0; for(;k2 < next_triangle.size();k2++){ Point p3 = next_triangle[k2].GetLeftPoint(); Point p4 = next_triangle[k2].GetRightPoint(); if(p1.Distance(p3) < delta_dist && p2.Distance(p4) < delta_dist){ HalfSegment hs; hs.Set(true,p1, p2); diagonals.push_back(hs); break; } if(p1.Distance(p4) < delta_dist && p2.Distance(p3) < delta_dist){ HalfSegment hs; hs.Set(true,p1, p2); diagonals.push_back(hs); break; } } if(k2 != next_triangle.size())break; } } // cout<<"diagnoals size "< funnel_front; list funnel_back; Point apex = *start; vector shortest_path; shortest_path.push_back(apex); funnel_front.push_back(MyPoint(apex, 0.0)); funnel_back.push_back(MyPoint(apex, 0.0)); bool funnel_front_flag = true; Point newvertex; Point newvertex_pair; for(unsigned int i = 0;i < diagonals.size();i++){ Point lp = diagonals[i].GetLeftPoint(); Point rp = diagonals[i].GetRightPoint(); if(i == 0){ funnel_front.push_back(MyPoint(lp, lp.Distance(apex))); funnel_back.push_back(MyPoint(rp, rp.Distance(apex))); continue; } Point last_lp = diagonals[i - 1].GetLeftPoint(); Point last_rp = diagonals[i - 1].GetRightPoint(); if(lp.Distance(last_lp) < delta_dist || lp.Distance(last_rp) < delta_dist){ newvertex = rp; newvertex_pair = lp; // cout<<"newvertex rp" < shortest_path_another; for(unsigned int i = 0;i < shortest_path.size();i++) shortest_path_another.push_back(shortest_path[i]); // cout<<"newvertex "< copy_funnel_front; list copy_funnel_back; list::iterator iter; for(iter = funnel_front.begin(); iter != funnel_front.end();iter++) copy_funnel_front.push_back(*iter); for(iter = funnel_back.begin(); iter != funnel_back.end();iter++) copy_funnel_back.push_back(*iter); Point cp1, cp2; ////////////////////////////////////////////////////////////////// SelectPointOnSeg(funnel_front, funnel_back, end, newvertex, cp1); if(newvertex.Distance(cp1) > delta_dist){ ConstructConvexChannel2(funnel_front, funnel_back, cp1, shortest_path, funnel_front_flag); shortest_path.push_back(cp1); }else{ MyPoint top_front = funnel_front.back(); MyPoint top_back = funnel_back.back(); if(top_front.loc.Distance(cp1) < delta_dist){ while(funnel_front.size() > 1){ MyPoint elem = funnel_front.back(); funnel_front.pop_back(); shortest_path.push_back(elem.loc); } }else if(top_back.loc.Distance(cp1) < delta_dist){ while(funnel_back.size() > 1){ MyPoint elem = funnel_back.back(); funnel_back.pop_back(); shortest_path.push_back(elem.loc); } }else assert(false); } /////////////////////////////////////////////////////////////////////// // cout<<"path1 size "< delta_dist){ ConstructConvexChannel2(copy_funnel_front, copy_funnel_back, cp2, shortest_path_another, !funnel_front_flag); shortest_path_another.push_back(cp2); }else{ MyPoint top_front = copy_funnel_front.back(); MyPoint top_back = copy_funnel_back.back(); if(top_front.loc.Distance(cp2) < delta_dist){ while(copy_funnel_front.size() > 1){ MyPoint elem = copy_funnel_front.back(); copy_funnel_front.pop_back(); shortest_path_another.push_back(elem.loc); } }else if(top_back.loc.Distance(cp2) < delta_dist){ while(copy_funnel_back.size() > 1){ MyPoint elem = copy_funnel_back.back(); copy_funnel_back.pop_back(); shortest_path_another.push_back(elem.loc); } }else assert(false); } // cout<<"path2 size "<StartBulkLoad(); int edgeno1 = 0; for(unsigned int i = 0;i < shortest_path.size() - 1;i++){ HalfSegment hs; Point p1 = shortest_path[i]; Point p2 = shortest_path[i + 1]; hs.Set(true, p1, p2); hs.attr.edgeno = edgeno1++; *l1 += hs; hs.SetLeftDomPoint(!hs.IsLeftDomPoint()); *l1 += hs; } l1->EndBulkLoad(); Line* l2 = new Line(0); l2->StartBulkLoad(); int edgeno2 = 0; for(unsigned int i = 0;i < shortest_path_another.size() - 1;i++){ HalfSegment hs; Point p1 = shortest_path_another[i]; Point p2 = shortest_path_another[i + 1]; hs.Set(true, p1, p2); hs.attr.edgeno = edgeno2++; *l2 += hs; hs.SetLeftDomPoint(!hs.IsLeftDomPoint()); *l2 += hs; } l2->EndBulkLoad(); if(l1->Length() < l2->Length()) *res_line = *l1; else *res_line = *l2; l1->DeleteIfAllowed(); l2->DeleteIfAllowed(); } /*The following describes a method for determining whether or not a polygon has its vertices ordered clockwise or anticlockwise for both convex and concave polygons. A polygon will be assumed to be described by N vertices, ordered (x0,y0), (x1,y1), (x2,y2), . . . (xn-1,yn-1) A simple test of vertex ordering for convex polygons is based on considerations of the cross product between adjacent edges. If the crossproduct is positive then it rises above the plane (z axis up out of the plane) and if negative then the cross product is into the plane. cross product = ((xi - xi-1),(yi - yi-1)) x ((xi+1 - xi),(yi+1 - yi)) = (xi - xi-1) * (yi+1 - yi) - (yi - yi-1) * (xi+1 - xi) A positive cross product means we have a counterclockwise polygon. To determine the vertex ordering for concave polygons one can use a result from the calculation of polygon areas, where the area is given by A = 1/2*Sum(for (i=0;i no_cycles(reg->Size(), -1); for(int i = 0;i < reg->Size();i++){ HalfSegment hs; reg->Get(i, hs); if(!hs.IsLeftDomPoint())continue; int cycleno = hs.attr.cycleno; no_cycles[cycleno] = cycleno; } unsigned int no_cyc = 0; for(unsigned int i = 0;i < no_cycles.size();i++){ if(no_cycles[i] != -1) no_cyc++; else break; } return no_cyc; } /* Initialize the point list */ void CompTriangle::PolygonContourPoint(unsigned int no_cyc, int no_p_contour[], vector& ps_contour_x, vector& ps_contour_y) { ps_contour_x.push_back(0.0); ps_contour_y.push_back(0.0); vector sl_contour; for(unsigned int i = 0;i < no_cyc;i++){ SimpleLine* sl = new SimpleLine(0); sl->StartBulkLoad(); sl_contour.push_back(sl); } vector edgenos(no_cyc, 0); for(int j = 0;j < reg->Size();j++){ HalfSegment hs1; reg->Get(j, hs1); if(!hs1.IsLeftDomPoint()) continue; HalfSegment hs2; hs2.Set(true, hs1.GetLeftPoint(), hs1.GetRightPoint()); hs2.attr.edgeno = edgenos[hs1.attr.cycleno]++; *sl_contour[hs1.attr.cycleno] += hs2; hs2.SetLeftDomPoint(!hs2.IsLeftDomPoint()); *sl_contour[hs1.attr.cycleno] += hs2; } // cout<<"get all boundary line"<EndBulkLoad(); vector mhs; SimpleLine* line = sl_contour[i]; if(! line->IsDefined()) { cout << "Ignoring undefined line" << endl; continue; } sp->ReorderLine(line, mhs); vector ps; for(size_t j = 0; j < mhs.size(); j++) { ps.push_back(mhs[j].from); } bool clock; if(0.0f < Area(ps)){//points counter-clockwise order clock = false; }else{// points clockwise clock = true; } no_p_contour[i] = ps.size(); if(i == 0){//outer contour, counter_clockwise if(clock == false){ for(unsigned int index = 0;index < ps.size();index++){ ps_contour_x.push_back(ps[index].GetX()); ps_contour_y.push_back(ps[index].GetY()); } }else{ for(unsigned int index = 0;index < ps.size();index++){ ps_contour_x.push_back(ps[ps.size() - 1 - index].GetX()); ps_contour_y.push_back(ps[ps.size() - 1 - index].GetY()); } } }else{//hole points, should be clockwise if(clock == false){ for(unsigned int index = 0;index < ps.size();index++){ ps_contour_x.push_back(ps[ps.size() -1 - index].GetX()); ps_contour_y.push_back(ps[ps.size() -1 - index].GetY()); } }else{ for(unsigned int index = 0;index < ps.size();index++){ ps_contour_x.push_back(ps[index].GetX()); ps_contour_y.push_back(ps[index].GetY()); } } } sl_contour[i]->DeleteIfAllowed(); } delete sp; } /* the same as PolygonContourPoint, but do not insert (0,0) for the first point for each cycle, it inserts the first point to the end to close the region */ void CompTriangle::PolygonContourPoint2(unsigned int no_cyc, int no_p_contour[], vector& ps_contour_x, vector& ps_contour_y) { vector sl_contour; for(unsigned int i = 0;i < no_cyc;i++){ SimpleLine* sl = new SimpleLine(0); sl->StartBulkLoad(); sl_contour.push_back(sl); } vector edgenos(no_cyc, 0); for(int j = 0;j < reg->Size();j++){ HalfSegment hs1; reg->Get(j, hs1); if(!hs1.IsLeftDomPoint()) continue; HalfSegment hs2; hs2.Set(true, hs1.GetLeftPoint(), hs1.GetRightPoint()); hs2.attr.edgeno = edgenos[hs1.attr.cycleno]++; *sl_contour[hs1.attr.cycleno] += hs2; hs2.SetLeftDomPoint(!hs2.IsLeftDomPoint()); *sl_contour[hs1.attr.cycleno] += hs2; } // cout<<"get all boundary line"<EndBulkLoad(); vector mhs; sp->ReorderLine(sl_contour[i], mhs); vector ps; for(unsigned int j = 0;j < mhs.size();j++) ps.push_back(mhs[j].from); bool clock; if(0.0f < Area(ps)){//points counter-clockwise order clock = false; }else{// points clockwise clock = true; } no_p_contour[i] = ps.size(); if(i == 0){//outer contour, counter_clockwise if(clock == false){ for(unsigned int index = 0;index < ps.size();index++){ ps_contour_x.push_back(ps[index].GetX()); ps_contour_y.push_back(ps[index].GetY()); } //////////insert the start point again to close the region/////// // unsigned int index = 0; // ps_contour_x.push_back(ps[index].GetX()); // ps_contour_y.push_back(ps[index].GetY()); }else{ for(unsigned int index = 0;index < ps.size();index++){ ps_contour_x.push_back(ps[ps.size() - 1 - index].GetX()); ps_contour_y.push_back(ps[ps.size() - 1 - index].GetY()); } //////////insert the start point again to close the region/////// // unsigned int index = 0; // ps_contour_x.push_back(ps[ps.size() - 1 - index].GetX()); // ps_contour_y.push_back(ps[ps.size() - 1 - index].GetY()); } }else{//hole points, should be clockwise if(clock == false){ for(unsigned int index = 0;index < ps.size();index++){ ps_contour_x.push_back(ps[ps.size() - 1 - index].GetX()); ps_contour_y.push_back(ps[ps.size() - 1 - index].GetY()); } //////////insert the start point again to close the region/////// // unsigned int index = 0; // ps_contour_x.push_back(ps[ps.size() -1 - index].GetX()); // ps_contour_y.push_back(ps[ps.size() -1 - index].GetY()); }else{ for(unsigned int index = 0;index < ps.size();index++){ ps_contour_x.push_back(ps[index].GetX()); ps_contour_y.push_back(ps[index].GetY()); } //////////insert the start point again to close the region/////// // unsigned int index = 0; // ps_contour_x.push_back(ps[index].GetX()); // ps_contour_y.push_back(ps[index].GetY()); } } sl_contour[i]->DeleteIfAllowed(); } delete sp; } /* Decompose a polygon with and without holes into a set of triangles Using the implementation by Atul Narkhede and Dinesh Manocha */ void CompTriangle::NewTriangulation() { if(reg->NoComponents() == 0){ cout<<"this is not a region"<NoComponents() > 1){ cout<<"can't handle region with more than one face"< ps_contour_x; vector ps_contour_y; PolygonContourPoint(no_cyc, no_p_contour, ps_contour_x, ps_contour_y); // cout<<"finish creating contour for the polgyon"< ps_reg; Point p1, p2, p3; Coord x, y; x = ps_contour_x[res_triangles[i][0]]; y = ps_contour_y[res_triangles[i][0]]; p1.Set(x, y); x = ps_contour_x[res_triangles[i][1]]; y = ps_contour_y[res_triangles[i][1]]; p2.Set(x, y); x = ps_contour_x[res_triangles[i][2]]; y = ps_contour_y[res_triangles[i][2]]; p3.Set(x, y); ps_reg.push_back(p1); ps_reg.push_back(p2); ps_reg.push_back(p3); vector reg; spacepart->ComputeRegion(ps_reg, reg); triangles.push_back(reg[0]); } delete spacepart; //////////////////////////////////////////////////////////////////// } /* Decompose a polygon with and without holes into a set of triangles Using the implementation by from codeproject holes: number of vertices - 2 without holes: number of vertices - 1 - 2 */ void CompTriangle::NewTriangulation2() { if(reg->NoComponents() == 0){ cout<<"this is not a region"<NoComponents() > 1){ cout<<"can't handle region with more than one face"< ps_contour_x; vector ps_contour_y; PolygonContourPoint2(no_cyc, no_p_contour, ps_contour_x, ps_contour_y); // cout<<"finish creating contour for the polgyon"< ps_reg; Point p1, p2, p3; Coord x, y; x = poly.mtabPnt[index1].X(); y = poly.mtabPnt[index1].Y(); p1.Set(x, y); x = poly.mtabPnt[index2].X(); y = poly.mtabPnt[index2].Y(); p2.Set(x, y); x = poly.mtabPnt[index3].X(); y = poly.mtabPnt[index3].Y(); p3.Set(x, y); ps_reg.push_back(p1); ps_reg.push_back(p2); ps_reg.push_back(p3); vector reg; // cout<ComputeRegion(ps_reg, reg); if(reg.size() > 0) //2012.3.9 rounding problem triangles.push_back(reg[0]); } delete spacepart; //////////////////////////////////////////////////////////////////// } /* collect all vertices of a polygon together with its two neighbors the two halfsegments One big region with a lot of holes inside. it collects the vertices of all these holes */ void CompTriangle::GetAllPoints() { if(reg->NoComponents() == 0){ cout<<"this is not a region"< ps_contour_x; vector ps_contour_y; ps_contour_x.push_back(0.0); ps_contour_y.push_back(0.0); vector sl_contour; for(unsigned int i = 0;i < no_cyc;i++){ SimpleLine* sl = new SimpleLine(0); sl->StartBulkLoad(); sl_contour.push_back(sl); } vector edgenos(no_cyc, 0); for(int j = 0;j < reg->Size();j++){ HalfSegment hs1; reg->Get(j, hs1); // if(!hs1.IsLeftDomPoint() || hs1.attr.cycleno == 0) continue; if(!hs1.IsLeftDomPoint()) continue; HalfSegment hs2; hs2.Set(true, hs1.GetLeftPoint(), hs1.GetRightPoint()); int cycle_no = hs1.attr.cycleno; hs2.attr.edgeno = edgenos[cycle_no]++; *sl_contour[cycle_no] += hs2; hs2.SetLeftDomPoint(!hs2.IsLeftDomPoint()); *sl_contour[cycle_no] += hs2; } // cout<<"get all boundary line"<EndBulkLoad(); vector mhs; sp->ReorderLine(sl_contour[i], mhs); for(unsigned int j = 0;j < mhs.size();j++){ plist1.push_back(mhs[j].from); reg_id.push_back(i + 1);//cycle_no id, start from 1; if(j == 0){ plist2.push_back(mhs[j + 1].from); plist3.push_back(mhs[mhs.size() - 1].from); }else if(j == mhs.size() - 1){ plist2.push_back(mhs[j - 1].from); plist3.push_back(mhs[0].from); }else{ plist2.push_back(mhs[j - 1].from); plist3.push_back(mhs[j + 1].from); } } } delete sp; // cout<& allps, Point& query_p, Point& hp, Point& p, SpacePartition* sp, Point* q1, Point* q2, int reg_id) { double angle = sp->GetAngle(query_p, hp, p); double dist = query_p.Distance(p); if(sp->GetClockwise(query_p, hp, p)){// clockwise angle = 2*TM_MYPI - angle; } RPoint rp(p, angle, dist, reg_id); rp.SetNeighbor(*q1, *q2); allps.push(rp); } /* insert segments that intersect the original sweep line into AVLTree */ void CompTriangle::InitializeAVL( multiset& sss, Point& query_p, Point& hp, Point& p, Point& neighbor, SpacePartition* sp) { HalfSegment hs1; hs1.Set(true, query_p, hp); HalfSegment hs2; hs2.Set(true, p, neighbor); Point ip; /////////////////do not insert such segment////////////////////////////// ///////as it needs more work to determin counter-clockwise or clockwise// ///////we collect the two endpoints as visible and determine the region ///face locates on which side of the segment if(hs2.Contains(query_p))return; if(hs1.Intersection(hs2, ip)){ double angle1 = sp->GetAngle(query_p, hp, p); double angle2 = sp->GetAngle(query_p, hp, neighbor); if(sp->GetClockwise(query_p, hp, p)) angle1 = 2*TM_MYPI-angle1; if(sp->GetClockwise(query_p, hp, neighbor)) angle2 = 2*TM_MYPI-angle2; if(AlmostEqual(angle1, angle2)){ double d1 = query_p.Distance(p); double d2 = query_p.Distance(neighbor); if(d1 < d2){ MySegDist myseg(true, p, neighbor, d1); // if(!(*(sss.find(myseg)) == myseg)) sss.insert(myseg); } }else{ double dist = hs2.Distance(query_p); MySegDist myseg(true, p, neighbor, dist); // if(!(*(sss.find(myseg)) == myseg)) sss.insert(myseg); } } } void CompTriangle::PrintAVLTree(multiset& sss, ofstream& outfile) { outfile<<"AVLTree"<::iterator start; multiset::iterator end = sss.end(); for(start = sss.begin();start != end; start++) outfile<<*start<& sss, RPoint& rp, Point& query_p, Point& neighbor, Point& hp, SpacePartition* sp, ofstream& outfile)*/ void CompTriangle::ProcessNeighbor(multiset& sss, RPoint& rp, Point& query_p, Point& neighbor, Point& hp, SpacePartition* sp) { HalfSegment hs; hs.Set(true, rp.p, neighbor); // outfile<<"rp.p "<GetAngle(query_p, hp, neighbor); if(sp->GetClockwise(query_p, hp, neighbor)) angle = 2*TM_MYPI - angle; if(AlmostEqual(angle, rp.angle)){ // outfile<<"on the same line as query_p "<::iterator iter = sss.find(myseg); // assert(iter != sss.end()); if(iter != sss.end()){ while(iter != sss.end()){ if(*iter == myseg){ sss.erase(iter); break; }else iter++; } } } return; } if(sp->GetClockwise(query_p, rp.p, neighbor) == false){ double dist = hs.Distance(query_p); MySegDist myseg(true, rp.p, neighbor, dist); // outfile<<"insert2 "<::iterator iter = sss.find(myseg); // assert(iter != sss.end()); if(iter != sss.end()){ while(iter != sss.end()){ if(*iter == myseg){ sss.erase(iter); break; }else iter++; } } } } /* using rotational plane sweep algorithm to find visible points. the query point should not locate on the outer contour boundary Micha Sharir and Amir Schorr On Shortest Paths in Polyhedral Spaces, SIAM Journal on Computing. 1986 */ void CompTriangle::GetVPoints(Relation* rel1, Relation* rel2, Rectangle<2>* bbox, Relation* rel3, int attr_pos) { // cout<<"attr_pos "<GetNoTuples() < 1){ cout<<"query relation is empty"<GetTuple(1, false); Point* query_p = new Point(*((Point*)query_tuple->GetAttribute(VisualGraph::QLOC2))); query_tuple->DeleteIfAllowed(); // outfile<<"query point "<<*query_p<MaxD(0) + 1.0; Point hp; hp.Set(xmax, query_p->GetY()); HalfSegment hs1; hs1.Set(true, *query_p, hp); // cout<<"horizonal p "< allps; multiset sss; vector neighbors; //one segment contains query_p //it represents query_p equals to the endpoint(=2) or not(=3) int no_contain = 0; int hole_id = 0; //record whether the query point locates on the hole boundary SpacePartition* sp = new SpacePartition(); for(int i = 1;i <= rel2->GetNoTuples();i++){ Tuple* p_tuple = rel2->GetTuple(i, false); Point* p = (Point*)p_tuple->GetAttribute(CompTriangle::V); if(AlmostEqual(*query_p, *p)){//equal points are ignored p_tuple->DeleteIfAllowed(); continue; } Point* q1 = (Point*)p_tuple->GetAttribute(CompTriangle::NEIGHBOR1); // outfile<<"vertex "<<*p<GetAngle(*query_p, hp, *p)<GetAttribute(CompTriangle::NEIGHBOR2); int reg_id = ((CcInt*)p_tuple->GetAttribute(CompTriangle::REGID))->GetIntval(); HalfSegment hs1; hs1.Set(true, *p, *q1); HalfSegment hs2; hs2.Set(true, *p, *q2); if(no_contain < 2 && hs1.Contains(*query_p)){ /* cout<<"segment contains query points "<DeleteIfAllowed(); return;*/ // cout<<"hs1 "<DeleteIfAllowed(); } delete sp; // PrintAVLTree(sss, outfile); double last_angle = -1.0; double angle1 = -1.0; double angle2 = -1.0; // bool face_direction; //false counter-clockwise, true clockwise bool face_direction = true; //false counter-clockwise, true clockwise //determine the region face on which side of the segment if(hole_id != 0){ // cout<GetTuple(hole_id, false); Region* r = (Region*)reg_tuple->GetAttribute(attr_pos); Line* boundary = new Line(0); r->Boundary(boundary); SimpleLine* sboundary = new SimpleLine(0); sboundary->fromLine(*boundary); vector mhs; //get all the points of the region SpacePartition* sp = new SpacePartition(); if(sboundary->Size() > 0) sp->ReorderLine(sboundary, mhs); else{ cout<<"can't covert the boundary to a sline, maybe there is a hole"<DeleteIfAllowed(); sboundary->DeleteIfAllowed(); return; } boundary->DeleteIfAllowed(); sboundary->DeleteIfAllowed(); vector ps; for(unsigned int i = 0;i < mhs.size();i++) ps.push_back(mhs[i].from); angle1 = sp->GetAngle(*query_p, hp, neighbors[0]); angle2 = sp->GetAngle(*query_p, hp, neighbors[1]); if(sp->GetClockwise(*query_p, hp, neighbors[0])) angle1 = 2*TM_MYPI - angle1; if(sp->GetClockwise(*query_p, hp, neighbors[1])) angle2 = 2*TM_MYPI - angle2; if(angle1 > angle2){ Point temp = neighbors[0]; neighbors[0] = neighbors[1]; neighbors[1] = temp; double temp_angle = angle1; angle1 = angle2; angle2 = temp_angle; } //combine with index1 and index2 //the point with smaller angle and larger angle //from smaller angle to larger angle, whether it is counter clockwisr or not if(0.0 < Area(ps)) face_direction = false;//counter-clockwise else face_direction = true; //query_p locates in one segment but not equal to endpoint if(no_contain > 2){ unsigned int index1 = ps.size(); unsigned int index2 = ps.size(); for(unsigned int i = 0;i < ps.size();i++){ if(AlmostEqual(ps[i], neighbors[0])) index1 = i; if(AlmostEqual(ps[i], neighbors[1])) index2 = i; } assert(index1 != ps.size() && index2 != ps.size()); if(hole_id == 1){ if(index1 == index2 + 1){ face_direction = !face_direction; }else if(index1 == 0 && index2 == ps.size() - 1){ face_direction = !face_direction; } }else{ if(index1 + 1 == index2){ face_direction = !face_direction; }else if(index1 == ps.size() - 1 && index2 == 0){ face_direction = !face_direction; } } }else if(no_contain == 2){//query_p equals to one endpoint of a segment unsigned int index1 = ps.size(); unsigned int index2 = ps.size(); for(unsigned int i = 0;i < ps.size();i++){ if(AlmostEqual(ps[i], neighbors[0])) index1 = i; if(AlmostEqual(ps[i], *query_p)) index2 = i; } assert(index1 != ps.size() && index2 != ps.size()); // outfile<<"index1 "<DeleteIfAllowed(); } Tuple* reg_tuple = rel3->GetTuple(1, false); Region* outer_region = (Region*)reg_tuple->GetAttribute(attr_pos); while(allps.empty() == false){ RPoint top = allps.top(); allps.pop(); ////////////////debug///////////////// // PrintAVLTree(sss, outfile); // outfile<StartBulkLoad(); HalfSegment hs; hs.Set(true, *query_p, top.p); hs.attr.edgeno = 0; *l += hs; hs.SetLeftDomPoint(!hs.IsLeftDomPoint()); *l += hs; l->EndBulkLoad(); connection.push_back(*l); l->DeleteIfAllowed(); } last_angle = top.angle; /* ProcessNeighbor(sss, top, *query_p, top.n1, hp, sp, outfile); ProcessNeighbor(sss, top, *query_p, top.n2, hp, sp, outfile);*/ ProcessNeighbor(sss, top, *query_p, top.n1, hp, sp); ProcessNeighbor(sss, top, *query_p, top.n2, hp, sp); continue; } ////////////// visibility checking /////////////////////////// if(!AlmostEqual(top.angle, last_angle)){ multiset::iterator start = sss.begin(); double d = query_p->Distance(top.p); double mindist = start->dist; bool visible = true; // outfile<<"d "< angle2)visible = false; } } if(visible){ if(d < mindist || AlmostEqual(d, mindist)){ // outfile<<"find visible point2"<dist < d && start != sss.end()){ HalfSegment cur_hs; cur_hs.Set(true, start->from, start->to); Point ip; if(test_hs.Intersection(cur_hs, ip)){ // outfile<<"test_hs "<StartBulkLoad(); HalfSegment hs; hs.Set(true, *query_p, top.p); hs.attr.edgeno = 0; *l += hs; hs.SetLeftDomPoint(!hs.IsLeftDomPoint()); *l += hs; l->EndBulkLoad(); connection.push_back(*l); l->DeleteIfAllowed(); } } // ProcessNeighbor(sss, top, *query_p,top.n1, hp, sp, outfile); // ProcessNeighbor(sss, top, *query_p,top.n2, hp, sp, outfile); ProcessNeighbor(sss, top, *query_p, top.n1, hp, sp); ProcessNeighbor(sss, top, *query_p, top.n2, hp, sp); ////////////////////////////////////////////////////////////////// last_angle = top.angle; ////////////////////////////////////////////////////////////// } reg_tuple->DeleteIfAllowed(); delete query_p; } /*********************implementation of basgraph********************/ BaseGraph::BaseGraph():g_id(0), node_rel(NULL), edge_rel(NULL), adj_list(0), entry_adj_list(0) { // cout<<"BaseGraph::BaseGraph()"<Close(); if(edge_rel != NULL) edge_rel->Close(); // adj_list.clean(); // entry_adj_list.clean(); } void BaseGraph::Destroy() { // cout<<"Destroy()"<Delete(); node_rel = NULL; } if(edge_rel != NULL){ edge_rel->Delete(); edge_rel = NULL; } } ListExpr BaseGraph::BaseGraphProp() { // cout<<"BaseGraphProp()"<TextAtom(); nl->AppendText(examplelist, "createdualgraph(,,)"); return nl->TwoElemList( nl->TwoElemList(nl->StringAtom("Creation"), nl->StringAtom("Example Creation")), nl->TwoElemList(examplelist, nl->StringAtom("let dg=createdualgraph(id,e-rel,n-rel)"))); } void* BaseGraph::CastBaseGraph(void* addr) { // cout<<"CastBaseGraph()"<& flag, vector& list) { ListEntry list_entry; entry_adj_list.Get(node_id - 1, list_entry); int low = list_entry.low; int high = list_entry.high; int j = low; while(j < high){ int oid; adj_list.Get(j, oid); j++; if(flag[oid - 1] == false){ list.push_back(oid); flag[oid - 1] = true; } } } void BaseGraph::FindAdj(int node_id, vector& list) { ListEntry list_entry; entry_adj_list.Get(node_id - 1, list_entry); int low = list_entry.low; int high = list_entry.high; int j = low; while(j < high){ int oid; adj_list.Get(j, oid); j++; list.push_back(oid); } } /*How can we find the shortest path for any polygon (with or without holes) and any startpoint and endpoint? As far as I know, an exhaustive search is required. However, the search can be optimized a bit so that it doesn’t take as long as testing every possible path. With the dual graph and visbility graph, it can be found efficiently*/ /*build a visibility graph, connect the start and end point to the graph*/ string DualGraph::NodeTypeInfo = "(rel(tuple((Oid int)(Rid int)(Pavement region))))"; string DualGraph::BTreeNodeTypeInfo = "(btree(tuple((Oid int)(Rid int)(Pavement region))) int)"; string DualGraph::EdgeTypeInfo = "(rel(tuple((Oid1 int)(Oid2 int)(Commarea line))))"; string DualGraph::NodeRTreeTypeInfo = "(rtree (tuple ((oid int)(rid int)\ (pavement region))) region FALSE)"; string DualGraph::TriangleTypeInfo1 = "(rel(tuple((V1 int)(V2 int)(V3 int)(Centroid point)(Oid int))))"; string DualGraph::TriangleTypeInfo2 = "(rel(tuple((Cycleno int)(Vertex point))))"; string DualGraph::TriangleTypeInfo3 = "(rel(tuple((V1 int)(V2 int)(V3 int)(Centroid point))))"; string DualGraph::TriangleTypeInfo4 = "(rel(tuple((Vid int)(Triid int))))"; ListExpr DualGraph::OutDualGraph(ListExpr typeInfo, Word value) { // cout<<"OutDualGraph()"<Out(typeInfo); } ListExpr DualGraph::Out(ListExpr typeInfo) { // cout<<"Out()"<TheEmptyList(); ListExpr xLast = nl->TheEmptyList(); ListExpr xNext = nl->TheEmptyList(); bool bFirst = true; for(int i = 1;i <= node_rel->GetNoTuples();i++){ Tuple* node_tuple = node_rel->GetTuple(i, false); CcInt* oid = (CcInt*)node_tuple->GetAttribute(OID); CcInt* rid = (CcInt*)node_tuple->GetAttribute(RID); Region* reg = (Region*)node_tuple->GetAttribute(PAVEMENT); ListExpr xRegion = OutRegion(nl->TheEmptyList(),SetWord(reg)); xNext = nl->FourElemList(nl->IntAtom(g_id), nl->IntAtom(oid->GetIntval()), nl->IntAtom(rid->GetIntval()), xRegion); if(bFirst){ xNode = nl->OneElemList(xNext); xLast = xNode; bFirst = false; }else xLast = nl->Append(xLast,xNext); node_tuple->DeleteIfAllowed(); } return nl->TwoElemList(nl->IntAtom(g_id),xNode); } Word DualGraph::InDualGraph(ListExpr in_xTypeInfo, ListExpr in_xValue, int in_iErrorPos, ListExpr& inout_xErrorInfo, bool& inout_bCorrect) { // cout<<"InDualGraph()"< (w.addr); w.addr = NULL; } void DualGraph::DeleteDualGraph(const ListExpr typeInfo, Word& w) { // cout<<"DeleteDualGraph()"<Destroy(); delete dg; w.addr = NULL; } bool DualGraph::CheckDualGraph(ListExpr type, ListExpr& errorInfo) { // cout<<"CheckDualGraph()"<IsEqual(type, "dualgraph"); } bool DualGraph::SaveDualGraph(SmiRecord& valueRecord, size_t& offset, const ListExpr typeInfo, Word& value) { // cout<<"SaveDualGraph()"<Save(valueRecord, offset, typeInfo); return result; } bool DualGraph::Save(SmiRecord& in_xValueRecord,size_t& inout_iOffset, const ListExpr in_xTypeInfo) { // cout<<"Save()"<ReadFromString(NodeTypeInfo,xType); xNumericType = SecondoSystem::GetCatalog()->NumericType(xType); if(!node_rel->Save(in_xValueRecord,inout_iOffset,xNumericType)) return false; /************************save sorted node****************************/ nl->ReadFromString(NodeTypeInfo,xType); xNumericType = SecondoSystem::GetCatalog()->NumericType(xType); if(!node_rel_sort->Save(in_xValueRecord,inout_iOffset,xNumericType)) return false; ///////////////////////save rtree on dual graph nodes/////////////////// if(!rtree_node->Save(in_xValueRecord, inout_iOffset)){ return false; } /************************save edge****************************/ nl->ReadFromString(EdgeTypeInfo,xType); xNumericType = SecondoSystem::GetCatalog()->NumericType(xType); if(!edge_rel->Save(in_xValueRecord,inout_iOffset,xNumericType)) return false; SecondoCatalog *ctlg = SecondoSystem::GetCatalog(); SmiRecordFile *rf = ctlg->GetFlobFile(); adj_list.saveToFile(rf, adj_list); SmiSize offset = 0; size_t bufsize = adj_list.headerSize(); char* buf = (char*) malloc(bufsize); adj_list.serializeHeader(buf,offset); assert(offset==bufsize); in_xValueRecord.Write(buf, bufsize, inout_iOffset); inout_iOffset += bufsize; free(buf); entry_adj_list.saveToFile(rf, entry_adj_list); offset = 0; buf = (char*) malloc(bufsize); entry_adj_list.serializeHeader(buf,offset); assert(offset==bufsize); in_xValueRecord.Write(buf,bufsize, inout_iOffset); free(buf); inout_iOffset += bufsize; return true; } bool DualGraph::OpenDualGraph(SmiRecord& valueRecord, size_t& offset, const ListExpr typeInfo, Word& value) { // cout<<"OpenDualGraph()"<Close(); if(rtree_node != NULL) delete rtree_node; } DualGraph::DualGraph():node_rel_sort(NULL), rtree_node(NULL) { // cout<<"DualGraph::DualGraph()"<ReadFromString(NodeTypeInfo,xType); xNumericType = SecondoSystem::GetCatalog()->NumericType(xType); node_rel = Relation::Open(in_xValueRecord, inout_iOffset, xNumericType); if(!node_rel) { return; } //////////////////////node relation after sorting////////////////////////// nl->ReadFromString(NodeTypeInfo,xType); xNumericType = SecondoSystem::GetCatalog()->NumericType(xType); node_rel_sort = Relation::Open(in_xValueRecord, inout_iOffset, xNumericType); if(!node_rel_sort) { node_rel->Delete(); return; } ///////////////////rtree on dual graph sorted nodes//////////////////// Word xValue; if(!(rtree_node->Open(in_xValueRecord,inout_iOffset, NodeRTreeTypeInfo,xValue))){ node_rel->Delete(); node_rel_sort->Delete(); return; } rtree_node = ( R_Tree<2,TupleId>* ) xValue.addr; /***********************Open relation for edge*********************/ nl->ReadFromString(EdgeTypeInfo,xType); xNumericType = SecondoSystem::GetCatalog()->NumericType(xType); edge_rel = Relation::Open(in_xValueRecord, inout_iOffset, xNumericType); if(!edge_rel) { node_rel->Delete(); node_rel_sort->Delete(); return; } ////////////////////adjaency list//////////////////////////////// size_t bufsize = DbArray::headerSize(); SmiSize offset = 0; char* buf = (char*) malloc(bufsize); in_xValueRecord.Read(buf, bufsize, inout_iOffset); inout_iOffset += bufsize; assert(buf != NULL); adj_list.restoreHeader(buf,offset); free(buf); offset = 0; buf = (char*) malloc(bufsize); in_xValueRecord.Read(buf, bufsize, inout_iOffset); assert(buf != NULL); entry_adj_list.restoreHeader(buf,offset); inout_iOffset += bufsize; free(buf); } /* let dg1 = createdualgraph(1, graph_node, graph_edge); delete dg1; close database; quit; //very important, otherwise, it can't create it again start Secondo let dg1 = createdualgraph(1, graph_node, graph_edge); */ void DualGraph::Load(int id, Relation* r1, Relation* r2) { // cout<<"Load()"<ToString(ptrList1) + ")))))"; Word xResult; int QueryExecuted = QueryProcessor::ExecuteQuery(strQuery, xResult); assert(QueryExecuted); node_rel = (Relation*)xResult.addr; //////////////////////////////////////////////////////// /////////////create sorting node relation/////////////// //////////////////////////////////////////////////////// LoadSortNode(r1); /////////////////edge relation///////////////////// ListExpr ptrList2 = listutils::getPtrList(r2); strQuery = "(consume(sort(feed(" + EdgeTypeInfo + "(ptr " + nl->ToString(ptrList2) + ")))))"; QueryExecuted = QueryProcessor::ExecuteQuery(strQuery, xResult); assert(QueryExecuted); edge_rel = (Relation*)xResult.addr; ////////////adjacency list //////////////////////////////// ListExpr ptrList3 = listutils::getPtrList(edge_rel); strQuery = "(createbtree (" + EdgeTypeInfo + "(ptr " + nl->ToString(ptrList3) + "))" + "Oid1)"; QueryExecuted = QueryProcessor::ExecuteQuery(strQuery,xResult); assert(QueryExecuted); BTree* btree_node_oid1 = (BTree*)xResult.addr; ListExpr ptrList4 = listutils::getPtrList(edge_rel); strQuery = "(createbtree (" + EdgeTypeInfo + "(ptr " + nl->ToString(ptrList4) + "))" + "Oid2)"; QueryExecuted = QueryProcessor::ExecuteQuery(strQuery, xResult); assert(QueryExecuted); BTree* btree_node_oid2 = (BTree*)xResult.addr; //////////////////////////////////////////////////////////////////////// /////////////////get minimum triangle oid/////////////////////////////// //////////////////////////////////////////////////////////////////////// int min_tri_oid = numeric_limits::max(); for(int i = 1;i <= node_rel->GetNoTuples();i++){ Tuple* tri_tuple = node_rel->GetTuple(i, false); int tri_oid = ((CcInt*)tri_tuple->GetAttribute(OID))->GetIntval(); if(tri_oid < min_tri_oid) min_tri_oid = tri_oid; tri_tuple->DeleteIfAllowed(); } // cout<<"min tri oid "<= 0); // cout<<"b-tree on edge is finished....."<GetNoTuples();i++){ Tuple* tri_tuple = node_rel->GetTuple(i, false); int tri_oid = ((CcInt*)tri_tuple->GetAttribute(OID))->GetIntval(); tri_tuple->DeleteIfAllowed(); CcInt* nodeid = new CcInt(true, tri_oid); BTreeIterator* btree_iter1 = btree_node_oid1->ExactMatch(nodeid); int start = adj_list.Size(); // cout<<"start "<Next()){ Tuple* edge_tuple = edge_rel->GetTuple(btree_iter1->GetId(), false); int oid = ((CcInt*)edge_tuple->GetAttribute(OIDSECOND))->GetIntval(); // adj_list.Append(oid); adj_list.Append(oid - min_tri_oid_1);//actually, it is node tuple id >= 1 edge_tuple->DeleteIfAllowed(); } delete btree_iter1; BTreeIterator* btree_iter2 = btree_node_oid2->ExactMatch(nodeid); while(btree_iter2->Next()){ Tuple* edge_tuple = edge_rel->GetTuple(btree_iter2->GetId(), false); int oid = ((CcInt*)edge_tuple->GetAttribute(OIDFIRST))->GetIntval(); // adj_list.Append(oid); adj_list.Append(oid - min_tri_oid_1);//actually, it is node tuple id >= 1 edge_tuple->DeleteIfAllowed(); } delete btree_iter2; int end = adj_list.Size(); entry_adj_list.Append(ListEntry(start, end)); delete nodeid; } delete btree_node_oid1; delete btree_node_oid2; /* for(int i = 0;i < entry_adj_list.Size();i++){ cout<<"i "<ToString(ptrList1) + ")))((Pavement asc))))"; // cout<GetNoTuples();i++){ // Tuple* tuple = node_rel_sort->GetTuple(i, false); // int oid = ((CcInt*)tuple->GetAttribute(OID))->GetIntval(); // cout<<"oid "<DeleteIfAllowed(); // } ListExpr ptrList2 = listutils::getPtrList(node_rel_sort); strQuery = "(bulkloadrtree(addid(feed (" + NodeTypeInfo + " (ptr " + nl->ToString(ptrList2) + ")))) Pavement)"; QueryExecuted = QueryProcessor::ExecuteQuery ( strQuery, xResult ); assert ( QueryExecuted ); rtree_node = ( R_Tree<2,TupleId>* ) xResult.addr; } /* find all triangles that intersect the input line and return all tid of these traingles */ void DualGraph::LineIntersectTri(Line* l, vector& line_list) { DFTraverse(rtree_node, rtree_node->RootRecordId(), l, line_list); } /* Using depth first method to travese the R-tree to find all triangles intersecting the line and record the triangle tuple id */ void DualGraph::DFTraverse(R_Tree<2,TupleId>* rtree, SmiRecordId adr, Line* line, vector& line_list) { const double delta_dist = 0.001; 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 = node_rel_sort->GetTuple(e.info, false); Region* candi_reg = (Region*)dg_tuple->GetAttribute(DualGraph::PAVEMENT); Line* res = new Line(0); line->Intersection(*candi_reg, *res); if(res->Length() > delta_dist){ line_list.push_back(*res); } res->DeleteIfAllowed(); dg_tuple->DeleteIfAllowed(); }else{ R_TreeInternalEntry<2> e = (R_TreeInternalEntry<2>&)(*node)[j]; if(e.box.Intersects(line->BoundingBox())){ DFTraverse(rtree, e.pointer, line, line_list); } } } delete node; } /* find which triangle contains the point */ int DualGraph::GetTriId_OfPoint(Point& loc) { vector tri_oid_list; DFTraverse2(rtree_node, rtree_node->RootRecordId(), loc, tri_oid_list); if(tri_oid_list.size() > 0) return tri_oid_list[0]; else return -1; } /* find which triangle contains the point */ void DualGraph::DFTraverse2(R_Tree<2,TupleId>* rtree, SmiRecordId adr, Point& loc, vector& tri_oid_list) { 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 = node_rel_sort->GetTuple(e.info, false); Region* candi_reg = (Region*)dg_tuple->GetAttribute(PAVEMENT); if(loc.Inside(*candi_reg)){ int oid = ((CcInt*)dg_tuple->GetAttribute(OID))->GetIntval(); tri_oid_list.push_back(oid); } dg_tuple->DeleteIfAllowed(); }else{ R_TreeInternalEntry<2> e = (R_TreeInternalEntry<2>&)(*node)[j]; if(loc.Inside(e.box)){ DFTraverse2(rtree, e.pointer, loc, tri_oid_list); } } } delete node; } /* find all triangles that their distances to the input point is smaller than the given distance threshold */ void DualGraph::DFTraverse3(R_Tree<2,TupleId>* rtree, SmiRecordId adr, Point& loc, vector& tri_oid_list, double dist) { 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 = node_rel_sort->GetTuple(e.info, false); Region* candi_reg = (Region*)dg_tuple->GetAttribute(PAVEMENT); if(candi_reg->Distance(loc) < dist){ tri_oid_list.push_back(e.info); } dg_tuple->DeleteIfAllowed(); }else{ R_TreeInternalEntry<2> e = (R_TreeInternalEntry<2>&)(*node)[j]; if(loc.Distance(e.box) < dist){ DFTraverse3(rtree, e.pointer, loc, tri_oid_list, dist); } } } delete node; } /* calculate a path connecting two cells for generating metro routes */ void DualGraph::Path_Weight(int start, int end, vector& path) { // cout<<"start "< area_flag; for(int i = 1;i <= node_rel->GetNoTuples();i++) area_flag.push_back(false); area_flag[start - 1] = true; ////////////////shortest path algorithm/////////////////////// priority_queue path_queue; vector expand_path; path_queue.push(SPath_elem(-1, 0, start, 1)); expand_path.push_back(SPath_elem(-1, 0, start, 1)); bool find = false; SPath_elem dest;//////////destination while(path_queue.empty() == false){ SPath_elem top = path_queue.top(); path_queue.pop(); // top.Print(); if(top.tri_index == end){ // cout<<"find the path"< adj_list; FindAdj(top.tri_index, area_flag, adj_list); int pos_expand_path = top.cur_index; for(unsigned int i = 0;i < adj_list.size();i++){ int expand_path_size = expand_path.size(); path_queue.push(SPath_elem(pos_expand_path, expand_path_size, adj_list[i], top.weight+1)); expand_path.push_back(SPath_elem(pos_expand_path, expand_path_size, adj_list[i], top.weight+1)); } area_flag[top.tri_index - 1] = true; } if(find){ vector path_record; while(dest.prev_index != -1){ // sleeve.push_back(triangles[dest.tri_index]); path_record.push_back(dest.tri_index); dest = expand_path[dest.prev_index]; } // sleeve.push_back(triangles[dest.tri_index]); path_record.push_back(dest.tri_index); for(int i = path_record.size() - 1;i >= 0;i--){ // cout<<"oid "<GetNoTuples() != 1 || rel2->GetNoTuples() != 1){ cout<<"input query relation is not correct"<GetTuple(1, false); int oid1 = ((CcInt*)t1->GetAttribute(VisualGraph::QOID))->GetIntval(); Point* p1 = (Point*)t1->GetAttribute(VisualGraph::QLOC2); Point loc1(*p1); t1->DeleteIfAllowed(); Tuple* t2 = rel2->GetTuple(1, false); int oid2 = ((CcInt*)t2->GetAttribute(VisualGraph::QOID))->GetIntval(); Point* p2 = (Point*)t2->GetAttribute(VisualGraph::QLOC2); Point loc2(*p2); t2->DeleteIfAllowed(); // cout<<"tri_id1 "<min_tri_oid_1; oid2 -= dg->min_tri_oid_1; int no_node_graph = dg->No_Of_Node(); if(oid1 < 1 || oid1 > no_node_graph){ cout<<"loc1 does not exist"< no_node_graph){ cout<<"loc2 does not exist"<GetNodeRel()->GetTuple(oid1, false); Region* reg1 = (Region*)tuple1->GetAttribute(DualGraph::PAVEMENT); CompTriangle* ct1 = new CompTriangle(reg1); assert(ct1->PolygonConvex()); delete ct1; if(loc1.Inside(*reg1) == false){ tuple1->DeleteIfAllowed(); cout<<"point1 is not inside the polygon"<GetNodeRel()->GetTuple(oid2, false); Region* reg2 = (Region*)tuple2->GetAttribute(DualGraph::PAVEMENT); CompTriangle* ct2 = new CompTriangle(reg2); assert(ct2->PolygonConvex()); delete ct2; if(loc2.Inside(*reg2) == false){ tuple1->DeleteIfAllowed(); tuple2->DeleteIfAllowed(); cout<<"point2 is not inside the polygon"<DeleteIfAllowed(); tuple2->DeleteIfAllowed(); //////////////////////////////////////////////////// ////////debuging euclidean connection////////////// // oid1 = 34450 - dg->min_tri_oid_1; // oid2 = 34430 - dg->min_tri_oid_1; // loc1.Set(24164.01, 15711.896); // loc2.Set(24170.12, 15720.85); ////////////////////////////////////////////////// WalkShortestPath2(oid1, oid2, loc1, loc2, res); } /* test shortest path for pedestrian */ void Walk_SP::TestWalkShortestPath(int tid1, int tid2) { // cout<<"WalkShortestPath"<GetTuple(tid1, false); int oid1 = ((CcInt*)t1->GetAttribute(VisualGraph::QOID))->GetIntval(); Point* p1 = (Point*)t1->GetAttribute(VisualGraph::QLOC2); Point loc1(*p1); Tuple* t2 = rel2->GetTuple(tid2, false); int oid2 = ((CcInt*)t2->GetAttribute(VisualGraph::QOID))->GetIntval(); Point* p2 = (Point*)t2->GetAttribute(VisualGraph::QLOC2); Point loc2(*p2); // cout<<"tri_id1 "<min_tri_oid_1; oid2 -= dg->min_tri_oid_1; int no_node_graph = dg->No_Of_Node(); if(oid1 < 1 || oid1 > no_node_graph){ cout<<"loc1 does not exist"< no_node_graph){ cout<<"loc2 does not exist"<GetNodeRel()->GetTuple(oid1, false); Region* reg1 = (Region*)tuple1->GetAttribute(DualGraph::PAVEMENT); CompTriangle* ct1 = new CompTriangle(reg1); assert(ct1->PolygonConvex()); delete ct1; if(loc1.Inside(*reg1) == false){ tuple1->DeleteIfAllowed(); cout<<"point1 is not inside the polygon"<GetNodeRel()->GetTuple(oid2, false); Region* reg2 = (Region*)tuple2->GetAttribute(DualGraph::PAVEMENT); CompTriangle* ct2 = new CompTriangle(reg2); assert(ct2->PolygonConvex()); delete ct2; if(loc2.Inside(*reg2) == false){ tuple1->DeleteIfAllowed(); tuple2->DeleteIfAllowed(); cout<<"point2 is not inside the polygon"<DeleteIfAllowed(); tuple2->DeleteIfAllowed(); if(oid1 == oid2){/////////////start and end point are located on the same tri Line* res = new Line(0); res->StartBulkLoad(); ///////////////////////////////////////////////////// HalfSegment hs; hs.Set(true, loc1, loc2); hs.attr.edgeno = 0; *res += hs; hs.SetLeftDomPoint(!hs.IsLeftDomPoint()); *res += hs; ///////////////////////////////////////////////////// res->EndBulkLoad(); oids1.push_back(tid1); //vertex id oids2.push_back(tid2); //vertex id path.push_back(*res); // double len = res->Length(); // printf("Euclidean length: %.4f Walk length: %.4f\n",loc1.Distance(loc2),len); res->DeleteIfAllowed(); return; } /////////////////////////////////////////////////////////////////////// ///////////////////check Eudlidean Connection////////////////////////// ////////////////////////////////////////////////////////////////////// if(EuclideanConnect2(oid1, loc1, oid2, loc2)){ Line* res = new Line(0); res->StartBulkLoad(); ///////////////////////////////////////////////////// HalfSegment hs; hs.Set(true, loc1, loc2); hs.attr.edgeno = 0; *res += hs; hs.SetLeftDomPoint(!hs.IsLeftDomPoint()); *res += hs; ///////////////////////////////////////////////////// res->EndBulkLoad(); oids1.push_back(tid1); //vertex id oids2.push_back(tid2); //vertex id path.push_back(*res); res->DeleteIfAllowed(); // double len = res->Length(); // printf("Euclidean length: %.4f Walk length: %.4f\n",loc1.Distance(loc2),len); return; } /////////////////////////////////////////////////////////////////////// priority_queue path_queue; vector expand_path; ////////////////find all visibility nodes to start node///////// ///////connect them to the visibility graph///////////////////// VGraph* vg1 = new VGraph(dg, NULL, rel3, vg->GetNodeRel()); vg1->GetVisibilityNode(oid1, loc1); assert(vg1->oids1.size() == vg1->p_list.size()); if(vg1->oids1.size() == 1){//start point equasl to triangle vertex double w = loc1.Distance(loc2); path_queue.push(WPath_elem(-1, 0, vg1->oids1[0], w, loc1, 0.0)); expand_path.push_back(WPath_elem(-1, 0, vg1->oids1[0], w, loc1, 0.0)); }else{ double w = loc1.Distance(loc2); path_queue.push(WPath_elem(-1, 0, -1, w, loc1,0.0));//start location expand_path.push_back(WPath_elem(-1, 0, -1, w, loc1,0.0));//start location int prev_index = 0; // cout<<"vnode id "; for(unsigned int i = 0;i < vg1->oids1.size();i++){ // cout<oids1[i]<<" "; int expand_path_size = expand_path.size(); double d = loc1.Distance(vg1->p_list[i]); w = d + vg1->p_list[i].Distance(loc2); path_queue.push(WPath_elem(prev_index, expand_path_size, vg1->oids1[i], w, vg1->p_list[i], d)); expand_path.push_back(WPath_elem(prev_index, expand_path_size, vg1->oids1[i], w, vg1->p_list[i], d)); } } // cout<GetNodeRel()); vg2->GetVisibilityNode(oid2, loc2); assert(vg2->oids1.size() == vg2->p_list.size()); //if the end node equals to triangle vertex. //it can be connected by adjacency list //we don't conenct it to the visibility graph if(vg2->oids1.size() == 1){ // cout<<"end point id "<oids1[0]<StartBulkLoad(); if(vg2->oids1.size() > 1){ for(unsigned int i = 0;i < vg2->oids1.size();i++){ Tuple* loc_tuple = vg->GetNodeRel()->GetTuple(vg2->oids1[i], false); Point* loc = (Point*)loc_tuple->GetAttribute(VisualGraph::LOC); *neighbor_end += *loc; loc_tuple->DeleteIfAllowed(); } neighbor_end->EndBulkLoad(); } /////////////////////searching path/////////////////////////////////// bool find = false; vector mark_flag; for(int i = 1;i <= vg->GetNodeRel()->GetNoTuples();i++) mark_flag.push_back(false); WPath_elem dest; while(path_queue.empty() == false){ WPath_elem top = path_queue.top(); path_queue.pop(); // top.Print(); if(AlmostEqual(top.loc, loc2)){ // cout<<"find the path"< 0 && mark_flag[top.tri_index - 1] == false){ vector adj_list; vg->FindAdj(top.tri_index, adj_list); int pos_expand_path = top.cur_index; for(unsigned int i = 0;i < adj_list.size();i++){ if(mark_flag[adj_list[i] - 1]) continue; int expand_path_size = expand_path.size(); Tuple* loc_tuple = vg->GetNodeRel()->GetTuple(adj_list[i], false); Point* loc = (Point*)loc_tuple->GetAttribute(VisualGraph::LOC); double w1 = top.real_w + top.loc.Distance(*loc); double w2 = w1 + loc->Distance(loc2); path_queue.push(WPath_elem(pos_expand_path, expand_path_size, adj_list[i], w2 ,*loc, w1)); expand_path.push_back(WPath_elem(pos_expand_path, expand_path_size, adj_list[i], w2, *loc, w1)); loc_tuple->DeleteIfAllowed(); mark_flag[top.tri_index - 1] = true; } } ////////////check visibility points to the end point//////////// if(neighbor_end->Size() > 0){ const double delta_dist = 0.1;//in theory, it should be 0.0 if(top.loc.Distance(neighbor_end->BoundingBox()) < delta_dist){ for(unsigned int i = 0;i < vg2->oids1.size();i++){ if(top.tri_index == vg2->oids1[i]){ int pos_expand_path = top.cur_index; int expand_path_size = expand_path.size(); double w1 = top.real_w + top.loc.Distance(loc2); double w2 = w1; path_queue.push(WPath_elem(pos_expand_path, expand_path_size, -1, w2 ,loc2, w1)); expand_path.push_back(WPath_elem(pos_expand_path, expand_path_size, -1, w2, loc2, w1)); break; } } } } /////////////////////////////////////////////////////////////// } delete neighbor_end; delete vg2; /////////////construct path/////////////////////////////////////////// double len = 0.0; if(find){ Line* l = new Line(0); l->StartBulkLoad(); while(dest.prev_index != -1){ Point p1 = dest.loc; dest = expand_path[dest.prev_index]; Point p2 = dest.loc; ///////////////////////////////////////////////////// HalfSegment hs; hs.Set(true, p1, p2); hs.attr.edgeno = 0; *l += hs; hs.SetLeftDomPoint(!hs.IsLeftDomPoint()); *l += hs; ///////////////////////////////////////////////////// } oids1.push_back(tid1); //vertex id oids2.push_back(tid2); //vertex id l->EndBulkLoad(); path.push_back(*l); len = l->Length(); l->DeleteIfAllowed(); finish = clock(); printf("tid1: %d, tid2: %d, Euclidean: %.4f Walk: %.4f Time: %f\n", tid1, tid2, loc1.Distance(loc2),len, (double)(finish - start) / CLOCKS_PER_SEC); } } /* called by WalkShortestPath */ void Walk_SP::WalkShortestPath2(int oid1, int oid2, Point loc1, Point loc2, Line* res) { // cout<<"WalkShortestPath2"<StartBulkLoad(); ///////////////////////////////////////////////////// if(!AlmostEqual(loc1, loc2)){/////////two locations are equal HalfSegment hs; hs.Set(true, loc1, loc2); hs.attr.edgeno = 0; *res += hs; hs.SetLeftDomPoint(!hs.IsLeftDomPoint()); *res += hs; } ///////////////////////////////////////////////////// res->EndBulkLoad(); // double len = res->Length(); // printf("Euclidean length: %.4f Walk length: %.4f\n",loc1.Distance(loc2),len); return; } /////////////////////////////////////////////////////////////////////// ///////////////////check Eudlidean Connection////////////////////////// /////////////////////////////////////////////////////////////////////// // clock_t start, finish; // start = clock(); if(EuclideanConnect2(oid1, loc1, oid2, loc2)){ res->StartBulkLoad(); ///////////////////////////////////////////////////// HalfSegment hs; hs.Set(true, loc1, loc2); hs.attr.edgeno = 0; *res += hs; hs.SetLeftDomPoint(!hs.IsLeftDomPoint()); *res += hs; ///////////////////////////////////////////////////// res->EndBulkLoad(); // double len = res->Length(); // printf("Euclidean length: %.4f Walk length: %.4f\n",loc1.Distance(loc2),len); return; } // finish = clock(); // printf("Time: %f\n",(double)(finish - start) / CLOCKS_PER_SEC); /////////////////////////////////////////////////////////////////////// priority_queue path_queue; vector expand_path; ////////////////find all visibility nodes to start node///////// ///////connect them to the visibility graph///////////////////// VGraph* vg1 = new VGraph(dg, NULL, rel3, vg->GetNodeRel()); vg1->GetVisibilityNode(oid1, loc1); assert(vg1->oids1.size() == vg1->p_list.size()); if(vg1->oids1.size() == 1){//start point equasl to triangle vertex double w = loc1.Distance(loc2); path_queue.push(WPath_elem(-1, 0, vg1->oids1[0], w, loc1, 0.0)); expand_path.push_back(WPath_elem(-1, 0, vg1->oids1[0], w, loc1, 0.0)); }else{ double w = loc1.Distance(loc2); path_queue.push(WPath_elem(-1, 0, -1, w, loc1,0.0));//start location expand_path.push_back(WPath_elem(-1, 0, -1, w, loc1,0.0));//start location int prev_index = 0; // cout<<"vnode id "; for(unsigned int i = 0;i < vg1->oids1.size();i++){ // cout<oids1[i]<<" "; int expand_path_size = expand_path.size(); double d = loc1.Distance(vg1->p_list[i]); w = d + vg1->p_list[i].Distance(loc2); path_queue.push(WPath_elem(prev_index, expand_path_size, vg1->oids1[i], w, vg1->p_list[i], d)); expand_path.push_back(WPath_elem(prev_index, expand_path_size, vg1->oids1[i], w, vg1->p_list[i], d)); } } delete vg1; ////////////////find all visibility nodes to the end node///////// VGraph* vg2 = new VGraph(dg, NULL, rel3, vg->GetNodeRel()); vg2->GetVisibilityNode(oid2, loc2); assert(vg2->oids1.size() == vg2->p_list.size()); //if the end node equals to triangle vertex. //it can be connected by adjacency list //we don't conenct it to the visibility graph if(vg2->oids1.size() == 1){ // cout<<"end point id "<oids1[0]<StartBulkLoad(); if(vg2->oids1.size() > 1){ for(unsigned int i = 0;i < vg2->oids1.size();i++){ Tuple* loc_tuple = vg->GetNodeRel()->GetTuple(vg2->oids1[i], false); Point* loc = (Point*)loc_tuple->GetAttribute(VisualGraph::LOC); *neighbor_end += *loc; loc_tuple->DeleteIfAllowed(); } neighbor_end->EndBulkLoad(); } /////////////////////searching path/////////////////////////////////// bool find = false; vector mark_flag; for(int i = 1;i <= vg->GetNodeRel()->GetNoTuples();i++) mark_flag.push_back(false); // clock_t start, finish; // start = clock(); WPath_elem dest; while(path_queue.empty() == false){ WPath_elem top = path_queue.top(); path_queue.pop(); // cout<<"top elem "< 0 && mark_flag[top.tri_index - 1] == false){ vector adj_list; vg->FindAdj(top.tri_index, adj_list); int pos_expand_path = top.cur_index; for(unsigned int i = 0;i < adj_list.size();i++){ if(mark_flag[adj_list[i] - 1]) continue; int expand_path_size = expand_path.size(); Tuple* loc_tuple = vg->GetNodeRel()->GetTuple(adj_list[i], false); Point* loc = (Point*)loc_tuple->GetAttribute(VisualGraph::LOC); double w1 = top.real_w + top.loc.Distance(*loc); double w2 = w1 + loc->Distance(loc2); path_queue.push(WPath_elem(pos_expand_path, expand_path_size, adj_list[i], w2 ,*loc, w1)); expand_path.push_back(WPath_elem(pos_expand_path, expand_path_size, adj_list[i], w2, *loc, w1)); loc_tuple->DeleteIfAllowed(); mark_flag[top.tri_index - 1] = true; // cout<<"neighbor "<Size() > 0){ const double delta_dist = 0.1;//in theory, it should be 0.0 if(top.loc.Distance(neighbor_end->BoundingBox()) < delta_dist){ for(unsigned int i = 0;i < vg2->oids1.size();i++){ if(top.tri_index == vg2->oids1[i]){ int pos_expand_path = top.cur_index; int expand_path_size = expand_path.size(); double w1 = top.real_w + top.loc.Distance(loc2); double w2 = w1; path_queue.push(WPath_elem(pos_expand_path, expand_path_size, -1, w2 ,loc2, w1)); expand_path.push_back(WPath_elem(pos_expand_path, expand_path_size, -1, w2, loc2, w1)); break; } } } } /////////////////////////////////////////////////////////////// } // finish = clock(); // printf("Time: %f\n",(double)(finish - start) / CLOCKS_PER_SEC); delete neighbor_end; delete vg2; /////////////construct path/////////////////////////////////////////// //double len = 0.0; if(find){ res->StartBulkLoad(); while(dest.prev_index != -1){ Point p1 = dest.loc; dest = expand_path[dest.prev_index]; Point p2 = dest.loc; ///////////////////////////////////////////////////// HalfSegment hs; hs.Set(true, p1, p2); hs.attr.edgeno = 0; *res += hs; hs.SetLeftDomPoint(!hs.IsLeftDomPoint()); *res += hs; ///////////////////////////////////////////////////// } res->EndBulkLoad(); //len = res->Length(); } } /* check whether the two points can be directly reachable by a line */ bool Walk_SP::EuclideanConnect(Point loc1, Point loc2) { Line* l = new Line(0); l->StartBulkLoad(); HalfSegment hs; hs.Set(true, loc1, loc2); hs.attr.edgeno = 0; *l += hs; hs.SetLeftDomPoint(!hs.IsLeftDomPoint()); *l += hs; l->EndBulkLoad(); double len1 = l->Length(); double len2 = 0.0; DFTraverse2(dg->rtree_node, dg->rtree_node->RootRecordId(), l, len2); l->DeleteIfAllowed(); // cout<<"l1: "<* rtree, SmiRecordId adr, Line* line, double& l) { const double delta_area = 0.01; 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 = dg->node_rel_sort->GetTuple(e.info, false); Region* candi_reg = (Region*)dg_tuple->GetAttribute(DualGraph::PAVEMENT); Line* len = new Line(0); /* int oid = ((CcInt*)dg_tuple->GetAttribute(DualGraph::OID))->GetIntval(); cout<Intersection(*candi_reg, *len); //crashes once for Houston MyIntersection(*line, *candi_reg, *len); if(candi_reg->Area() > delta_area && len->Length() > 0.0){ l += len->Length(); } len->DeleteIfAllowed(); dg_tuple->DeleteIfAllowed(); }else{ R_TreeInternalEntry<2> e = (R_TreeInternalEntry<2>&)(*node)[j]; if(e.box.Intersects(line->BoundingBox())){ DFTraverse2(rtree, e.pointer, line, l); } } } delete node; } /* check whether the two points can be directly reachable by a line */ bool Walk_SP::EuclideanConnect2(int oid1, Point loc1, int oid2, Point loc2) { // cout<<"EuclideanConnect2 oid1 "<StartBulkLoad(); HalfSegment hs; hs.Set(true, loc1, loc2); hs.attr.edgeno = 0; *l += hs; hs.SetLeftDomPoint(!hs.IsLeftDomPoint()); *l += hs; l->EndBulkLoad(); Tuple* node_tuple = dg->GetNodeRel()->GetTuple(oid1, false); Region* reg = (Region*)node_tuple->GetAttribute(DualGraph::PAVEMENT); Line* res = new Line(0); MyIntersection(*l, *reg, *res); res->DeleteIfAllowed(); node_tuple->DeleteIfAllowed(); bool flag = true; // oid1 -= dg->min_tri_oid_1; // oid2 -= dg->min_tri_oid_1; int start_tri = oid1; int last_tri = oid1; bool find = false; while(flag){ vector adj_list; // cout<<"tri "<min_tri_oid_1 <FindAdj(start_tri, adj_list);////find all neighbor triangles unsigned int i = 0; /* cout<min_tri_oid_1 <<" neighbor size "<GetNodeRel()->GetTuple(adj_list[i], false); Region* reg = (Region*)tuple->GetAttribute(DualGraph::PAVEMENT); int tri_id = ((CcInt*)tuple->GetAttribute(DualGraph::OID))->GetIntval(); // cout<<"neighbor id "<min_tri_oid_1; if(tri_id == last_tri){ tuple->DeleteIfAllowed(); continue; } Line* res = new Line(0); MyIntersection(*l, *reg, *res); if(res->Length() > 0.0){ last_tri = start_tri; start_tri = tri_id; res->DeleteIfAllowed(); tuple->DeleteIfAllowed(); break; } res->DeleteIfAllowed(); tuple->DeleteIfAllowed(); } if(i == adj_list.size()){ flag = false; }else if(start_tri == oid2){ find = true; flag = false; } } l->DeleteIfAllowed(); return find; } /* Randomly generates points inside pavement polygon 1) randomly selects a polygon/polygon 2) randomly generates a number between [xmin,xmax], and [ymin,ymax] */ void Walk_SP::GenerateData1(int no_p) { int no_node_graph = rel1->GetNoTuples(); // struct timeval tval; // struct timezone tzone; // gettimeofday(&tval, &tzone); // srand48(tval.tv_sec); for (int i = 1; i <= no_p;){ // int m = lrand48() % no_node_graph + 1; int m = GetRandom() % no_node_graph + 1; Tuple* tuple = rel1->GetTuple(m, false); int oid = ((CcInt*)tuple->GetAttribute(DualGraph::OID))->GetIntval(); Region* reg = (Region*)tuple->GetAttribute(DualGraph::PAVEMENT); if(reg->Area() < 0.5){ //too small area, not useful for a human tuple->DeleteIfAllowed(); continue; } /*neighbor triangles for testing Euclidean connection*/ // if(!(oid == 96621 || oid == 96619 || oid == 97639)){ // tuple->DeleteIfAllowed(); // continue; // } BBox<2> bbox = reg->BoundingBox(); int xx = (int)(bbox.MaxD(0) - bbox.MinD(0)) + 1; int yy = (int)(bbox.MaxD(1) - bbox.MinD(1)) + 1; Point p1; Point p2; bool inside = false; int count = 1; while(inside == false && count <= 100){ int x = GetRandom() % (xx*100); int y = GetRandom() % (yy*100); double coord_x = x/100.0; double coord_y = y/100.0; Coord x_cord = coord_x + bbox.MinD(0); Coord y_cord = coord_y + bbox.MinD(1); p2.Set(x_cord, y_cord); p1.Set(coord_x, coord_y); //set back to relative position //lower the precision Modify_Point_3(p1); Modify_Point_3(p2); inside = p2.Inside(*reg); count++; } if(inside){ // oids.push_back(m); oids.push_back(oid); q_loc1.push_back(p1); q_loc2.push_back(p2); i++; } tuple->DeleteIfAllowed(); } } /* Randomly generates points inside pavement polygon 1) randomly selects a polygon/polygon 2) randomly generates a vertex of the triangle 3) the point equals to one of triangle vertices */ void Walk_SP::GenerateData2(int no_p) { int no_node_graph = rel1->GetNoTuples(); for (int i = 1; i <= no_p;i++){ int m = GetRandom() % no_node_graph + 1; Tuple* tuple = rel1->GetTuple(m, false); int oid = ((CcInt*)tuple->GetAttribute(DualGraph::OID))->GetIntval(); Region* reg = (Region*)tuple->GetAttribute(DualGraph::PAVEMENT); Points* ps = new Points(0); reg->Vertices(ps); unsigned index = GetRandom() % 3; Point p2; ps->Get(index, p2); BBox<2> bbox = reg->BoundingBox(); Point p1(true, p2.GetX() - bbox.MinD(0), p2.GetY() - bbox.MinD(1)); // oids.push_back(m); oids.push_back(oid); q_loc1.push_back(p1);//relative position in the polygon q_loc2.push_back(p2);//absolute position ps->DeleteIfAllowed(); tuple->DeleteIfAllowed(); } } /* Randomly generates points inside pavement polygon 1) randomly selects a polygon/polygon 2) randomly generates a vertex of the triangle 3) the vertex is the internal point of a triangle. not on the edge */ void Walk_SP::GenerateData3(int no_p) { int no_node_graph = rel1->GetNoTuples(); // struct timeval tval; // struct timezone tzone; // gettimeofday(&tval, &tzone); // srand48(tval.tv_sec); for (int i = 1; i <= no_p;){ // int m = lrand48() % no_node_graph + 1; int m = GetRandom() % no_node_graph + 1; Tuple* tuple = rel1->GetTuple(m, false); int oid = ((CcInt*)tuple->GetAttribute(DualGraph::OID))->GetIntval(); Region* reg = (Region*)tuple->GetAttribute(DualGraph::PAVEMENT); if(reg->Area() < 0.5){ //too small area, not useful for a human tuple->DeleteIfAllowed(); continue; } BBox<2> bbox = reg->BoundingBox(); int xx = (int)(bbox.MaxD(0) - bbox.MinD(0)) + 1; int yy = (int)(bbox.MaxD(1) - bbox.MinD(1)) + 1; Point p1; Point p2; bool inside = false; int count = 1; vector segs; for(int j = 0;j < reg->Size();j++){ HalfSegment hs; reg->Get(j,hs); if(!hs.IsLeftDomPoint())continue; segs.push_back(hs); } while(inside == false && count <= 100){ int x = GetRandom() % (xx*100); int y = GetRandom() % (yy*100); double coord_x = x/100.0; double coord_y = y/100.0; Coord x_cord = coord_x + bbox.MinD(0); Coord y_cord = coord_y + bbox.MinD(1); p2.Set(x_cord, y_cord); p1.Set(coord_x, coord_y); //set back to relative position //lower the precision Modify_Point_3(p1); Modify_Point_3(p2); inside = p2.Inside(*reg); for(unsigned int k = 0;k < segs.size();k++){ if(segs[k].Contains(p2)){ inside = false; break; } } count++; } if(inside){ // oids.push_back(m); oids.push_back(oid); q_loc1.push_back(p1); q_loc2.push_back(p2); i++; } tuple->DeleteIfAllowed(); } } /* create a random point on the given triangle */ bool Walk_SP::GenerateData4(int tid) { if(rel1 == NULL){ cout<<"realtion no initialize "<GetNoTuples(); assert(1 <= tid && tid <= no_node_graph); Tuple* tuple = rel1->GetTuple(tid, false); int oid = ((CcInt*)tuple->GetAttribute(DualGraph::OID))->GetIntval(); Region* reg = (Region*)tuple->GetAttribute(DualGraph::PAVEMENT); if(reg->Area() < 0.5){ //too small area, not useful for a human tuple->DeleteIfAllowed(); return false; } BBox<2> bbox = reg->BoundingBox(); int xx = (int)(bbox.MaxD(0) - bbox.MinD(0)) + 1; int yy = (int)(bbox.MaxD(1) - bbox.MinD(1)) + 1; Point p1; Point p2; bool inside = false; int count_tmp = 1; while(inside == false && count_tmp <= 100){ int x = GetRandom() % (xx*100); int y = GetRandom() % (yy*100); double coord_x = x/100.0; double coord_y = y/100.0; Coord x_cord = coord_x + bbox.MinD(0); Coord y_cord = coord_y + bbox.MinD(1); p2.Set(x_cord, y_cord); p1.Set(coord_x, coord_y); //set back to relative position //lower the precision Modify_Point_3(p1); Modify_Point_3(p2); inside = p2.Inside(*reg); count_tmp++; } tuple->DeleteIfAllowed(); if(inside){ // oids.push_back(m); oids.push_back(oid); q_loc1.push_back(p1); q_loc2.push_back(p2); return true; } return false; } /* set pavement rid */ void Walk_SP::SetPaveRid(R_Tree<2,TupleId>* rtree) { SmiRecordId adr = rtree->RootRecordId(); for(int i = 1;i <= rel1->GetNoTuples();i++){ Tuple* tri_tuple = rel1->GetTuple(i, false); int oid = ((CcInt*)tri_tuple->GetAttribute(DualGraph::OID))->GetIntval(); Region* reg = (Region*)tri_tuple->GetAttribute(DualGraph::PAVEMENT); vector r_id_list; DFTraverse(rtree, adr, reg, r_id_list); // cout<<"tid "<DeleteIfAllowed(); } } /* Using depth first method to travese the R-tree to find the big pavement intersects the triangle (decomposed from the big pavement) */ void Walk_SP::DFTraverse(R_Tree<2,TupleId>* rtree, SmiRecordId adr, Region* reg, vector& r_id_list) { 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 = rel2->GetTuple(e.info, false); Region* candi_reg = (Region*)dg_tuple2->GetAttribute(DualGraph::PAVEMENT); if(reg->Intersects(*candi_reg)){ int rid = ((CcInt*)dg_tuple2->GetAttribute(DualGraph::RID))->GetIntval(); unsigned int i = 0; for(;i < r_id_list.size();i++) if(r_id_list[i] == rid)break; if(i == r_id_list.size()) r_id_list.push_back(rid); } dg_tuple2->DeleteIfAllowed(); }else{ R_TreeInternalEntry<2> e = (R_TreeInternalEntry<2>&)(*node)[j]; if(e.box.Intersects(reg->BoundingBox())){ DFTraverse(rtree, e.pointer, reg, r_id_list); } } } delete node; } /* map points in pavements to gpoints */ void Walk_SP::PaveLocToGP(Network* n) { //rel1 query locations , rel2 dgnode for(int i = 1;i <= rel1->GetNoTuples();i++){ Tuple* tuple1 = rel1->GetTuple(i, false); int oid = ((CcInt*)tuple1->GetAttribute(VisualGraph::QOID))->GetIntval(); Point* loc = (Point*)tuple1->GetAttribute(VisualGraph::QLOC2); /////////////////find which road the pavement corresponds to//////// CcInt* search_id = new CcInt(true, oid); BTreeIterator* btree_iter = btree->ExactMatch(search_id); vector route_id_list; while(btree_iter->Next()){ Tuple* tuple = rel2->GetTuple(btree_iter->GetId(), false); int rid = ((CcInt*)tuple->GetAttribute(DualGraph::RID))->GetIntval(); route_id_list.push_back(rid); tuple->DeleteIfAllowed(); } delete btree_iter; delete search_id; // for(unsigned int i = 0;i < route_id_list.size();i++) // cout<<"rid "<DeleteIfAllowed(); // break; } } /* for a point, location in pavement, find its mapping gpoint */ struct MyPoint_Id:public MyPoint{ int id; MyPoint_Id(){} MyPoint_Id(const Point& p, double d, int i): MyPoint(p,d),id(i){} MyPoint_Id(const MyPoint_Id& mpi): MyPoint(mpi), id(mpi.id){} MyPoint_Id& operator=(const MyPoint_Id& mpi) { MyPoint::operator=(mpi); id = mpi.id; return *this; } void Print() { cout<<" loc " < route_id_list) { vector mp_list; for(unsigned int i = 0;i < route_id_list.size();i++){ int rid = route_id_list[i]; Tuple* route_tuple = n->GetRoute(rid); SimpleLine* l = (SimpleLine*)route_tuple->GetAttribute(ROUTE_CURVE); // cout<<"l : "<Length()<Size();j++){ HalfSegment hs; l->Get(j, hs); if(!hs.IsLeftDomPoint())continue; SpacePartition* sp = new SpacePartition(); Point res; double dist = sp->GetClosestPoint(hs, *loc, res); delete sp; MyPoint_Id mp(res, dist, rid); mp_list.push_back(mp); } route_tuple->DeleteIfAllowed(); } assert(mp_list.size() > 0); sort(mp_list.begin(), mp_list.end()); // cout<<"rid "<GetRoute(mp_list[0].id); SimpleLine* sl = (SimpleLine*)route_tuple->GetAttribute(ROUTE_CURVE); bool s = ((CcBool*)route_tuple->GetAttribute(ROUTE_STARTSSMALLER))->GetBoolval(); double pos; bool ok = sl->AtPoint(mp_list[0].loc, s, pos); ////////////MyAtPoint()//////////////// if(ok){ GPoint gp(true, n->GetId(), mp_list[0].id, pos); route_tuple->DeleteIfAllowed(); p_list.push_back(mp_list[0].loc); gp_list.push_back(gp); } return ok; } /* type constructors */ VGraph::VGraph() { dg = NULL; rel1 = NULL; rel2 = NULL; rel3 = NULL; count = 0; resulttype = NULL; vg = NULL; } VGraph::VGraph(DualGraph* g, Relation* r1, Relation* r2, Relation* r3):dg(g), rel1(r1), rel2(r2), rel3(r3), count(0), resulttype(NULL), vg(NULL) { } VGraph::VGraph(VisualGraph* g):dg(NULL), rel1(NULL), rel2(NULL), rel3(NULL), count(0), resulttype(NULL), vg(g) { } VGraph:: ~VGraph() { if(resulttype != NULL) delete resulttype; } /* get all adjacent nodes for a given node. dual graph */ void VGraph::GetAdjNodeDG(int oid) { if(oid <= dg->min_tri_oid_1 || oid > dg->min_tri_oid_1 + dg->node_rel->GetNoTuples()){ cout<<"invalid oid "<min_tri_oid_1 + 1<min_tri_oid_1 + dg->node_rel->GetNoTuples()<GetNodeRel()->GetNoTuples()<<" nodes "< adj_list; assert(dg->min_tri_oid_1 >= 0); dg->FindAdj(oid - dg->min_tri_oid_1, adj_list); for(unsigned int i = 0;i < adj_list.size();i++){ Tuple* node_tuple = dg->GetNodeRel()->GetTuple(adj_list[i], false); CcInt* tri_id = (CcInt*)node_tuple->GetAttribute(DualGraph::OID); Region* reg = (Region*)node_tuple->GetAttribute(DualGraph::PAVEMENT); oids1.push_back(tri_id->GetIntval()); regs.push_back(*reg); node_tuple->DeleteIfAllowed(); } } /* get all adjacent nodes for a given node. visibility graph */ void VGraph::GetAdjNodeVG(int oid) { if(oid < 1 || oid > vg->GetNodeRel()->GetNoTuples()){ cout<<"invalid oid "<GetNodeRel()->GetNoTuples()<<" nodes "<GetNodeRel()->GetTuple(oid, false); Point* query_p = (Point*)node_tuple->GetAttribute(VisualGraph::LOC); Point query_loc(*query_p); node_tuple->DeleteIfAllowed(); vector adj_list; vg->FindAdj(oid, adj_list); for(unsigned int i = 0;i < adj_list.size();i++){ node_tuple = vg->GetNodeRel()->GetTuple(adj_list[i], false); CcInt* id = (CcInt*)node_tuple->GetAttribute(VisualGraph::OID); Point* loc = (Point*)node_tuple->GetAttribute(VisualGraph::LOC); oids1.push_back(id->GetIntval()); p_list.push_back(*loc); //////////////////////////////////////////////// Line* l = new Line(0); l->StartBulkLoad(); HalfSegment hs; hs.Set(true, query_loc, *loc); hs.attr.edgeno = 0; *l += hs; hs.SetLeftDomPoint(!hs.IsLeftDomPoint()); *l += hs; l->EndBulkLoad(); line.push_back(*l); l->DeleteIfAllowed(); //////////////////////////////////////////////// node_tuple->DeleteIfAllowed(); } } /* get the visibile points for one vertex */ void VGraph::GetVNodeOnVertex(int vid, Point* query_p) { CcInt* vertex_id = new CcInt(true, vid); BTreeIterator* btreeiter = btree->ExactMatch(vertex_id); while(btreeiter->Next()){ Tuple* ver_tri = rel4->GetTuple(btreeiter->GetId(), false); int triangle_id = ((CcInt*)ver_tri->GetAttribute(DualGraph::TRIID))->GetIntval(); // cout<<"tid_start "<min_tri_oid_1) >= 1); triangle_id = triangle_id - dg->min_tri_oid_1; assert(triangle_id >= 1 && triangle_id <= rel2->GetNoTuples()); Tuple* tri_tuple = rel2->GetTuple(triangle_id, false); int v1 =((CcInt*)tri_tuple->GetAttribute(DualGraph::V1))->GetIntval(); int v2 =((CcInt*)tri_tuple->GetAttribute(DualGraph::V2))->GetIntval(); int v3 =((CcInt*)tri_tuple->GetAttribute(DualGraph::V3))->GetIntval(); tri_tuple->DeleteIfAllowed(); vector vid_list; if(v1 == vid){ vid_list.push_back(v2); vid_list.push_back(v3); for(unsigned int i = 0;i < vid_list.size();i++){ unsigned int j = 0; for(;j < oids1.size();j++){ if(vid_list[i] == oids1[j]) break; } if(j == oids1.size()){ oids1.push_back(vid_list[i]); } } GetVisibleNode2(triangle_id, query_p, 3); }else if(v2 == vid){ vid_list.push_back(v1); vid_list.push_back(v3); for(unsigned int i = 0;i < vid_list.size();i++){ unsigned int j = 0; for(;j < oids1.size();j++){ if(vid_list[i] == oids1[j]) break; } if(j == oids1.size()){ oids1.push_back(vid_list[i]); } } GetVisibleNode2(triangle_id, query_p, 2); }else if(v3 == vid){ vid_list.push_back(v1); vid_list.push_back(v2); for(unsigned int i = 0;i < vid_list.size();i++){ unsigned int j = 0; for(;j < oids1.size();j++){ if(vid_list[i] == oids1[j]) break; } if(j == oids1.size()){ oids1.push_back(vid_list[i]); } } GetVisibleNode2(triangle_id, query_p, 1); }else assert(false); ver_tri->DeleteIfAllowed(); } delete btreeiter; delete vertex_id; } /* create the edge relation for the visibility graph */ void VGraph::GetVGEdge() { // cout<min_tri_oid_1<GetNoTuples();i++){ Tuple* vertex_tuple = rel1->GetTuple(i, false); int vid = ((CcInt*)vertex_tuple->GetAttribute(VisualGraph::OID))->GetIntval(); Point* p1 = (Point*)vertex_tuple->GetAttribute(VisualGraph::LOC); // if(vid != 1200){ // vertex_tuple->DeleteIfAllowed(); // continue; // } GetVNodeOnVertex(vid, p1); for(unsigned int j = 0;j < oids1.size();j++){ oids2.push_back(vid); oids3.push_back(oids1[j]); ///////////////////////// Tuple* loc_tuple2 = rel3->GetTuple(oids1[j], false); Point* p2 = (Point*)loc_tuple2->GetAttribute(VisualGraph::LOC); ///////////////////////// Line* l = new Line(0); l->StartBulkLoad(); HalfSegment hs; hs.Set(true, *p1, *p2); hs.attr.edgeno = 0; *l += hs; hs.SetLeftDomPoint(!hs.IsLeftDomPoint()); *l += hs; l->EndBulkLoad(); line.push_back(*l); l->DeleteIfAllowed(); loc_tuple2->DeleteIfAllowed(); } vertex_tuple->DeleteIfAllowed(); oids1.clear(); } } inline bool VGraph::Collineation(Point& p1, Point& p2, Point& p3) { if(AlmostEqual(p1.GetX(), p2.GetX())){ if(AlmostEqual(p2.GetX(), p3.GetX())) return true; } if(AlmostEqual(p1.GetY(), p2.GetY())){ if(AlmostEqual(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(AlmostEqual(k1, k2)) return true; return false; } /* it checks whether vertex (vp) is inside the clamp structure constructed by vertex and two points endp1, endp2 */ bool VGraph::CheckVisibility1(Clamp& clamp, Point& checkp, int vp) { // cout<<"CheckVisibility1()"<GetAngle(clamp.apex, clamp.foot1, checkp); double angle2 = sp->GetAngle(clamp.apex, checkp, clamp.foot2); cout< ps; ps.push_back(clamp.apex); ps.push_back(clamp.foot1); ps.push_back(checkp); ps.push_back(clamp.foot2); CompTriangle* ct = new CompTriangle(); visibility = ct->IsConvex(ps);//convex. checkp is inside delete ct; if(visibility){ //it is impossible that clamp.apex, foot1(2), checkp are on the same line //and checkp locates between clamp.apex and foot1(2) //because in this case, checkp should be found first //because we start from the triangle that queryp locates and the inside //checking condition bool flag1 = Collineation(clamp.apex, clamp.foot1, checkp); bool flag2 = Collineation(clamp.apex, clamp.foot2, checkp); // cout<<"flag1 "<p4, store the results in ip if it has, returns true, otherwise returns false */ bool VGraph::GetIntersectionPoint(Point& p1, Point& p2, Clamp& clamp, Point& ip, bool flag) { Point p3; Point p4; if(flag){ p3 = clamp.apex; p4 = clamp.foot1; }else{ p3 = clamp.apex; p4 = clamp.foot2; } Coord x, y; //get the intersection point if(AlmostEqual(p1.GetX(), p2.GetX())){ if(AlmostEqual(p3.GetX(), p4.GetX())) return false; //parallel double a = (p3.GetY() - p4.GetY())/(p3.GetX() - p4.GetX()); double b = p3.GetY() - a*p3.GetX(); x = p1.GetX(); y = a*x + b; }else if(AlmostEqual(p1.GetY(), p2.GetY())){ if(AlmostEqual(p3.GetY(), p4.GetY())) return false; //parallel if(AlmostEqual(p3.GetX(), p4.GetX())){ x = p3.GetX(); y = p1.GetY(); }else{ double a = (p3.GetY() - p4.GetY())/(p3.GetX() - p4.GetX()); double b = p3.GetY() - a*p3.GetX(); y = p1.GetY(); x = (y - b)/a; } }else{ double a1 = (p1.GetY() - p2.GetY())/(p1.GetX() - p2.GetX()); double b1 = p1.GetY() - a1*p1.GetX(); if(AlmostEqual(p3.GetX(), p4.GetX())){ x = p3.GetX(); y = a1*x + b1; }else{ double a2 = (p3.GetY() - p4.GetY())/(p3.GetX() - p4.GetX()); double b2 = p3.GetY() - a2*p3.GetX(); if(AlmostEqual(a1, a2)) return false;//parallel x = (b2-b1)/(a1-a2); y = a1*x + b1; } } ip.Set(x, y); //check whether it is available HalfSegment hs; hs.Set(true,p1,p2); if(hs.Contains(ip)){ if(AlmostEqual(p3.GetX(), p4.GetX())){ if(p3.GetY() < p4.GetY()){ if(AlmostEqual(y, p3.GetY()) || y > p3.GetY()) return true; else return false; }else{ if(AlmostEqual(y, p3.GetY()) || y < p3.GetY()) return true; else return false; } }else{ if(p3.GetX() < p4.GetX()){ if(x > p3.GetX() || AlmostEqual(x, p3.GetX())) return true; else return false; }else{ if(x < p3.GetX() || AlmostEqual(x, p3.GetX())) return true; else return false; } } }else return false; } /* it checks whether the segment(checkp1, checkp2) is inside the clamp structure Different from CheckVisibility1, now if checkp is on the line (apex,foot1) or (apex, foot2), it might also return false. one is outside and one is on the line. it returns false. */ bool VGraph::CheckVisibility2(Clamp& clamp, Point& checkp1, Point& checkp2) { // cout<<"CheckVisibility2()"< intersection_points; Point p1; if(GetIntersectionPoint(checkp1, checkp2, clamp, p1, true)) intersection_points.push_back(p1); Point p2; if(GetIntersectionPoint(checkp1, checkp2, clamp, p2, false)) intersection_points.push_back(p2); //the number of intersection point //0 return false //1 if intersection point is not checkp2, return true, otherwise false //2 return true // cout<<"intersection_points.size() "< tri_list, HalfSegment hs) { // cout<<"PathContainHS() "<<"HS "< 0); Line* l = new Line(0); l->StartBulkLoad(); hs.attr.edgeno = 0; *l += hs; hs.SetLeftDomPoint(!hs.IsLeftDomPoint()); *l += hs; l->EndBulkLoad(); double len2 = 0.0; for(unsigned int i = 0;i < tri_list.size();i++){ cout<<"tri id "<GetNodeRel()->GetTuple(tri_list[i], false); Region* reg = (Region*)tri->GetAttribute(DualGraph::PAVEMENT); if(reg->Area() > 0.0){ Line* inter_l = new Line(0); l->Intersection(*reg,*inter_l);//it has numeric problem if(inter_l->Size() > 0){ cout<<"inter_l length "<Length()<Length(); } delete inter_l; } tri->DeleteIfAllowed(); } delete l; cout<<"len1 "<next; Tuple* tri = dg->GetNodeRel()->GetTuple(tri_list[0], false); Region* reg = (Region*)tri->GetAttribute(DualGraph::PAVEMENT); for(int i = 0;i < reg->Size();i++){ HalfSegment hs; reg->Get(i, hs); if(!hs.IsLeftDomPoint()) continue; HSNode* hsnode = new HSNode(hs,NULL); cur = hsnode; prev->next = cur; prev = cur; cur = cur->next; } tri->DeleteIfAllowed(); for(unsigned int i = 1;i < tri_list.size();i++){ tri = dg->GetNodeRel()->GetTuple(tri_list[i], false); reg = (Region*)tri->GetAttribute(DualGraph::PAVEMENT); for(int j = 0;j < reg->Size();j++){ HalfSegment hs; reg->Get(j, hs); if(!hs.IsLeftDomPoint())continue; prev = head; cur = prev->next; Point lp1 = hs.GetLeftPoint(); Point rp1 = hs.GetRightPoint(); bool insert = true; while(cur != NULL && insert){//to find all block segments Point lp2 = cur->hs.GetLeftPoint(); Point rp2 = cur->hs.GetRightPoint(); if((AlmostEqual(lp1,lp2) && AlmostEqual(rp1, rp2))|| (AlmostEqual(lp1,rp2) && AlmostEqual(rp1, lp2))){ //delete it HSNode* temp = cur; cur = cur->next; prev->next = cur; delete temp; insert = false; }else{ prev = cur; cur = cur->next; } } if(insert){ //insert the halfsegment assert(cur == NULL); HSNode* node = new HSNode(hs, NULL); cur = node; prev->next = cur; } } tri->DeleteIfAllowed(); } bool cross = false; prev = head; cur = prev->next; while(cur != NULL){ // cout<<"cur hs "<hs<hs); // cout<<"cross "<hs)<next; delete node; } return !cross; } /* Depth first searching on the dual graph to find all visible vertices */ void VGraph::DFTraverse(int tri_id, Clamp& clamp, int pre_id, int type1) { // cout<<"DFTraverse()"< adj_list; dg->FindAdj(tri_id, adj_list); //get the vertex Tuple* tri_tuple = rel2->GetTuple(tri_id, false); int v1 =((CcInt*)tri_tuple->GetAttribute(DualGraph::V1))->GetIntval(); int v2 =((CcInt*)tri_tuple->GetAttribute(DualGraph::V2))->GetIntval(); int v3 =((CcInt*)tri_tuple->GetAttribute(DualGraph::V3))->GetIntval(); tri_tuple->DeleteIfAllowed(); Triangle tri1(v1, v2, v3); // cout<<"v1 "<GetTuple(adj_list[i], false); int ver1 =((CcInt*)tri_tuple->GetAttribute(DualGraph::V1))->GetIntval(); int ver2 =((CcInt*)tri_tuple->GetAttribute(DualGraph::V2))->GetIntval(); int ver3 =((CcInt*)tri_tuple->GetAttribute(DualGraph::V3))->GetIntval(); tri_tuple->DeleteIfAllowed(); /////////////////////////////////////////////////////////////////////// Tuple* loc_tuple1 = rel3->GetTuple(ver1, false); Point* p1 = (Point*)loc_tuple1->GetAttribute(VisualGraph::LOC); Point foot1(*p1); loc_tuple1->DeleteIfAllowed(); Tuple* loc_tuple2 = rel3->GetTuple(ver2, false); Point* p2 = (Point*)loc_tuple2->GetAttribute(VisualGraph::LOC); Point foot2(*p2); loc_tuple2->DeleteIfAllowed(); Tuple* loc_tuple3 = rel3->GetTuple(ver3, false); Point* p3 = (Point*)loc_tuple3->GetAttribute(VisualGraph::LOC); Point foot3(*p3); loc_tuple3->DeleteIfAllowed(); /////////////////////////////////////////////////////////////////////// Triangle tri2(ver1, ver2, ver3); int sharetype1 = tri2.ShareEdge(tri1); int sharetype2 = tri1.ShareEdge(tri2); // cout<<"sharetype1 "<GetNoTuples();i++){ Tuple* tri_tuple = rel1->GetTuple(i, false); int v1 = ((CcInt*)tri_tuple->GetAttribute(DualGraph::V1))->GetIntval(); int v2 = ((CcInt*)tri_tuple->GetAttribute(DualGraph::V2))->GetIntval(); int v3 = ((CcInt*)tri_tuple->GetAttribute(DualGraph::V3))->GetIntval(); int triid = ((CcInt*)tri_tuple->GetAttribute(DualGraph::TOID))->GetIntval(); oids1.push_back(v1); oids2.push_back(triid); oids1.push_back(v2); oids2.push_back(triid); oids1.push_back(v3); oids2.push_back(triid); tri_tuple->DeleteIfAllowed(); } } /* find all triangles that contain vertex (vid) and depth first searching */ void VGraph::FindTriContainVertex(int vid, int tri_id, Point* query_p) { // cout<<"FindTriContainVertex() "<ExactMatch(vertex_id); while(btreeiter->Next()){ Tuple* ver_tri = rel4->GetTuple(btreeiter->GetId(), false); int triangle_id = ((CcInt*)ver_tri->GetAttribute(DualGraph::TRIID))->GetIntval(); if(triangle_id != tri_id){ // cout<<"triangle_id "<GetTuple(triangle_id, false); int v1 =((CcInt*)tri_tuple->GetAttribute(DualGraph::V1))->GetIntval(); int v2 =((CcInt*)tri_tuple->GetAttribute(DualGraph::V2))->GetIntval(); int v3 =((CcInt*)tri_tuple->GetAttribute(DualGraph::V3))->GetIntval(); ///////////////////////////////////////////////////////////////////// Tuple* loc_tuple1 = rel3->GetTuple(v1, false); Point* p1 = (Point*)loc_tuple1->GetAttribute(VisualGraph::LOC); Point foot1(*p1); loc_tuple1->DeleteIfAllowed(); Tuple* loc_tuple2 = rel3->GetTuple(v2, false); Point* p2 = (Point*)loc_tuple2->GetAttribute(VisualGraph::LOC); Point foot2(*p2); loc_tuple2->DeleteIfAllowed(); Tuple* loc_tuple3 = rel3->GetTuple(v3, false); Point* p3 = (Point*)loc_tuple3->GetAttribute(VisualGraph::LOC); Point foot3(*p3); loc_tuple3->DeleteIfAllowed(); /////////////////////////////////////////////////////////////////////// // cout<<"v1 "< vid_list; if(v1 == vid){ vid_list.push_back(v2); vid_list.push_back(v3); for(unsigned int i = 0;i < vid_list.size();i++){ unsigned int j = 0; for(;j < oids1.size();j++){ if(vid_list[i] == oids1[j]) break; } if(j == oids1.size()){ oids1.push_back(vid_list[i]); Tuple* loc_tuple = rel3->GetTuple(vid_list[i], false); Point* p = (Point*)loc_tuple->GetAttribute(VisualGraph::LOC); p_list.push_back(*p); loc_tuple->DeleteIfAllowed(); } } Clamp clamp(*query_p, foot2, foot3); DFTraverse(triangle_id, clamp, tri_id, 3); }else if(v2 == vid){ vid_list.push_back(v1); vid_list.push_back(v3); for(unsigned int i = 0;i < vid_list.size();i++){ unsigned int j = 0; for(;j < oids1.size();j++){ if(vid_list[i] == oids1[j]) break; } if(j == oids1.size()){ oids1.push_back(vid_list[i]); Tuple* loc_tuple = rel3->GetTuple(vid_list[i], false); Point* p = (Point*)loc_tuple->GetAttribute(VisualGraph::LOC); p_list.push_back(*p); loc_tuple->DeleteIfAllowed(); } } Clamp clamp(*query_p, foot1, foot3); DFTraverse(triangle_id, clamp, tri_id, 2); }else if(v3 == vid){ vid_list.push_back(v1); vid_list.push_back(v2); for(unsigned int i = 0;i < vid_list.size();i++){ unsigned int j = 0; for(;j < oids1.size();j++){ if(vid_list[i] == oids1[j]) break; } if(j == oids1.size()){ oids1.push_back(vid_list[i]); Tuple* loc_tuple = rel3->GetTuple(vid_list[i], false); Point* p = (Point*)loc_tuple->GetAttribute(VisualGraph::LOC); p_list.push_back(*p); loc_tuple->DeleteIfAllowed(); } } Clamp clamp(*query_p, foot1, foot2); DFTraverse(triangle_id, clamp, tri_id, 1); }else assert(false); tri_tuple->DeleteIfAllowed(); } ver_tri->DeleteIfAllowed(); } delete btreeiter; delete vertex_id; } /* check the triangle with the only given type */ void VGraph::GetVisibleNode2(int tri_id, Point* query_p, int type) { //cout<<"GetVisibleNode2() "<<"query tri_id "<min_tri_oid_1< adj_list; dg->FindAdj(tri_id, adj_list); Tuple* tri_tuple1 = rel2->GetTuple(tri_id, false); int v1 =((CcInt*)tri_tuple1->GetAttribute(DualGraph::V1))->GetIntval(); int v2 =((CcInt*)tri_tuple1->GetAttribute(DualGraph::V2))->GetIntval(); int v3 =((CcInt*)tri_tuple1->GetAttribute(DualGraph::V3))->GetIntval(); tri_tuple1->DeleteIfAllowed(); Triangle tri1(v1, v2, v3); // cout<<"v1 "<min_tri_oid_1<GetTuple(adj_list[i], false); int ver1 =((CcInt*)tri_tuple->GetAttribute(DualGraph::V1))->GetIntval(); int ver2 =((CcInt*)tri_tuple->GetAttribute(DualGraph::V2))->GetIntval(); int ver3 =((CcInt*)tri_tuple->GetAttribute(DualGraph::V3))->GetIntval(); tri_tuple->DeleteIfAllowed(); // cout<<"ver1 "<GetTuple(ver1, false); Point* p1 = (Point*)loc_tuple1->GetAttribute(VisualGraph::LOC); Point foot1(*p1); loc_tuple1->DeleteIfAllowed(); Tuple* loc_tuple2 = rel3->GetTuple(ver2, false); Point* p2 = (Point*)loc_tuple2->GetAttribute(VisualGraph::LOC); Point foot2(*p2); loc_tuple2->DeleteIfAllowed(); Tuple* loc_tuple3 = rel3->GetTuple(ver3, false); Point* p3 = (Point*)loc_tuple3->GetAttribute(VisualGraph::LOC); Point foot3(*p3); loc_tuple3->DeleteIfAllowed(); /////////////////////////////////////////////////////////////////////// Triangle tri2(ver1, ver2, ver3); int sharetype1 = tri2.ShareEdge(tri1); int sharetype2 = tri1.ShareEdge(tri2); if(sharetype2 != type) continue; Point clamp_foot1; Point clamp_foot2; if(sharetype1 == 1){ clamp_foot1 = foot1; clamp_foot2 = foot2; } else if(sharetype1 == 2){ clamp_foot1 = foot1; clamp_foot2 = foot3; } else if(sharetype1 == 3){ clamp_foot1 = foot2; clamp_foot2 = foot3; } else assert(false); double d1 = query_p->Distance(clamp_foot1); double d2 = query_p->Distance(clamp_foot2); //apex foot1(2),checkp on the same line because apex=foot1(2) if(AlmostEqual(d1*d2, 0.0)){ continue; } Clamp clamp(*query_p, clamp_foot1, clamp_foot2); //DFTraverse(adj_list[i], clamp1, tri_id,0); //1. triangle to be expanded 2. clamp 3. previous triangle //4. edge can't be expanded //a special case that the clamp's angle can be 180. but this can only //happen at the start time. because when the procedure proceeds, the //clamp angle always becomes smaller and smaller bool visibility; switch(sharetype1){ case 1: // cout<<"case1"<GetTuple(v1, false); Point* p1 = (Point*)tuple1->GetAttribute(VisualGraph::LOC); Point vp1(*p1); Tuple* tuple2 = rel3->GetTuple(v2, false); Point* p2 = (Point*)tuple2->GetAttribute(VisualGraph::LOC); Point vp2(*p2); Tuple* tuple3 = rel3->GetTuple(v3, false); Point* p3 = (Point*)tuple3->GetAttribute(VisualGraph::LOC); Point vp3(*p3); tuple1->DeleteIfAllowed(); tuple2->DeleteIfAllowed(); tuple3->DeleteIfAllowed(); int type = 0; if(AlmostEqual(vp1, *query_p)) type = 1; else if(AlmostEqual(vp2, *query_p)) type = 2; else if(AlmostEqual(vp3, *query_p)) type = 3; switch(type){ case 1: oids1.push_back(v2); oids1.push_back(v3); for(unsigned int i = 0;i < oids1.size();i++){ Tuple* loc_tuple = rel3->GetTuple(oids1[i], false); Point* p = (Point*)loc_tuple->GetAttribute(VisualGraph::LOC); p_list.push_back(*p); loc_tuple->DeleteIfAllowed(); } FindTriContainVertex(v1, tri_id, query_p); GetVisibleNode2(tri_id, query_p, 3); break; case 2: oids1.push_back(v1); oids1.push_back(v3); for(unsigned int i = 0;i < oids1.size();i++){ Tuple* loc_tuple = rel3->GetTuple(oids1[i], false); Point* p = (Point*)loc_tuple->GetAttribute(VisualGraph::LOC); p_list.push_back(*p); loc_tuple->DeleteIfAllowed(); } FindTriContainVertex(v2, tri_id, query_p); GetVisibleNode2(tri_id, query_p, 2); break; case 3: oids1.push_back(v1); oids1.push_back(v2); for(unsigned int i = 0;i < oids1.size();i++){ Tuple* loc_tuple = rel3->GetTuple(oids1[i], false); Point* p = (Point*)loc_tuple->GetAttribute(VisualGraph::LOC); p_list.push_back(*p); loc_tuple->DeleteIfAllowed(); } FindTriContainVertex(v3, tri_id, query_p); GetVisibleNode2(tri_id, query_p, 1); break; } if(type != 0)return true; else return false; } /* find all visible nodes for query_p in some cases, there are numberic problems or java display numberic. */ void VGraph::GetVisibleNode1(int tri_id, Point* query_p) { // cout<<"GetVisibleNode1() "<<"query tri_id "< adj_list; dg->FindAdj(tri_id, adj_list); assert(oids1.size() == 3); int v1 = oids1[0]; int v2 = oids1[1]; int v3 = oids1[2]; Triangle tri1(v1, v2, v3); /////////////////////////////////////////////////////////////////////// for(unsigned int i = 0;i < adj_list.size();i++){ // cout<<"adj_list GVN "<GetTuple(adj_list[i], false); int ver1 =((CcInt*)tri_tuple->GetAttribute(DualGraph::V1))->GetIntval(); int ver2 =((CcInt*)tri_tuple->GetAttribute(DualGraph::V2))->GetIntval(); int ver3 =((CcInt*)tri_tuple->GetAttribute(DualGraph::V3))->GetIntval(); tri_tuple->DeleteIfAllowed(); /////////////////////////////////////////////////////////////////////// Tuple* loc_tuple1 = rel3->GetTuple(ver1, false); Point* p1 = (Point*)loc_tuple1->GetAttribute(VisualGraph::LOC); Point foot1(*p1); loc_tuple1->DeleteIfAllowed(); Tuple* loc_tuple2 = rel3->GetTuple(ver2, false); Point* p2 = (Point*)loc_tuple2->GetAttribute(VisualGraph::LOC); Point foot2(*p2); loc_tuple2->DeleteIfAllowed(); Tuple* loc_tuple3 = rel3->GetTuple(ver3, false); Point* p3 = (Point*)loc_tuple3->GetAttribute(VisualGraph::LOC); Point foot3(*p3); loc_tuple3->DeleteIfAllowed(); /////////////////////////////////////////////////////////////////////// Triangle tri2(ver1, ver2, ver3); int sharetype = tri2.ShareEdge(tri1); Clamp clamp12(*query_p, foot1, foot2); Clamp clamp13(*query_p, foot1, foot3); Clamp clamp23(*query_p, foot2, foot3); //DFTraverse(adj_list[i], clamp1, tri_id,0); //1. triangle to be expanded 2. clamp 3. previous triangle //4. edge can't be expanded //a special case that the clamp's angle can be 180. but this can only //happen at the start time. because when the procedure proceeds, the //clamp angle always becomes smaller and smaller bool visibility; switch(sharetype){ case 1: // cout<<"case1"<GetNoTuples()); /////////three vertices of the triangle//////////////////////// Tuple* tri_tuple1 = rel2->GetTuple(tri_id, false); int v1 =((CcInt*)tri_tuple1->GetAttribute(DualGraph::V1))->GetIntval(); int v2 =((CcInt*)tri_tuple1->GetAttribute(DualGraph::V2))->GetIntval(); int v3 =((CcInt*)tri_tuple1->GetAttribute(DualGraph::V3))->GetIntval(); tri_tuple1->DeleteIfAllowed(); ///if the query_p equals to one of the triangle vertices /// Tuple* tuple1 = rel3->GetTuple(v1, false); Point* p1 = (Point*)tuple1->GetAttribute(VisualGraph::LOC); Point vp1(*p1); Tuple* tuple2 = rel3->GetTuple(v2, false); Point* p2 = (Point*)tuple2->GetAttribute(VisualGraph::LOC); Point vp2(*p2); Tuple* tuple3 = rel3->GetTuple(v3, false); Point* p3 = (Point*)tuple3->GetAttribute(VisualGraph::LOC); Point vp3(*p3); tuple1->DeleteIfAllowed(); tuple2->DeleteIfAllowed(); tuple3->DeleteIfAllowed(); int type = 0; if(AlmostEqual(vp1, query_p)) type = 1; else if(AlmostEqual(vp2, query_p)) type = 2; else if(AlmostEqual(vp3, query_p)) type = 3; ///////////////////////////////////////////////////////////// switch(type){ case 0: oids1.push_back(v1); oids1.push_back(v2); oids1.push_back(v3); p_list.push_back(vp1); p_list.push_back(vp2); p_list.push_back(vp3); ///////searching in the dual graph to find all visible vertices//// GetVisibleNode1(tri_id, &query_p); break; //if it equals to one of the vertices of the triangle, it directly //put the vertex and return. //its visibile vertices can be found by adjacency list case 1: oids1.push_back(v1); p_list.push_back(vp1); break; case 2: oids1.push_back(v2); p_list.push_back(vp2); break; case 3: oids1.push_back(v3); p_list.push_back(vp3); break; default:assert(false); } } /* for a given point, find all its visible nodes connect the point to the visibility graph node rel1--query location relation rel2--triangle relation v1 int v2 int v3 int rel3--vertex relation1 (oid int) (loc point) rel4--vertex relation2 (vid(oid) int) (triid int) */ void VGraph::GetVNode() { if(rel1->GetNoTuples() < 1){ cout<<"query relation is empty"<GetTuple(1, false); int query_oid = ((CcInt*)query_tuple->GetAttribute(VisualGraph::QOID))->GetIntval(); Point* query_p = new Point(*((Point*)query_tuple->GetAttribute(VisualGraph::QLOC2))); query_tuple->DeleteIfAllowed(); query_oid -= dg->min_tri_oid_1; assert(1 <= query_oid && query_oid <= dg->node_rel->GetNoTuples()); /////////three vertices of the triangle//////////////////////// Tuple* tri_tuple1 = rel2->GetTuple(query_oid, false); int v1 =((CcInt*)tri_tuple1->GetAttribute(DualGraph::V1))->GetIntval(); int v2 =((CcInt*)tri_tuple1->GetAttribute(DualGraph::V2))->GetIntval(); int v3 =((CcInt*)tri_tuple1->GetAttribute(DualGraph::V3))->GetIntval(); tri_tuple1->DeleteIfAllowed(); ///if the query_p equals to one of the triangle vertices /// if(GetVNode_QV(query_oid, query_p,v1,v2,v3)){ }else{ ////////////////////////////////////////////////////////////////////////// ////////three vertices of the triangle that the point is located in/////// ////////////////////////////////////////////////////////////////////////// oids1.push_back(v1); oids1.push_back(v2); oids1.push_back(v3); for(unsigned int i = 0;i < oids1.size();i++){ Tuple* loc_tuple = rel3->GetTuple(oids1[i], false); Point* p = (Point*)loc_tuple->GetAttribute(VisualGraph::LOC); p_list.push_back(*p); loc_tuple->DeleteIfAllowed(); } ///////////searching in the dual graph to find all visible vertices////// GetVisibleNode1(query_oid, query_p); } ///////build a halfsegment between query point and its visibility point//// for(unsigned int i = 0;i < p_list.size();i++){ Line* l = new Line(0); l->StartBulkLoad(); HalfSegment hs; hs.Set(true, p_list[i], *query_p); hs.attr.edgeno = 0; *l += hs; hs.SetLeftDomPoint(!hs.IsLeftDomPoint()); *l += hs; l->EndBulkLoad(); line.push_back(*l); l->DeleteIfAllowed(); } delete query_p; } /* create a relation for the vertices of the region with the cycleno */ void RegVertex::CreateVertex() { /* //naive method to compute the cycle of a region vector cycle; for(int i = 0;i < reg->Size();i++){ HalfSegment hs; reg->Get(i, hs); if(!hs.IsLeftDomPoint())continue; int cycle_no = hs.attr.cycleno; unsigned int j = 0; for(;j < cycle.size();j++) if(cycle[j] == cycle_no) break; if(j == cycle.size()) cycle.push_back(cycle_no); } cout<<"polgyon with "<NoOfCycles(); assert(no_cyc > 0); //const int ncontours = no_cyc; //int no_p_contour[ncontours]; vector ps_contour_x; vector ps_contour_y; vector sl_contour; for(unsigned int i = 0;i < no_cyc;i++){ SimpleLine* sl = new SimpleLine(0); sl->StartBulkLoad(); sl_contour.push_back(sl); } vector edgenos(no_cyc, 0); for(int j = 0;j < reg->Size();j++){ HalfSegment hs1; reg->Get(j, hs1); if(!hs1.IsLeftDomPoint()) continue; HalfSegment hs2; hs2.Set(true, hs1.GetLeftPoint(), hs1.GetRightPoint()); hs2.attr.edgeno = edgenos[hs1.attr.cycleno]++; *sl_contour[hs1.attr.cycleno] += hs2; hs2.SetLeftDomPoint(!hs2.IsLeftDomPoint()); *sl_contour[hs1.attr.cycleno] += hs2; } SpacePartition* sp = new SpacePartition(); for(unsigned int i = 0;i < no_cyc;i++){ // cout<<"i "<EndBulkLoad(); vector mhs; sp->ReorderLine(sl_contour[i], mhs); vector ps; for(unsigned int j = 0;j < mhs.size();j++) ps.push_back(mhs[j].from); bool clock; if(0.0f < ct->Area(ps)){//points counter-clockwise order clock = false; }else{// points clockwise clock = true; } //no_p_contour[i] = ps.size(); if(i == 0){//outer contour, counter_clockwise if(clock == false){ for(unsigned int index = 0;index < ps.size();index++){ // ps_contour_x.push_back(ps[index].GetX()); // ps_contour_y.push_back(ps[index].GetY()); regnodes.push_back(ps[index]); cycleno.push_back(i); } }else{ for(unsigned int index = 0;index < ps.size();index++){ // ps_contour_x.push_back(ps[ps.size() - 1 - index].GetX()); // ps_contour_y.push_back(ps[ps.size() - 1 - index].GetY()); regnodes.push_back(ps[ps.size() - 1 - index]); cycleno.push_back(i); } } }else{//hole points, should be clockwise if(clock == false){ for(unsigned int index = 0;index < ps.size();index++){ // ps_contour_x.push_back(ps[ps.size() -1 - index].GetX()); // ps_contour_y.push_back(ps[ps.size() -1 - index].GetY()); regnodes.push_back(ps[ps.size() - 1 - index]); cycleno.push_back(i); } }else{ for(unsigned int index = 0;index < ps.size();index++){ // ps_contour_x.push_back(ps[index].GetX()); // ps_contour_y.push_back(ps[index].GetY()); regnodes.push_back(ps[index]); cycleno.push_back(i); } } } sl_contour[i]->DeleteIfAllowed(); } delete ct; delete sp; } /* for each triangle, it returns the number of each point and the centroid */ void RegVertex::TriangulationNew() { CompTriangle* ct = new CompTriangle(reg); unsigned int no_cyc = ct->NoOfCycles(); assert(no_cyc > 0); const int ncontours = no_cyc; int no_p_contour[ncontours]; vector ps_contour_x;//start from 1 vector ps_contour_y;//start from 1 ct->PolygonContourPoint(no_cyc, no_p_contour, ps_contour_x, ps_contour_y); int result_trig[SEGSIZE][3]; int (*res_triangles)[3] = &result_trig[0]; int no_triangle; no_triangle = triangulate_polygon(no_cyc, no_p_contour, ps_contour_x, ps_contour_y, res_triangles); // cout<<"no_triangle "<NoOfCycles(); assert(no_cyc > 0); const int ncontours = no_cyc; int no_p_contour[ncontours]; vector ps_contour_x;//start from 1 vector ps_contour_y;//start from 1 ct->PolygonContourPoint(no_cyc, no_p_contour, ps_contour_x, ps_contour_y); int result_trig[SEGSIZE][3]; int (*res_triangles)[3] = &result_trig[0]; int no_triangle; no_triangle = triangulate_polygon(no_cyc, no_p_contour, ps_contour_x, ps_contour_y, res_triangles); // cout<<"no_triangle "< ps_list; ps_list.push_back(p1); ps_list.push_back(p2); ps_list.push_back(p3); SpacePartition* sp = new SpacePartition(); vector reg_list; sp->ComputeRegion(ps_list, reg_list); tri_list.push_back(reg_list[0]); delete sp; } delete ct; } /* for each triangle, it returns the number of each point and the centroid */ void RegVertex::TriangulationNew2() { CompTriangle* ct = new CompTriangle(reg); unsigned int no_cyc = ct->NoOfCycles(); assert(no_cyc > 0); const int ncontours = no_cyc; int no_p_contour[ncontours]; vector ps_contour_x;//start from 0 vector ps_contour_y;//start from 0 ct->PolygonContourPoint2(no_cyc, no_p_contour, ps_contour_x, ps_contour_y); HPolygon poly; int no_triangle = poly.Triangulation2(no_cyc, no_p_contour, ps_contour_x, ps_contour_y); // cout<<"no_triangle "< ps_list; ps_list.push_back(p1); ps_list.push_back(p2); ps_list.push_back(p3); vector reg; spacepart->ComputeRegion(ps_list, reg); /////////////////////////////////////////////// if(reg.size() > 0){ //calculate the centroid point Point p; p.Set(x/3.0, y/3.0); regnodes.push_back(p); v1_list.push_back(poly.p_id_list[index1]); v2_list.push_back(poly.p_id_list[index2]); v3_list.push_back(poly.p_id_list[index3]); } } delete ct; delete spacepart; } void RegVertex::TriangulationExt2() { CompTriangle* ct = new CompTriangle(reg); unsigned int no_cyc = ct->NoOfCycles(); assert(no_cyc > 0); const int ncontours = no_cyc; int no_p_contour[ncontours]; vector ps_contour_x;//start from 0 vector ps_contour_y;//start from 0 ct->PolygonContourPoint2(no_cyc, no_p_contour, ps_contour_x, ps_contour_y); HPolygon poly; int no_triangle = poly.Triangulation2(no_cyc, no_p_contour, ps_contour_x, ps_contour_y); // cout<<"no_triangle "< ps_list; ps_list.push_back(p1); ps_list.push_back(p2); ps_list.push_back(p3); SpacePartition* sp = new SpacePartition(); vector reg_list; sp->ComputeRegion(ps_list, reg_list); // tri_list.push_back(reg_list[0]); if(reg_list.size() > 0){ /////////2012.3.9 rounding problem tri_list.push_back(reg_list[0]); v1_list.push_back(poly.p_id_list[index1]); v2_list.push_back(poly.p_id_list[index2]); v3_list.push_back(poly.p_id_list[index3]); } delete sp; } delete ct; } /* For each triangle, it sets the number of neighbors it has already. If the numbers of two vertices are consecutive and they belong to the same cycle, then the edge connecting them is the boundary. Thus, there is no triangle adjacent to it by this edge. So we increase the number of neighbor. As for a triangle, the maximum neighbor it can have is 3 (three edges). */ void SetNeighbor(Triangle& tri, vector& no_points_cycles, vector& index_contour) { //v1 and v2 are consecutive boundary points if(tri.c1 == tri.c2){ if(fabs(tri.v1 - tri.v2) == 1){ tri.neighbor_no++; } else if(tri.v1 == index_contour[tri.c1] && //first tri.v2 == index_contour[tri.c1] + no_points_cycles[tri.c2] - 1)//last tri.neighbor_no++; else if(tri.v2 == index_contour[tri.c1] && tri.v1 == index_contour[tri.c1] + no_points_cycles[tri.c1] - 1) tri.neighbor_no++; } //v1 and v3 are consecutive boundary points if(tri.c1 == tri.c3){ if(fabs(tri.v1 - tri.v3) == 1){ tri.neighbor_no++; } else if(tri.v1 == index_contour[tri.c1] && tri.v3 == index_contour[tri.c3] + no_points_cycles[tri.c3] - 1){ tri.neighbor_no++; } else if(tri.v3 == index_contour[tri.c3] && tri.v1 == index_contour[tri.c1] + no_points_cycles[tri.c1] - 1) tri.neighbor_no++; } //v2 and v3 are consecutive boundary points if(tri.c2 == tri.c3){ if(fabs(tri.v2 - tri.v3) == 1) tri.neighbor_no++; else if(tri.v2 == index_contour[tri.c2] && tri.v3 == index_contour[tri.c3] + no_points_cycles[tri.c3] - 1) tri.neighbor_no++; else if(tri.v3 == index_contour[tri.c3] && tri.v2 == index_contour[tri.c2] + no_points_cycles[tri.c2] - 1){ tri.neighbor_no++; } } } /* get the dual graph edge relation. if two triangles have the same edge, an edge in dual graph is created. Each node corresponds to a triangle. 1. number the vertex. order them by z-order 2. use a list 3. find the neighbor by the number of vertex instead of intersection detecting */ void RegVertex::GetDGEdge() { //the number it stores is the number of points inside //cycleno->number of points vector no_points_cycles(rel2->GetNoTuples(), 0); vector vertex_cycleno; //vertex -> cycleno vector vertex_point; //relation (cycleno int)(vertex point) for(int i = 1;i <= rel2->GetNoTuples();i++){ Tuple* t = rel2->GetTuple(i, false); int cycleno = ((CcInt*)t->GetAttribute(DualGraph::CYCLENO))->GetIntval(); Point* p = (Point*)t->GetAttribute(DualGraph::VERTEX); vertex_cycleno.push_back(cycleno); vertex_point.push_back(*p); t->DeleteIfAllowed(); no_points_cycles[cycleno]++; } vector index_contour; unsigned int no_cyc = 0; for(unsigned int i = 0;i < no_points_cycles.size();i++){ // cout<<"no_cyc "< 0) no_cyc++; else break; } // cout<<"no of cycles "<GetNoTuples();i++){ Tuple* t = rel1->GetTuple(i, false); int v1 = ((CcInt*)t->GetAttribute(DualGraph::V1))->GetIntval(); int v2 = ((CcInt*)t->GetAttribute(DualGraph::V2))->GetIntval(); int v3 = ((CcInt*)t->GetAttribute(DualGraph::V3))->GetIntval(); int oid = ((CcInt*)t->GetAttribute(DualGraph::TOID))->GetIntval(); int c1 = vertex_cycleno[v1 - 1]; int c2 = vertex_cycleno[v2 - 1]; int c3 = vertex_cycleno[v3 - 1]; /* if(!(oid == 93 || oid == 94 || oid == 95)){ t->DeleteIfAllowed(); continue; }*/ Triangle tri(oid, v1, v2, v3, c1, c2, c3); SetNeighbor(tri, no_points_cycles, index_contour); // cout<<"new elem "; // tri.Print(); trinode = new TriNode(tri,NULL); ////////////////traverse the list ////////////////////////////// if(i == 1){ head->next = trinode; t->DeleteIfAllowed(); continue; } TriNode* prev = head; TriNode* cur = prev->next; bool insert = true; while(cur != NULL && insert){ // cout<<" cur elem in list "; // cur->tri.Print(); int sharetype = trinode->tri.ShareEdge(cur->tri); // cout<<"sharetype "< 0){ //find a common edge // cout<<"oid1 "<tri.oid<<"oid2 "<tri.oid<tri.oid); v2_list.push_back(cur->tri.oid); Point p1, p2; switch(sharetype){ case 1: p1 = vertex_point[tri.v1 - 1]; p2 = vertex_point[tri.v2 - 1]; break; case 2: p1 = vertex_point[tri.v1 - 1]; p2 = vertex_point[tri.v3 - 1]; break; case 3: p1 = vertex_point[tri.v2 - 1]; p2 = vertex_point[tri.v3 - 1]; break; default: assert(false); } /* hs.Set(true, p1, p2); Line* l = new Line(0); l->StartBulkLoad(); hs.attr.edgeno = 0; *l += hs; hs.SetLeftDomPoint(!hs.IsLeftDomPoint()); *l += hs; l->EndBulkLoad(); line.push_back(*l); delete l;*/ Line* l = new Line(0); l->StartBulkLoad(); // if(!AlmostEqual(p1, p2)){ HalfSegment hs; hs.Set(true, p1, p2); hs.attr.edgeno = 0; *l += hs; hs.SetLeftDomPoint(!hs.IsLeftDomPoint()); *l += hs; // } l->EndBulkLoad(); line.push_back(*l); l->DeleteIfAllowed(); ////////////////////////////////////////////////////// //trinode trinode->tri.neighbor_no++; if(trinode->tri.neighbor_no == 3){ // cout<<"do not insert new"<tri.neighbor_no++; if(cur->tri.neighbor_no == 3){//find all neighbors // cout<<"delete cur "<next = cur->next; cur = cur->next; delete temp; }else{ prev = cur; cur = cur->next; } }else{ prev = cur; cur = cur->next; } } if(insert){ prev->next = trinode; } /////////////////////////////////////////////////////////////// t->DeleteIfAllowed(); } //for debuging, detect whether there are some elements not processed if(head->next){ cout<<"it should not come here. "; cout<<"there are some elements not processed in the list"<next; while(temp){ temp->tri.Print(); cout<tri.v1 - 1]<<" " <tri.v2 - 1]<<" " <tri.v3 - 1]<<" "<next; } assert(false); } delete head; } /* two triangles sharing the same edge */ void RegVertex::ShareEdge(Region* reg1, Region* reg2, int oid1, int oid2, vector >& adj_node) { for(int i = 0;i < reg1->Size();i++){ HalfSegment hs1; reg1->Get(i, hs1); for(int j = 0;j < reg2->Size();j++){ HalfSegment hs2; reg2->Get(j, hs2); if((AlmostEqual(hs1.GetLeftPoint(), hs2.GetLeftPoint())&& AlmostEqual(hs1.GetRightPoint(), hs2.GetRightPoint())) || (AlmostEqual(hs1.GetRightPoint(), hs2.GetLeftPoint()) && AlmostEqual(hs1.GetLeftPoint(), hs2.GetRightPoint()))){ if(adj_node[oid2 - 1].size() == 0){ Line* l = new Line(0); l->StartBulkLoad(); hs1.attr.edgeno = 0; *l += hs1; hs1.SetLeftDomPoint(!hs1.IsLeftDomPoint()); *l += hs1; l->EndBulkLoad(); line.push_back(*l); l->DeleteIfAllowed(); v1_list.push_back(oid1); v2_list.push_back(oid2); adj_node[oid1 - 1].push_back(oid2); }else{ unsigned int index = 0; for(;index < adj_node[oid2 - 1].size();index++){ if(adj_node[oid2 - 1][index] == oid1)break; } if(index == adj_node[oid2 - 1].size()){ Line* l = new Line(0); l->StartBulkLoad(); hs1.attr.edgeno = 0; *l += hs1; hs1.SetLeftDomPoint(!hs1.IsLeftDomPoint()); *l += hs1; l->EndBulkLoad(); line.push_back(*l); l->DeleteIfAllowed(); v1_list.push_back(oid1); v2_list.push_back(oid2); adj_node[oid1 - 1].push_back(oid2); } } return; } } } } /* Using depth first method to travese the R-tree to find all neighbors for the triangle (oid,reg) */ void RegVertex::DFTraverse(R_Tree<2,TupleId>* rtree, SmiRecordId adr,int oid, Region* reg, vector >& adj_node) { 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 = rel1->GetTuple(e.info,false); Region* candi_reg = (Region*)dg_tuple2->GetAttribute(DualGraph::PAVEMENT); // cout<<"e.info "<Area()<GetAttribute(DualGraph::OID))->GetIntval(); // if(oid != (int)e.info){ if(oid != cand_oid){ // ShareEdge(reg, candi_reg, oid, e.info, adj_node); ShareEdge(reg, candi_reg, oid, cand_oid, adj_node); } dg_tuple2->DeleteIfAllowed(); }else{ R_TreeInternalEntry<2> e = (R_TreeInternalEntry<2>&)(*node)[j]; // if(reg->Intersects(e.box)){ if(reg->Intersects(Region(e.box))){ DFTraverse(rtree, e.pointer, oid, reg, adj_node); } } } delete node; } /* for each triangle, it searches all its neighbors by traversing the RTree it creates the edge relation for dual graph. depth-first is a little faster than breadth-first in create berlin and houston data, we have an unique oid for each IFOB. so the value of oid may not start from 1. not the same as tuple id !!!Be Careful!!! */ void RegVertex::GetDGEdgeRTree(R_Tree<2,TupleId>* rtree) { SmiRecordId adr = rtree->RootRecordId(); int max_no = 0; for(int i = 1;i <= rel1->GetNoTuples();i++){ Tuple* dg_tuple = rel1->GetTuple(i, false); int oid = ((CcInt*)dg_tuple->GetAttribute(DualGraph::OID))->GetIntval(); if(oid > max_no) max_no = oid; dg_tuple->DeleteIfAllowed(); } // vector > adj_node(rel1->GetNoTuples()); vector > adj_node(max_no);//oid may not start from 1, e.g., 3000 for(int i = 1;i <= rel1->GetNoTuples();i++){ // for(int i = 1;i <= 500;i++){ Tuple* dg_tuple1 = rel1->GetTuple(i, false); int oid = ((CcInt*)dg_tuple1->GetAttribute(DualGraph::OID))->GetIntval(); Region* reg = (Region*)dg_tuple1->GetAttribute(DualGraph::PAVEMENT); ///////////////////traverse RTree////////////////////////////////// /* queue record_list; record_list.push(adr); while(record_list.empty() == false){ // width first method SmiRecordId node_recid = record_list.front(); record_list.pop(); R_TreeNode<2,TupleId>* node = rtree->GetMyNode(node_recid,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 = rel1->GetTuple(e.info,false); Region* candi_reg = (Region*)dg_tuple2->GetAttribute(DualGraph::PAVEMENT); if(oid != e.info){ // cout<<"find neighbor "<DeleteIfAllowed(); }else{ R_TreeInternalEntry<2> e = (R_TreeInternalEntry<2>&)(*node)[j]; if(reg->Intersects(e.box)) record_list.push(e.pointer); } } delete node; }*/ /////////////////depth first method//////////////////////////////////// DFTraverse(rtree, adr, oid, reg, adj_node); ////////////////////////////////////////////////////////////////////// dg_tuple1->DeleteIfAllowed(); } } string VisualGraph::NodeTypeInfo = "(rel(tuple((Oid int)(Loc point))))"; string VisualGraph::EdgeTypeInfo = "(rel(tuple((Oid1 int)(Oid2 int)(Connection line))))"; string VisualGraph::QueryTypeInfo = "(rel(tuple((Oid int)(Loc1 point)(Loc2 point))))"; VisualGraph::~VisualGraph() { // cout<<"~VisualGraph()"<ReadFromString(NodeTypeInfo,xType); xNumericType = SecondoSystem::GetCatalog()->NumericType(xType); node_rel = Relation::Open(in_xValueRecord, inout_iOffset, xNumericType); if(!node_rel) { return; } /***********************Open relation for edge*********************/ nl->ReadFromString(EdgeTypeInfo,xType); xNumericType = SecondoSystem::GetCatalog()->NumericType(xType); edge_rel = Relation::Open(in_xValueRecord, inout_iOffset, xNumericType); if(!edge_rel) { node_rel->Delete(); return; } ////////////////////adjaency list//////////////////////////////// size_t bufsize = DbArray::headerSize(); SmiSize offset = 0; char* buf = (char*) malloc(bufsize); in_xValueRecord.Read(buf, bufsize, inout_iOffset); inout_iOffset += bufsize; assert(buf != NULL); adj_list.restoreHeader(buf,offset); free(buf); offset = 0; buf = (char*) malloc(bufsize); in_xValueRecord.Read(buf, bufsize, inout_iOffset); assert(buf != NULL); entry_adj_list.restoreHeader(buf,offset); inout_iOffset += bufsize; free(buf); } void VisualGraph::Load(int id, Relation* r1, Relation* r2) { // cout<<"VisualGraph::Load()"<ToString(ptrList1) + ")))))"; Word xResult; int QueryExecuted = QueryProcessor::ExecuteQuery(strQuery, xResult); assert(QueryExecuted); node_rel = (Relation*)xResult.addr; /////////////////edge relation///////////////////// ListExpr ptrList2 = listutils::getPtrList(r2); strQuery = "(consume(sort(feed(" + EdgeTypeInfo + "(ptr " + nl->ToString(ptrList2) + ")))))"; QueryExecuted = QueryProcessor::ExecuteQuery(strQuery, xResult); assert(QueryExecuted); edge_rel = (Relation*)xResult.addr; ////////////adjacency list //////////////////////////////// ListExpr ptrList3 = listutils::getPtrList(edge_rel); strQuery = "(createbtree (" + EdgeTypeInfo + "(ptr " + nl->ToString(ptrList3) + "))" + "Oid1)"; QueryExecuted = QueryProcessor::ExecuteQuery(strQuery,xResult); assert(QueryExecuted); BTree* btree_node_oid1 = (BTree*)xResult.addr; // cout<<"b-tree on edge is finished....."<GetNoTuples();i++){ CcInt* nodeid = new CcInt(true, i); BTreeIterator* btree_iter1 = btree_node_oid1->ExactMatch(nodeid); int start = adj_list.Size(); // cout<<"start "<Next()){ Tuple* edge_tuple = edge_rel->GetTuple(btree_iter1->GetId(), false); int oid = ((CcInt*)edge_tuple->GetAttribute(OIDSECOND))->GetIntval(); adj_list.Append(oid); edge_tuple->DeleteIfAllowed(); } delete btree_iter1; int end = adj_list.Size(); entry_adj_list.Append(ListEntry(start, end)); // cout<<"end "<Out(typeInfo); } ListExpr VisualGraph::Out(ListExpr typeInfo) { // cout<<"Out()"<TheEmptyList(); ListExpr xLast = nl->TheEmptyList(); ListExpr xNext = nl->TheEmptyList(); bool bFirst = true; for(int i = 1;i <= edge_rel->GetNoTuples();i++){ Tuple* edge_tuple = edge_rel->GetTuple(i, false); CcInt* oid1 = (CcInt*)edge_tuple->GetAttribute(OIDFIRST); CcInt* oid2 = (CcInt*)edge_tuple->GetAttribute(OIDSECOND); Line* connection = (Line*)edge_tuple->GetAttribute(CONNECTION); ListExpr xline = OutLine(nl->TheEmptyList(),SetWord(connection)); xNext = nl->FourElemList(nl->IntAtom(g_id), nl->IntAtom(oid1->GetIntval()), nl->IntAtom(oid2->GetIntval()), xline); if(bFirst){ xNode = nl->OneElemList(xNext); xLast = xNode; bFirst = false; }else xLast = nl->Append(xLast,xNext); edge_tuple->DeleteIfAllowed(); } return nl->TwoElemList(nl->IntAtom(g_id),xNode); } bool VisualGraph::CheckVisualGraph(ListExpr type, ListExpr& errorInfo) { // cout<<"CheckVisualGraph()"<IsEqual(type, "visualgraph"); } void VisualGraph::CloseVisualGraph(const ListExpr typeInfo, Word& w) { // cout<<"CloseVisualGraph()"< (w.addr); w.addr = NULL; } void VisualGraph::DeleteVisualGraph(const ListExpr typeInfo, Word& w) { // cout<<"DeleteVisualGraph()"<Save(valueRecord, offset, typeInfo); return result; } bool VisualGraph::Save(SmiRecord& in_xValueRecord,size_t& inout_iOffset, const ListExpr in_xTypeInfo) { // cout<<"Save()"<ReadFromString(NodeTypeInfo,xType); xNumericType = SecondoSystem::GetCatalog()->NumericType(xType); if(!node_rel->Save(in_xValueRecord,inout_iOffset,xNumericType)) return false; /************************save edge****************************/ nl->ReadFromString(EdgeTypeInfo,xType); xNumericType = SecondoSystem::GetCatalog()->NumericType(xType); if(!edge_rel->Save(in_xValueRecord,inout_iOffset,xNumericType)) return false; SecondoCatalog *ctlg = SecondoSystem::GetCatalog(); SmiRecordFile *rf = ctlg->GetFlobFile(); adj_list.saveToFile(rf, adj_list); SmiSize offset = 0; size_t bufsize = adj_list.headerSize(); char* buf = (char*) malloc(bufsize); adj_list.serializeHeader(buf,offset); assert(offset==bufsize); in_xValueRecord.Write(buf, bufsize, inout_iOffset); inout_iOffset += bufsize; free(buf); entry_adj_list.saveToFile(rf, entry_adj_list); offset = 0; buf = (char*) malloc(bufsize); entry_adj_list.serializeHeader(buf,offset); assert(offset==bufsize); in_xValueRecord.Write(buf,bufsize, inout_iOffset); free(buf); inout_iOffset += bufsize; return true; } /* checks whether the region halfsegment self intersects */ bool Hole::NoSelfIntersects(Region* r) { for(int i = 0;i < r->Size();i++){ HalfSegment hs1; r->Get(i, hs1); if(!hs1.IsLeftDomPoint())continue; for(int j = 0;j < r->Size();j++){ HalfSegment hs2; r->Get(j, hs2); if(!hs2.IsLeftDomPoint() || i == j)continue; Point ip; if(hs1.Intersection(hs2, ip)){ if(!AlmostEqual(ip, hs1.GetLeftPoint()) && !AlmostEqual(ip, hs1.GetRightPoint()) && !AlmostEqual(ip, hs2.GetLeftPoint()) && !AlmostEqual(ip, hs2.GetRightPoint())) return false; } } } return true; } /* collect the holes of a region */ void Hole::GetHole(Region* r) { CompTriangle* ct = new CompTriangle(r); unsigned int no_cyc = ct->NoOfCycles();//ignore the first cycle delete ct; // cout<<"holes "< edgeno; vector partnerno; for(unsigned int i = 0;i < no_cyc;i++){ Region* new_reg = new Region(0); new_reg->StartBulkLoad(); new_reg->EndBulkLoad(); regs.push_back(*new_reg); new_reg->DeleteIfAllowed(); edgeno.push_back(0); partnerno.push_back(0); } // cout<<"here "<Size()<Size();i++){ // cout<<"i1 "<Get(i, hs); if(!hs.IsLeftDomPoint()) continue; HalfSegment temp_hs; temp_hs.Set(true, hs.GetLeftPoint(), hs.GetRightPoint()); temp_hs.SetLeftDomPoint(hs.IsLeftDomPoint()); temp_hs.attr.faceno = 0; int cycle_no = hs.attr.cycleno; // cout<<"cycle_no "< r2.Area(); } /* query getcontour('Transportationmode/Polygon-Data/GermanyPPPoly') count; read polygon data from a file */ void Hole::GetContour() { Coord x1, y1, x2, y2; int index = 0; MHSNode* head = new MHSNode(MyHalfSegment(),NULL); Points* ps = new Points(0); ps->StartBulkLoad(); while( !in.eof()){ in>>index; if(!in.good()) break; in>>x1; if(!in.good()) break; in>>y1; if(!in.good()) break; in>>x2; if(!in.good()) break; in>>y2; if(!in.good()) break; // printf("%.12f %.12f %.12f %.12f\n",x1,y1,x2,y2); Point p1(true,x1,y1); Point p2(true,x2,y2); MyHalfSegment hs(true,p1,p2); if(AlmostEqual(p1,p2)) continue; // if(index > 10000)break; MHSNode* node = new MHSNode(hs,NULL); node->next = head->next; head->next = node; *ps += p1; *ps += p2; } ps->EndBulkLoad(); BBox<2> bbox; double min[2]; double max[2]; const double delta = 5.0; min[0] = ps->BoundingBox().MinD(0) - delta; min[1] = ps->BoundingBox().MinD(1) - delta; max[0] = ps->BoundingBox().MaxD(0) + delta; max[1] = ps->BoundingBox().MaxD(1) + delta; bbox.Set(true, min, max); Region* outer_contour = new Region(bbox); // GrahamScan::convexHull(ps,outer_contour); regs.push_back(*outer_contour);//the first is the outer contour outer_contour->DeleteIfAllowed(); //////////////////////////////////////////////// while(head->next != NULL){ list contours; MHSNode* prev = head; MHSNode* cur = head->next; contours.push_back(cur->mhs); prev->next = cur->next; MHSNode* temp = cur; delete temp; MyHalfSegment front = contours.front(); MyHalfSegment back = contours.back(); while(1){ cur = head->next; prev = head; while(cur != NULL){ if(AlmostEqual(front.from, cur->mhs.to)){ contours.push_front(cur->mhs); prev->next = cur->next; delete cur; break; } if(AlmostEqual(front.from, cur->mhs.from)){ cur->mhs.Exchange(); contours.push_front(cur->mhs); prev->next = cur->next; delete cur; break; } if(AlmostEqual(back.to, cur->mhs.from)){ contours.push_back(cur->mhs); prev->next = cur->next; delete cur; break; } if(AlmostEqual(back.to, cur->mhs.to)){ cur->mhs.Exchange(); contours.push_back(cur->mhs); prev->next = cur->next; delete cur; break; } prev = cur; cur = cur->next; } front = contours.front(); back = contours.back(); // cout<<"front ";front.Print(); // cout<<"back "; back.Print(); if(AlmostEqual(front.from, back.to) && contours.size() > 2){ // cout<<"cycle found "< ps; while(contours.empty() == false){ MyHalfSegment top = contours.front(); contours.pop_front(); ps.push_back(top.from); } SpacePartition* sp = new SpacePartition(); CompTriangle* ct = new CompTriangle(); vector regions; if(ct->Area(ps) > 0){ sp->ComputeRegion(ps,regions); regs1.push_back(regions[0]); regs2.push_back(regions[0]); }else{ vector temp_ps; for(int i = ps.size() - 1;i >= 0;i--) temp_ps.push_back(ps[i]); sp->ComputeRegion(temp_ps,regions); regs1.push_back(regions[0]); regs2.push_back(regions[0]); } delete ct; delete sp; contours.clear(); break; } if(cur == NULL){ contours.clear(); break; } } } sort(regs1.begin(),regs1.end(), RegionCom); sort(regs2.begin(),regs2.end(), RegionCom); for(unsigned int i = 0;i < regs1.size();i++){ unsigned int j = 0; // cout<DeleteIfAllowed(); } /* create no_reg regions(cycles) */ void Hole::GetContour(unsigned int no_reg) { vector contour; vector regions; SpacePartition* sp = new SpacePartition(); //////////////////the outer contour///////////////////////////////// contour.push_back(Point(true,0.0,0.0)); contour.push_back(Point(true,100000.0,0.0)); contour.push_back(Point(true,100000.0,100000.0)); contour.push_back(Point(true,0.0,100000.0)); sp->ComputeRegion(contour,regions); regs.push_back(regions[0]); //////////////////////////////////////////////////////// // struct timeval tval; // struct timezone tzone; // gettimeofday(&tval, &tzone); // srand48(tval.tv_sec); unsigned int reg_count = no_reg; while(no_reg > 1){ // int px = lrand48() % 98700 + 600; // int py = lrand48() % 98700 + 600; int px = GetRandom() % 98700 + 600; int py = GetRandom() % 98700 + 600; // int radius = lrand48() % 496 + 5;//5-500 10-1000 int radius = GetRandom() % 496 + 5;//5-500 10-1000 contour.clear(); regions.clear(); contour.push_back(Point(true, px - radius, py - radius)); contour.push_back(Point(true, px + radius, py - radius)); contour.push_back(Point(true, px + radius, py + radius)); contour.push_back(Point(true, px - radius, py + radius)); sp->ComputeRegion(contour,regions); unsigned int i = 1; for(;i < regs.size();i++){ if(regs[i].Intersects(regions[0]))break; } if(i == regs.size()){ ///create convex hull Points* outer_ps = new Points(0); // int outer_ps_no = lrand48() % 191 + 10;///10-200 int outer_ps_no = GetRandom() % 191 + 10;///10-200 // int outer_ps_no = radius;///10-200 double xmin = px - radius; double ymin = py - radius; outer_ps->StartBulkLoad(); vector temp_ps; while(outer_ps_no > 0){ // int x = lrand48() %(2*radius*100); // int y = lrand48() %(2*radius*100); int x = GetRandom() %(2*radius*100); int y = GetRandom() %(2*radius*100); double coord_x = x/100.0 + xmin; double coord_y = y/100.0 + ymin; Point newp(true,coord_x,coord_y); if(newp.Inside(regions[0])){ outer_ps_no--; *outer_ps += newp; temp_ps.push_back(newp); } } outer_ps->EndBulkLoad(); if(no_reg % 3 == 0){ Region* newregion = new Region(0); GrahamScan::convexHull(outer_ps,newregion); regs.push_back(*newregion); newregion->DeleteIfAllowed(); } else if(no_reg % 3 == 1){ Region* newregion = new Region(0); DiscoverContour(outer_ps,newregion); regs.push_back(*newregion); newregion->DeleteIfAllowed(); } else{ Region* newregion = new Region(outer_ps->BoundingBox()); regs.push_back(*newregion); newregion->DeleteIfAllowed(); } outer_ps->DeleteIfAllowed(); ///////////////////////////////////////////////// // regs.push_back(regions[0]); no_reg--; } } delete sp; assert(reg_count == regs.size()); } void Hole::SpacePartitioning(vector ps, vector& hs_segs, Point sf, Point sl) { // cout<<"sf "< ls; vector rs; for(unsigned int i = 0;i < ps.size();i++){ if(AlmostEqual(ps[i], mid_p1) || AlmostEqual(ps[i], mid_p1)) continue; if(ps[i].GetX() < mid_p1.GetX() || AlmostEqual(ps[i].GetX(), mid_p1.GetX())) ls.push_back(ps[i]); else rs.push_back(ps[i]); } if(sf.GetX() < mid_p1.GetX()){ // cout<<"1 "<<"left "< ls; vector rs; for(unsigned int i = 0;i < ps.size();i++){ if(AlmostEqual(ps[i], mid_p1) || AlmostEqual(ps[i], mid_p1)) continue; if(ps[i].GetY() < mid_p1.GetY() || AlmostEqual(ps[i].GetY(), mid_p1.GetY())) ls.push_back(ps[i]); else rs.push_back(ps[i]); } if(sf.GetY() < mid_p1.GetY()){ // cout<<"2 "<<"left "< ls; vector rs; double a = (mid_p1.GetY() - mid_p2.GetY())/ (mid_p1.GetX() - mid_p2.GetX()); double b = mid_p1.GetY() - a*mid_p1.GetX(); for(unsigned int i = 0;i < ps.size();i++){ if(AlmostEqual(ps[i], mid_p1) || AlmostEqual(ps[i], mid_p1)) continue; if(ps[i].GetY() < (a*ps[i].GetX() + b)|| AlmostEqual(ps[i].GetY(), (a*ps[i].GetX() + b))) ls.push_back(ps[i]); else rs.push_back(ps[i]); } if(sf.GetY() < a*sf.GetX() + b){ // cout<<"3 "<<"left "<& hs_segs) { vector ps1; for(int i = 0;i < gen_ps->Size();i++){ Point temp_p; gen_ps->Get(i, temp_p); ps1.push_back(temp_p); } Point sf = ps1[0]; Point sl = ps1[1]; //cout<<"sf "< ls; vector rs; for(unsigned int i = 0;i < ps1.size();i++){ if(AlmostEqual(ps1[i], sf) || AlmostEqual(ps1[i],sl)) continue; if(ps1[i].GetX() < sf.GetX() || AlmostEqual(ps1[i].GetX(), sf.GetX())) ls.push_back(ps1[i]); else rs.push_back(ps1[i]); } // cout<<"1 "<<"left "< ls; vector rs; for(unsigned int i = 0;i < ps1.size();i++){ if(AlmostEqual(ps1[i], sf) || AlmostEqual(ps1[i],sl)) continue; if(ps1[i].GetY() < sf.GetY() || AlmostEqual(ps1[i].GetY(), sf.GetY())) ls.push_back(ps1[i]); else rs.push_back(ps1[i]); } // cout<<"2 "<<"left "< ls; vector rs; double a = (sf.GetY() - sl.GetY())/(sf.GetX() - sl.GetX()); double b = sf.GetY() - a*sf.GetX(); for(unsigned int i = 0;i < ps1.size();i++){ if(AlmostEqual(ps1[i], sf) || AlmostEqual(ps1[i],sl)) continue; if(ps1[i].GetY() < (a*ps1[i].GetX() + b)|| AlmostEqual(ps1[i].GetY(), (a*ps1[i].GetX() + b))) ls.push_back(ps1[i]); else rs.push_back(ps1[i]); } // cout<<"3 "<<"left "< ps1; if(no_ps < 3){ cout<<"at least three points"<StartBulkLoad(); while(no_ps > 0){ // int x = lrand48() %100000; // int y = lrand48() %100000; int x = GetRandom() % 100000; int y = GetRandom() % 100000; double coord_x = x/100.0; double coord_y = y/100.0; Point p(true,coord_x, coord_y); *gen_ps += p; no_ps--; } gen_ps->EndBulkLoad(); Region* reg = new Region(0); DiscoverContour(gen_ps, reg);//store the polygon in regs regs.push_back(*reg); reg->DeleteIfAllowed(); gen_ps->DeleteIfAllowed(); } /* using the space partitining method to create randomly polygon by a given set of vertices */ void Hole::DiscoverContour(Points* gen_ps, Region* r) { vector hs_segs; SpacePartitioning(gen_ps, hs_segs); MHSNode* head = new MHSNode(MyHalfSegment(),NULL); for(unsigned int i = 0;i < hs_segs.size();i++){ MHSNode* node = new MHSNode( MyHalfSegment(true,hs_segs[i].GetLeftPoint(), hs_segs[i].GetRightPoint()),NULL); node->next = head->next; head->next = node; } DiscoverContour(head, r); delete head; } /* given a set of segments, it discovers whether a cycle exists. if yes, a region is returned */ void Hole::DiscoverContour(MHSNode* head, Region* r) { list contours; MHSNode* prev = head; MHSNode* cur = head->next; contours.push_back(cur->mhs); prev->next = cur->next; MHSNode* temp = cur; delete temp; MyHalfSegment front = contours.front(); MyHalfSegment back = contours.back(); while(1){ cur = head->next; prev = head; while(cur != NULL){ if(AlmostEqual(front.from, cur->mhs.to)){ contours.push_front(cur->mhs); prev->next = cur->next; delete cur; break; } if(AlmostEqual(front.from, cur->mhs.from)){ cur->mhs.Exchange(); contours.push_front(cur->mhs); prev->next = cur->next; delete cur; break; } if(AlmostEqual(back.to, cur->mhs.from)){ contours.push_back(cur->mhs); prev->next = cur->next; delete cur; break; } if(AlmostEqual(back.to, cur->mhs.to)){ cur->mhs.Exchange(); contours.push_back(cur->mhs); prev->next = cur->next; delete cur; break; } prev = cur; cur = cur->next; } front = contours.front(); back = contours.back(); if(AlmostEqual(front.from, back.to) && contours.size() > 2){ vector ps; while(contours.empty() == false){ MyHalfSegment top = contours.front(); contours.pop_front(); ps.push_back(top.from); } SpacePartition* sp = new SpacePartition(); vector regions; sp->ComputeRegion(ps,regions); *r = regions[0]; delete sp; contours.clear(); break; } if(cur == NULL){ contours.clear(); break; } } } /////////////////////////////////////////////////////////////////////// ////////////////// get the maximum area rectangle in a region///////// ////////////////////////////////////////////////////////////////////// bool SortByY(const MyPoint& mp1, const MyPoint& mp2) { if(mp1.loc.GetY() < mp2.loc.GetY() || AlmostEqual(mp1.loc.GetY(), mp2.loc.GetY())) return false; return true; } /* locate which Quadrant the point belongs to */ int GetQuadrant(double x, double y, Rectangle<2> reg_box) { double m_x = (reg_box.MinD(0) + reg_box.MaxD(0))/2; double m_y = (reg_box.MinD(1) + reg_box.MaxD(1))/2; if(x < m_x || AlmostEqual(x, m_x)){ if(y < m_y || AlmostEqual(y, m_y ))return 3; else return 2; }else{ if(y < m_y || AlmostEqual(y, m_y ))return 4; else return 1; } return -1; } /* the region should only have one face. it can be convex or concave, but without holes if the polygon is a triangle, we can directly get the maximum rectangle */ Rectangle<2> GetMaxRect(Region* reg) { if(reg->NoComponents() != 1){ cout<<"only one face is allowed"<(false); } CompTriangle* ct = new CompTriangle(reg); unsigned int no_cyc = ct->NoOfCycles(); if(no_cyc != 1){ cout<<"has holes inside or no cycle"<(false); } Line* boundary = new Line(0); reg->Boundary(boundary); SimpleLine* sboundary = new SimpleLine(0); sboundary->fromLine(*boundary); vector mhs; SpacePartition* sp = new SpacePartition(); if(sboundary->Size() > 0) sp->ReorderLine(sboundary, mhs); else{ cout<<"can't covert the boundary to a sline"<DeleteIfAllowed(); sboundary->DeleteIfAllowed(); delete sp; delete ct; return Rectangle<2>(false); } vector ps; for(unsigned int i = 0;i < mhs.size();i++) ps.push_back(mhs[i].from); if(ct->IsConvex(ps) == false){ cout<<"concave polygon"<(false); } /////////////////////////////////////////////////////////////////////// /////////////// finish checking ////////////////////////////////////// ////////////////////////////////////////////////////////////////////// Rectangle<2> reg_box = reg->BoundingBox(); // cout<<"ps size "< 0); switch(range){ case 1: x = floor(x); y = floor(y); break; case 2: x = ceil(x); y = floor(y); break; case 3: x = ceil(x); y = ceil(y); break; case 4: x = floor(x); y = ceil(y); break; } ps[i].Set(x,y); // cout<<"x "< 0){ Point p1 = ps[i - 1]; Point p2 = ps[i]; if(AlmostEqual(p1, p2)){ boundary->DeleteIfAllowed(); sboundary->DeleteIfAllowed(); delete sp; delete ct; return Rectangle<2>(false); } } ///////////////////////////////////////////////////////////////// //more checking, three points collineation, cannot be a region/// //////////////////////////////////////////////////////////////// if(ps.size() == 3){ SpacePartition* sp = new SpacePartition(); if(sp->Collineation(ps[0], ps[1], ps[2])){ delete sp; return Rectangle<2>(false); } delete sp; } } boundary->DeleteIfAllowed(); sboundary->DeleteIfAllowed(); if(AlmostEqual(ps[0], ps[ps.size() - 1])){ delete sp; delete ct; return Rectangle<2>(false); } vector regs; sp->ComputeRegion(ps, regs); delete sp; delete ct; if(ct->GetClockwise(ps) == false){ vector temp_ps; for(int i = ps.size() - 1; i >= 0;i--) temp_ps.push_back(ps[i]); ps.clear(); for(unsigned int i = 0;i < temp_ps.size();i++) ps.push_back(temp_ps[i]); } if(ps.size() >= 3){ vector polygon; for(unsigned int i = 0;i < ps.size();i++){ GeomPoint gp(ps[i].GetX(), ps[i].GetY()); polygon.push_back(gp); } MaxRect max_rect; max_rect.Init(); max_rect.SetPoint(polygon); if(max_rect.computeEdgeList()){ max_rect.computeLargestRectangle(); if(max_rect.result != -1) return max_rect.RectList[max_rect.result]; else return Rectangle<2>(false); }else return Rectangle<2>(false); } return Rectangle<2>(false); } /* simple and approximate method to get a rectangle from a polygon. the method above takes too much time */ Rectangle<2> GetMaxRect2(Region* reg) { if(reg->NoComponents() != 1){ cout<<"only one face is allowed"<(false); } CompTriangle* ct = new CompTriangle(reg); unsigned int no_cyc = ct->NoOfCycles(); if(no_cyc != 1){ cout<<"has holes inside or no cycle"<(false); } delete ct; Rectangle<2> bbox = reg->BoundingBox(); double mid_x = (bbox.MinD(0) + bbox.MaxD(0))/2; double mid_y = (bbox.MinD(1) + bbox.MaxD(1))/2; double dist_delta1; double dist_delta2; if(GetRandom() % 2 ==0){ dist_delta1 = 5.0; dist_delta2 = 3.0; }else{ dist_delta1 = 3.0; dist_delta2 = 5.0; } double min[2], max[2]; min[0] = mid_x - dist_delta1; max[0] = mid_x + dist_delta1; min[1] = mid_y - dist_delta2; max[1] = mid_y + dist_delta2; Rectangle<2> max_bbox(true, min, max); if(RegContainRect(reg, max_bbox)){ bool valid = true; Rectangle<2> last_box = max_bbox; while(valid){ dist_delta1 += dist_delta1; dist_delta2 += dist_delta2; min[0] = mid_x - dist_delta1; max[0] = mid_x + dist_delta1; min[1] = mid_y - dist_delta2; max[1] = mid_y + dist_delta2; Rectangle<2> temp_bbox(true, min, max); if(RegContainRect(reg, temp_bbox) && temp_bbox.Area() < maxi_rect_area){ last_box = temp_bbox; }else{ valid = false; } } return last_box; }else{ return Rectangle<2>(false); } } ///////////////////////////////////////////////////////////////////////// //////////// the following implementation from ///////////////////////// ////H. Alt, D. Hsu, and J. Snoeyink. //////////////////////////////////// ////////Computing the largest inscribed isothetic rectangle. /////////// //////////In Proc. 7th Canadian Conf. Comput. Geom.,/////////////////// ////////////Universit'e Laval, Qu'ebec, August 1995, pp. 67--72.///////// //////// the original code is by Java, I conver it to C, c++///////////// ///////////////////////////////////////////////////////////////////////// void MaxRect::SetPoint(vector& list) { for(unsigned int i = 0;i < list.size();i++){ // geo_p_list.push_back(list[i]); int x = list[i].x; int y = list[i].y; GeomPoint p(x,y); // this.polygon.add(p); if (geo_p_list.size() <2){ geo_p_list.push_back(p); status = 1; changed = true; }else if (geo_p_list.size() == 2){ GeomPoint ha = geo_p_list[0]; GeomPoint hb = geo_p_list[1]; if (onLeft(ha, hb, p)){ geo_p_list.push_back(p); status = 2; changed = true; }else{ GeomPoint q = geo_p_list[1]; geo_p_list[1] = p; geo_p_list.push_back(q); status = 2; } }else{ geo_p_list.push_back(p); } } } bool MaxRect::onLeft(GeomPoint a, GeomPoint b, GeomPoint c) { int area = (b.x -a.x)*(c.y - a.y) - (c.x - a.x)*(b.y - a.y); return (area<0); } bool MaxRect::pointOutside(GeomPoint p) {//, int start, int stop){ bool ptIn = true, currIn, prevIn = true; GeomPoint a = geo_p_list[0]; GeomPoint b; for(unsigned int i=0; i g_xmax){ g_xmax = a.x; yxmax = a.y; } if (a.y < g_ymin){ g_ymin = a.y; } if (a.y > g_ymax){ g_ymax = a.y; } } if(a.x == b.x) return false; GeomEdge* e = new GeomEdge(a,b); geo_e_list.push_back(*e); a = b; delete e; } //for return true; } /* compute y intersection with an edge first pixel completely inside ceil function if edge is on top, floor otherwise (+y is down) */ inline int MaxRect::yIntersect(int xi, GeomEdge e) { int y; double yfirst = (e.m) * (xi-0.5) + e.b; double ylast = (e.m) * (xi+0.5) + e.b; if (!e.isTop){ y = (int)floor(MIN(yfirst, ylast)); } else { y = (int)ceil(MAX(yfirst, ylast)); } return y; } /* find largest pixel completely inside look through all edges for intersection */ int MaxRect::xIntersect(int y){ int x=0; double x0=0, x1=0; for(unsigned int i=0; i< geo_p_list.size(); i++){ GeomEdge e = geo_e_list[i]; if (e.isRight && e.ymin <= y && e.ymax >= y){ x0 = (double)(y+0.5 - e.b)/e.m; x1 = (double)(y-0.5 - e.b)/e.m; } } x = (int)floor(MIN(x0,x1)); //System.out.println("xIntersect, x is " + x); return x; } GeomEdge MaxRect::findEdge(int x, bool isTop) { GeomEdge e; GeomEdge emax= geo_e_list[0]; //int count = 0; for (unsigned int i=0; i< geo_p_list.size(); i++){ e = geo_e_list[i]; if (e.xmin == x){ if (e.xmax != e.xmin){ if ((e.isTop && isTop)||(!e.isTop && !isTop)){ emax = e; } } } } return emax; } /* to get more precise data: for the coordinates of original point, we can multiply the value by 1000. because the original code only uses the type int. in the end, we have to div the value by 1000. This depends on the application requirment */ void MaxRect::computeLargestRectangle(){ changed = false; GeomEdge top, bottom; int ymax, ymin, xright, xlo, xhi; int area, maxArea = 0; int width, height, maxh=0, maxw=0; /* all 2-corner and 3-corner largest rectangles */ int aAC=0,aBD=0,aABC=0,aABD=0,aACD=0,aBCD=0; GeomPoint pAC, pBD, pABC, pABD, pACD, pBCD; int hAC=0,wAC=0,hBD=0,wBD=0,hABC=0,wABC=0,hABD=0,wABD=0; int hACD=0,wACD=0,hBCD=0,wBCD=0; bool onA, onB, onC, onD; GeomPoint maxp(0, 0); pAC = maxp; pBD = maxp; pABC = maxp; pABD = maxp; pACD = maxp; pBCD = maxp; vector xint; for(int i=0;i< g_ymax;i++){ int x = xIntersect(i); GeomPoint px(x, i); xint.push_back(px); // cout<= ymin;ylo--){//ylo from to to bottom // cout<<"ylo "<ylo){ onA = (yhi == ymax && !bottom.isRight); onD = (ylo == ymin && !top.isRight); //xIntersect(ylo,edgeList); xlo = (int)((GeomPoint)xint[ylo]).x; //xIntersect(yhi,edgeList); xhi = (int)((GeomPoint)xint[yhi]).x; xright = maxp.min(xlo,xhi); onC = (xright == xlo && yxmax >= ylo); onB = (xright == xhi && yxmax <= yhi); height = yhi-ylo; width = xright - xi; if (!fixed){ }//!fixed else{ int fixedWidth = (int)ceil( ((double)height*fixedX)/((double)fixedY)); if (fixedWidth <= width){ width = fixedWidth; } else{ width = 0; } } area = width * height; //AC if (onA && onC && !onB && !onD){ if (area > aAC){ aAC = area; // pAC = new GeomPoint(xi, ylo); pAC.x = xi; pAC.y = ylo; // cout<<" xi "< aBD){ aBD = area; // pBD = new GeomPoint(xi, ylo); pBD.x = xi; pBD.y = ylo; hBD = height; wBD = width; } } //ABC if (onA && onB && onC){ if (area > aABC){ aABC = area; // pABC = new GeomPoint(xi, ylo); pABC.x = xi; pABC.y = ylo; hABC = height; wABC = width; } } //ABD if (onA && onB && onD){ if (area > aABD){ aABD = area; // pABD = new GeomPoint(xi, ylo); pABD.x = xi; pABD.y = ylo; hABD = height; wABD = width; } } //ACD if (onA && onC && onD){ if (area > aACD){ aACD = area; // pACD = new GeomPoint(xi, ylo); pACD.x = xi; pACD.y = ylo; hACD = height; wACD = width; } } //BCD if (onB && onC && onD){ if (area > aBCD){ aBCD = area; // pBCD = new GeomPoint(xi, ylo); pBCD.x = xi; pBCD.y = ylo; hBCD = height; wBCD = width; } } if(area>maxArea){ maxArea = area; // maxp = new GeomPoint(xi, ylo); maxp.x = xi; maxp.y = ylo; maxw = width; maxh = height; } }//yhi > ylo }//for yhi }//for ylo if (xi == top.xmax){ top = findEdge(xi, true); } if(xi == bottom.xmax){ bottom = findEdge(xi, false); } }//xi rectp = maxp; recth = maxh; rectw = maxw; /* RectList.push_back(Rectangle<2>(true, pAC.x, pAC.y, wAC, hAC)); RectList.push_back(Rectangle<2>(true, pBD.x, pBD.y, wBD, hBD)); RectList.push_back(Rectangle<2>(true, pABC.x, pABC.y, wABC, hABC)); RectList.push_back(Rectangle<2>(true, pABD.x, pABD.y, wABD, hABD)); RectList.push_back(Rectangle<2>(true, pACD.x, pACD.y, wACD, hACD)); RectList.push_back(Rectangle<2>(true, pBCD.x, pBCD.y, wBCD, hBCD)); RectList.push_back(Rectangle<2>(true, maxp.x, maxp.y, maxw, maxh));*/ double x_1 = pAC.x; double x_2 = pAC.x + wAC; double y_1 = pAC.y; double y_2 = pAC.y + hAC; // Rectangle<2> rect(true, x_1, x_2, y_1, y_2); // cout<<"x1 "<(true,minMax)); } x_1 = pBD.x; x_2 = x_1 + wBD; y_1 = pBD.y; y_2 = pBD.y + hBD; // cout<<"x1 "<(true,minMax )); } x_1 = pABC.x; x_2 = x_1 + wABC; y_1 = pABC.y; y_2 = y_1 + hABC; // cout<<"x1 "<(true,minMax )); } x_1 = pABD.x; x_2 = x_1 + wABD; y_1 = pABD.y; y_2 = y_1 + hABD; // cout<<"x1 "<(true, minMax)); } x_1 = pACD.x; x_2 = x_1 + wACD; y_1 = pACD.y; y_2 = y_1 + hACD; // cout<<"x1 "<(true,minMax )); } x_1 = pBCD.x; x_2 = x_1 + wBCD; y_1 = pBCD.y; y_2 = y_1 + hBCD; // cout<<"x1 "<(true, minMax)); } x_1 = maxp.x; x_2 = x_1 + maxw; y_1 = maxp.y; y_2 = y_1 + maxh; // cout<<"x1 "<(true, minMax)); } float rect_area = 0.0; result = -1; for(unsigned int i = 0;i < RectList.size();i++){ // cout< rect_area){ rect_area = RectList[i].Area(); result = i; } } // cout<GetNoTuples();i++){ Tuple* region_tuple = rel1->GetTuple(i, false); int reg_id = ((CcInt*)region_tuple->GetAttribute(attr1))->GetIntval(); Region* r = (Region*)region_tuple->GetAttribute(attr2); if(reg_id == 1){ //the outer cycle reg_id_list.push_back(reg_id); reg_list.push_back(*r); region_tuple->DeleteIfAllowed(); continue; } CompTriangle* ct = new CompTriangle(r); int error; //0-concave 1 non-region 2 hole or faces 3 dirty region bool convex = ct->PolygonConvex2(error); if(convex){ //convex polygon reg_id_list.push_back(reg_id); reg_list.push_back(*r); }else if(convex == false && error == 0){ //concave polygon reg_id_list.push_back(reg_id); reg_list.push_back(*r); }else{ // cout<<"dirty data"<DeleteIfAllowed(); } } /* a point that appears four times. it is a vertex that two regions intersect */ void MaxRect::RemoveDirtyRegion(int regid, Region* reg) { vector ps_list; vector hs_list; for(int i = 0;i < reg->Size();i++){ HalfSegment hs; reg->Get(i, hs); if(!hs.IsLeftDomPoint())continue; Point lp = hs.GetLeftPoint(); Point rp = hs.GetRightPoint(); if(ps_list.size() == 0){ ps_list.push_back(MyPoint(lp, 1)); ps_list.push_back(MyPoint(rp, 1)); }else{ unsigned int j; for(j = 0;j < ps_list.size();j++){ if(AlmostEqual(ps_list[j].loc, lp)){ ps_list[j].dist++; break; } } if(j == ps_list.size())ps_list.push_back(MyPoint(lp, 1)); for(j = 0;j < ps_list.size();j++){ if(AlmostEqual(ps_list[j].loc, rp)){ ps_list[j].dist++; break; } } if(j == ps_list.size())ps_list.push_back(MyPoint(rp, 1)); } HalfSegment temp_hs(true, hs.GetLeftPoint(), hs.GetRightPoint()); hs_list.push_back(temp_hs); } Point dirty_p; for(unsigned int i = 0;i index_list; for(unsigned int i = 0;i < hs_list.size();i++){ HalfSegment hs = hs_list[i]; if(AlmostEqual(hs.GetLeftPoint(), dirty_p))index_list.push_back(i); if(AlmostEqual(hs.GetRightPoint(), dirty_p))index_list.push_back(i); } assert(index_list.size() == 4); //four halfsegments // cout< new_hs_list; for(unsigned int i = 0;i < hs_list.size();i++){ unsigned int j = 0; for(;j < index_list.size();j++) if(i == index_list[j])break; if(j == index_list.size())new_hs_list.push_back(hs_list[i]); } // cout< sl_contour; for(unsigned int i = 0;i < index_list.size();i++){ for(unsigned int j = i + 1;j < index_list.size();j++){ SimpleLine* sl = new SimpleLine(0); sl->StartBulkLoad(); vector sl_hs_list; HalfSegment hs1 = hs_list[index_list[i]]; HalfSegment hs2 = hs_list[index_list[j]]; vector cut_hs_list; for(unsigned int k = 0;k < index_list.size();k++){ if(index_list[k] != index_list[i] && index_list[k] != index_list[j]) cut_hs_list.push_back(hs_list[index_list[k]]); } int edgeno = 0; for(unsigned int k1 = 0;k1 < new_hs_list.size();k1++){ HalfSegment hs = new_hs_list[k1]; unsigned int k2 = 0; for(;k2 < cut_hs_list.size();k2++){ if(hs.Intersects(cut_hs_list[k2]))break; } if(k2 == cut_hs_list.size()){ hs.attr.edgeno = edgeno++; *sl += hs; hs.SetLeftDomPoint(!hs.IsLeftDomPoint()); *sl += hs; } } *sl += hs1; hs1.SetLeftDomPoint(!hs1.IsLeftDomPoint()); *sl += hs1; *sl += hs2; hs2.SetLeftDomPoint(!hs2.IsLeftDomPoint()); *sl += hs2; sl->EndBulkLoad(); if(sl->Length() > 0) sl_contour.push_back(*sl); // cout<Length()<DeleteIfAllowed(); } } //////////// get the refinement region /////////////////// for(unsigned int i = 0;i < sl_contour.size();i++){ if(IsCycle(&sl_contour[i])){ // cout<<"a cycle"< mhs; sp->ReorderLine(&sl_contour[i], mhs); vector ps; for(unsigned int j = 0;j < mhs.size();j++){ ps.push_back(mhs[j].from); } vector regs; sp->ComputeRegion(ps, regs); if(regs.size() > 0 ){ reg_id_list.push_back(regid); reg_list.push_back(regs[0]); } delete sp; } } } /* check whether the simpleline is a cycle */ bool MaxRect::IsCycle(SimpleLine* sl) { vector ps_list; for(int i = 0;i < sl->Size();i++){ HalfSegment hs; sl->Get(i, hs); if(!hs.IsLeftDomPoint())continue; // cout<GetNoTuples();i++){ Tuple* region_tuple = rel1->GetTuple(i, false); int reg_id = ((CcInt*)region_tuple->GetAttribute(attr1))->GetIntval(); // cout<<"reg_id "<DeleteIfAllowed(); continue; }*/ Region* r = (Region*)region_tuple->GetAttribute(attr2); CompTriangle* ct = new CompTriangle(r); int error; bool convex = ct->PolygonConvex2(error); if(convex){ //convex polygon reg_id_list.push_back(reg_id); reg_list.push_back(*r); }else if(convex == false && error == 0){ //concave polygon ///decompose the convex polygon into several convex polygons /// // cout<<"reg_id "<NewTriangulation(); // cout<triangles.size()<DeleteIfAllowed(); } } /* merge triangles to get convex polygons */ void MaxRect::MergeTriangle(CompTriangle* ct, int reg_id) { vector convex_list; vector mark_list; for(unsigned int i = 0;i < ct->triangles.size();i++) mark_list.push_back(false); for(unsigned int i = 0;i < ct->triangles.size();i++){ if(mark_list[i]) continue; Region* r1 = &(ct->triangles[i]); if(r1->Area() > mini_reg_area){ convex_list.push_back(*r1); mark_list[i] = true; continue; } unsigned int j = i + 1; for(;j < ct->triangles.size();j++){ Region* r2 = &(ct->triangles[j]); if(mark_list[j] == false && NeighborTriangle(r1,r2)){ Region* res = new Region(0); r1->Union(*r2, *res); convex_list.push_back(*res); res->DeleteIfAllowed(); mark_list[j] = true; break; } } if(j != ct->triangles.size()) mark_list[i] = true; } for(unsigned int i = 0;i < mark_list.size();i++) if(mark_list[i] == false)convex_list.push_back(ct->triangles[i]); vector res_list; for(unsigned int i = 0;i < convex_list.size();i++){ CompTriangle* ct1 = new CompTriangle(&convex_list[i]); if(ct1->PolygonConvex()){ res_list.push_back(convex_list[i]); } delete ct1; } vector flag_list; for(unsigned int i = 0;i < res_list.size();i++){ flag_list.push_back(true); } for(unsigned int i = 0;i < res_list.size();i++){ if(flag_list[i] == false)continue; Region* r1 = &(res_list[i]); if(r1->Area() > mini_reg_area){ // cout<<"mini area "<Area()<BoundingBox().Distance(r2->BoundingBox()) < 50.0){ flag_list[j] = false; } } } } } /* two triangles share one edge */ bool MaxRect::NeighborTriangle(Region* reg1, Region* reg2) { for(int i = 0;i < reg1->Size();i++){ HalfSegment hs1; reg1->Get(i, hs1); for(int j = 0;j < reg2->Size();j++){ HalfSegment hs2; reg2->Get(j, hs2); if((AlmostEqual(hs1.GetLeftPoint(), hs2.GetLeftPoint())&& AlmostEqual(hs1.GetRightPoint(), hs2.GetRightPoint())) || (AlmostEqual(hs1.GetRightPoint(), hs2.GetLeftPoint()) && AlmostEqual(hs1.GetLeftPoint(), hs2.GetRightPoint()))){ return true; } } } return false; } /* check whether a region contains a rectangle */ bool RegContainRect(Region* reg, Rectangle<2>& rect) { Point p1(true, rect.MinD(0), rect.MinD(1)); Point p2(true, rect.MaxD(0), rect.MinD(1)); Point p3(true, rect.MaxD(0), rect.MaxD(1)); Point p4(true, rect.MinD(0), rect.MaxD(1)); HalfSegment hs1(true, p1, p2); HalfSegment hs2(true, p2, p3); HalfSegment hs3(true, p3, p4); HalfSegment hs4(true, p1, p4); if(RegContainHS(reg, hs1) && RegContainHS(reg, hs2) && RegContainHS(reg, hs3) && RegContainHS(reg, hs4))return true; return false; } /* for the input relation, it gets a maximum rectangle for each region */ void MaxRect::GetRectangle1(int attr1, int attr2, Relation* building_para) { if(building_para->GetNoTuples() == 0){ cout<<"para relation empty"<GetTuple(1, false); float area_para = ((CcReal*)para_tuple->GetAttribute(0))->GetRealval(); para_tuple->DeleteIfAllowed(); int reg_id = 1; for(int i = 1;i <= rel1->GetNoTuples();i++){ // for(int i = 1;i <= 50;i++){ Tuple* poly_tuple = rel1->GetTuple(i, false); int poly_id = ((CcInt*)poly_tuple->GetAttribute(attr1))->GetIntval(); Region* poly = (Region*)poly_tuple->GetAttribute(attr2); if(poly_id == 1){ poly_tuple->DeleteIfAllowed(); continue; } // cout<<"poly_id "<NewTriangulation(); // cout<triangles.size()< > rect_box_list; for(unsigned int j = 0;j < ct->triangles.size();j++){ if(ct->triangles[j].Area() > mini_tri_area && ct->triangles[j].Area() < maxi_tri_area){ // printf("%f\n",ct->triangles[j].Area()); // if(ct->triangles[j].Area() > 28000.0) poly_count++; if(ValidRegion(&ct->triangles[j])){//coordinates should be positive Rectangle<2> rect_box(false); // if(type == "Berlin"){ // rect_box = GetMaxRect(&ct->triangles[j]); // }else if(type == "Houston"){ // if(ct->triangles[j].Area() > 0.9 * maxi_tri_area){ // rect_box = GetMaxRect(&ct->triangles[j]); // }else{ // rect_box = GetMaxRect2(&ct->triangles[j]); // } // }else { // assert(false); // } if(ct->triangles[j].Area() > area_para * maxi_tri_area){ rect_box = GetMaxRect(&ct->triangles[j]); }else{ rect_box = GetMaxRect2(&ct->triangles[j]); } // cout< mini_rect_area && rect_box.Area() < maxi_rect_area && (max / min < 5.0)){ if(RegContainRect(poly, rect_box)) rect_box_list.push_back(rect_box); } } }else{ Rectangle<2> bbox = ct->triangles[j].BoundingBox(); double minx = bbox.MinD(0); double miny = bbox.MinD(1); double tran_x = fabs(minx) + 1.0; double tran_y = fabs(miny) + 1.0; Region* r = new Region(0); ct->triangles[j].Translate(tran_x, tran_y, *r); assert(ValidRegion(r)); Rectangle<2> rect_box(false); // if(type == "Berlin"){ // rect_box = GetMaxRect(r); // }else if(type == "Houston"){ // if(r->Area() > 0.9 * maxi_tri_area){ // rect_box = GetMaxRect(r); // }else{ // rect_box = GetMaxRect2(r); // } // }else{ // assert(false); // // } if(r->Area() > area_para * maxi_tri_area){ rect_box = GetMaxRect(r); }else{ rect_box = GetMaxRect2(r); } if(rect_box.IsDefined()){ double x = fabs(rect_box.MaxD(0) - rect_box.MinD(0)); double y = fabs(rect_box.MaxD(1) - rect_box.MinD(1)); double min = MIN(x,y); double max = MAX(x,y); if(rect_box.Area() > mini_rect_area && rect_box.Area() < maxi_rect_area && (max / min < 5.0)){ double mini[2], maxi[2]; mini[0] = rect_box.MinD(0) - tran_x; mini[1] = rect_box.MinD(1) - tran_y; maxi[0] = rect_box.MaxD(0) - tran_x; maxi[1] = rect_box.MaxD(1) - tran_y; Rectangle<2>* res_box = new Rectangle<2>(true, mini, maxi); if(RegContainRect(poly, rect_box)) rect_box_list.push_back(*res_box); delete res_box; } } delete r; } } } delete ct; poly_tuple->DeleteIfAllowed(); //////////the distance between two buildings should be large//////// for(unsigned int k1 = 0;k1 < rect_box_list.size();k1++){ Rectangle<2> bbox1 = rect_box_list[k1]; unsigned int k2 = k1; for(k2 += 1;k2 < rect_box_list.size();k2++){ Rectangle<2> bbox2 = rect_box_list[k2]; if(bbox1.Distance(bbox2) < mini_dist_build) break; } if(k2 == rect_box_list.size()){ /* reg_id_list.push_back(reg_id); rect_list.push_back(bbox1); poly_id_list.push_back(poly_id); reg_id++;*/ // if(bbox1.Area() < 4000.0 || bbox1.Area() > 8500.0){ if(bbox1.Area() < 4000.0){/////we do not have the airport now. 2011.8 reg_id_list.push_back(reg_id); rect_list.push_back(bbox1); poly_id_list.push_back(poly_id); reg_id++; }else{//set this value considering airport /////////decompose the large rectangle to have more //////////// /////////keep large region for airport /////////////////// float w = bbox1.MaxD(0) - bbox1.MinD(0); float h = bbox1.MaxD(1) - bbox1.MinD(1); int row = w/length_limit; int col = h/length_limit; double x_min = bbox1.MinD(0); // double x_max = bbox1.MaxD(0); double y_min = bbox1.MinD(1); // double y_max = bbox1.MaxD(1); ///////35 x 30 /////////////////// double x = 35.0; double y = 30.0; // cout<<"row "< temp_box(true, min, max); if(bbox1.Contains(temp_box)){ reg_id_list.push_back(reg_id); rect_list.push_back(temp_box); poly_id_list.push_back(poly_id); reg_id++; } } }/////end for }///end else } } } } } /* check whether all coordinates are positive. because for the function GetMaxRect(), all coordinates should be positive */ bool MaxRect::ValidRegion(Region* r) { for(int i = 0;i < r->Size();i++){ HalfSegment hs; r->Get(i, hs); if(!hs.IsLeftDomPoint())continue; Point lp = hs.GetLeftPoint(); Point rp = hs.GetRightPoint(); if(lp.GetX() < 0.0)return false; if(lp.GetY() < 0.0)return false; if(rp.GetX() < 0.0)return false; if(rp.GetY() < 0.0)return false; } return true; } /* for each start point, choose the one that is the closest to the polygon boundary record which side it belongs to */ void MaxRect::SetStartAndEndPoint(Region* r, vector& build_sp_list, vector& build_ep_list) { SpacePartition* s_p = new SpacePartition(); for(unsigned int i = 0;i < build_sp_list.size();i++){ vector point_dist_list; for(int j = 0;j < r->Size();j++){ HalfSegment hs; r->Get(j, hs); if(!hs.IsLeftDomPoint())continue; double d; Point cp(true, 0, 0); d = s_p->GetClosestPoint(hs, build_sp_list[i], cp); MyPoint mpe(cp, d); point_dist_list.push_back(mpe); } sort(point_dist_list.begin(), point_dist_list.end()); // for(unsigned int k = 0;k < point_dist_list.size();k++) // point_dist_list[k].Print(); build_ep_list.push_back(point_dist_list[0].loc); } delete s_p; } ///////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// /* load the pointers to all types of buildings */ void MaxRect::OpenBuilding() { for(unsigned int i = 0;i < ARR_SIZE(str_build_type);i++){ if(i == 0){ build_pointer.push_back(NULL); continue; } bool found = false; ListExpr xObjectList = SecondoSystem::GetCatalog()->ListObjects(); xObjectList = nl->Rest(xObjectList); while(!nl->IsEmpty(xObjectList)){ // Next element in list ListExpr xCurrent = nl->First(xObjectList); xObjectList = nl->Rest(xObjectList); // Type of object is at fourth position in list ListExpr xObjectType = nl->First(nl->Fourth(xCurrent)); if(nl->IsAtom(xObjectType) && nl->SymbolValue(xObjectType) == "building"){ // Get name of the graph ListExpr xObjectName = nl->Second(xCurrent); string strObjectName = nl->SymbolValue(xObjectName); // Load object to find out the id Word xValue; bool bDefined; bool bOk = SecondoSystem::GetCatalog()->GetObject(strObjectName, xValue, bDefined); if(!bDefined || !bOk){ // Undefined continue; } Building* building = (Building*)xValue.addr; if(building->GetType() == i){ build_pointer.push_back(building); found = true; break; }else{ SecondoSystem::GetCatalog()->CloseObject(nl->SymbolAtom( "building" ), xValue); } } } if(found == false) build_pointer.push_back(NULL); } } void MaxRect::CloseBuilding() { for(unsigned int i = 0;i < ARR_SIZE(str_build_type);i++){ if(build_pointer[i] != NULL){ Word xValue; xValue.addr = build_pointer[i]; SecondoSystem::GetCatalog()->CloseObject(nl->SymbolAtom( "building" ), xValue); } } } /* for each building, it opens and closes the indoor graph */ void MaxRect::OpenIndoorGraph() { for(unsigned int i = 0;i < build_pointer.size();i++){ if(build_pointer[i] == NULL){ igraph_pointer.push_back(NULL); continue; } igraph_pointer.push_back(build_pointer[i]->OpenIndoorGraph()); } } /* read indoor paths of each building from disk files */ void MaxRect::LoadIndoorPaths(vector< map >& paths, vector< map >& rooms) { for(unsigned int i = 0;i < build_pointer.size();i++){ if(build_pointer[i] != NULL){ // cout<GetType()]< path_list; map room_id_list; build_pointer[i]->LoadPaths(path_list, room_id_list); paths.push_back(path_list); rooms.push_back(room_id_list);//store groom id for each point3d }else{ map path_list; map room_id_list; paths.push_back(path_list); rooms.push_back(room_id_list);//store groom id for each point3d } } } void MaxRect::CloseIndoorGraph() { for(unsigned int i = 0;i < igraph_pointer.size();i++){ if(igraph_pointer[i] == NULL){ continue; } build_pointer[i]->CloseIndoorGraph(igraph_pointer[i]); } } /* build the path between the entrance of the building and pavement area which point to select on the polygon boundary: which point to set as the entrance of the building on the rectangle create the path from building entrance to pavement area */ void MaxRect::PathToBuilding(Space* gl_sp) { // cout<<"build the connection between the entrance of building and pavement" // <LoadPavement(IF_REGION); DualGraph* dg = pave->GetDualGraph(); ////////////////load all buildings and indoor graphs//////////////////////// OpenBuilding(); OpenIndoorGraph(); // for(unsigned int i = 0;i < build_pointer.size();i++){ // if(build_pointer[i] != NULL)cout<GetNoTuples();i++){ Tuple* poly_tuple = rel2->GetTuple(i, false); int poly_id = ((CcInt*)poly_tuple->GetAttribute(REGID))->GetIntval(); CcInt* search_id = new CcInt(true, poly_id); BTreeIterator* btree_iter = btree->ExactMatch(search_id); vector rect_tid_list; while(btree_iter->Next()){ Tuple* tuple = rel1->GetTuple(btree_iter->GetId(), false); int poly_id2 = ((CcInt*)tuple->GetAttribute(POLY_ID_EXT))->GetIntval(); assert(poly_id == poly_id2); rect_tid_list.push_back(btree_iter->GetId()); tuple->DeleteIfAllowed(); } delete btree_iter; delete search_id; if(rect_tid_list.size() > 0){ Region* poly = (Region*)poly_tuple->GetAttribute(COVAREA); CreateEntranceforBuilding(poly, rect_tid_list, dg); } poly_tuple->DeleteIfAllowed(); } pave->CloseDualGraph(dg); gl_sp->ClosePavement(pave); /////////////close all buildings and indoor graphs////////////////////// CloseIndoorGraph(); CloseBuilding(); } ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// /* create the path in the polygon for the building entrance where the entrances of a building is selected from the indoor floor plan */ void MaxRect::CreateEntranceforBuilding(Region* r, vector& tid_list, DualGraph* dg) { HalfSegment hs; r->Get(0, hs); Point boundary_p = hs.GetLeftPoint(); vector > hole_list; for(unsigned int i = 0;i < tid_list.size();i++){ Tuple* rect_tuple = rel1->GetTuple(tid_list[i], false); Rectangle<2>* rect = (Rectangle<2>*)rect_tuple->GetAttribute(GEODATA_EXT); hole_list.push_back(*rect); rect_tuple->DeleteIfAllowed(); } ////////////////create a region using these rectangels as holes///////////// for(unsigned int i = 0;i < tid_list.size();i++){ Tuple* rect_tuple = rel1->GetTuple(tid_list[i], false); int reg_id = ((CcInt*)rect_tuple->GetAttribute(REG_ID_EXT))->GetIntval(); Rectangle<2>* rect = (Rectangle<2>*)rect_tuple->GetAttribute(GEODATA_EXT); int build_type = ((CcInt*)rect_tuple->GetAttribute(BUILDING_TYPE))->GetIntval(); if(build_type == 0 || (build_type > 1 && build_pointer[build_type] == NULL)){ rect_tuple->DeleteIfAllowed(); continue; } vector build_sp_list; vector build_ep_list; if(build_type > 1){ BuildingEntrance(build_type, rect, build_sp_list); SetStartAndEndPoint(r, build_sp_list, build_ep_list); }else{/////////////entrance for personal apartment BuildingEntranceHouse(rect, build_sp_list, build_ep_list, r); } for(unsigned int j = 0;j < build_sp_list.size();j++){ Point sp = build_sp_list[j]; Point ep = build_ep_list[j]; reg_id_list.push_back(reg_id); sp_list.push_back(sp); // ep_list.push_back(ep); // MapToPavement(dg, ep); /////build the path from building entrance to pavement area////// Path_BuildingPave(sp, ep, rect, r, dg); /////////////which entrance it is////////////////////////// sp_index_list.push_back(j + 1); } rect_tuple->DeleteIfAllowed(); } } /* set the building entrance point according to the floor plan */ void MaxRect::BuildingEntrance(int build_type, Rectangle<2>* rect, vector& build_sp_list) { double min[2]={0,0}; double max[2]={1,1}; Rectangle<2> build_area(true, min, max); vector door_list; ///////////////get the floor plan for 2D areas and entrance point////////// Get2DAreadAndDoor(build_type, build_area, door_list); double length = build_area.MaxD(0) - build_area.MinD(0); double width = build_area.MaxD(1) - build_area.MinD(1); double length_new = rect->MaxD(0) - rect->MinD(0); double width_new = rect->MaxD(1) - rect->MinD(1); const double delta = 0.001; for(unsigned int i = 0;i < door_list.size();i++){ double scale_x = (door_list[i].GetX() - build_area.MinD(0))/length; double scale_y = (door_list[i].GetY() - build_area.MinD(1))/width; double new_x; if(fabs(scale_x) < delta){ new_x = rect->MinD(0); }else{ new_x = rect->MinD(0) + scale_x*length_new; } double new_y; if(fabs(scale_y) < delta){ new_y = rect->MinD(1); }else{ new_y = rect->MinD(1) + scale_y* width_new; } Point new_door(true, new_x, new_y); build_sp_list.push_back(new_door); } } /* set the building entrance point for personal apartments */ void MaxRect::BuildingEntranceHouse(Rectangle<2>* rect, vector& build_sp_list, vector& build_ep_list, Region* r) { double min_x = rect->MinD(0); double max_x = rect->MaxD(0); double min_y = rect->MinD(1); double max_y = rect->MaxD(1); Point p1(true, (min_x + max_x)/2, min_y); Point p2(true, (min_x + max_x)/2, max_y); Point p3(true, min_x, (min_y + max_y)/2); Point p4(true, max_x, (min_y + max_y)/2); build_sp_list.push_back(p1); build_sp_list.push_back(p2); build_sp_list.push_back(p3); build_sp_list.push_back(p4); SpacePartition* s_p = new SpacePartition(); vector point_dist_list; for(unsigned int i = 0;i < build_sp_list.size();i++){ for(int j = 0;j < r->Size();j++){ HalfSegment hs; r->Get(j, hs); if(!hs.IsLeftDomPoint())continue; double d; Point cp(true, 0, 0); d = s_p->GetClosestPoint(hs, build_sp_list[i], cp); MyPoint_Ext mpe(build_sp_list[i], cp, d, 0.0); point_dist_list.push_back(mpe); } } delete s_p; sort(point_dist_list.begin(), point_dist_list.end()); build_sp_list.clear(); build_ep_list.clear(); build_sp_list.push_back(point_dist_list[0].loc); build_ep_list.push_back(point_dist_list[0].loc2); } /* get the 2d area for a building and the location of entrance door from the floor plan(indoor graph) */ void MaxRect::Get2DAreadAndDoor(int build_type, Rectangle<2>& build_area, vector& door_list) { Building* build = build_pointer[build_type]; IndoorGraph* ig = igraph_pointer[build_type]; if(build == NULL || ig == NULL){ cout<<"such a building or indoor graph are not loaded"<* rtree = build->GetRTree(); Rectangle<3> bbox = rtree->BoundingBox(); double min[2], max[2]; min[0] = bbox.MinD(0); min[1] = bbox.MinD(1); max[0] = bbox.MaxD(0); max[1] = bbox.MaxD(1); build_area.Set(true, min, max); // cout<<"2D building area "<GetGraphType())<GetEntranceDoor(door_list); // cout<<"number of entrance "<rtree_node->RootRecordId(); vector tri_oid_list; const double dist = 5.0; dg->DFTraverse3(dg->rtree_node, root_id, loc, tri_oid_list, dist); if(tri_oid_list.size() == 0){ cout<node_rel_sort->GetTuple(tri_oid_list[i], false); Region* reg = (Region*)tuple->GetAttribute(DualGraph::PAVEMENT); // int oid = ((CcInt*)tuple->GetAttribute(DualGraph::OID))->GetIntval(); double d2 = reg->Distance(loc); // cout<<"oid "<DeleteIfAllowed(); } Tuple* tuple = dg->node_rel_sort->GetTuple(tri_oid_list[index], false); Region* reg = (Region*)tuple->GetAttribute(DualGraph::PAVEMENT); vector point_dist_list; SpacePartition* s_p = new SpacePartition(); for(int i = 0;i < reg->Size();i++){ HalfSegment hs; reg->Get(i, hs); if(!hs.IsLeftDomPoint())continue; double d1; Point cp(true, 0, 0); d1 = s_p->GetClosestPoint(hs, loc, cp); MyPoint mpe(cp, d1); point_dist_list.push_back(mpe); } delete s_p; sort(point_dist_list.begin(), point_dist_list.end()); Point map_loc = point_dist_list[0].loc; ep_list2.push_back(map_loc); int tri_oid = ((CcInt*)tuple->GetAttribute(DualGraph::OID))->GetIntval(); // cout<<"tri_oid "< bbox = reg->BoundingBox(); tuple->DeleteIfAllowed(); // if(map_loc.Distance(loc) > 1.0) cout<* rect, Region* r, DualGraph* dg) { ////////////////////////////////////////////////////////////////////////// //////////get the rectangle boundary line excluding the segment////////// ////////////containing the start point/////////////////////////////////// ///////////////////////////////////////////////////////////////////////// Region* temp_reg = new Region(*rect); Line* boundary_temp = new Line(0); temp_reg->Boundary(boundary_temp); Line* boundary = new Line(0); boundary->StartBulkLoad(); int edgeno = 0; for(int i = 0;i < boundary_temp->Size();i++){ HalfSegment hs; boundary_temp->Get(i, hs); if(!hs.IsLeftDomPoint() || hs.Contains(sp)) continue; HalfSegment new_hs(true, hs.GetLeftPoint(), hs.GetRightPoint()); new_hs.attr.edgeno = edgeno++; *boundary += new_hs; // new_hs.SetLeftDomPoint(!hs.IsLeftDomPoint()); new_hs.SetLeftDomPoint(!new_hs.IsLeftDomPoint()); *boundary += new_hs; } boundary->EndBulkLoad(); ////////////////////////////////////////////////////////////// //////////////direction connection between sp and ep///////// ///////////////////////////////////////////////////////////// Line* path = new Line(0); if(AlmostEqual(sp, ep)){ path_list.push_back(*path); ep_list.push_back(ep); MapToPavement(dg, ep); }else{ path->StartBulkLoad(); HalfSegment hs(true, sp, ep); hs.attr.edgeno = 0; *path += hs; hs.SetLeftDomPoint(!hs.IsLeftDomPoint()); *path += hs; path->EndBulkLoad(); assert(path->Length() > 0.0); Points* ps = new Points(0); path->Crossings(*boundary, *ps); // cout<Size()<Size() == 0){ path_list.push_back(*path); ep_list.push_back(ep); MapToPavement(dg, ep); } else if(ps->Size() == 1){////////a new end point ////////////////////////////////////////////////////////////////// ////////////select one of the closest vertex to sp//////////////// /////////plus the path from sp to the closet point on pavement/// //////////////////////////////////////////////////////////////// Point p1(true, rect->MinD(0), rect->MinD(1)); Point p2(true, rect->MaxD(0), rect->MinD(1)); Point p3(true, rect->MaxD(0), rect->MaxD(1)); Point p4(true, rect->MinD(0), rect->MaxD(1)); vector p_list; p_list.push_back(p1); p_list.push_back(p2); p_list.push_back(p3); p_list.push_back(p4); vector mp_list; SpacePartition* s_p = new SpacePartition(); for(unsigned int i = 0;i < p_list.size();i++){ for(int j = 0;j < r->Size();j++){ HalfSegment temp_hs; r->Get(j, temp_hs); if(!temp_hs.IsLeftDomPoint())continue; double d; Point cp(true, 0, 0); d = s_p->GetClosestPoint(temp_hs, p_list[i], cp); MyPoint_Ext mpe(p_list[i], cp, d, 0.0); mp_list.push_back(mpe); } } delete s_p; sort(mp_list.begin(), mp_list.end()); Point cp_border = mp_list[0].loc; Point new_ep = mp_list[0].loc2; ////////////////////////////////////////////////////////////////// ///////////////new path has two parts: sp to cpborder,/////////// //////////////// cpborder to ep ///////////////////////////////// ///////////////////////////////////////////////////////////////// Line* path2 = new Line(0); path2->StartBulkLoad(); int edgeno = 0; if(!AlmostEqual(cp_border, new_ep)){ HalfSegment hs(true, cp_border, new_ep); hs.attr.edgeno = edgeno++; *path2 += hs; hs.SetLeftDomPoint(!hs.IsLeftDomPoint()); *path2 += hs; } PathOnBorder(boundary_temp, sp, cp_border, path2, edgeno); path2->EndBulkLoad(); path_list.push_back(*path2); path2->DeleteIfAllowed(); ep_list.push_back(new_ep); MapToPavement(dg, new_ep); }else assert(false); ps->DeleteIfAllowed(); } /////////////////////////////////////////////////////////////// boundary_temp->DeleteIfAllowed(); temp_reg->DeleteIfAllowed(); path->DeleteIfAllowed(); boundary->DeleteIfAllowed(); } /* calculate the shortest path between two points on a line. the line is a cycle so there are two options */ void MaxRect::PathOnBorder(Line* boundary_temp, Point sp, Point cp_border, Line* path2, int& edgeno) { SpacePartition* s_p = new SpacePartition(); //////////////////find the closest point to sp along the line/////////////// if(sp.Inside(*boundary_temp) == false){ vector mp_list; for(int j = 0;j < boundary_temp->Size();j++){ HalfSegment temp_hs; boundary_temp->Get(j, temp_hs); if(!temp_hs.IsLeftDomPoint())continue; double d; Point cp(true, 0, 0); d = s_p->GetClosestPoint(temp_hs, sp, cp); MyPoint mpe(cp, d); mp_list.push_back(mpe); } sort(mp_list.begin(), mp_list.end()); Point sp_map = mp_list[0].loc; HalfSegment hs(true, sp, sp_map); hs.attr.edgeno = edgeno++; *path2 += hs; hs.SetLeftDomPoint(!hs.IsLeftDomPoint()); *path2 += hs; sp = sp_map; } /////////////////////////////////////////////////////////////////////// ////////////////connect sp and cp border along the line/////////////// ///////////////as the boundary is a cycle, there are two paths/////// /////////////// select the shorter one /////////////////////// ////////////////////////////////////////////////////////////////////// SimpleLine* sline = new SimpleLine(0); sline->fromLine(*boundary_temp); vector seq_halfseg; s_p->ReorderLine(sline, seq_halfseg); sline->DeleteIfAllowed(); int index1 = -1; for(unsigned int i = 0;i < seq_halfseg.size();i++){ HalfSegment hs(true, seq_halfseg[i].from, seq_halfseg[i].to); if(hs.Contains(sp)){ index1 = i; break; } } int index2 = -1; for(unsigned int i = 0;i < seq_halfseg.size();i++){ HalfSegment hs(true, seq_halfseg[i].from, seq_halfseg[i].to); if(hs.Contains(cp_border)){ index2 = i; break; } } assert(0 <= index1 && index1 < (int)seq_halfseg.size()); assert(0 <= index2 && index2 < (int)seq_halfseg.size()); // cout<<"index1 "<StartBulkLoad(); int no = 0; if(index1 < index2 ){ for(int i = index1;i <= index2;i++){ Point p1, p2; if(i == index1){ p1 = sp; p2 = seq_halfseg[i].to; }else if(i == index2){ p1 = seq_halfseg[i].from; p2 = cp_border; }else{ p1 = seq_halfseg[i].from; p2 = seq_halfseg[i].to; } if(!AlmostEqual(p1,p2)){ HalfSegment hs(true, p1, p2); hs.attr.edgeno = no++; *temp += hs; hs.SetLeftDomPoint(!hs.IsLeftDomPoint()); *temp += hs; } } }else{ for(int i = index2;i <= index1;i++){ Point p1, p2; if(i == index2){ p1 = cp_border; p2 = seq_halfseg[i].to; }else if(i == index1){ p1 = seq_halfseg[i].from; p2 = sp; }else{ p1 = seq_halfseg[i].from; p2 = seq_halfseg[i].to; } if(!AlmostEqual(p1,p2)){ HalfSegment hs(true, p1, p2); hs.attr.edgeno = no++; *temp += hs; hs.SetLeftDomPoint(!hs.IsLeftDomPoint()); *temp += hs; } } } temp->EndBulkLoad(); /////////////////////////////////////////////////////////////////// double l1 = temp->Length(); double l2 = boundary_temp->Length() - l1; // cout<<"l1 "<Size();i++){ HalfSegment hs1; temp->Get(i, hs1); if(!hs1.IsLeftDomPoint())continue; HalfSegment hs2(true, hs1.GetLeftPoint(), hs1.GetRightPoint()); hs2.attr.edgeno = edgeno++; *path2 += hs2; hs2.SetLeftDomPoint(!hs2.IsLeftDomPoint()); *path2 += hs2; } }else{///////////////select the other one, use bounday minus temp Line* res = new Line(0); boundary_temp->Minus(*temp, *res); for(int i = 0;i < res->Size();i++){ HalfSegment hs1; res->Get(i, hs1); if(!hs1.IsLeftDomPoint())continue; HalfSegment hs2(true, hs1.GetLeftPoint(), hs1.GetRightPoint()); hs2.attr.edgeno = edgeno++; *path2 += hs2; hs2.SetLeftDomPoint(!hs2.IsLeftDomPoint()); *path2 += hs2; } res->DeleteIfAllowed(); } temp->DeleteIfAllowed(); } delete s_p; } /* create a new region where r is outer cycle and the rectangles inside are holes 1. we have all points of all cycle so that we can call the function buildRegion(). but very important: for each cycle, the first and the last point should be the same. 2. we can directly use the outer region minus these rectangles which is much simpler */ bool MaxRect::RegionWithHole(vector >& hole_list, Region* reg) { /* for(unsigned int i = 0;i < hole_list.size();i++){ Region* temp = new Region(hole_list[i]); // cout<<*temp<Minus(*temp, *res); *reg = *res; delete res; delete temp; }*/ ////////////////////////////////////////////////////////////////////////// Region* r = new Region(0); for(unsigned int i = 0;i < hole_list.size();i++){ Region* temp = new Region(hole_list[i]); Region* res = new Region(0); temp->Union(*r, *res); *r = *res; res->DeleteIfAllowed(); temp->DeleteIfAllowed(); } Region* res = new Region(0); reg->Minus(*r, *res); *reg = *res; res->DeleteIfAllowed(); r->DeleteIfAllowed(); return true; } /* for each rectangle, it sets which kind of building it is, e.g., office or cinema 1 airport, 1-2 trainstations, 8 cinemas, 32 hotels, 48 shopping malls, 20 hospitals, 32 schooles, 4 libraries, 16 universities, 200 office 24, houses and apartments: 1000 the left are of type none */ void MaxRect::SetBuildingType(R_Tree<2,TupleId>* rtree, Space* gl_sp) { Rectangle<2> bbox = rtree->BoundingBox(); Point center(true, (bbox.MinD(0) + bbox.MaxD(0))/2, (bbox.MinD(1) + bbox.MaxD(1))/2); vector build_rect_list; for(int i = 1;i <= rel1->GetNoTuples();i++){ Tuple* tuple = rel1->GetTuple(i, false); int reg_id = ((CcInt*)tuple->GetAttribute(REG_ID))->GetIntval(); Rectangle<2>* rect = (Rectangle<2>*)tuple->GetAttribute(GEODATA); int poly_id = ((CcInt*)tuple->GetAttribute(POLY_ID))->GetIntval(); int reg_type = ((CcInt*)tuple->GetAttribute(REG_TYPE))->GetIntval(); Build_Rect br(reg_id, *rect, poly_id, reg_type); Point p(true, (rect->MinD(0) + rect->MaxD(0))/2, (rect->MinD(1) + rect->MaxD(1))/2); if(p.GetX() > center.GetX()){ if(p.GetY() > center.GetY()) br.quadrant = 1; else br.quadrant = 4; }else{ if(p.GetY() > center.GetY()) br.quadrant = 2; else br.quadrant = 3; } build_rect_list.push_back(br); tuple->DeleteIfAllowed(); } // cout<MaxRefId() + 1; /////////////////////////////////////////////////////////////// ///////////////max int 21474 83647////////////////////////////// /////////////max int64_t 9223372036854775807/////////////////// //////////////////////////////////////////////////////////////// // cout<<"max int "<::max()<::max()< 0){ build_no++; } } int max_id = min_id + build_no; char buf1[64], buf2[64]; sprintf(buf1, "%d", min_id); sprintf(buf2, "%d", max_id); // cout<<"min_id "<::max()); assert(false);///////// can be deleted the above code should be correct } ////////////////////////////////////////////////////////////////// for(unsigned int i = 0;i < build_rect_list.size();i++){ if(build_rect_list[i].build_type > 0){ reg_id_list.push_back(build_rect_list[i].reg_id); rect_list.push_back(build_rect_list[i].rect); poly_id_list.push_back(build_rect_list[i].poly_id); reg_type_list.push_back(build_rect_list[i].reg_type); build_type_list.push_back(build_rect_list[i].build_type); build_type2_list.push_back(GetBuildingStr(build_rect_list[i].build_type)); build_id_list.push_back(cur_max_ref_id); cur_max_ref_id++; } } if(cur_max_ref_id > numeric_limits::max() - 1){ cout<<"!!!! building id number overflow !!!"<& list, R_Tree<2,TupleId>* rtree) { sort(list.begin(), list.end(), Build_Rect_COM1); /* for(unsigned int i = 0;i < list.size();i++) list[i].Print();*/ for(int i = list.size() - 1;i >= 0;i--){ if(list[i].rect.Area() > AIRPORT_AREA && list[i].reg_type == 3 && list[i].init == false && NoNeighbor(list[i], rtree)){ // cout<<"find an airport site"<* rtree) { vector tid_list; DFTraverse1(rtree, rtree->RootRecordId(), br.rect, tid_list); // cout<<"reg id "<* rtree, SmiRecordId adr, Rectangle<2>& rect, vector& tri_oid_list) { const double dist = 1000.0; 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 = rel1->GetTuple(e.info, false); Rectangle<2>* reg = (Rectangle<2>*)dg_tuple->GetAttribute(GEODATA); int reg_id = ((CcInt*)dg_tuple->GetAttribute(REG_ID))->GetIntval(); double d = rect.Distance(*reg); if(d > 0.0 && d < dist){ tri_oid_list.push_back(reg_id); } dg_tuple->DeleteIfAllowed(); }else{ R_TreeInternalEntry<2> e = (R_TreeInternalEntry<2>&)(*node)[j]; if(rect.Distance(e.box) < dist){ DFTraverse1(rtree, e.pointer, rect, tri_oid_list); } } } delete node; } /* set the train station */ #define TRAINSTATION_AREA_MIN 800.0 #define TRAINSTATION_AREA_MAX 2000.0 void MaxRect::SetTrainStation(vector& list) { sort(list.begin(), list.end(), Build_Rect_COM1); /* for(unsigned int i = 0;i < list.size();i++) list[i].Print();*/ for(int i = list.size() - 1;i >= 0;i--){ if(list[i].rect.Area() > TRAINSTATION_AREA_MIN && list[i].rect.Area() < TRAINSTATION_AREA_MAX && list[i].reg_type == 1 && list[i].init == false){ // cout<<"find a train station site"<& list, unsigned int no, Rectangle<2> bbox) { vector cand_list; vector quad_list; quad_list.push_back(0); quad_list.push_back(0); quad_list.push_back(0); quad_list.push_back(0); for(int i = list.size() - 1;i >= 0;i--){ if(list[i].rect.Area() > CINEMA_AREA_MIN && list[i].rect.Area() < CINEMA_AREA_MAX && (list[i].reg_type == 1 || list[i].reg_type == 2) && list[i].init == false && NoNeighborCinema(cand_list, list[i], bbox)){ // cout<<"find a cinema site"<& list, Build_Rect br, Rectangle<2> bbox) { const double min_dist = 5000.0; // Point p1(true, bbox.MinD(0), bbox.MinD(1)); // Point p2(true, bbox.MaxD(0), bbox.MaxD(1)); // // const double min_dist = p1.Distance(p2)/4; if(list.size() == 0)return true; for(unsigned int i = 0;i < list.size();i++) if(list[i].rect.Distance(br.rect) < min_dist) return false; return true; } /* set the places for hotels, uniformly distributed in each quadrant */ #define HOTEL_AREA_MIN 800.0 #define HOTEL_AREA_MAX 1600.0 void MaxRect::SetHotel(vector& list, unsigned int no, Rectangle<2> bbox) { vector quad_list; quad_list.push_back(0); quad_list.push_back(0); quad_list.push_back(0); quad_list.push_back(0); vector cand_list; for(int i = list.size() - 1;i >= 0;i--){ if(list[i].rect.Area() > HOTEL_AREA_MIN && list[i].rect.Area() < HOTEL_AREA_MAX && list[i].init == false && NoNeighborHotel(cand_list, list[i], bbox)){ // cout<<"find a hotel site"<& list, Build_Rect br, Rectangle<2> bbox) { const double min_dist = 3000.0; // Point p1(true, bbox.MinD(0), bbox.MinD(1)); // Point p2(true, bbox.MaxD(0), bbox.MaxD(1)); // // const double min_dist = p1.Distance(p2)/8; if(list.size() == 0)return true; for(unsigned int i = 0;i < list.size();i++) if(list[i].rect.Distance(br.rect) < min_dist) return false; return true; } /* set the places for shopping malls, uniformly distributed in each quadrant */ #define SHOPMALL_AREA_MIN 1000.0 #define SHOPMALL_AREA_MAX 2000.0 void MaxRect::SetShopMall(vector& list, unsigned int no, Rectangle<2> bbox) { vector quad_list; quad_list.push_back(0); quad_list.push_back(0); quad_list.push_back(0); quad_list.push_back(0); vector cand_list; for(int i = list.size() - 1;i >= 0;i--){ if(list[i].rect.Area() > SHOPMALL_AREA_MIN && list[i].rect.Area() < SHOPMALL_AREA_MAX && list[i].init == false && NoNeighborShopMall(cand_list, list[i], bbox)){ // cout<<"find a hotel site"<& list, Build_Rect br, Rectangle<2> bbox) { const double min_dist = 1500.0; // Point p1(true, bbox.MinD(0), bbox.MinD(1)); // Point p2(true, bbox.MaxD(0), bbox.MaxD(1)); // // const double min_dist = p1.Distance(p2)/8; if(list.size() == 0)return true; for(unsigned int i = 0;i < list.size();i++) if(list[i].rect.Distance(br.rect) < min_dist) return false; return true; } /* set the places for office24, uniformly distributed in each quadrant */ #define OFFICE24_AREA_MIN 600.0 #define OFFICE24_AREA_MAX 2500.0 void MaxRect::SetOffice24(vector& list, unsigned int no) { vector quad_list; quad_list.push_back(0); quad_list.push_back(0); quad_list.push_back(0); quad_list.push_back(0); vector cand_list; vector reg_type_list; reg_type_list.push_back(0); reg_type_list.push_back(0); reg_type_list.push_back(0); for(int i = list.size() - 1;i >= 0;i--){ if(list[i].rect.Area() > OFFICE24_AREA_MIN && list[i].rect.Area() < OFFICE24_AREA_MAX && list[i].init == false){ // cout<<"find a office24 site"<& list, unsigned int no) { vector quad_list; quad_list.push_back(0); quad_list.push_back(0); quad_list.push_back(0); quad_list.push_back(0); vector cand_list; vector reg_type_list; reg_type_list.push_back(0); reg_type_list.push_back(0); reg_type_list.push_back(0); for(int i = list.size() - 1;i >= 0;i--){ if(list[i].rect.Area() > OFFICE38_AREA_MIN && list[i].rect.Area() < OFFICE38_AREA_MAX && list[i].init == false){ // cout<<"find a office38 site"<& list, unsigned int no) { vector quad_list; quad_list.push_back(0); quad_list.push_back(0); quad_list.push_back(0); quad_list.push_back(0); vector cand_list; for(int i = list.size() - 1;i >= 0;i--){ if(list[i].rect.Area() > HOSPITAL_AREA_MIN && list[i].rect.Area() < HOSPITAL_AREA_MAX && list[i].init == false && NoNeighborHospital(cand_list, list[i]) && NoNearbyShopMallAndCinema(list, list[i])){ // cout<<"find a hotel site"<& list, Build_Rect br) { const double min_dist = 2000.0; if(list.size() == 0)return true; for(unsigned int i = 0;i < list.size();i++) if(list[i].rect.Distance(br.rect) < min_dist) return false; return true; } /* a hospital should not have a shopping mall and cinema so close it is also not too close to a train station */ bool MaxRect::NoNearbyShopMallAndCinema(vector& list, Build_Rect br) { const double min_dist1 = 1000.0; const double min_dist2 = 500.0; const double min_dist3 = 300.0; if(list.size() == 0)return true; for(unsigned int i = 0;i < list.size();i++){ if((list[i].build_type == BUILD_SHOPPINGMALL || list[i].build_type == BUILD_CINEMA) && list[i].rect.Distance(br.rect) < min_dist1) return false; if(list[i].build_type == BUILD_HOTEL && list[i].rect.Distance(br.rect) < min_dist2) return false; if(list[i].build_type == BUILD_TRAINSTATION && list[i].rect.Distance(br.rect) < min_dist3) return false; } return true; } /* set the places for libraries , uniformly distributed in each quadrant */ #define LIBRARY_AREA_MIN 1000.0 #define LIBRARY_AREA_MAX 2000.0 void MaxRect::SetLibrary(vector& list, unsigned int no) { vector quad_list; quad_list.push_back(0); quad_list.push_back(0); quad_list.push_back(0); quad_list.push_back(0); vector cand_list; for(int i = list.size() - 1;i >= 0;i--){ if(list[i].rect.Area() > LIBRARY_AREA_MIN && list[i].rect.Area() < LIBRARY_AREA_MAX && list[i].reg_type == 2 && list[i].init == false && NoNeighborLibrary(cand_list, list[i]) && NoNearbyCommercialBuilding(list, list[i])){ // cout<<"find a hotel site"<& list, Build_Rect br) { const double min_dist = 3000.0; if(list.size() == 0)return true; for(unsigned int i = 0;i < list.size();i++) if(list[i].rect.Distance(br.rect) < min_dist) return false; return true; } /* a library should not so close to cinemas, hotels, shopping malls */ bool MaxRect::NoNearbyCommercialBuilding(vector& list, Build_Rect br) { const double min_dist1 = 1000.0; const double min_dist2 = 500.0; const double min_dist3 = 300.0; if(list.size() == 0) return true; for(unsigned int i = 0;i < list.size();i++){ if((list[i].build_type == BUILD_SHOPPINGMALL || list[i].build_type == BUILD_CINEMA) && list[i].rect.Distance(br.rect) < min_dist1) return false; if((list[i].build_type == BUILD_HOTEL || list[i].build_type == BUILD_HOSPITAL )&& list[i].rect.Distance(br.rect) < min_dist2) return false; if(list[i].build_type == BUILD_TRAINSTATION && list[i].rect.Distance(br.rect) < min_dist3) return false; } return true; } /* set the places for schools, uniformly distributed in each quadrant */ #define SCHOOL_AREA_MIN 2000.0 #define SCHOOL_AREA_MAX 3000.0 void MaxRect::SetSchool(vector& list, unsigned int no) { vector quad_list; quad_list.push_back(0); quad_list.push_back(0); quad_list.push_back(0); quad_list.push_back(0); vector cand_list; for(int i = list.size() - 1;i >= 0;i--){ if(list[i].rect.Area() > SCHOOL_AREA_MIN && list[i].rect.Area() < SCHOOL_AREA_MAX && (list[i].reg_type == 1 || list[i].reg_type == 2)&& list[i].init == false && NoNeighborSchool(cand_list, list[i]) && NoNearbyCommercialBuilding(list, list[i])){ // cout<<"find a school site"<& list, Build_Rect br) { const double min_dist = 600.0; if(list.size() == 0)return true; for(unsigned int i = 0;i < list.size();i++) if(list[i].rect.Distance(br.rect) < min_dist) return false; return true; } /* set the places for universities, uniformly distributed in each quadrant */ #define UNIVERSITY_AREA_MIN 2000.0 #define UNIVERSITY_AREA_MAX 5000.0 void MaxRect::SetUniversity(vector& list, unsigned int no) { vector quad_list; quad_list.push_back(0); quad_list.push_back(0); quad_list.push_back(0); quad_list.push_back(0); vector cand_list; for(int i = list.size() - 1;i >= 0;i--){ if(list[i].rect.Area() > UNIVERSITY_AREA_MIN && list[i].rect.Area() < UNIVERSITY_AREA_MAX && (list[i].reg_type == 2 || list[i].reg_type == 3)&& list[i].init == false && NoNeighborUniversity(cand_list, list[i]) && NoNearbyCommercialBuilding(list, list[i])){ // cout<<"find a hotel site"<& list, Build_Rect br) { const double min_dist = 500.0; if(list.size() == 0)return true; for(unsigned int i = 0;i < list.size();i++) if(list[i].rect.Distance(br.rect) < min_dist) return false; return true; } /* set the places for houses, uniformly distributed in each quadrant */ #define HOUSE_AREA_MAX 1500.0 void MaxRect::SetHouse(vector& list, unsigned int no) { vector quad_list; quad_list.push_back(0); quad_list.push_back(0); quad_list.push_back(0); quad_list.push_back(0); vector cand_list; for(int i = list.size() - 1;i >= 0;i--){ if( list[i].rect.Area() < HOUSE_AREA_MAX && list[i].init == false && NoNearbyNeighbors1(list, list[i])){ // if(quad_list[list[i].quadrant - 1] < no / 4){ list[i].build_type = BUILD_HOUSE; list[i].init = true; cand_list.push_back(list[i]); quad_list[list[i].quadrant - 1]++; if(cand_list.size() == no)return; // } } } } /* neighbor building limitations for personal houses and apartments */ bool MaxRect::NoNearbyNeighbors1(vector& list, Build_Rect br) { // const double min_dist1 = 800.0;/////////cinema, hotel // const double min_dist2 = 400.0;//////shopping mall // const double min_dist3 = 200.0;////////others const double min_dist1 = 500.0;/////////cinema, const double min_dist2 = 300.0;//////shopping mall, hotel const double min_dist3 = 100.0;////////others if(list.size() == 0){ return true; } for(unsigned int i = 0;i < list.size();i++){ if((list[i].build_type == BUILD_CINEMA) && list[i].rect.Distance(br.rect) < min_dist1) return false; if((list[i].build_type == BUILD_SHOPPINGMALL || list[i].build_type == BUILD_HOTEL) && list[i].rect.Distance(br.rect) < min_dist2) return false; if(( list[i].build_type == BUILD_SCHOOL || list[i].build_type == BUILD_HOSPITAL || list[i].build_type == BUILD_LIBRARY || list[i].build_type == BUILD_OFFICE24 || list[i].build_type == BUILD_UNIVERSITY || list[i].build_type == BUILD_TRAINSTATION ) && list[i].rect.Distance(br.rect) < min_dist3) return false; } return true; } /////////////////////////////////////////////////////////////////////////// ///////////////Infrastructure Region Based Outdoor Pavement//////////////// /////////////////////////////////////////////////////////////////////////// ListExpr PavementProperty() { return (nl->TwoElemList( nl->FourElemList(nl->StringAtom("Signature"), nl->StringAtom("Example Type List"), nl->StringAtom("List Rep"), nl->StringAtom("Example List")), nl->FourElemList(nl->StringAtom("-> DATA"), nl->StringAtom("pavement"), nl->StringAtom("((def, id))"), nl->StringAtom("((TRUE 1))")))); } /* output the pavement infrastructure */ ListExpr OutPavement( ListExpr typeInfo, Word value ) { // cout<<"OutPavement"<IsDefined()){ return nl->SymbolAtom("undef"); } ListExpr list1 = nl->TwoElemList( nl->StringAtom("Pavement Id:"), nl->IntAtom(pn->GetId())); ListExpr list2 = nl->TheEmptyList(); if(pn->IsDGInit()){ list2 = nl->TwoElemList( nl->StringAtom("Dual Graph Id:"), nl->IntAtom(pn->GetDGId())); }else list2 = nl->OneElemList( nl->StringAtom("Dual Graph undef")); ListExpr list3 = nl->TheEmptyList(); if(pn->IsVGInit()){ list3 = nl->TwoElemList( nl->StringAtom("Visbility Graph Id:"), nl->IntAtom(pn->GetVGId())); }else list3 = nl->OneElemList( nl->StringAtom("Visibility Graph undef")); ListExpr list4 = nl->TheEmptyList(); return nl->FourElemList(list1, list2, list3, list4); } /* In function. there is not nested list expression here. */ Word InPavement( const ListExpr typeInfo, const ListExpr instance, const int errorPos, ListExpr& errorInfo, bool& correct ) { // cout<<"length "<ListLength(instance)<IsAtom( instance ) ){ if(nl->ListLength(instance) != 2){ cout<<"length should be 2"<First(instance); ListExpr second = nl->Second(instance); if(!nl->IsAtom(first) || nl->AtomType(first) != BoolType){ cout<< "pavenetwork(): definition must be bool type"<BoolValue(first); if(!nl->IsAtom(second) || nl->AtomType(second) != IntType){ cout<< "pavenetwork(): pavement infrastructure id must be int type"<IntValue(second); Pavement* pn = new Pavement(d, id); ////////////////very important ///////////////////////////// correct = true; /////////////////////////////////////////////////////////// return SetWord(pn); } correct = false; return SetWord(Address(0)); } bool SavePavement(SmiRecord& valueRecord, size_t& offset, const ListExpr typeInfo, Word& value) { Pavement* pn = (Pavement*)value.addr; return pn->Save(valueRecord, offset, typeInfo); } bool OpenPavement(SmiRecord& valueRecord, size_t& offset, const ListExpr typeInfo, Word& value) { value.addr = Pavement::Open(valueRecord, offset, typeInfo); return value.addr != NULL; } Word CreatePavement(const ListExpr typeInfo) { // cout<<"CreatePavement()"<(w.addr); w.addr = 0; } Word ClonePavement( const ListExpr typeInfo, const Word& w ) { // cout<<"ClonePavement"<IsEqual( type, "pavenetwork" )); } Pavement::Pavement():def(false), pave_id(0), dg_init(false), dg_id(0), vg_init(false), vg_id(0), pave_rel(NULL) { } Pavement::Pavement(bool d, unsigned int i):def(d), pave_id(i), dg_init(false), dg_id(0), vg_init(false), vg_id(0), pave_rel(NULL) { } Pavement::Pavement(SmiRecord& valueRecord, size_t& offset, const ListExpr typeInfo):def(false), pave_id(0), dg_init(false), dg_id(0), vg_init(false), vg_id(0), pave_rel(NULL) { valueRecord.Read(&def, sizeof(bool), offset); offset += sizeof(bool); valueRecord.Read(&pave_id, sizeof(int), offset); offset += sizeof(int); valueRecord.Read(&dg_init, sizeof(bool), offset); offset += sizeof(bool); valueRecord.Read(&dg_id, sizeof(int), offset); offset += sizeof(int); valueRecord.Read(&vg_init, sizeof(bool), offset); offset += sizeof(bool); valueRecord.Read(&vg_id, sizeof(int), offset); offset += sizeof(int); ListExpr xType; ListExpr xNumericType; /***********************Open relation for triangles*********************/ // nl->ReadFromString(PaveTypeInfo,xType); nl->ReadFromString(DualGraph::NodeTypeInfo,xType); xNumericType = SecondoSystem::GetCatalog()->NumericType(xType); pave_rel = Relation::Open(valueRecord, offset, xNumericType); if(!pave_rel) { return; } } Pavement::~Pavement() { if(pave_rel != NULL) pave_rel->Close(); } /* create the pavement infrastructure by a relation storing all triangles */ void Pavement::Load(unsigned int i, Relation* r) { if(i < 1){ cout<<"invalid id "<ToString(ptrList) + "))))"; // cout<GetNoTuples()<ReadFromString(PaveTypeInfo, xType); nl->ReadFromString(DualGraph::NodeTypeInfo, xType); xNumericType = SecondoSystem::GetCatalog()->NumericType(xType); if(!pave_rel->Save(valueRecord,offset,xNumericType)) return false; return true; } /* open a pavement object */ Pavement* Pavement::Open(SmiRecord& valueRecord, size_t& offset, const ListExpr typeInfo) { return new Pavement(valueRecord, offset, typeInfo); } /* set the dual graph id for the pavement */ void Pavement::SetDualGraphId(int id) { dg_id = id; dg_init = true; } /* set the visual graph id for the pavement */ void Pavement::SetVisualGraphId(int id) { vg_id = id; vg_init = true; } /* load dual graph if it is stored */ DualGraph* Pavement::GetDualGraph() { if(dg_init == false) return NULL; ListExpr xObjectList = SecondoSystem::GetCatalog()->ListObjects(); xObjectList = nl->Rest(xObjectList); while(!nl->IsEmpty(xObjectList)) { // Next element in list ListExpr xCurrent = nl->First(xObjectList); xObjectList = nl->Rest(xObjectList); // Type of object is at fourth position in list ListExpr xObjectType = nl->First(nl->Fourth(xCurrent)); if(nl->IsAtom(xObjectType) && nl->SymbolValue(xObjectType) == "dualgraph"){ // Get name of the dual graph ListExpr xObjectName = nl->Second(xCurrent); string strObjectName = nl->SymbolValue(xObjectName); // Load object to find out the id of the dual graph. Word xValue; bool bDefined; bool bOk = SecondoSystem::GetCatalog()->GetObject(strObjectName, xValue, bDefined); if(!bDefined || !bOk) { // Undefined continue; } DualGraph* dg = (DualGraph*)xValue.addr; if(dg->g_id == dg_id){ // This is the dual graph we have been looking for return dg; } } } return NULL; } void Pavement::CloseDualGraph(DualGraph* dg) { if(dg == NULL) return; Word xValue; xValue.addr = dg; SecondoSystem::GetCatalog()->CloseObject(nl->SymbolAtom( "dualgraph" ), xValue); } /* load visual graph if it is stored */ VisualGraph* Pavement::GetVisualGraph() { if(vg_init == false) return NULL; ListExpr xObjectList = SecondoSystem::GetCatalog()->ListObjects(); xObjectList = nl->Rest(xObjectList); while(!nl->IsEmpty(xObjectList)) { // Next element in list ListExpr xCurrent = nl->First(xObjectList); xObjectList = nl->Rest(xObjectList); // Type of object is at fourth position in list ListExpr xObjectType = nl->First(nl->Fourth(xCurrent)); if(nl->IsAtom(xObjectType) && nl->SymbolValue(xObjectType) == "visualgraph"){ // Get name of the visual graph ListExpr xObjectName = nl->Second(xCurrent); string strObjectName = nl->SymbolValue(xObjectName); // Load object to find out the id of the visual graph. Word xValue; bool bDefined; bool bOk = SecondoSystem::GetCatalog()->GetObject(strObjectName, xValue, bDefined); if(!bDefined || !bOk) { // Undefined continue; } VisualGraph* vg = (VisualGraph*)xValue.addr; if(vg->g_id == vg_id){ // This is the dual graph we have been looking for return vg; } } } return NULL; } void Pavement::CloseVisualGraph(VisualGraph* vg) { if(vg == NULL) return; Word xValue; xValue.addr = vg; SecondoSystem::GetCatalog()->CloseObject(nl->SymbolAtom( "visualgraph" ), xValue); } Relation* Pavement::GetPaveRel() { if(IsDefined()) return pave_rel; else return NULL; } /* check the maximum distance between two lines, if the value is larger than d return false */ bool SmallerD(Line* l1, Line* l2, float d) { if(l1->IsEmpty() || l2->IsEmpty()){ cout<<"line empty"<IsOrdered() ); assert( l2->IsOrdered() ); HalfSegment hs1, hs2; for( int i = 0; i < l1->Size(); ++i ){ l1->Get( i, hs1 ); Point lp1 = hs1.GetLeftPoint(); Point rp1 = hs1.GetRightPoint(); if(hs1.IsLeftDomPoint() == false) continue; for( int j = 0; j < l2->Size(); ++j ) { l2->Get( j, hs2 ); if(hs2.IsLeftDomPoint() == false) continue; Point lp2 = hs2.GetLeftPoint(); Point rp2 = hs2.GetRightPoint(); if(lp1.Distance(lp2) > d) return false; if(lp1.Distance(rp2) > d) return false; if(rp1.Distance(lp2) > d) return false; if(rp1.Distance(rp2) > d) return false; } } return true; }