18113 lines
562 KiB
C++
18113 lines
562 KiB
C++
/*
|
|
----
|
|
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
|
|
|
|
Oct, 2010 Jianqiu Xu
|
|
|
|
[TOC]
|
|
|
|
1 Overview
|
|
|
|
This source file essentially contains the necessary implementations for
|
|
creating bus network
|
|
|
|
*/
|
|
#include "BusNetwork.h"
|
|
#include "PaveGraph.h"
|
|
|
|
using namespace std;
|
|
using namespace network;
|
|
using namespace temporalalgebra;
|
|
using namespace datetime;
|
|
|
|
|
|
string BusRoute::StreetSectionCellTypeInfo =
|
|
"(rel (tuple ((Secid int)(Cellid int) (Cnt int) (Cover_area region))))";
|
|
|
|
string BusRoute::BusRoutesTmpTypeInfo =
|
|
"(rel (tuple ((Br_id int) (Bus_route1 gline) (Bus_route2 line)\
|
|
(Start_loc point)(End_loc point) (Route_type int))))";
|
|
|
|
string BusRoute::NewBusRoutesTmpTypeInfo =
|
|
"(rel (tuple ((Br_id int) (Bus_route1 line) (Bus_route2 line) (Route_type int)\
|
|
(Br_uid int))))";
|
|
|
|
string BusRoute::FinalBusRoutesTypeInfo =
|
|
"(rel (tuple ((Br_id int) (Bus_route line) (Route_type int) (Br_uid int)\
|
|
(Bus_direction bool) (StartSmaller bool))))";
|
|
|
|
|
|
string BusRoute::BusStopTemp1TypeInfo =
|
|
"(rel (tuple ((Br_id int) (Bus_stop_id int) (Bus_stop1 gpoint)\
|
|
(Bus_stop2 point))))";
|
|
|
|
string BusRoute::BusNetworkParaInfo = "(rel (tuple ((para real))))";
|
|
|
|
|
|
/*
|
|
create route bus route
|
|
a pair of cells, start cell-end cell.
|
|
the start cell can be considered as the start location of a bus route
|
|
and the end cell is the end location of a bus route.
|
|
Then it randomly selectes two locations in these two cells
|
|
|
|
it creates three kinds of routes determined by cells
|
|
high density - low density;
|
|
middle denstiy - low density ;
|
|
low density - lowdenstiy;
|
|
|
|
Berlin and Houston have different roads distribution.
|
|
|
|
*/
|
|
void BusRoute::CreateRoute1(int attr1,int attr2,int attr3, Relation* bus_para)
|
|
{
|
|
// cout<<"attr1 "<<attr1<<" attr2 "<<attr2<<" attr3 "<<attr3<<endl;
|
|
// cout<<"CreateBusRoute()"<<endl;
|
|
|
|
int max_cell_id = -1;
|
|
int max_cnt = -1;
|
|
for(int i = 1;i <= rel1->GetNoTuples();i++){
|
|
Tuple* tuple_cell = rel1->GetTuple(i,false);
|
|
CcInt* cell_id = (CcInt*)tuple_cell->GetAttribute(attr1);
|
|
CcInt* cnt = (CcInt*)tuple_cell->GetAttribute(attr2);
|
|
|
|
// cout<<sec_id->GetIntval()<<" "
|
|
// <<cell_id->GetIntval()<<" "<<cnt->GetIntval()<<endl;
|
|
|
|
if(cell_id->GetIntval() > max_cell_id)
|
|
max_cell_id = cell_id->GetIntval();
|
|
|
|
if(cnt->GetIntval() > max_cnt)
|
|
max_cnt = cnt->GetIntval();
|
|
|
|
tuple_cell->DeleteIfAllowed();
|
|
}
|
|
|
|
// cout<<"max_cell_id "<<max_cell_id<<endl;
|
|
// cout<<"max_cnt "<<max_cnt<<endl;
|
|
|
|
/********initialize the array storing section_cell structure**************/
|
|
vector<Section_Cell> cell_list; //////////////////////array
|
|
|
|
// cell_list.resize(max_cell_id);
|
|
// for(int i = 0;i < max_cell_id;i++)
|
|
// cell_list[i].def = false; //crashes if all BuildRoute is called 3 times
|
|
|
|
for(int i = 0;i < max_cell_id;i++){
|
|
double min[2], max[2];
|
|
min[0] = 0;
|
|
min[1] = 0;
|
|
max[0] = 1;
|
|
max[1] = 1;
|
|
BBox<2>* reg = new BBox<2>(true,min,max);
|
|
Section_Cell* sc_ptr = new Section_Cell(0,0,0,false,*reg);
|
|
cell_list.push_back(*sc_ptr);
|
|
reg->DeleteIfAllowed();
|
|
delete sc_ptr;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
// float div_number1 = 0.5;
|
|
float div_number1 = 0.4;
|
|
|
|
// float div_number2 = 0.2;
|
|
float div_number2 = 0.25;
|
|
|
|
|
|
for(int i = 1;i <= rel1->GetNoTuples();i++){
|
|
Tuple* tuple_cell = rel1->GetTuple(i,false);
|
|
|
|
CcInt* cell_id = (CcInt*)tuple_cell->GetAttribute(attr1);
|
|
CcInt* cnt = (CcInt*)tuple_cell->GetAttribute(attr2);
|
|
Region* reg = (Region*)tuple_cell->GetAttribute(attr3);
|
|
|
|
int cellid = cell_id->GetIntval();
|
|
cell_list[cellid - 1].cell_id = cellid;
|
|
cell_list[cellid - 1].sec_intersect_count = cnt->GetIntval();
|
|
cell_list[cellid - 1].reg = reg->BoundingBox();
|
|
|
|
if(cnt->GetIntval() > (int)(max_cnt*div_number1)){
|
|
cell_list[cellid - 1].count_1 = 3;
|
|
}
|
|
else if(cnt->GetIntval() > (int)(max_cnt*div_number2) ){
|
|
cell_list[cellid - 1].count_1 = 2;
|
|
}
|
|
else{
|
|
cell_list[cellid - 1].count_1 = 1;
|
|
}
|
|
|
|
cell_list[cellid - 1].def = true;
|
|
|
|
tuple_cell->DeleteIfAllowed();
|
|
}
|
|
|
|
// cout<<"cell list size "<<cell_list.size()<<endl;
|
|
|
|
//create priority_queue
|
|
int count = 0;
|
|
|
|
priority_queue<Section_Cell> cell_queue; //////////priority_queue
|
|
////////////cells are ordered by intersecting number from large to small////
|
|
for(unsigned int i = 0;i < cell_list.size();i++)
|
|
if(cell_list[i].def){
|
|
// cell_list[i].Print();
|
|
count++;
|
|
cell_queue.push(cell_list[i]);
|
|
}
|
|
// cout<<"count "<<count<<endl;
|
|
|
|
|
|
vector<Section_Cell> cell_list3; //////////////////////array
|
|
vector<Section_Cell> cell_list2; //////////////////////array
|
|
vector<Section_Cell> cell_list1; //////////////////////array
|
|
|
|
while(cell_queue.empty() == false){
|
|
Section_Cell top = cell_queue.top();
|
|
cell_queue.pop();
|
|
// top.Print();
|
|
|
|
if(top.count_1 == 3)
|
|
cell_list3.push_back(top);
|
|
if(top.count_1 == 2)
|
|
cell_list2.push_back(top);
|
|
if(top.count_1 == 1)
|
|
cell_list1.push_back(top);
|
|
}
|
|
//3---13 2---49 1---204 //berlin roads---div1 0.5
|
|
//3---21 2---41 1---204 //berlin roads---div1 0.4
|
|
//3---27 2---21 1---218 //berlin roads---div1 0.4; div 0.25
|
|
|
|
//3---10 2---8 1---619 //houston roads
|
|
|
|
cout<<cell_list3.size()<<" "
|
|
<<cell_list2.size()<<" "<<cell_list1.size()<<endl;
|
|
|
|
|
|
if(bus_para->GetNoTuples() != 3){
|
|
cout<<"wrong bus parameter relation"<<endl;
|
|
return;
|
|
}
|
|
|
|
Tuple* tuple1 = bus_para->GetTuple(1, false);
|
|
unsigned int limit_no =
|
|
(unsigned int)((CcReal*)tuple1->GetAttribute(0))->GetRealval();
|
|
tuple1->DeleteIfAllowed();
|
|
|
|
|
|
Tuple* tuple2 = bus_para->GetTuple(2, false);
|
|
float dist_para1 = ((CcReal*)tuple2->GetAttribute(0))->GetRealval();
|
|
tuple2->DeleteIfAllowed();
|
|
|
|
Tuple* tuple3 = bus_para->GetTuple(3, false);
|
|
float dist_para2 = ((CcReal*)tuple3->GetAttribute(0))->GetRealval();
|
|
tuple3->DeleteIfAllowed();
|
|
|
|
// cout<<limit_no<<" "<<dist_para1<<" "<<dist_para2<<endl;
|
|
|
|
BuildRoute1(cell_list3, cell_list1, 1, true, dist_para1);//type 1
|
|
BuildRoute1(cell_list2, cell_list1, 2, false, dist_para1);//type 2
|
|
BuildRoute2(cell_list1, cell_list1, limit_no, dist_para2); //type 3
|
|
|
|
|
|
}
|
|
|
|
/*
|
|
highest density area with low density area
|
|
|
|
*/
|
|
void BusRoute::BuildRoute1(vector<Section_Cell>& from_cell_list,
|
|
vector<Section_Cell> to_cell_list,
|
|
int type, bool start, float dist_val)
|
|
{
|
|
for(unsigned int i = 0;i < from_cell_list.size();i++){
|
|
Section_Cell elem = from_cell_list[i];
|
|
int end_cellid =
|
|
FindEndCell1(from_cell_list[i],to_cell_list,dist_val, start);
|
|
|
|
if(end_cellid >= 0){
|
|
// cout<<"start cell "<<from_cell_list[i].cell_id
|
|
// <<" end cell "<<to_cell_list[end_cellid].cell_id<<endl;
|
|
|
|
start_cells.push_back(from_cell_list[i].reg);
|
|
end_cells.push_back(to_cell_list[end_cellid].reg);
|
|
start_cell_id.push_back(from_cell_list[i].cell_id);
|
|
end_cell_id.push_back(to_cell_list[end_cellid].cell_id);
|
|
|
|
|
|
bus_route_type.push_back(type);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
lown density area with low density area
|
|
with the limit number of bus routes
|
|
Houston larger area than Berlin, so the distance value is also large, given
|
|
by the input parameter
|
|
|
|
*/
|
|
void BusRoute::BuildRoute2(vector<Section_Cell>& from_cell_list,
|
|
vector<Section_Cell> to_cell_list,
|
|
unsigned int limit_no, float dist_val)
|
|
{
|
|
unsigned int count = 0;
|
|
for(unsigned int i = 0;i < from_cell_list.size();i++){
|
|
Section_Cell elem = from_cell_list[i];
|
|
|
|
if(from_cell_list[i].def == false) continue;
|
|
int end_cellid = FindEndCell2(from_cell_list[i],to_cell_list,dist_val);
|
|
|
|
if(end_cellid >= 0){
|
|
// cout<<"start cell "<<from_cell_list[i].cell_id
|
|
// <<" end cell "<<to_cell_list[end_cellid].cell_id<<endl;
|
|
|
|
start_cells.push_back(from_cell_list[i].reg);
|
|
end_cells.push_back(to_cell_list[end_cellid].reg);
|
|
start_cell_id.push_back(from_cell_list[i].cell_id);
|
|
end_cell_id.push_back(to_cell_list[end_cellid].cell_id);
|
|
|
|
bus_route_type.push_back(3);//the lowest route
|
|
|
|
to_cell_list[i].def = false;
|
|
from_cell_list[end_cellid].def = false;
|
|
count++;
|
|
}
|
|
if(count > limit_no/2) break;
|
|
}
|
|
|
|
count = 0;
|
|
for(int i = from_cell_list.size() - 1;i >= 0;i--){
|
|
Section_Cell elem = from_cell_list[i];
|
|
|
|
if(from_cell_list[i].def == false) continue;
|
|
int end_cellid = FindEndCell2(from_cell_list[i],to_cell_list,dist_val);
|
|
|
|
if(end_cellid >= 0){
|
|
|
|
start_cells.push_back(from_cell_list[i].reg);
|
|
end_cells.push_back(to_cell_list[end_cellid].reg);
|
|
start_cell_id.push_back(from_cell_list[i].cell_id);
|
|
end_cell_id.push_back(to_cell_list[end_cellid].cell_id);
|
|
|
|
bus_route_type.push_back(3);//the lowest route
|
|
|
|
to_cell_list[i].def = false;
|
|
from_cell_list[end_cellid].def = false;
|
|
count++;
|
|
}
|
|
if(count > limit_no/2) break;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
use the first paramter as the start cell and find a cell from the
|
|
second parameter that the distance between them is larger than a value
|
|
if flag is true, from small index to large. otherwise from large to small
|
|
|
|
*/
|
|
int BusRoute::FindEndCell1(Section_Cell& start_cell,
|
|
vector<Section_Cell>& cell_list,
|
|
float dist_val, bool flag)
|
|
{
|
|
if(flag){
|
|
for(unsigned int i = 0;i < cell_list.size();i++){
|
|
if(cell_list[i].def){
|
|
if(start_cell.reg.Distance(cell_list[i].reg) > dist_val){
|
|
cell_list[i].def = false;
|
|
return i;
|
|
}
|
|
}
|
|
}
|
|
}else{
|
|
for(int i = cell_list.size() - 1;i >= 0;i--){
|
|
if(cell_list[i].def){
|
|
if(start_cell.reg.Distance(cell_list[i].reg) > dist_val){
|
|
cell_list[i].def = false;
|
|
return i;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
use the first paramter as the start cell and find a cell from the
|
|
second parameter that the distance between them is larger than a value
|
|
|
|
*/
|
|
int BusRoute::FindEndCell2(Section_Cell& start_cell,
|
|
vector<Section_Cell>& cell_list, float dist_val)
|
|
{
|
|
for(unsigned int i = 0;i < cell_list.size();i++){
|
|
if(cell_list[i].def){
|
|
if(start_cell.reg.Distance(cell_list[i].reg) > dist_val){
|
|
cell_list[i].def = false;
|
|
return i;
|
|
}
|
|
}
|
|
}
|
|
// cout<<"do not find an end cell for cell "<<start_cell.cell_id<<endl;
|
|
return -1;
|
|
}
|
|
|
|
|
|
/*
|
|
create bus routes, use the relation of a pair of cells
|
|
1.given a pair of cells where the first is the start location and the second is
|
|
the end location of a bus route
|
|
2.for each cell, it (randomly) selects a point as the start (end) point.
|
|
3.use the shortest path connecting the two points as the bus route
|
|
|
|
*/
|
|
|
|
void BusRoute::CreateRoute2(Space* sp, int attr,int attr1,int attr2,int attr3)
|
|
{
|
|
// cout<<"attr "<<attr<<" attr1 "<<attr1 <<" attr2 "<<attr2<<endl;
|
|
// cout<<"CreateRoute2()"<<endl;
|
|
|
|
Network* rn = sp->LoadRoadNetwork(IF_LINE);
|
|
if(rn == NULL){
|
|
cout<<"load road network error"<<endl;
|
|
return;
|
|
}
|
|
n = rn;
|
|
|
|
RoadGraph* rg = sp->LoadRoadGraph();
|
|
|
|
for(int i = 1;i <= rel2->GetNoTuples();i++){
|
|
|
|
Tuple* tuple_cell_pair = rel2->GetTuple(i, false);
|
|
int from_cell_id =
|
|
((CcInt*)tuple_cell_pair->GetAttribute(attr1))->GetIntval();
|
|
int end_cell_id =
|
|
((CcInt*)tuple_cell_pair->GetAttribute(attr2))->GetIntval();
|
|
|
|
int route_type =
|
|
((CcInt*)tuple_cell_pair->GetAttribute(attr3))->GetIntval();
|
|
// cout<<"from_cell "<<from_cell_id<<" end_cell "<<end_cell_id<<endl;
|
|
|
|
// cout<<"route_type "<<route_type<<endl;
|
|
|
|
ConnectCell(rg, attr,from_cell_id,end_cell_id,route_type, i);
|
|
tuple_cell_pair->DeleteIfAllowed();
|
|
|
|
|
|
}
|
|
|
|
sp->CloseRoadGraph(rg);
|
|
sp->CloseRoadNetwork(rn);
|
|
|
|
///////////////////add several special routes//////////////////////////
|
|
/////////maybe not the shortest path, cycle route//////////////////////
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
}
|
|
|
|
/*
|
|
randomly choose two positions in two cells and find the shortest path
|
|
connecting them. use the shortest path as the bus route
|
|
|
|
*/
|
|
|
|
void BusRoute::ConnectCell(RoadGraph* rg, int attr,int from_cell_id,
|
|
int end_cell_id, int route_type, int seed)
|
|
{
|
|
Relation* routes = n->GetRoutes();
|
|
RoadNav* road_nav = new RoadNav();
|
|
|
|
////use btree to get the sections that this cell interesects////////
|
|
CcInt* search_cell_id_from = new CcInt(true, from_cell_id);
|
|
BTreeIterator* btree_iter1 = btree->ExactMatch(search_cell_id_from);
|
|
vector<int> sec_id_list_from;
|
|
while(btree_iter1->Next()){
|
|
Tuple* tuple_cell = rel1->GetTuple(btree_iter1->GetId(), false);
|
|
CcInt* sec_id = (CcInt*)tuple_cell->GetAttribute(attr);
|
|
sec_id_list_from.push_back(sec_id->GetIntval());
|
|
tuple_cell->DeleteIfAllowed();
|
|
}
|
|
delete btree_iter1;
|
|
search_cell_id_from->DeleteIfAllowed();
|
|
|
|
////////////////////create first gpoint////////////////////////
|
|
int index1 = 0;
|
|
index1 = (index1 + seed) % sec_id_list_from.size();
|
|
int sec_id_1 = sec_id_list_from[index1];
|
|
|
|
|
|
///////// create two gpoints from selected two sections///////////////
|
|
/////////choose the first road section for each cell/////////////////
|
|
|
|
Tuple* tuple_sec_1 = n->GetSection(sec_id_1);
|
|
int rid1 = ((CcInt*)tuple_sec_1->GetAttribute(SECTION_RID))->GetIntval();
|
|
double loc1 =
|
|
((CcReal*)tuple_sec_1->GetAttribute(SECTION_MEAS1))->GetRealval();
|
|
|
|
GPoint* gp1 = new GPoint(true,n->GetId(),rid1,loc1,None);
|
|
Point* location1 = new Point();
|
|
|
|
Tuple* road_tuple1 = routes->GetTuple(gp1->GetRouteId(), false);
|
|
SimpleLine* sl1 = (SimpleLine*)road_tuple1->GetAttribute(ROUTE_CURVE);
|
|
assert(sl1->GetStartSmaller());
|
|
assert(sl1->AtPosition(gp1->GetPosition(), true, *location1));
|
|
road_tuple1->DeleteIfAllowed();
|
|
|
|
start_gp.push_back(*location1);
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
CcInt* search_cell_id_end = new CcInt(true, end_cell_id);
|
|
BTreeIterator* btree_iter2 = btree->ExactMatch(search_cell_id_end);
|
|
vector<int> sec_id_list_end;
|
|
while(btree_iter2->Next()){
|
|
Tuple* tuple_cell = rel1->GetTuple(btree_iter2->GetId(), false);
|
|
CcInt* sec_id = (CcInt*)tuple_cell->GetAttribute(attr);
|
|
sec_id_list_end.push_back(sec_id->GetIntval());
|
|
tuple_cell->DeleteIfAllowed();
|
|
}
|
|
delete btree_iter2;
|
|
search_cell_id_end->DeleteIfAllowed();
|
|
|
|
|
|
///////////////////create second gpoint/////////////////////////////
|
|
int index2 = 0;
|
|
index2 = (index2 + seed) % sec_id_list_end.size();
|
|
int sec_id_2 = sec_id_list_end[index2];
|
|
|
|
Tuple* tuple_sec_2 = n->GetSection(sec_id_2);
|
|
int rid2 = ((CcInt*)tuple_sec_2->GetAttribute(SECTION_RID))->GetIntval();
|
|
double loc2 =
|
|
((CcReal*)tuple_sec_2->GetAttribute(SECTION_MEAS1))->GetRealval();
|
|
GPoint* gp2 = new GPoint(true,n->GetId(),rid2,loc2,None);
|
|
Point* location2 = new Point();
|
|
|
|
Tuple* road_tuple2 = routes->GetTuple(gp2->GetRouteId(), false);
|
|
SimpleLine* sl2 = (SimpleLine*)road_tuple2->GetAttribute(ROUTE_CURVE);
|
|
assert(sl2->GetStartSmaller());
|
|
assert(sl2->AtPosition(gp2->GetPosition(), true, *location2));
|
|
road_tuple2->DeleteIfAllowed();
|
|
|
|
end_gp.push_back(*location2);
|
|
|
|
|
|
GLine* gl = new GLine(0);
|
|
|
|
// cout<<"gp1 "<<*gp1<<" gp2 "<<*gp2<<endl;
|
|
|
|
// road_nav->ShortestPathSub(gp1, gp2, rg, n, gl);
|
|
|
|
if(route_type == 1){
|
|
if(GetRandom() % 2 == 0)
|
|
road_nav->ShortestPathSub(gp1, gp2, rg, n, gl);
|
|
else{
|
|
road_nav->ShortestPathSub3(gp1, gp2, rg, n, gl);
|
|
if(gl->IsDefined() == false)
|
|
road_nav->ShortestPathSub(gp1, gp2, rg, n, gl);
|
|
}
|
|
}else if(route_type == 2){
|
|
if(GetRandom() % 2 == 0){
|
|
road_nav->ShortestPathSub(gp1, gp2, rg, n, gl);
|
|
}else{
|
|
road_nav->ShortestPathSub3(gp1, gp2, rg, n, gl);
|
|
if(gl->IsDefined() == false)
|
|
road_nav->ShortestPathSub(gp1, gp2, rg, n, gl);
|
|
}
|
|
}else{ //////paths avoid city center area
|
|
if(GetRandom() % 2 == 0){
|
|
road_nav->ShortestPathSub2(gp1, gp2, rg, n, gl);
|
|
if(gl->IsDefined() == false){//in case cannot find such a path
|
|
road_nav->ShortestPathSub(gp1, gp2, rg, n, gl);
|
|
}
|
|
}else{
|
|
road_nav->ShortestPathSub3(gp1, gp2, rg, n, gl);
|
|
if(gl->IsDefined() == false){//in case cannot find such a path
|
|
road_nav->ShortestPathSub(gp1, gp2, rg, n, gl);
|
|
}
|
|
}
|
|
}
|
|
|
|
location1->DeleteIfAllowed();
|
|
gp1->DeleteIfAllowed();
|
|
|
|
location2->DeleteIfAllowed();
|
|
gp2->DeleteIfAllowed();
|
|
|
|
tuple_sec_1->DeleteIfAllowed();
|
|
tuple_sec_2->DeleteIfAllowed();
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
bus_lines1.push_back(*gl);
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
Line* l = new Line(0);
|
|
gl->Gline2line(l);
|
|
bus_lines2.push_back(*l);
|
|
l->DeleteIfAllowed();
|
|
gl->DeleteIfAllowed();
|
|
|
|
bus_route_type.push_back(route_type);
|
|
|
|
delete road_nav;
|
|
|
|
}
|
|
|
|
/*
|
|
Refine bus routes: filter some routes which are very similar to each other
|
|
map each bus route to the road line, gline (rid,pos1)-(rid,pos2)
|
|
(rel (tuple ((br id int) (bus route1 gline) (bus route2 line)
|
|
(start loc point) (end loc point) (route type int))))
|
|
|
|
*/
|
|
void BusRoute::RefineBusRoute(int attr1, int attr2, int attr3, int attr4,
|
|
int attr5, int attr6)
|
|
{
|
|
// cout<<"attr1 "<<attr1<<" attr2 "<<attr2<<" attr3 "<<attr3
|
|
// <<" attr4 "<<attr4<<" "<<attr5<<" attr6 " <<attr6<<endl;
|
|
|
|
vector<bool> routes_def;
|
|
for(int i = 0;i < rel1->GetNoTuples();i++)
|
|
routes_def.push_back(true);
|
|
|
|
for(int i = 1;i <= rel1->GetNoTuples();i++){
|
|
Tuple* tuple_bus_route1 = rel1->GetTuple(i, false);
|
|
int br_id1 = ((CcInt*)tuple_bus_route1->GetAttribute(attr1))->GetIntval();
|
|
|
|
|
|
if(routes_def[br_id1 - 1] == false){
|
|
tuple_bus_route1->DeleteIfAllowed();
|
|
continue;
|
|
}
|
|
GLine* gl1 = (GLine*)tuple_bus_route1->GetAttribute(attr2);
|
|
|
|
for(int j = i + 1; j <= rel1->GetNoTuples();j++){
|
|
Tuple* tuple_bus_route2 = rel1->GetTuple(j, false);
|
|
int br_id2 = ((CcInt*)tuple_bus_route2->GetAttribute(attr1))->GetIntval();
|
|
|
|
|
|
if(routes_def[br_id2 - 1] == false){
|
|
tuple_bus_route2->DeleteIfAllowed();
|
|
continue;
|
|
}
|
|
GLine* gl2 = (GLine*)tuple_bus_route2->GetAttribute(attr2);
|
|
|
|
// cout<<"br_id1 "<<br_id1<<" br_id2 "<<br_id2<<endl;
|
|
// cout<<gl1->GetLength()<<" "<<gl2->GetLength()<<endl;
|
|
|
|
int filter_br_id = FilterBusRoute(gl1,gl2,br_id1,br_id2);
|
|
if(filter_br_id > 0){
|
|
// cout<<" br_1 "<<br_id1<<" br_2 "<<br_id2
|
|
// <<" filter "<<filter_br_id<<endl;
|
|
routes_def[filter_br_id - 1] = false;
|
|
if(filter_br_id == br_id1){
|
|
tuple_bus_route2->DeleteIfAllowed();
|
|
break;
|
|
}
|
|
}
|
|
|
|
tuple_bus_route2->DeleteIfAllowed();
|
|
|
|
}
|
|
tuple_bus_route1->DeleteIfAllowed();
|
|
}
|
|
/////////////////////collect the non-filtered bus routes/////////////////
|
|
/* unsigned int final_no = 0;
|
|
for(unsigned int i = 0;i < routes_def.size();i++){
|
|
if(routes_def[i])final_no++;
|
|
}
|
|
cout<<"final bus routes no "<<final_no<<endl; */
|
|
|
|
int new_br_id = 1;
|
|
for(int i = 1;i <= rel1->GetNoTuples();i++){
|
|
Tuple* tuple_bus_route = rel1->GetTuple(i, false);
|
|
int br_id = ((CcInt*)tuple_bus_route->GetAttribute(attr1))->GetIntval();
|
|
if(routes_def[br_id - 1] == false){
|
|
tuple_bus_route->DeleteIfAllowed();
|
|
continue;
|
|
}
|
|
|
|
GLine* gl = (GLine*)tuple_bus_route->GetAttribute(attr2);
|
|
Line* l = (Line*)tuple_bus_route->GetAttribute(attr3);
|
|
Point* start_p = (Point*)tuple_bus_route->GetAttribute(attr4);
|
|
Point* end_p = (Point*)tuple_bus_route->GetAttribute(attr5);
|
|
int route_type =
|
|
((CcInt*)tuple_bus_route->GetAttribute(attr6))->GetIntval();
|
|
|
|
br_id_list.push_back(new_br_id);
|
|
bus_lines1.push_back(*gl);
|
|
bus_lines2.push_back(*l);
|
|
start_gp.push_back(*start_p);
|
|
end_gp.push_back(*end_p);
|
|
bus_route_type.push_back(route_type);
|
|
|
|
new_br_id++;
|
|
tuple_bus_route->DeleteIfAllowed();
|
|
}
|
|
|
|
|
|
}
|
|
|
|
/*
|
|
compare two bus routes represented by gline
|
|
it checkes whether one of them needs to be filtered
|
|
|
|
*/
|
|
bool CompareRouteInterval(const RouteInterval& ri1, const RouteInterval& ri2)
|
|
{
|
|
if(ri1.GetRouteId() < ri2.GetRouteId()) return true;
|
|
else if(ri1.GetRouteId() > ri2.GetRouteId()) return false;
|
|
else{
|
|
double start1 = ri1.GetStartPos();
|
|
double end1 = ri1.GetEndPos();
|
|
if(start1 > end1){
|
|
double temp = start1;
|
|
start1 = end1;
|
|
end1 = temp;
|
|
}
|
|
double start2 = ri2.GetStartPos();
|
|
double end2 = ri2.GetEndPos();
|
|
if(start2 > end2){
|
|
double temp = start2;
|
|
start2 = end2;
|
|
end2 = temp;
|
|
}
|
|
if(AlmostEqual(start1, start2)){
|
|
if(AlmostEqual(end1, end2))return true;
|
|
else if(end1 < end2) return true;
|
|
else return false;
|
|
}
|
|
else if(start1 < start2 )return true;
|
|
else return false;
|
|
}
|
|
}
|
|
|
|
int BusRoute::FilterBusRoute(GLine* gl1, GLine* gl2, int br_id1, int br_id2)
|
|
{
|
|
//////////////////////convert GLine to RouteInterval////////////////////////
|
|
vector<RouteInterval> ri_list1;
|
|
for(int i = 0; i < gl1->Size();i++){
|
|
RouteInterval* ri = new RouteInterval();
|
|
gl1->Get(i, *ri);
|
|
ri_list1.push_back(*ri);
|
|
}
|
|
|
|
|
|
sort(ri_list1.begin(), ri_list1.end(), CompareRouteInterval);
|
|
double length1 = 0.0;
|
|
// cout<<"GLine1"<<endl;
|
|
for(unsigned int i = 0;i < ri_list1.size();i++){
|
|
// ri_list1[i].Print(cout);
|
|
length1 += fabs(ri_list1[i].GetStartPos() - ri_list1[i].GetEndPos());
|
|
}
|
|
// cout<<"GLine1 br_id1 "<<br_id1<<" length1 "<<length1<<endl;
|
|
|
|
vector<RouteInterval> ri_list2;
|
|
for(int i = 0; i < gl2->Size();i++){
|
|
RouteInterval* ri = new RouteInterval();
|
|
gl2->Get(i, *ri);
|
|
ri_list2.push_back(*ri);
|
|
}
|
|
|
|
|
|
sort(ri_list2.begin(), ri_list2.end(), CompareRouteInterval);
|
|
double length2 = 0.0;
|
|
// cout<<"GLine2"<<endl;
|
|
for(unsigned int i = 0;i < ri_list2.size();i++){
|
|
// ri_list2[i].Print(cout);
|
|
length2 += fabs(ri_list2[i].GetStartPos() - ri_list2[i].GetEndPos());
|
|
}
|
|
|
|
// cout<<"GLine2 br_id2 "<<br_id2<<" length2 "<<length2<<endl;
|
|
|
|
////use a factor and choose the length of the shorter bus route/////////
|
|
const double comm_factor = 0.8;// 0.9, 0.7
|
|
|
|
double comm_length;
|
|
if(length1 < length2) comm_length = length1*comm_factor;
|
|
else comm_length = length2*comm_factor;
|
|
|
|
// cout<<"comm length "<<comm_length<<endl;
|
|
|
|
///////////////find the common length////////////////////////////
|
|
unsigned int index2 = 0;
|
|
double find_comm = 0.0;
|
|
|
|
for(unsigned int i = 0;i < ri_list1.size();){
|
|
|
|
int rid1 = ri_list1[i].GetRouteId();
|
|
int rid2 = ri_list2[index2].GetRouteId();
|
|
// cout<<"rid1 "<<rid1<<" rid2 "<<rid2<<endl;
|
|
if(rid1 < rid2){
|
|
i++;
|
|
}
|
|
else if(rid1 == rid2){ //find the common route interval
|
|
double s1 = ri_list1[i].GetStartPos();
|
|
double e1 = ri_list1[i].GetEndPos();
|
|
if(s1 > e1){
|
|
double temp = s1;
|
|
s1 = e1;
|
|
e1 = temp;
|
|
}
|
|
double s2 = ri_list2[index2].GetStartPos();
|
|
double e2 = ri_list2[index2].GetEndPos();
|
|
if(s2 > e2){
|
|
double temp = s2;
|
|
s2 = e2;
|
|
e2 = temp;
|
|
}
|
|
// cout<<"s1 "<<s1<<"s2 "<<s2<<endl;
|
|
//////////////////////////////////////////////////////////////
|
|
if(AlmostEqual(s1,s2)){ //the same start position
|
|
// cout<<"AlmostEqual() "<<endl;
|
|
if(AlmostEqual(e1,e2)){
|
|
find_comm += fabs(e1-s1);
|
|
}else if(e1 > e2){
|
|
find_comm += fabs(e2-s2);
|
|
}else{//e1 < e2
|
|
find_comm += fabs(e1-s1);
|
|
}
|
|
}else if(s1 < s2){//check the position between e1, s2
|
|
// cout<<"s1 < s2"<<endl;
|
|
if(e1 > s2 && e1 < e2){ // exists common part
|
|
find_comm += fabs(e1-s2);
|
|
}
|
|
}else{//s1 > s2
|
|
// cout<<"s1 > s2 "<<endl;
|
|
if(e2 > s1 && e2 < e1){ // exists common part
|
|
find_comm += fabs(e2-s1);
|
|
}
|
|
}
|
|
if(find_comm > comm_length){
|
|
// if(length1 < length2) return br_id1;//filter shorter one
|
|
// else return br_id2;
|
|
break;
|
|
}
|
|
i++;
|
|
if(index2 + 1 < ri_list2.size())
|
|
index2++;
|
|
}
|
|
else if(rid1 > rid2){
|
|
while((index2 + 1) < ri_list2.size() && rid1 > rid2){
|
|
index2++;
|
|
rid2 = ri_list2[index2].GetRouteId();
|
|
}
|
|
if(index2 + 1 == ri_list2.size())break;
|
|
}
|
|
else assert(false);
|
|
// cout<<"find comm "<<find_comm<<endl;
|
|
}
|
|
|
|
if(find_comm > comm_length){
|
|
// cout<<"br_id1 "<<br_id1<<" br_id2 "<<br_id2
|
|
// <<" comm length "<<comm_length<<" real comm length "<<find_comm<<endl;
|
|
|
|
if(length1 < length2) return br_id1;//filter shorter one
|
|
else return br_id2;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
translate a bus route into two routes, down and up
|
|
|
|
*/
|
|
|
|
void BusRoute::CreateRoute3(int attr1, int attr2, int attr3, int w)
|
|
{
|
|
// cout<<"attr1 "<<attr1<<" attr2 "<<attr2
|
|
// <<" attr3 "<<attr3<<" width "<<w<<endl;
|
|
|
|
int bus_route_uid = 1;
|
|
////////////// relation ///////////////////////////
|
|
///////////// bus route uid = br id * 2 -1///////////
|
|
//////////// bus route uid = br id * 2 /////////////
|
|
//////////////////////////////////////////////////////
|
|
|
|
for(int i = 1;i <= rel1->GetNoTuples();i++){
|
|
|
|
Tuple* tuple_bus_route = rel1->GetTuple(i, false);
|
|
int br_id = ((CcInt*)tuple_bus_route->GetAttribute(attr1))->GetIntval();
|
|
Line* l = (Line*)tuple_bus_route->GetAttribute(attr2);
|
|
int route_type =
|
|
((CcInt*)tuple_bus_route->GetAttribute(attr3))->GetIntval();
|
|
|
|
// if(br_id != 38){
|
|
// tuple_bus_route->DeleteIfAllowed();
|
|
// continue;
|
|
// }
|
|
|
|
////////////////////////translate/////////////////////////////////
|
|
SimpleLine* sl = new SimpleLine(0);
|
|
sl->fromLine(*l);
|
|
|
|
SpacePartition* sp = new SpacePartition();
|
|
vector<MyHalfSegment> seq_halfseg; //reorder it from start to end
|
|
sp->ReorderLine(sl, seq_halfseg);
|
|
|
|
// cout<<"l1 "<<l->Length()<<" l2 "<<sl->Length()<<endl;
|
|
// cout<<"br_id "<<br_id<<endl;
|
|
|
|
vector<Point> outer_l;
|
|
vector<Point> outer_r;
|
|
sp->ExtendSeg3(seq_halfseg, w, true, outer_l);
|
|
sp->ExtendSeg3(seq_halfseg, w, false, outer_r);
|
|
/////////////////////////////////////////////////////////////
|
|
Line* l1 = new Line(0);
|
|
l1->StartBulkLoad();
|
|
ComputeLine(outer_l, l1);
|
|
l1->EndBulkLoad();
|
|
bus_sections1.push_back(*l1);
|
|
|
|
|
|
br_id_list.push_back(br_id);
|
|
bus_lines2.push_back(*l);
|
|
bus_route_type.push_back(route_type);
|
|
br_uid_list.push_back(bus_route_uid);
|
|
bus_route_uid++;
|
|
|
|
|
|
Line* l2 = new Line(0);
|
|
l2->StartBulkLoad();
|
|
ComputeLine(outer_r, l2);
|
|
l2->EndBulkLoad();
|
|
bus_sections1.push_back(*l2);
|
|
|
|
|
|
br_id_list.push_back(br_id);
|
|
bus_lines2.push_back(*l);
|
|
bus_route_type.push_back(route_type);
|
|
br_uid_list.push_back(bus_route_uid);
|
|
bus_route_uid++;
|
|
|
|
////////////////////////////////////////////////////////////
|
|
|
|
l1->DeleteIfAllowed();
|
|
l2->DeleteIfAllowed();
|
|
delete sp;
|
|
sl->DeleteIfAllowed();
|
|
tuple_bus_route->DeleteIfAllowed();
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
it inputs a list of points and computes a line value
|
|
|
|
*/
|
|
|
|
void BusRoute::ComputeLine(vector<Point>& point_list, Line* l)
|
|
{
|
|
assert(point_list.size() > 0);
|
|
int edgeno = 0;
|
|
|
|
// for(unsigned int i = 0;i < point_list.size() - 1;i++){
|
|
// Point lp = point_list[i];
|
|
// Point rp = point_list[i + 1];
|
|
//
|
|
// HalfSegment* hs = new HalfSegment(true, lp, rp);
|
|
// hs->attr.edgeno = edgeno++;
|
|
// *l += *hs;
|
|
//
|
|
// hs->SetLeftDomPoint(!hs->IsLeftDomPoint());
|
|
// *l += *hs;
|
|
//
|
|
// delete hs;
|
|
//
|
|
// }
|
|
|
|
for(unsigned int i = 0;i < point_list.size() - 1;i++){
|
|
Point lp = point_list[i];
|
|
Point rp = point_list[i + 1];
|
|
HalfSegment hs1(true, lp, rp);
|
|
unsigned int j = i + 2;
|
|
for(; j < point_list.size() - 1;j++){
|
|
Point p1 = point_list[j];
|
|
Point p2 = point_list[j + 1];
|
|
HalfSegment hs2(true, p1, p2);
|
|
Point res;
|
|
if(hs1.Intersection(hs2, res)){
|
|
// cout<<"crossing"<<endl;
|
|
point_list[j] = res;
|
|
point_list[j + 1] = res;
|
|
break;
|
|
}
|
|
}
|
|
if(j >= point_list.size() - 1){
|
|
HalfSegment* hs = new HalfSegment(true, lp, rp);
|
|
hs->attr.edgeno = edgeno++;
|
|
*l += *hs;
|
|
hs->SetLeftDomPoint(!hs->IsLeftDomPoint());
|
|
*l += *hs;
|
|
delete hs;
|
|
}else{
|
|
rp = point_list[j];
|
|
HalfSegment* hs = new HalfSegment(true, lp, rp);
|
|
hs->attr.edgeno = edgeno++;
|
|
*l += *hs;
|
|
hs->SetLeftDomPoint(!hs->IsLeftDomPoint());
|
|
*l += *hs;
|
|
delete hs;
|
|
i = j;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
/*
|
|
for each bus route, it creates a sequence of points on it as bus stops
|
|
|
|
*/
|
|
void BusRoute::CreateBusStop1(int attr1, int attr2, int attr3,
|
|
int attr4, Relation* pave_rel,
|
|
BTree* btree_pave, Relation* stop_para)
|
|
{
|
|
////////////initialize distance for stops///////////////////////
|
|
vector<double> dist_stops;// distance between two bus stops
|
|
|
|
InitializeDistStop(dist_stops, stop_para);
|
|
///////////////////////////////////////////////////////
|
|
|
|
for(int i = 1;i <= rel1->GetNoTuples();i++){
|
|
|
|
Tuple* tuple_bus_route = rel1->GetTuple(i, false);
|
|
int br_id = ((CcInt*)tuple_bus_route->GetAttribute(attr1))->GetIntval();
|
|
GLine* gl = (GLine*)tuple_bus_route->GetAttribute(attr2);
|
|
Line* l = (Line*)tuple_bus_route->GetAttribute(attr3);
|
|
int route_type =
|
|
((CcInt*)tuple_bus_route->GetAttribute(attr4))->GetIntval();
|
|
|
|
// if(br_id != 5){
|
|
// tuple_bus_route->DeleteIfAllowed();
|
|
// continue;
|
|
// }
|
|
|
|
// cout<<"br_id "<<br_id<<endl;
|
|
// cout<<"route_type "<<route_type<<endl;
|
|
|
|
unsigned int cur_size = bus_stop_loc_1.size();
|
|
|
|
CreateStops(br_id, gl,l, route_type, dist_stops);
|
|
tuple_bus_route->DeleteIfAllowed();
|
|
|
|
///modify the bus stops if they are located on the zebracrossing/////
|
|
CheckBusStopZC(cur_size, pave_rel, btree_pave);
|
|
}
|
|
}
|
|
|
|
/*
|
|
set the distance value for two adjacent bus stops
|
|
|
|
*/
|
|
void BusRoute::InitializeDistStop(vector<double>& dist_for_stops,
|
|
Relation* stop_para)
|
|
{
|
|
// cout<<stop_para->GetNoTuples()<<endl;
|
|
int index = 1;
|
|
Tuple* tuple_tmp = stop_para->GetTuple(index, false);
|
|
int no_1 = (int)((CcReal*)tuple_tmp->GetAttribute(0))->GetRealval();
|
|
// cout<<no_1<<endl;
|
|
for(int i = index + 1; i <= index + no_1;i++){
|
|
Tuple* tuple = stop_para->GetTuple(i, false);
|
|
float dist = ((CcReal*)tuple->GetAttribute(0))->GetRealval();
|
|
// cout<<dist<<endl;
|
|
tuple->DeleteIfAllowed();
|
|
dist_for_stops.push_back(dist);
|
|
}
|
|
|
|
tuple_tmp->DeleteIfAllowed();
|
|
|
|
|
|
/* if(type == "Berlin"){
|
|
dist_for_stops1.push_back(1000.0);
|
|
dist_for_stops1.push_back(900.0);
|
|
dist_for_stops1.push_back(1100.0);
|
|
dist_for_stops1.push_back(1050.0);
|
|
dist_for_stops1.push_back(1500.0);
|
|
dist_for_stops1.push_back(1300.0);
|
|
dist_for_stops1.push_back(950.0);
|
|
dist_for_stops1.push_back(1200.0);
|
|
dist_for_stops1.push_back(1400.0);
|
|
dist_for_stops1.push_back(1300.0);
|
|
|
|
dist_for_stops1.push_back(800.0);////////add smaller distance
|
|
dist_for_stops1.push_back(500.0);////////add smaller distance
|
|
}else if(type == "Houston"){
|
|
dist_for_stops1.push_back(2600.0);
|
|
dist_for_stops1.push_back(2350.0);
|
|
dist_for_stops1.push_back(2000.0);
|
|
dist_for_stops1.push_back(2100.0);
|
|
dist_for_stops1.push_back(2300.0);
|
|
dist_for_stops1.push_back(2400.0);
|
|
dist_for_stops1.push_back(2200.0);
|
|
dist_for_stops1.push_back(2500.0);
|
|
dist_for_stops1.push_back(2700.0);
|
|
|
|
}
|
|
|
|
if(type == "Berlin"){
|
|
dist_for_stops2.push_back(900.0);
|
|
dist_for_stops2.push_back(1100.0);
|
|
dist_for_stops2.push_back(1150.0);
|
|
dist_for_stops2.push_back(1250.0);
|
|
dist_for_stops2.push_back(1050.0);
|
|
dist_for_stops2.push_back(1000.0);
|
|
dist_for_stops2.push_back(1200.0);
|
|
|
|
dist_for_stops2.push_back(800.0);////////add smaller distance
|
|
dist_for_stops2.push_back(500.0);////////add smaller distance
|
|
}else if(type == "Houston"){
|
|
dist_for_stops2.push_back(2000.0);
|
|
dist_for_stops2.push_back(2200.0);
|
|
dist_for_stops2.push_back(2100.0);
|
|
dist_for_stops1.push_back(2600.0);
|
|
dist_for_stops2.push_back(2700.0);
|
|
dist_for_stops2.push_back(2300.0);
|
|
dist_for_stops2.push_back(2400.0);
|
|
dist_for_stops2.push_back(2500.0);
|
|
|
|
}
|
|
|
|
if(type == "Berlin"){
|
|
dist_for_stops3.push_back(900.0);
|
|
dist_for_stops3.push_back(1100.0);
|
|
dist_for_stops3.push_back(950.0);
|
|
dist_for_stops3.push_back(1300.0);
|
|
dist_for_stops3.push_back(1000.0);
|
|
dist_for_stops3.push_back(1200.0);
|
|
dist_for_stops3.push_back(1150.0);
|
|
|
|
dist_for_stops3.push_back(800.0); ////////add smaller distance
|
|
dist_for_stops3.push_back(500.0);
|
|
}else if(type == "Houston"){
|
|
|
|
dist_for_stops3.push_back(2000.0);
|
|
dist_for_stops3.push_back(2200.0);
|
|
dist_for_stops3.push_back(2600.0);
|
|
dist_for_stops3.push_back(2100.0);
|
|
dist_for_stops3.push_back(2300.0);
|
|
dist_for_stops3.push_back(2400.0);
|
|
dist_for_stops3.push_back(2500.0);
|
|
dist_for_stops3.push_back(2700.0);
|
|
|
|
}
|
|
*/
|
|
|
|
}
|
|
|
|
/*
|
|
for such a gline, create a set of points on it
|
|
|
|
*/
|
|
|
|
void BusRoute::CreateStops(int br_id, GLine* gl, Line* l,
|
|
int route_type,vector<double> dist_for_stops)
|
|
{
|
|
|
|
|
|
////we have to know it goes from start to end or the other direction/////
|
|
vector<bool> start_from; //or end_from
|
|
|
|
vector<SectTreeEntry> sec_list;
|
|
|
|
GetSectionList(gl, sec_list, start_from);
|
|
|
|
/* for(unsigned int i = 0;i < sec_list.size();i++){
|
|
SectTreeEntry nEntry = sec_list[i];
|
|
cout<<"i "<<i<<" rid "<<nEntry.rid<<" secid "<<nEntry.secttid
|
|
<<"start "<<nEntry.start<<" end "<<nEntry.end<<endl;
|
|
}*/
|
|
|
|
if(sec_list.size() < 2) return;
|
|
|
|
const double dist_to_jun = 15.0; //minimum distance between bus stop and jun
|
|
/////////////////create the first bus stop///////////////////////////
|
|
int stop_count = 0;
|
|
unsigned int last_sec_index = 0;
|
|
double last_sec_start;
|
|
double last_sec_end;
|
|
double last_sec_gp_pos;
|
|
|
|
|
|
assert(start_from.size() == sec_list.size());
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
while(true){
|
|
SectTreeEntry entry = sec_list[last_sec_index];
|
|
last_sec_start = entry.start;
|
|
last_sec_end = entry.end;
|
|
|
|
if(fabs(last_sec_start - last_sec_end) < 2*dist_to_jun){
|
|
last_sec_index++;
|
|
continue;
|
|
}
|
|
|
|
|
|
if(start_from[last_sec_index]){ //start from small
|
|
last_sec_gp_pos = last_sec_start + dist_to_jun;
|
|
}else{ //start from big
|
|
last_sec_gp_pos = last_sec_end - dist_to_jun;
|
|
}
|
|
|
|
|
|
GPoint* gp =
|
|
new GPoint(true,n->GetId(),entry.rid,last_sec_gp_pos,None);
|
|
bus_stop_loc_1.push_back(*gp);
|
|
// Point* p = new Point();
|
|
// gp->ToPoint(p);
|
|
// bus_stop_loc_2.push_back(*p);
|
|
|
|
Point res;
|
|
MyToPoint(n, gp, res);
|
|
assert(res.IsDefined());
|
|
bus_stop_loc_2.push_back(res);
|
|
|
|
|
|
// delete p;
|
|
gp->DeleteIfAllowed();
|
|
|
|
br_id_list.push_back(br_id);
|
|
br_stop_id.push_back(stop_count + 1);
|
|
|
|
stop_count++;
|
|
break;
|
|
}
|
|
//////////////create more bus stops////////////////////////////////////////
|
|
while(true){
|
|
double next_stop_dist;
|
|
if(route_type == 1 || route_type == 2 || route_type == 3)
|
|
next_stop_dist = dist_for_stops[(stop_count - 1)% dist_for_stops.size()];
|
|
else assert(false);
|
|
|
|
/* cout<<"stop_id "<<stop_count
|
|
<<" current dist stop "<<next_stop_dist<<endl; */
|
|
//////////////////////////////////////////////////////////////////////
|
|
if(FindNextStop(sec_list,last_sec_index,last_sec_start,
|
|
last_sec_end, last_sec_gp_pos,next_stop_dist,
|
|
dist_to_jun,start_from)){
|
|
|
|
br_id_list.push_back(br_id);
|
|
br_stop_id.push_back(stop_count + 1);
|
|
stop_count++;
|
|
}else
|
|
break;
|
|
//////////////////////////////////////////////////////////////////////
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
create more bus stops along the given gline
|
|
use nextstopdist to control the distance between two consecutive bus stops
|
|
|
|
*/
|
|
bool BusRoute::FindNextStop(vector<SectTreeEntry> sec_list,
|
|
unsigned int& last_sec_index,double& last_sec_start,
|
|
double& last_sec_end, double& last_sec_gp_pos,
|
|
double next_stop_dist,
|
|
double dist_to_jun, vector<bool> start_from)
|
|
{
|
|
|
|
if(start_from[last_sec_index]){ //from small to big
|
|
|
|
// int rid;
|
|
int rid = -1;
|
|
//still in the same section, very long road section
|
|
if(fabs(last_sec_gp_pos - last_sec_end) > (next_stop_dist + dist_to_jun)){
|
|
last_sec_gp_pos += next_stop_dist;
|
|
rid = sec_list[last_sec_index].rid;
|
|
|
|
}else{//move to the next road section
|
|
next_stop_dist -= fabs(last_sec_gp_pos - last_sec_end);
|
|
for(last_sec_index++;last_sec_index < sec_list.size();last_sec_index++){
|
|
|
|
double cur_start = sec_list[last_sec_index].start;
|
|
double cur_end = sec_list[last_sec_index].end;
|
|
//////////////////////////////////////////////////////
|
|
/* cout<<"rid "<<sec_list[last_sec_index].rid
|
|
<<" secid "<<sec_list[last_sec_index].secttid
|
|
<<" start pos "<<sec_list[last_sec_index].start
|
|
<<" end pos "<<sec_list[last_sec_index].end<<endl; */
|
|
|
|
/////////////////////////////////////////////////////////
|
|
if(fabs(cur_end - cur_start) < 2*dist_to_jun){
|
|
// next_stop_dist -= fabs(cur_end - cur_start);
|
|
double temp_dist = next_stop_dist - fabs(cur_end - cur_start);
|
|
if(temp_dist > 0.0){//if smaller than 0, keep the value, skip the part
|
|
next_stop_dist = temp_dist;
|
|
}
|
|
continue;
|
|
}
|
|
|
|
if(next_stop_dist - fabs(cur_end - cur_start) < 0){
|
|
|
|
if(start_from[last_sec_index]){ //from small to big
|
|
double temp_pos = cur_start + next_stop_dist;
|
|
if(fabs(temp_pos - cur_start) < dist_to_jun)
|
|
temp_pos = cur_start + dist_to_jun;
|
|
if(fabs(cur_end - temp_pos) < dist_to_jun)
|
|
temp_pos = cur_end - dist_to_jun;
|
|
|
|
last_sec_gp_pos = temp_pos;
|
|
}else{ //from big to small
|
|
double temp_pos = cur_end - next_stop_dist;
|
|
if(fabs(temp_pos - cur_end) < dist_to_jun)
|
|
temp_pos = cur_end - dist_to_jun;
|
|
if(fabs(temp_pos - cur_start) < dist_to_jun)
|
|
temp_pos = cur_start + dist_to_jun;
|
|
|
|
last_sec_gp_pos = temp_pos;
|
|
}
|
|
|
|
last_sec_start = cur_start;
|
|
last_sec_end = cur_end;
|
|
rid = sec_list[last_sec_index].rid;
|
|
break;
|
|
}else
|
|
next_stop_dist -= fabs(cur_end - cur_start);
|
|
|
|
}
|
|
if(last_sec_index == sec_list.size()) return false;
|
|
}
|
|
|
|
// cout<<"last_sec_index "<<last_sec_index<<" rid " <<rid<<endl;
|
|
|
|
GPoint* gp =
|
|
new GPoint(true,n->GetId(),rid,last_sec_gp_pos,None);
|
|
bus_stop_loc_1.push_back(*gp);
|
|
|
|
// Point* p = new Point();
|
|
// gp->ToPoint(p);
|
|
// bus_stop_loc_2.push_back(*p);
|
|
// delete p;
|
|
|
|
Point res;
|
|
MyToPoint(n, gp, res);
|
|
assert(res.IsDefined());
|
|
bus_stop_loc_2.push_back(res);
|
|
|
|
gp->DeleteIfAllowed();
|
|
|
|
return true;
|
|
|
|
}else{///from big to small
|
|
|
|
// cout<<"from big to small"<<endl;
|
|
|
|
// int rid;
|
|
int rid = -1;
|
|
//still in the same section, very long road section
|
|
if(fabs(last_sec_gp_pos - last_sec_start) > (next_stop_dist + dist_to_jun)){
|
|
last_sec_gp_pos -= next_stop_dist;
|
|
rid = sec_list[last_sec_index].rid;
|
|
|
|
}else{
|
|
|
|
next_stop_dist -= fabs(last_sec_gp_pos - last_sec_start);
|
|
for(last_sec_index++;last_sec_index < sec_list.size();last_sec_index++){
|
|
|
|
double cur_start = sec_list[last_sec_index].start;
|
|
double cur_end = sec_list[last_sec_index].end;
|
|
////////////////////////////////////////////////////////////////
|
|
// cout<<"cur_start "<<cur_start<<" cur_end "<<cur_end<<endl;
|
|
|
|
/* cout<<"rid "<<sec_list[last_sec_index].rid
|
|
<<" secid "<<sec_list[last_sec_index].secttid
|
|
<<" start pos "<<sec_list[last_sec_index].start
|
|
<<" end pos "<<sec_list[last_sec_index].end<<endl; */
|
|
// cout<<"next_stop_dist "<<next_stop_dist<<endl;
|
|
|
|
////////////////////////////////////////////////////////////////
|
|
if(fabs(cur_end - cur_start) < 2*dist_to_jun){//close to junction area
|
|
double temp_dist = next_stop_dist - fabs(cur_end - cur_start);
|
|
if(temp_dist > 0.0){//if smaller than 0, keep the value, skip the part
|
|
next_stop_dist = temp_dist;
|
|
}
|
|
continue;
|
|
}
|
|
|
|
if(next_stop_dist - fabs(cur_end - cur_start) < 0){
|
|
|
|
if(start_from[last_sec_index]){ //from small to big
|
|
double temp_pos = cur_start + next_stop_dist;
|
|
if(fabs(temp_pos - cur_start) < dist_to_jun)
|
|
temp_pos = cur_start + dist_to_jun;
|
|
if(fabs(cur_end - temp_pos) < dist_to_jun)
|
|
temp_pos = cur_end - dist_to_jun;
|
|
|
|
last_sec_gp_pos = temp_pos;
|
|
}else{ //from big to small
|
|
// cout<<"next_stop_dist "<<next_stop_dist<<endl;
|
|
|
|
double temp_pos = cur_end - next_stop_dist;
|
|
// cout<<"temp_pos "<<temp_pos<<endl;
|
|
|
|
if(fabs(temp_pos - cur_end) < dist_to_jun)
|
|
temp_pos = cur_end - dist_to_jun;
|
|
if(fabs(temp_pos - cur_start) < dist_to_jun)
|
|
temp_pos = cur_start + dist_to_jun;
|
|
|
|
last_sec_gp_pos = temp_pos;
|
|
}
|
|
|
|
// cout<<"last_sec_gp_pos: "<<last_sec_gp_pos<<endl;
|
|
|
|
last_sec_start = cur_start;
|
|
last_sec_end = cur_end;
|
|
rid = sec_list[last_sec_index].rid;
|
|
break;
|
|
}else
|
|
next_stop_dist -= fabs(cur_end - cur_start);
|
|
|
|
}
|
|
if(last_sec_index == sec_list.size()) return false;
|
|
|
|
}
|
|
|
|
GPoint* gp = new GPoint(true,n->GetId(),rid,last_sec_gp_pos,None);
|
|
bus_stop_loc_1.push_back(*gp);
|
|
/* Point* p = new Point();
|
|
gp->ToPoint(p);
|
|
bus_stop_loc_2.push_back(*p);
|
|
delete p;*/
|
|
|
|
Point res;
|
|
MyToPoint(n, gp, res);
|
|
assert(res.IsDefined());
|
|
bus_stop_loc_2.push_back(res);
|
|
|
|
gp->DeleteIfAllowed();
|
|
|
|
return true;
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
if the bus stops are located on the zebra crossing, we modify the position by
|
|
a small distance
|
|
|
|
*/
|
|
void BusRoute::CheckBusStopZC(unsigned int cur_size, Relation* pave_rel,
|
|
BTree* btree_pave)
|
|
{
|
|
for(;cur_size < bus_stop_loc_1.size(); cur_size++){
|
|
|
|
GPoint gp = bus_stop_loc_1[cur_size];
|
|
Point p = bus_stop_loc_2[cur_size];
|
|
int rid = gp.GetRouteId();
|
|
|
|
CcInt* search_id = new CcInt(true, rid);
|
|
BTreeIterator* btree_iter = btree_pave->ExactMatch(search_id);
|
|
|
|
while(btree_iter->Next()){
|
|
Tuple* pave_tuple = pave_rel->GetTuple(btree_iter->GetId(), false);
|
|
Region* reg = (Region*)pave_tuple->GetAttribute(DualGraph::PAVEMENT);
|
|
/////////////////bus stops are on the zebra crossing/////////////////
|
|
if(p.Inside(*reg)){
|
|
// cout<<"br id "<<br_id_list[cur_size]<<" stop id "
|
|
// <<br_stop_id[cur_size]<<endl;
|
|
|
|
Tuple* sec = n->GetSectionOnRoute(&gp);
|
|
double meas1 =
|
|
((CcReal*)sec->GetAttribute(SECTION_MEAS1))->GetRealval();
|
|
double meas2 =
|
|
((CcReal*)sec->GetAttribute(SECTION_MEAS2))->GetRealval();
|
|
// cout<<gp<<endl;
|
|
// cout<<"meas1 "<<meas1<<" meas2 "<<meas2<<endl;
|
|
sec->DeleteIfAllowed();
|
|
double m1 = MIN(meas1, meas2);
|
|
double m2 = MAX(meas1, meas2);
|
|
double pos = gp.GetPosition();
|
|
assert(pos > m1 && pos < m2);
|
|
double delta;
|
|
if((pos - m1) > (m2 - pos)) delta = -2.0;
|
|
else
|
|
delta = 2.0;
|
|
|
|
GPoint* new_gp = new GPoint(gp);
|
|
while(true){
|
|
new_gp->SetPosition(new_gp->GetPosition() + delta);
|
|
Point* new_p = new Point();
|
|
// new_gp->ToPoint(new_p);
|
|
|
|
MyToPoint(n, new_gp, *new_p);
|
|
assert(new_p->IsDefined());
|
|
|
|
if(new_p->Inside(*reg) == false){
|
|
bus_stop_loc_1[cur_size] = *new_gp;
|
|
bus_stop_loc_2[cur_size] = *new_p;
|
|
new_p->DeleteIfAllowed();
|
|
break;
|
|
}
|
|
new_p->DeleteIfAllowed();
|
|
|
|
assert(new_gp->GetPosition() > m1 && new_gp->GetPosition() < m2);
|
|
}
|
|
new_gp->DeleteIfAllowed();
|
|
|
|
}
|
|
pave_tuple->DeleteIfAllowed();
|
|
}
|
|
delete btree_iter;
|
|
search_id->DeleteIfAllowed();
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
merge bus stops
|
|
for several bus stops on the same road section, it might be merge them into one
|
|
the minimum length of road section is 0.055
|
|
the maximum length of road section is 5046.577
|
|
|
|
we merge bus stops that locate on the same road section
|
|
|
|
*/
|
|
|
|
|
|
void BusRoute::CreateBusStop2(int attr1,int attr2,int attr3)
|
|
{
|
|
// cout<<"attr1 "<<attr1<<" attr2 "<<attr2<<" attr3 "<<attr3<<endl;
|
|
// cout<<"CreateBusStop2()"<<endl;
|
|
|
|
vector<BusStop> bus_stop_list;
|
|
|
|
for(int i = 1;i <= rel1->GetNoTuples();i++){
|
|
Tuple* tuple_bus_stop = rel1->GetTuple(i, false);
|
|
|
|
int br_id = ((CcInt*)tuple_bus_stop->GetAttribute(attr1))->GetIntval();
|
|
|
|
/* if(br_id != 108){
|
|
tuple_bus_stop->DeleteIfAllowed();
|
|
continue;
|
|
}*/
|
|
|
|
int stop_id = ((CcInt*)tuple_bus_stop->GetAttribute(attr2))->GetIntval();
|
|
GPoint* gp = (GPoint*)tuple_bus_stop->GetAttribute(attr3);
|
|
// cout<<"br_id "<<br_id<<*gp<<endl;
|
|
|
|
Tuple* temp = n->GetSectionOnRoute(gp);
|
|
assert(temp != NULL);
|
|
|
|
int sid = n->GetSectionOnRoute(gp)->GetTupleId();
|
|
|
|
// cout<<*tuple_bus_stop<<endl;
|
|
// cout<<*n->GetSectionOnRoute(gp)<<endl;
|
|
|
|
BusStop* bs = new BusStop(br_id,stop_id,gp->GetRouteId(),
|
|
gp->GetPosition(), sid, true);
|
|
bus_stop_list.push_back(*bs);
|
|
delete bs;
|
|
|
|
tuple_bus_stop->DeleteIfAllowed();
|
|
}
|
|
sort(bus_stop_list.begin(),bus_stop_list.end());
|
|
|
|
/* for(int i = 0;i < bus_stop_list.size();i++){
|
|
bus_stop_list[i].Print();
|
|
}*/
|
|
////////////////take all stops in one route////////////////////////
|
|
int count = 0;
|
|
for(unsigned int i = 0;i < bus_stop_list.size();i++){
|
|
unsigned int sid = bus_stop_list[i].sid;
|
|
|
|
vector<BusStop> temp_list;
|
|
temp_list.push_back(bus_stop_list[i]);
|
|
|
|
while((i + 1)< bus_stop_list.size() &&
|
|
bus_stop_list[i + 1].sid == sid){
|
|
i++;
|
|
temp_list.push_back(bus_stop_list[i]);
|
|
}
|
|
|
|
MergeBusStop1(temp_list);
|
|
|
|
count += temp_list.size();
|
|
}
|
|
|
|
// cout<<bus_stop_list.size()<<" count "<<count<<endl;
|
|
|
|
}
|
|
|
|
/*
|
|
take all bus stops in the same section and merge some of them if they are close
|
|
to each other. there is one condition:
|
|
after merging, all bus stops should still locate on their original bus routes.
|
|
they can't move to another different route
|
|
|
|
*/
|
|
void BusRoute::MergeBusStop1(vector<BusStop>& stop_list)
|
|
{
|
|
// cout<<"stop_list size "<<stop_list.size()<<endl;
|
|
// cout<<stop_list.size()<<endl;
|
|
if(stop_list.size() == 1){
|
|
br_id_list.push_back(stop_list[0].br_id);
|
|
br_stop_id.push_back(stop_list[0].br_stop_id);
|
|
GPoint* gp = new GPoint(true,n->GetId(),stop_list[0].rid,stop_list[0].pos);
|
|
bus_stop_loc_1.push_back(*gp);
|
|
|
|
/* Point* p = new Point();
|
|
gp->ToPoint(p);
|
|
bus_stop_loc_2.push_back(*p);
|
|
delete p; */
|
|
|
|
Point res;
|
|
MyToPoint(n, gp, res);
|
|
assert(res.IsDefined());
|
|
bus_stop_loc_2.push_back(res);
|
|
|
|
gp->DeleteIfAllowed();
|
|
|
|
// point_id_list.push_back(point_id);
|
|
sec_id_list.push_back(stop_list[0].sid);
|
|
|
|
}else{//there are several bus stops on the same road section
|
|
|
|
//to avoid that two bus stops coming from the same bus route are mereged
|
|
//into one position
|
|
|
|
// const double dist_val = 800.0; //the minimum distance between stops
|
|
const double dist_val = 300.0; //the minimum distance between stops
|
|
const double dist_to_jun = 15.0;//minimum distance between bus stop and jun
|
|
|
|
int sec_id = stop_list[0].sid;
|
|
Tuple* tuple_sec = n->GetSection(sec_id);
|
|
SimpleLine* curve = (SimpleLine*)tuple_sec->GetAttribute(SECTION_CURVE);
|
|
|
|
if(curve->Length() < dist_val){//merge all stops in one position
|
|
double final_pos = 0.0;
|
|
for(unsigned int i = 0;i < stop_list.size();i++){
|
|
// cout<<"stop_list pos "<<stop_list[i].pos<<" ";
|
|
final_pos += stop_list[i].pos;
|
|
}
|
|
|
|
final_pos = final_pos / stop_list.size();
|
|
// cout<<endl<<" final pos "<<final_pos<<endl;
|
|
|
|
int count1 = 0;
|
|
for(unsigned int i = 0;i < stop_list.size();i++){
|
|
|
|
br_id_list.push_back(stop_list[i].br_id);
|
|
br_stop_id.push_back(stop_list[i].br_stop_id);
|
|
GPoint* gp = new GPoint(true,n->GetId(),stop_list[i].rid,final_pos);
|
|
bus_stop_loc_1.push_back(*gp);
|
|
|
|
// cout<<"gp "<<*gp<<endl
|
|
|
|
Point* p = new Point();
|
|
// gp->ToPoint(p);
|
|
MyToPoint(n, gp, *p);
|
|
assert(p->IsDefined());
|
|
bus_stop_loc_2.push_back(*p);
|
|
p->DeleteIfAllowed();
|
|
gp->DeleteIfAllowed();
|
|
count1++;
|
|
|
|
sec_id_list.push_back(stop_list[i].sid);
|
|
}
|
|
|
|
// cout<<"count1 "<<count1<<endl;
|
|
|
|
}else{//partition a road section into severl parts and there is a bus stop
|
|
//for each part
|
|
|
|
double sec_pos1 =
|
|
((CcReal*)tuple_sec->GetAttribute(SECTION_MEAS1))->GetRealval();
|
|
double sec_pos2 =
|
|
((CcReal*)tuple_sec->GetAttribute(SECTION_MEAS2))->GetRealval();
|
|
if(sec_pos1 > sec_pos2){
|
|
double temp = sec_pos1;
|
|
sec_pos1 = sec_pos2;
|
|
sec_pos2 = temp;
|
|
}
|
|
|
|
|
|
// int interval = curve->Length() / dist_val;
|
|
int interval = (int) (curve->Length() / dist_val);
|
|
|
|
/* cout<<"interval "<<interval
|
|
<<"curve length "<<curve->Length()<<endl; */
|
|
|
|
for(unsigned int i = 0;i < stop_list.size();i++){
|
|
double stop_pos = stop_list[i].pos;
|
|
// int interval_pos = stop_pos / dist_val;
|
|
// int interval_pos = (stop_pos - sec_pos1)/ dist_val;
|
|
int interval_pos = (int)((stop_pos - sec_pos1)/ dist_val);
|
|
|
|
/* stop_list[i].Print();
|
|
cout<<"stop_pos "<<stop_pos
|
|
<<" interval_pos "<<interval_pos<<endl; */
|
|
|
|
assert(interval_pos >= 0 && interval_pos <= interval);
|
|
double new_pos = dist_val / 4 + interval_pos*dist_val;
|
|
if(new_pos > curve->Length()){
|
|
// new_pos = interval_pos*dist_val;
|
|
new_pos = curve->Length() - dist_to_jun;
|
|
}
|
|
/////////////////////////////////
|
|
new_pos += sec_pos1;
|
|
/////////////////////////////////
|
|
|
|
br_id_list.push_back(stop_list[i].br_id);
|
|
br_stop_id.push_back(stop_list[i].br_stop_id);
|
|
GPoint* gp = new GPoint(true,n->GetId(),stop_list[i].rid,new_pos);
|
|
bus_stop_loc_1.push_back(*gp);
|
|
|
|
Point* p = new Point();
|
|
// gp->ToPoint(p);
|
|
MyToPoint(n, gp, *p);
|
|
assert(p->IsDefined());
|
|
bus_stop_loc_2.push_back(*p);
|
|
p->DeleteIfAllowed();
|
|
|
|
gp->DeleteIfAllowed();
|
|
|
|
sec_id_list.push_back(stop_list[i].sid);
|
|
}
|
|
|
|
}
|
|
|
|
tuple_sec->DeleteIfAllowed();
|
|
}
|
|
|
|
|
|
}
|
|
|
|
/*
|
|
Merge bus stops locating on different road sections (adjacent)
|
|
use a distance threshold value to expand the bus stop (gpoint) to a gline value
|
|
|
|
after changing the position of some bus stops, they should still locate on
|
|
their original bus route
|
|
|
|
Note: each bus route covers a complete road section or none of it.
|
|
it can't only cover part of a road section
|
|
|
|
It also calculates the startSmaller value for each bus route.
|
|
|
|
very important value startSmaller. It records whether the simpleline starts
|
|
from the small or big. The simpleline comes from coverting gline.
|
|
gline records the shortest path. We have to know after converting where the
|
|
start point is.
|
|
|
|
*/
|
|
void BusRoute::CreateBusStop3(int attr,int attr1,int attr2,int attr3)
|
|
{
|
|
// cout<<"attr "<<attr<<endl;
|
|
// cout<<"attr1 "<<attr1<<" attr2 "<<attr2<<" attr3 "<<attr3<<endl;
|
|
|
|
///////////////// collect all the bus stops ////////////////////////
|
|
vector<BusStop> bus_stop_list;
|
|
for(int i = 1;i <= rel2->GetNoTuples();i++){
|
|
Tuple* tuple_bus_stop = rel2->GetTuple(i, false);
|
|
int br_id = ((CcInt*)tuple_bus_stop->GetAttribute(attr1))->GetIntval();
|
|
int stop_id = ((CcInt*)tuple_bus_stop->GetAttribute(attr2))->GetIntval();
|
|
GPoint* gp = (GPoint*)tuple_bus_stop->GetAttribute(attr3);
|
|
|
|
|
|
int sid = n->GetSectionOnRoute(gp)->GetTupleId();
|
|
|
|
BusStop* bs =
|
|
new BusStop(br_id,stop_id,gp->GetRouteId(),gp->GetPosition(),sid,true);
|
|
|
|
bus_stop_list.push_back(*bs);
|
|
delete bs;
|
|
tuple_bus_stop->DeleteIfAllowed();
|
|
}
|
|
|
|
// cout<<"bus_stop_list size "<<bus_stop_list.size()<<endl;
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// const double dist_val = 500.0; //distance used to expand road section
|
|
// const double dist_val = 300.0; //distance used to expand road section
|
|
const double dist_val = 200.0; //distance used to expand road section
|
|
|
|
int last_br_id = 0;
|
|
vector<SectTreeEntry> sec_list;
|
|
vector<bool> start_from;
|
|
for(unsigned int i = 0;i < bus_stop_list.size();i++){
|
|
|
|
// if(bus_stop_list[i].br_id > 10) continue;
|
|
|
|
|
|
if(bus_stop_list[i].def == false) continue;
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//collect road sections that are with the distance distval to the bus stop/
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//if it is false, it means the section starts from the big value
|
|
//instead of the small value
|
|
|
|
if(bus_stop_list[i].br_id != last_br_id){
|
|
sec_list.clear();
|
|
start_from.clear();
|
|
Tuple* tuple_bus_route = rel1->GetTuple(bus_stop_list[i].br_id,false);
|
|
GLine* gl = (GLine*)tuple_bus_route->GetAttribute(attr);
|
|
GetSectionList(gl, sec_list, start_from);
|
|
tuple_bus_route->DeleteIfAllowed();
|
|
last_br_id = bus_stop_list[i].br_id;
|
|
|
|
///////////////////////////////////////////////////////
|
|
assert(sec_list.size() == start_from.size());
|
|
/* for(unsigned int j = 0;j < sec_list.size();j++){
|
|
cout<<" rid "<<sec_list[j].rid<<" secid "<<sec_list[j].secttid
|
|
<<" start "<<sec_list[j].start<<" end "<<sec_list[j].end
|
|
<<" start from small "<<start_from[j]<<endl;
|
|
}*/
|
|
/////////////////////////////////////////////////////////
|
|
}
|
|
/////////find the position of this bus stop in section/////////////
|
|
int sec_index = -1;
|
|
for(unsigned int j = 0;j < sec_list.size();j++){
|
|
if(sec_list[j].secttid == bus_stop_list[i].sid){
|
|
sec_index = j;
|
|
break;
|
|
}
|
|
}
|
|
assert(sec_index != -1);
|
|
|
|
/////////////// find the up adjacent sections //////////////////////////
|
|
vector<SectTreeEntry> sec_down;
|
|
vector<SectTreeEntry> sec_up;
|
|
//we only consider adjacent section.
|
|
//the same section has been processed before
|
|
if(start_from[sec_index])
|
|
{
|
|
if(fabs(bus_stop_list[i].pos - sec_list[sec_index].start) < dist_val){
|
|
FindDownSection(bus_stop_list[i].pos,sec_list,sec_index,
|
|
dist_val,sec_down,start_from);
|
|
}
|
|
/////////////// find the down adjacent sections ///////////////////////
|
|
|
|
if(fabs(bus_stop_list[i].pos - sec_list[sec_index].end) < dist_val){
|
|
FindUpSection(bus_stop_list[i].pos,sec_list,sec_index,
|
|
dist_val,sec_up,start_from);
|
|
}
|
|
|
|
}else{
|
|
|
|
if(fabs(bus_stop_list[i].pos - sec_list[sec_index].end) < dist_val){
|
|
FindDownSection(bus_stop_list[i].pos,sec_list,sec_index,
|
|
dist_val,sec_down,start_from);
|
|
}
|
|
/////////////// find the down adjacent sections ///////////////////////
|
|
if(fabs(bus_stop_list[i].pos - sec_list[sec_index].start) < dist_val){
|
|
FindUpSection(bus_stop_list[i].pos,sec_list,sec_index,
|
|
dist_val,sec_up,start_from);
|
|
}
|
|
}
|
|
//////////////////////////////////////////////////////////////////////
|
|
/* cout<<"bus route down direction"<<endl;
|
|
for(unsigned int j = 0;j < sec_down.size();j++){
|
|
cout<<" rid "<<sec_down[j].rid<<" secid "<<sec_down[j].secttid
|
|
<<" start "<<sec_down[j].start<<" end "<<sec_down[j].end<<endl;
|
|
}
|
|
|
|
cout<<"bus route up direction"<<endl;
|
|
for(unsigned int j = 0;j < sec_up.size();j++){
|
|
cout<<" rid "<<sec_up[j].rid<<" secid "<<sec_up[j].secttid
|
|
<<" start "<<sec_up[j].start<<" end "<<sec_up[j].end<<endl;
|
|
}*/
|
|
/////////////////////////////////////////////////////////////////////
|
|
////////collect all bus stops on these sections/////////////////////
|
|
////////////////////////////////////////////////////////////////////
|
|
MergeBusStop2(sec_down,sec_up,bus_stop_list,i,attr);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
///////////////clear some redundant stops after merging////////////////
|
|
///////////////clear some stops are too close or equal to each other////
|
|
////////////////////////////////////////////////////////////////////////
|
|
vector<BusStop> temp_bus_stop_list;
|
|
int last_br = 0;
|
|
const double delta_dist = 50.0;
|
|
for(unsigned int i = 0;i < bus_stop_list.size();i++){
|
|
if(temp_bus_stop_list.size() == 0){
|
|
temp_bus_stop_list.push_back(bus_stop_list[i]);
|
|
last_br = bus_stop_list[i].br_id;
|
|
}else{
|
|
if(bus_stop_list[i].br_id != last_br){
|
|
temp_bus_stop_list.push_back(bus_stop_list[i]);
|
|
last_br = bus_stop_list[i].br_id;
|
|
}else{
|
|
BusStop tmp_bs = temp_bus_stop_list[temp_bus_stop_list.size() - 1];
|
|
if(fabs(tmp_bs.pos - bus_stop_list[i].pos) > delta_dist){
|
|
int sid1 = tmp_bs.br_stop_id;
|
|
int sid2 = bus_stop_list[i].br_stop_id;
|
|
if(fabs(sid1 - sid2) > 1){
|
|
if(sid1 < sid2)
|
|
bus_stop_list[i].br_stop_id = sid1 + 1;
|
|
else if(sid1 > sid2)
|
|
bus_stop_list[i].br_stop_id = sid1 - 1;
|
|
else assert(false);
|
|
}
|
|
temp_bus_stop_list.push_back(bus_stop_list[i]);
|
|
last_br = bus_stop_list[i].br_id;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
bus_stop_list.clear();
|
|
for(unsigned int i = 0;i < temp_bus_stop_list.size();i++)
|
|
bus_stop_list.push_back(temp_bus_stop_list[i]);
|
|
/////////////////////////////////////////////////////////////////////
|
|
///////////////////////get the result///////////////////////////////
|
|
for(unsigned int i = 0;i < bus_stop_list.size();i++){
|
|
br_id_list.push_back(bus_stop_list[i].br_id);
|
|
br_stop_id.push_back(bus_stop_list[i].br_stop_id);
|
|
sec_id_list.push_back(bus_stop_list[i].sid);
|
|
int rid = bus_stop_list[i].rid;
|
|
double pos = bus_stop_list[i].pos;
|
|
GPoint* gp = new GPoint(true,n->GetId(),rid,pos,None);
|
|
bus_stop_loc_1.push_back(*gp);
|
|
|
|
Point* p = new Point();
|
|
// gp->ToPoint(p);
|
|
MyToPoint(n, gp, *p);
|
|
assert(p->IsDefined());
|
|
bus_stop_loc_2.push_back(*p);
|
|
p->DeleteIfAllowed();
|
|
gp->DeleteIfAllowed();
|
|
}
|
|
///////////////////////calculate the startsmaller value/////////////
|
|
|
|
unsigned int index = 0;
|
|
for(int i = 1;i <= rel1->GetNoTuples();i++){
|
|
|
|
Tuple* tuple_bus_route = rel1->GetTuple(i, false);
|
|
GLine* gl = (GLine*)tuple_bus_route->GetAttribute(attr);
|
|
|
|
vector<bool> start_from; //or end_from
|
|
vector<SectTreeEntry> sec_list;
|
|
|
|
GetSectionList(gl, sec_list, start_from);
|
|
/////collect bus stops from the same bus route /////
|
|
int start = index;
|
|
while(bus_stop_list[index].br_id == i && index < bus_stop_list.size()){
|
|
index++;
|
|
}
|
|
int end = index;
|
|
// cout<<"br_id "<<i<<" ";
|
|
vector<double> dist_list;
|
|
|
|
////////////get the startsmaller value //////////////////////////////
|
|
Line* l = new Line(0);
|
|
gl->Gline2line(l);
|
|
SimpleLine* sl = new SimpleLine(0);
|
|
sl->fromLine(*l);
|
|
|
|
|
|
CalculateStartSmaller(bus_stop_list,start,end,sec_list,
|
|
start_from, dist_list, sl);
|
|
sl->DeleteIfAllowed();
|
|
l->DeleteIfAllowed();
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
tuple_bus_route->DeleteIfAllowed();
|
|
}
|
|
|
|
assert(bus_stop_list.size() == startSmaller.size());
|
|
}
|
|
|
|
/*
|
|
Merge bus stops that locate on adjacent road sections
|
|
|
|
*/
|
|
void BusRoute::MergeBusStop2(vector<SectTreeEntry> sec_down,
|
|
vector<SectTreeEntry> sec_up,
|
|
vector<BusStop>& bus_stop_list,
|
|
int cur_index, int attr)
|
|
{
|
|
vector<SectTreeEntry> sec_all;
|
|
for(unsigned int i = 0;i < sec_down.size();i++)
|
|
sec_all.push_back(sec_down[i]);
|
|
|
|
for(unsigned int i = 0;i < sec_up.size();i++){
|
|
if(sec_down.size() > 0 &&
|
|
sec_up[i].secttid == sec_down[0].secttid)continue; //the same section
|
|
|
|
sec_all.push_back(sec_up[i]);
|
|
}
|
|
|
|
if(sec_all.size() > 0){
|
|
vector<int> bus_stop_id_list;
|
|
for(unsigned int i = 0;i < sec_all.size();i++){
|
|
int sec_id = sec_all[i].secttid;
|
|
double start = sec_all[i].start;
|
|
double end = sec_all[i].end;
|
|
/////////collect all bus stops on these sections/////////////
|
|
|
|
CcInt* search_cell_id = new CcInt(true, sec_id);
|
|
BTreeIterator* btree_iter = btree->ExactMatch(search_cell_id);
|
|
while(btree_iter->Next()){
|
|
|
|
int tuple_id = btree_iter->GetId();
|
|
if(tuple_id - 1 != cur_index){//do not include itself
|
|
if(start <= bus_stop_list[tuple_id - 1].pos &&
|
|
bus_stop_list[tuple_id - 1].pos <= end){//bus stop locate on it
|
|
bus_stop_id_list.push_back(tuple_id - 1);
|
|
|
|
}
|
|
}
|
|
}
|
|
delete btree_iter;
|
|
search_cell_id->DeleteIfAllowed();
|
|
|
|
}
|
|
//check whether the route of the bus stop changed position /////////////
|
|
/////////////////has the section id //////////
|
|
//do not merge bus stops come from the same route /////////////
|
|
vector<int> bus_stop_id_list_new;
|
|
vector<int> br_id_array;
|
|
br_id_array.push_back(bus_stop_list[cur_index].br_id);
|
|
|
|
for(unsigned int i = 0;i < bus_stop_id_list.size();i++){
|
|
|
|
unsigned int j = 0;
|
|
for(;j < br_id_array.size();j++){
|
|
int index = bus_stop_id_list[i];
|
|
BusStop bs = bus_stop_list[index];
|
|
if(bs.br_id == br_id_array[j])
|
|
break;
|
|
}
|
|
if(j == br_id_array.size()){
|
|
bus_stop_id_list_new.push_back(bus_stop_id_list[i]);
|
|
BusStop bs = bus_stop_list[bus_stop_id_list[i]];
|
|
br_id_array.push_back(bs.br_id);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// for(unsigned int i = 0;i < bus_stop_id_list.size();i++){
|
|
for(unsigned int i = 0;i < bus_stop_id_list_new.size();i++){
|
|
// int index = bus_stop_id_list[i];
|
|
int index = bus_stop_id_list_new[i];
|
|
BusStop bs = bus_stop_list[index];
|
|
int br_id = bs.br_id;
|
|
Tuple* tuple_bus_route = rel1->GetTuple(br_id,false);
|
|
GLine* gl = (GLine*)tuple_bus_route->GetAttribute(attr);
|
|
|
|
vector<SectTreeEntry> sec_list;
|
|
vector<bool> start_from;
|
|
GetSectionList(gl, sec_list, start_from);
|
|
for(unsigned int j = 0;j < sec_list.size();j++){
|
|
if(sec_list[j].secttid == bus_stop_list[cur_index].sid){
|
|
//do not move bus stops that come from the same bus route
|
|
|
|
bus_stop_list[index].rid = bus_stop_list[cur_index].rid;
|
|
bus_stop_list[index].pos = bus_stop_list[cur_index].pos;
|
|
bus_stop_list[index].sid = bus_stop_list[cur_index].sid;
|
|
|
|
|
|
bus_stop_list[cur_index].def = false;
|
|
bus_stop_list[index].def = false;
|
|
break;
|
|
}
|
|
}
|
|
tuple_bus_route->DeleteIfAllowed();
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
find the section to down direction. bus route goes down
|
|
|
|
*/
|
|
|
|
void BusRoute::FindDownSection(double cur_bus_stop_pos,
|
|
vector<SectTreeEntry> sec_list,int sec_index,
|
|
const double dist_val,
|
|
vector<SectTreeEntry>& sec_down,vector<bool> start_from)
|
|
|
|
{
|
|
double temp_dist;
|
|
if(start_from[sec_index]){
|
|
int secttid = sec_list[sec_index].secttid;
|
|
int rid = sec_list[sec_index].rid;
|
|
double start = sec_list[sec_index].start;
|
|
double end = cur_bus_stop_pos;
|
|
SectTreeEntry* tmp_entry =
|
|
new SectTreeEntry(secttid,rid,start,end,true,true);
|
|
sec_down.push_back(*tmp_entry);
|
|
delete tmp_entry;
|
|
temp_dist = dist_val - fabs(end - start);
|
|
}else{
|
|
int secttid = sec_list[sec_index].secttid;
|
|
int rid = sec_list[sec_index].rid;
|
|
double start = cur_bus_stop_pos;
|
|
double end = sec_list[sec_index].end;
|
|
SectTreeEntry* tmp_entry =
|
|
new SectTreeEntry(secttid,rid,start,end,true,true);
|
|
sec_down.push_back(*tmp_entry);
|
|
delete tmp_entry;
|
|
temp_dist = dist_val - fabs(end - start);
|
|
}
|
|
|
|
int temp_index = sec_index;
|
|
while(temp_dist > 0.0){
|
|
temp_index--;
|
|
if(temp_index >= 0){
|
|
SectTreeEntry entry = sec_list[temp_index];
|
|
|
|
if(temp_dist - fabs(entry.start - entry.end) > 0){
|
|
sec_down.push_back(entry);
|
|
temp_dist -= fabs(entry.start - entry.end);
|
|
}else{
|
|
if(start_from[temp_index] == false){
|
|
|
|
int secttid = entry.secttid;
|
|
int rid = entry.rid;
|
|
double start = entry.start;
|
|
double end = start + temp_dist;
|
|
SectTreeEntry* temp_entry =
|
|
new SectTreeEntry(secttid,rid,start,end,true,true);
|
|
sec_down.push_back(*temp_entry);
|
|
delete temp_entry;
|
|
temp_dist -= fabs(entry.start - entry.end);
|
|
|
|
}else{
|
|
int secttid = entry.secttid;
|
|
int rid = entry.rid;
|
|
double start = entry.end - temp_dist;
|
|
double end = entry.end;
|
|
SectTreeEntry* temp_entry =
|
|
new SectTreeEntry(secttid,rid,start,end,true,true);
|
|
sec_down.push_back(*temp_entry);
|
|
delete temp_entry;
|
|
temp_dist -= fabs(entry.start - entry.end);
|
|
}
|
|
}
|
|
}else break;
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
find the section to up direction. bus route goes up
|
|
|
|
*/
|
|
|
|
void BusRoute::FindUpSection(double cur_bus_stop_pos,
|
|
vector<SectTreeEntry> sec_list,int sec_index,
|
|
const double dist_val,
|
|
vector<SectTreeEntry>& sec_up,vector<bool> start_from)
|
|
|
|
{
|
|
double temp_dist;
|
|
if(start_from[sec_index]){
|
|
int secttid = sec_list[sec_index].secttid;
|
|
int rid = sec_list[sec_index].rid;
|
|
double start = cur_bus_stop_pos;
|
|
double end = sec_list[sec_index].end;
|
|
SectTreeEntry* tmp_entry =
|
|
new SectTreeEntry(secttid,rid,start,end,true,true);
|
|
sec_up.push_back(*tmp_entry);
|
|
delete tmp_entry;
|
|
|
|
temp_dist = dist_val - fabs(end - start);
|
|
|
|
}else{
|
|
int secttid = sec_list[sec_index].secttid;
|
|
int rid = sec_list[sec_index].rid;
|
|
double start = sec_list[sec_index].start;
|
|
double end = cur_bus_stop_pos;
|
|
SectTreeEntry* tmp_entry =
|
|
new SectTreeEntry(secttid,rid,start,end,true,true);
|
|
sec_up.push_back(*tmp_entry);
|
|
delete tmp_entry;
|
|
|
|
temp_dist = dist_val - fabs(end - start);
|
|
|
|
}
|
|
|
|
unsigned int temp_index = sec_index;
|
|
while(temp_dist > 0.0){
|
|
temp_index++;
|
|
if(temp_index < sec_list.size()){
|
|
|
|
SectTreeEntry entry = sec_list[temp_index];
|
|
|
|
if(temp_dist - fabs(entry.start - entry.end) > 0){
|
|
sec_up.push_back(entry);
|
|
temp_dist -= fabs(entry.start - entry.end);
|
|
}else{
|
|
if(start_from[temp_index]){
|
|
|
|
int secttid = entry.secttid;
|
|
int rid = entry.rid;
|
|
double start = entry.start;
|
|
double end = start + temp_dist;
|
|
SectTreeEntry* temp_entry =
|
|
new SectTreeEntry(secttid,rid,start,end,true,true);
|
|
sec_up.push_back(*temp_entry);
|
|
delete temp_entry;
|
|
temp_dist -= fabs(entry.start - entry.end);
|
|
|
|
}else{
|
|
int secttid = entry.secttid;
|
|
int rid = entry.rid;
|
|
double start = entry.end - temp_dist;
|
|
double end = entry.end;
|
|
SectTreeEntry* temp_entry =
|
|
new SectTreeEntry(secttid,rid,start,end,true,true);
|
|
sec_up.push_back(*temp_entry);
|
|
delete temp_entry;
|
|
temp_dist -= fabs(entry.start - entry.end);
|
|
}
|
|
}
|
|
}else break;
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
convert a gline object to a list of section representations
|
|
|
|
*/
|
|
|
|
void BusRoute::GetSectionList(GLine* gl,vector<SectTreeEntry>& sec_list,
|
|
vector<bool>& start_from)
|
|
{
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
for(int i = 0; i < gl->Size();i++){
|
|
RouteInterval* ri = new RouteInterval();
|
|
gl->Get(i, *ri);
|
|
|
|
// cout<<"rid "<<ri->GetRouteId()
|
|
// <<"start "<<ri->GetStartPos()
|
|
// <<"end "<<ri->GetEndPos()<<endl;
|
|
|
|
if(!AlmostEqual(ri->GetStartPos(), ri->GetEndPos())){
|
|
|
|
vector<SectTreeEntry> actSections;
|
|
n->GetSectionsOfRouteInterval(ri,actSections);
|
|
|
|
SectTreeEntry nEntry;
|
|
|
|
vector<SectTreeEntry> sec_list_temp;
|
|
|
|
for(unsigned int j = 0;j < actSections.size();j++){
|
|
nEntry = actSections[j];
|
|
|
|
////////////////////////////////////////////////////
|
|
// cout<<"entry "<<nEntry.rid
|
|
// <<" start "<<nEntry.start
|
|
// <<" end "<<nEntry.end<<endl;
|
|
|
|
if(AlmostEqual(nEntry.start,nEntry.end))continue;
|
|
|
|
sec_list_temp.push_back(nEntry);
|
|
|
|
if(ri->GetStartPos() < ri->GetEndPos()) start_from.push_back(true);
|
|
else
|
|
start_from.push_back(false);
|
|
|
|
}
|
|
|
|
if(ri->GetStartPos() < ri->GetEndPos()){
|
|
for(unsigned int k = 0;k < sec_list_temp.size();k++)
|
|
sec_list.push_back(sec_list_temp[k]);
|
|
}else{
|
|
for(int k = sec_list_temp.size() - 1;k >= 0;k--)
|
|
sec_list.push_back(sec_list_temp[k]);
|
|
}
|
|
|
|
|
|
}
|
|
delete ri;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
change the representation for bus stop, get the pos value.
|
|
i.e., the relative position on its bus route
|
|
|
|
*/
|
|
void BusRoute::CalculateStartSmaller(vector<BusStop>& bus_stop_list,
|
|
int start, int end,
|
|
vector<SectTreeEntry>& sec_list,
|
|
vector<bool>& start_from,
|
|
vector<double>& dist_list, SimpleLine* sl)
|
|
{
|
|
// cout<<"start "<<start<<" end "<<end<<endl;
|
|
double dist = 0.0;
|
|
unsigned int bus_stop_index = start;
|
|
|
|
// bool startsmaller;
|
|
bool startsmaller = true;
|
|
bool initialize = false;
|
|
///////////use the section list of the bus route/////////////////
|
|
//////////bus stops are ordered from id small to id big///////////
|
|
|
|
for(unsigned int i = 0;i < sec_list.size();i++){
|
|
unsigned int sec_id = sec_list[i].secttid;
|
|
double start = sec_list[i].start;
|
|
double end = sec_list[i].end;
|
|
|
|
// cout<<"sec_id "<<sec_id
|
|
// <<" busstop sec id "<<bus_stop_list[bus_stop_index].sid<<endl;
|
|
|
|
//find the section where the bus stop locates
|
|
while(bus_stop_list[bus_stop_index].sid == sec_id){
|
|
double temp_dist = 0.0;
|
|
if(start_from[i]){
|
|
temp_dist = fabs(bus_stop_list[bus_stop_index].pos - start);
|
|
dist += temp_dist;
|
|
// cout<<"pos1 "<<dist<<endl;
|
|
dist_list.push_back(dist);
|
|
}else{
|
|
temp_dist = fabs(bus_stop_list[bus_stop_index].pos - end);
|
|
dist += temp_dist;
|
|
// cout<<"pos2 "<<dist<<endl;
|
|
dist_list.push_back(dist);
|
|
}
|
|
///////////////////////////////////////////////////////////////
|
|
|
|
int rid = bus_stop_list[bus_stop_index].rid;
|
|
double pos = bus_stop_list[bus_stop_index].pos;
|
|
GPoint* gp = new GPoint(true, n->GetId(), rid, pos, None);
|
|
Point* p = new Point();
|
|
// gp->ToPoint(p);
|
|
MyToPoint(n, gp, *p);
|
|
assert(p->IsDefined());
|
|
|
|
//////////////////////////////////////////////////////////////
|
|
if(initialize == false){
|
|
Point temp_p;
|
|
assert(sl->AtPosition(dist, true, temp_p));
|
|
const double dist_delta = 1.0;
|
|
if(temp_p.Distance(*p) < dist_delta)
|
|
startsmaller = true;
|
|
else
|
|
startsmaller = false;
|
|
|
|
initialize = true;
|
|
/* cout<<"loc1 "<<*p<<" loc2 "<<temp_p
|
|
<<" startsmaller "<<startsmaller<<endl; */
|
|
}
|
|
|
|
startSmaller.push_back(startsmaller);
|
|
|
|
//////////////////////////////////////////////////////////////
|
|
p->DeleteIfAllowed();
|
|
gp->DeleteIfAllowed();
|
|
//////////////////////////////////////////////////////////////
|
|
bus_stop_index++;
|
|
dist -= temp_dist;
|
|
}
|
|
|
|
if(bus_stop_list[bus_stop_index].sid != sec_id)
|
|
dist += fabs(start - end);
|
|
}
|
|
|
|
assert((int)dist_list.size() == (end - start));
|
|
}
|
|
|
|
/*
|
|
change the position of bus stops after translate the bus route: down and up
|
|
and for each route, it gets pos value.
|
|
bus stops on up direction are from small to big
|
|
bus tops on down direction are from big to small, but the pos value is set
|
|
according to the smaller start point
|
|
|
|
*/
|
|
void BusRoute::CreateBusStop4(int attr_a,int attr_b,int attr1,int attr2,
|
|
int attr3, int attr4)
|
|
{
|
|
// cout<<"attr_a "<<attr_a<<" attr_b "<<attr_b<<" attr1 "<<attr1
|
|
// <<" attr2 "<<attr2<<" attr3 "<<attr3<<" attr4 "<<attr4<<endl;
|
|
|
|
vector<BusStop_Ext> bus_stop_list;
|
|
for(int i = 1;i <= rel2->GetNoTuples();i++){
|
|
Tuple* tuple_bus_stop = rel2->GetTuple(i, false);
|
|
int br_id = ((CcInt*)tuple_bus_stop->GetAttribute(attr1))->GetIntval();
|
|
int stop_id =
|
|
((CcInt*)tuple_bus_stop->GetAttribute(attr2))->GetIntval();
|
|
Point* loc = (Point*)tuple_bus_stop->GetAttribute(attr3);
|
|
|
|
bool start_small =
|
|
((CcBool*)tuple_bus_stop->GetAttribute(attr4))->GetBoolval();
|
|
|
|
BusStop_Ext* bse = new BusStop_Ext(br_id,stop_id,0,*loc,start_small);
|
|
bus_stop_list.push_back(*bse);
|
|
delete bse;
|
|
tuple_bus_stop->DeleteIfAllowed();
|
|
}
|
|
|
|
sort(bus_stop_list.begin(), bus_stop_list.end());
|
|
|
|
/* for(unsigned int i = 0;i < bus_stop_list.size();i++)
|
|
bus_stop_list[i].Print(); */
|
|
|
|
vector<Line> line_list1;
|
|
|
|
vector<Line> line_list2;
|
|
vector<SimpleLine> sline_list;
|
|
|
|
|
|
vector<bool> bus_route_direction;
|
|
|
|
for(int i = 1;i <= rel1->GetNoTuples();i+= 2){
|
|
Tuple* tuple_bus_route1 = rel1->GetTuple(i, false);
|
|
Tuple* tuple_bus_route2 = rel1->GetTuple(i + 1, false);
|
|
Line* l = (Line*)tuple_bus_route1->GetAttribute(attr_a);
|
|
Line* l1 = (Line*)tuple_bus_route1->GetAttribute(attr_b);
|
|
Line* l2 = (Line*)tuple_bus_route2->GetAttribute(attr_b);
|
|
SimpleLine* sl1 = new SimpleLine(0);
|
|
SimpleLine* sl2 = new SimpleLine(0);
|
|
sl1->fromLine(*l1);
|
|
sl2->fromLine(*l2);
|
|
|
|
line_list1.push_back(*l);
|
|
|
|
line_list2.push_back(*l1);
|
|
line_list2.push_back(*l2);
|
|
sline_list.push_back(*sl1);
|
|
sline_list.push_back(*sl2);
|
|
|
|
if(sl1->Length() < 1.0 || sl2->Length() < 1.0){
|
|
cout<<i<<endl;
|
|
cout<<"not correct routes"<<endl;
|
|
assert(false);
|
|
}
|
|
|
|
sl1->DeleteIfAllowed();
|
|
sl2->DeleteIfAllowed();
|
|
|
|
tuple_bus_route1->DeleteIfAllowed();
|
|
tuple_bus_route2->DeleteIfAllowed();
|
|
|
|
}
|
|
|
|
// cout<<"line list size "<<line_list1.size()
|
|
// <<" sline list size "<<sline_list.size()<<endl;
|
|
|
|
const double dist_delta = 0.01;
|
|
int stop_loc_id = 1; //unique spatial location before transfer up and down
|
|
|
|
for(unsigned int i = 0;i < bus_stop_list.size();i++){
|
|
vector<BusStop_Ext> bus_stop_list_new;
|
|
|
|
bus_stop_list_new.push_back(bus_stop_list[i]);
|
|
|
|
////////collect all bus stops mapping to the same 2D point in space/////
|
|
unsigned int j = i + 1;
|
|
BusStop_Ext bse = bus_stop_list_new[0];
|
|
|
|
while(j < bus_stop_list.size() &&
|
|
bus_stop_list[j].loc.Distance(bse.loc) < dist_delta ){
|
|
bus_stop_list_new.push_back(bus_stop_list[j]);
|
|
j++;
|
|
}
|
|
i = j - 1;
|
|
|
|
////////////get the intersection point//////////////////////////////
|
|
BusStop_Ext bse_0 = bus_stop_list_new[0];
|
|
|
|
// bse_0.Print();
|
|
|
|
Line* l = &line_list1[bse_0.br_id - 1];
|
|
HalfSegment hs;
|
|
int index = -1;
|
|
|
|
double hs_p_dist = numeric_limits<double>::max();
|
|
int temp_index = -1;
|
|
|
|
for(index = 0;index < l->Size();index++){
|
|
l->Get(index, hs);
|
|
if(hs.IsLeftDomPoint() == false)continue;
|
|
if(hs.Contains(bse_0.loc))break;
|
|
if(hs.Distance(bse_0.loc) < hs_p_dist){ //solve numeric problem
|
|
hs_p_dist = hs.Distance(bse_0.loc);
|
|
temp_index = index;
|
|
}
|
|
}
|
|
|
|
if(index == -1 || index == l->Size()){
|
|
if(temp_index != -1){
|
|
l->Get(temp_index, hs);
|
|
}else{
|
|
cout<<"can't find the point (might be numeric problem)"<<endl;
|
|
assert(false);
|
|
}
|
|
}
|
|
|
|
// cout<<"hs "<<hs<<endl;
|
|
|
|
|
|
//for each translated bus route simple
|
|
|
|
for(unsigned int k = 0;k < bus_stop_list_new.size();k++){
|
|
|
|
BusStop_Ext bs_ext = bus_stop_list_new[k];
|
|
|
|
// SimpleLine* sl1 = &sline_list[(bse_0.br_id * 2 - 1) - 1];
|
|
// SimpleLine* sl2 = &sline_list[(bse_0.br_id * 2 ) - 1];
|
|
|
|
// bool sm = bse_0.start_small;
|
|
bool sm = bs_ext.start_small;
|
|
double pos1,pos2;
|
|
|
|
// cout<<"br_id "<<bs_ext.br_id<<"bs_stop_id "<<bs_ext.br_stop_id<<endl;
|
|
|
|
Line* l1 = &line_list2[(bs_ext.br_id * 2 - 1) - 1];
|
|
Line* l2 = &line_list2[(bs_ext.br_id * 2) - 1];
|
|
|
|
vector<MyPoint> intersect_ps;
|
|
GetInterestingPoints(hs, bse_0.loc, intersect_ps, l1, l2);
|
|
|
|
assert(intersect_ps.size() == 2);
|
|
|
|
// cout<<"0 "<<intersect_ps[0].loc
|
|
// <<" 1 "<<intersect_ps[1].loc<<endl;
|
|
|
|
SimpleLine* sl1 = &sline_list[(bs_ext.br_id * 2 - 1) - 1];
|
|
SimpleLine* sl2 = &sline_list[(bs_ext.br_id * 2 ) - 1];
|
|
|
|
|
|
// assert(sl1->AtPoint(intersect_ps[0].loc,sm,pos1));
|
|
// assert(sl2->AtPoint(intersect_ps[1].loc,sm,pos2));
|
|
|
|
//to solve numeric problem
|
|
if(sl1->AtPoint(intersect_ps[0].loc,sm,pos1) == false)
|
|
assert(MyAtPoint(sl1,intersect_ps[0].loc,sm,pos1,dist_delta));
|
|
//to solve numeric problem
|
|
if(sl2->AtPoint(intersect_ps[1].loc,sm,pos2) == false)
|
|
assert(MyAtPoint(sl2,intersect_ps[1].loc,sm,pos2,dist_delta));
|
|
|
|
// cout<<"pos1 "<<pos1<<" pos2 "<<pos2<<endl;
|
|
|
|
br_id_list.push_back(bs_ext.br_id);
|
|
br_uid_list.push_back(bs_ext.br_id*2 - 1);//line l1
|
|
br_stop_id.push_back(bs_ext.br_stop_id);
|
|
start_gp.push_back(bs_ext.loc);
|
|
end_gp.push_back(intersect_ps[0].loc);
|
|
bus_stop_loc_3.push_back(pos1);
|
|
// bus_sections1.push_back(*l1); /////////////for debuging/////////
|
|
|
|
/// unique spatial location: no up and down
|
|
stop_loc_id_list.push_back(stop_loc_id);
|
|
|
|
|
|
br_id_list.push_back(bs_ext.br_id);
|
|
br_stop_id.push_back(bs_ext.br_stop_id);
|
|
br_uid_list.push_back(bs_ext.br_id*2);//line l2
|
|
start_gp.push_back(bs_ext.loc);
|
|
end_gp.push_back(intersect_ps[1].loc);
|
|
bus_stop_loc_3.push_back(pos2);
|
|
// bus_sections1.push_back(*l2); /////////////for debuging/////////
|
|
|
|
/// unique spatial location: no up and down
|
|
stop_loc_id_list.push_back(stop_loc_id);///// unique spatial location
|
|
|
|
}
|
|
|
|
stop_loc_id++;//another differnt spatial location in space
|
|
}
|
|
|
|
////////////// relation ///////////////////////////
|
|
///////////// br uid = br id * 2 -1////////line l1 ///
|
|
//////////// br uid = br id * 2 //////////line l2 ///
|
|
//////////////////////////////////////////////////////
|
|
}
|
|
|
|
|
|
/*
|
|
get the intersecting points between the create small line and two bus routes
|
|
|
|
*/
|
|
|
|
void BusRoute::GetInterestingPoints(HalfSegment hs, Point ip,
|
|
vector<MyPoint>& list,
|
|
Line* reg1, Line* reg2)
|
|
{
|
|
Point p1 = hs.GetLeftPoint();
|
|
Point p2 = hs.GetRightPoint();
|
|
|
|
const double delta_dist = 10.0;
|
|
Line* line1 = new Line(0);
|
|
|
|
if(MyAlmostEqual(p1.GetX(), p2.GetX())){
|
|
double y = ip.GetY();
|
|
double x1 = ip.GetX() - delta_dist;
|
|
double x2 = ip.GetX() + delta_dist;
|
|
|
|
line1->StartBulkLoad();
|
|
HalfSegment hs;
|
|
Point lp,rp;
|
|
lp.Set(x1, y);
|
|
rp.Set(x2, y);
|
|
hs.Set(true,lp,rp);
|
|
int edgeno = 0;
|
|
hs.attr.edgeno = edgeno++;
|
|
*line1 += hs;
|
|
hs.SetLeftDomPoint(!hs.IsLeftDomPoint());
|
|
*line1 += hs;
|
|
line1->EndBulkLoad();
|
|
|
|
}else if(MyAlmostEqual(p1.GetY(), p2.GetY())){
|
|
double y1 = ip.GetY() - delta_dist;
|
|
double y2 = ip.GetY() + delta_dist;
|
|
double x = ip.GetX();
|
|
|
|
line1->StartBulkLoad();
|
|
HalfSegment hs;
|
|
Point lp,rp;
|
|
lp.Set(x, y1);
|
|
rp.Set(x, y2);
|
|
hs.Set(true,lp,rp);
|
|
int edgeno = 0;
|
|
hs.attr.edgeno = edgeno++;
|
|
*line1 += hs;
|
|
hs.SetLeftDomPoint(!hs.IsLeftDomPoint());
|
|
*line1 += hs;
|
|
line1->EndBulkLoad();
|
|
|
|
|
|
}else{//not vertical
|
|
double k1 = (p2.GetY() - p1.GetY())/(p2.GetX() - p1.GetX());
|
|
double k2 = -1/k1;
|
|
double c2 = ip.GetY() - ip.GetX()*k2;
|
|
|
|
double x1 = ip.GetX() - delta_dist;
|
|
double x2 = ip.GetX() + delta_dist;
|
|
|
|
|
|
line1->StartBulkLoad();
|
|
HalfSegment hs;
|
|
Point lp,rp;
|
|
lp.Set(x1, x1*k2 + c2);
|
|
rp.Set(x2, x2*k2 + c2);
|
|
hs.Set(true,lp,rp);
|
|
int edgeno = 0;
|
|
hs.attr.edgeno = edgeno++;
|
|
*line1 += hs;
|
|
hs.SetLeftDomPoint(!hs.IsLeftDomPoint());
|
|
*line1 += hs;
|
|
line1->EndBulkLoad();
|
|
}
|
|
|
|
// cout<<"ip "<<ip<<" created line "<<*line1<<endl;
|
|
|
|
Points* ps1 = new Points(0);
|
|
Points* ps2 = new Points(0);
|
|
line1->Crossings(*reg1, *ps1);
|
|
line1->Crossings(*reg2, *ps2);
|
|
|
|
// cout<<l1->Size()<<" "<<l2->Size()<<endl;
|
|
// cout<<*line1<<endl;
|
|
// cout<<ps1->Size()<<" "<<ps2->Size()<<endl;
|
|
|
|
if(ps1->Size() ==0 || ps2->Size() == 0){
|
|
SpacePartition* sp = new SpacePartition();
|
|
|
|
vector<MyPoint> temp1;
|
|
for(int i = 0;i < reg1->Size();i++){
|
|
HalfSegment hs;
|
|
reg1->Get(i, hs);
|
|
if(!hs.IsLeftDomPoint()) continue;
|
|
Point cp;
|
|
sp->GetClosestPoint(hs, ip , cp);
|
|
MyPoint mp(cp, ip.Distance(cp));
|
|
temp1.push_back(mp);
|
|
}
|
|
sort(temp1.begin(),temp1.end());
|
|
list.push_back(temp1[0]);
|
|
|
|
|
|
vector<MyPoint> temp2;
|
|
for(int i = 0;i < reg2->Size();i++){
|
|
HalfSegment hs;
|
|
reg2->Get(i, hs);
|
|
if(!hs.IsLeftDomPoint()) continue;
|
|
Point cp;
|
|
sp->GetClosestPoint(hs, ip , cp);
|
|
MyPoint mp(cp, ip.Distance(cp));
|
|
temp2.push_back(mp);
|
|
}
|
|
sort(temp2.begin(),temp2.end());
|
|
list.push_back(temp2[0]);
|
|
|
|
delete sp;
|
|
ps1->DeleteIfAllowed();
|
|
ps2->DeleteIfAllowed();
|
|
line1->DeleteIfAllowed();
|
|
return;
|
|
}
|
|
|
|
assert(ps1->Size() >= 1 && ps2->Size() >= 1);
|
|
|
|
// cout<<*ps1<<" "<<*ps2<<endl;
|
|
|
|
/////////////calculate the distance to ip and get the two closest/////
|
|
vector<MyPoint> temp1;
|
|
for(int i = 0;i <ps1->Size();i++){
|
|
Point p;
|
|
ps1->Get(i,p);
|
|
MyPoint mp(p, p.Distance(ip));
|
|
temp1.push_back(mp);
|
|
}
|
|
sort(temp1.begin(),temp1.end());
|
|
list.push_back(temp1[0]);
|
|
|
|
|
|
vector<MyPoint> temp2;
|
|
for(int i = 0;i <ps2->Size();i++){
|
|
Point p;
|
|
ps2->Get(i,p);
|
|
MyPoint mp(p, p.Distance(ip));
|
|
temp2.push_back(mp);
|
|
}
|
|
sort(temp2.begin(),temp2.end());
|
|
list.push_back(temp2[0]);
|
|
|
|
ps1->DeleteIfAllowed();
|
|
ps2->DeleteIfAllowed();
|
|
line1->DeleteIfAllowed();
|
|
}
|
|
|
|
/*
|
|
If the original SimpleLine::AtPoint does not work.
|
|
use this one. It uses the distance (a very small distance)
|
|
between the point and halfsegment to
|
|
determine whether the point locates on the simpleline
|
|
|
|
*/
|
|
bool BusRoute::MyAtPoint(SimpleLine* sl, Point& loc,
|
|
bool sm, double& res, double dist_delta)
|
|
{
|
|
SpacePartition* sp = new SpacePartition();
|
|
|
|
vector<MyHalfSegment> seq_halfseg; //reorder it from start to end
|
|
sp->ReorderLine(sl, seq_halfseg);
|
|
bool find = false;
|
|
double pos = 0.0;
|
|
if(sm){
|
|
for(unsigned int i = 0;i < seq_halfseg.size();i++){
|
|
HalfSegment hs(true,seq_halfseg[i].from,seq_halfseg[i].to);
|
|
if(hs.Distance(loc) < dist_delta){
|
|
pos += loc.Distance(seq_halfseg[i].from);
|
|
res = pos;
|
|
find = true;
|
|
break;
|
|
}else
|
|
pos += hs.Length();
|
|
}
|
|
}else{
|
|
for(int i = seq_halfseg.size() - 1;i >= 0;i--){
|
|
HalfSegment hs(true,seq_halfseg[i].from,seq_halfseg[i].to);
|
|
if(hs.Distance(loc) < dist_delta){
|
|
pos += loc.Distance(seq_halfseg[i].to);
|
|
res = pos;
|
|
find = true;
|
|
break;
|
|
}else
|
|
pos += hs.Length();
|
|
}
|
|
}
|
|
|
|
delete sp;
|
|
|
|
return find;
|
|
}
|
|
|
|
/*
|
|
for the two new generated bus routes, it sets the up and down value
|
|
|
|
*/
|
|
|
|
void BusRoute::CreateRoute4(int attr1, int attr2, int attr3, int attr4,
|
|
int attr_a, int attr_b)
|
|
{
|
|
// cout<<"attr1 "<<attr1<<" attr2 "<<attr2<<" attr3 "<<attr3
|
|
// <<"attr4 "<<attr4<<"attr_a "<<attr_a<<" attr_b "<<attr_b<<endl;
|
|
|
|
vector<bool> start_small_list;
|
|
int last_br_id = 0;
|
|
for(int i = 1;i <= rel2->GetNoTuples();i++){
|
|
Tuple* tuple_bus_stop = rel2->GetTuple(i, false);
|
|
int br_id = ((CcInt*)tuple_bus_stop->GetAttribute(attr_a))->GetIntval();
|
|
bool sm = ((CcBool*)tuple_bus_stop->GetAttribute(attr_b))->GetBoolval();
|
|
if(start_small_list.size() == 0){
|
|
start_small_list.push_back(sm);
|
|
last_br_id = br_id;
|
|
}
|
|
else{
|
|
if(br_id != last_br_id){
|
|
last_br_id = br_id;
|
|
start_small_list.push_back(sm);
|
|
}
|
|
}
|
|
|
|
tuple_bus_stop->DeleteIfAllowed();
|
|
}
|
|
// cout<<"start_small_list size "<<start_small_list.size()<<endl;
|
|
|
|
assert((int)start_small_list.size() == rel1->GetNoTuples() / 2);
|
|
|
|
for(int i = 1;i <= rel1->GetNoTuples();i+=2){
|
|
Tuple* tuple_bus_route1 = rel1->GetTuple(i, false);
|
|
Tuple* tuple_bus_route2 = rel1->GetTuple(i + 1, false);
|
|
|
|
int br_id1 = ((CcInt*)tuple_bus_route1->GetAttribute(attr1))->GetIntval();
|
|
int br_id2 = ((CcInt*)tuple_bus_route2->GetAttribute(attr1))->GetIntval();
|
|
assert(br_id1 == br_id2);
|
|
|
|
Line* l1 = (Line*)tuple_bus_route1->GetAttribute(attr2);
|
|
Line* l2 = (Line*)tuple_bus_route2->GetAttribute(attr2);
|
|
|
|
SimpleLine* sl1 = new SimpleLine(0);
|
|
SimpleLine* sl2 = new SimpleLine(0);
|
|
sl1->fromLine(*l1);
|
|
sl2->fromLine(*l2);
|
|
|
|
// cout<<br_id1 - 1<<endl;
|
|
CalculateUpandDown(sl1, sl2, start_small_list[br_id1 - 1]);
|
|
|
|
sl1->DeleteIfAllowed();
|
|
|
|
sl2->DeleteIfAllowed();
|
|
|
|
int route_type1 =
|
|
((CcInt*)tuple_bus_route1->GetAttribute(attr3))->GetIntval();
|
|
int route_type2 =
|
|
((CcInt*)tuple_bus_route2->GetAttribute(attr3))->GetIntval();
|
|
|
|
|
|
int br_uid_1 =
|
|
((CcInt*)tuple_bus_route1->GetAttribute(attr4))->GetIntval();
|
|
int br_uid_2 =
|
|
((CcInt*)tuple_bus_route2->GetAttribute(attr4))->GetIntval();
|
|
|
|
|
|
br_id_list.push_back(br_id1);
|
|
br_id_list.push_back(br_id2);
|
|
|
|
bus_sections1.push_back(*l1);
|
|
bus_sections1.push_back(*l2);
|
|
|
|
bus_route_type.push_back(route_type1);
|
|
bus_route_type.push_back(route_type2);
|
|
|
|
br_uid_list.push_back(br_uid_1);
|
|
br_uid_list.push_back(br_uid_2);
|
|
|
|
///////////////////add the startsmaller value /////////////////////////
|
|
startSmaller.push_back(start_small_list[br_id1 - 1]);
|
|
startSmaller.push_back(start_small_list[br_id1 - 1]);
|
|
|
|
tuple_bus_route1->DeleteIfAllowed();
|
|
tuple_bus_route2->DeleteIfAllowed();
|
|
|
|
}
|
|
|
|
assert(startSmaller.size() == br_id_list.size());
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
define the up and down for each route.
|
|
if it is up, the bus stop id increases
|
|
if it is down, the bus stop id decreases
|
|
use l1, and l2 to build a cycle. use the cycle (counter-clockwise or clockwise)
|
|
to determine the direction for l1 and l2.
|
|
we also have to the start smaller value because it needs to identify where the
|
|
route starts
|
|
|
|
We assume all buses moving on the right side of the road (Germany,China)
|
|
|
|
*/
|
|
|
|
void BusRoute::CalculateUpandDown( SimpleLine* sl1, SimpleLine* sl2, bool sm)
|
|
{
|
|
|
|
SpacePartition* sp = new SpacePartition();
|
|
|
|
vector<MyHalfSegment> seq_halfseg1; //reorder it from start to end
|
|
sp->ReorderLine(sl1, seq_halfseg1);
|
|
|
|
vector<MyHalfSegment> seq_halfseg2; //reorder it from start to end
|
|
sp->ReorderLine(sl2, seq_halfseg2);
|
|
|
|
|
|
assert(sl1->Size() >= 2);
|
|
assert(sl2->Size() >= 2);
|
|
vector<Point> point_list;
|
|
|
|
//assume we start from sl1 (up direction)
|
|
if(sm){
|
|
unsigned int index1 = 0;
|
|
unsigned int index2 = 1;
|
|
|
|
point_list.push_back(seq_halfseg1[index1].from);
|
|
point_list.push_back(seq_halfseg1[index2].from);
|
|
point_list.push_back(seq_halfseg1[index2].to);
|
|
point_list.push_back(seq_halfseg2[index2].to);
|
|
point_list.push_back(seq_halfseg2[index2].from);
|
|
point_list.push_back(seq_halfseg2[index1].from);
|
|
|
|
}else{
|
|
unsigned int index1 = seq_halfseg1.size() - 1;
|
|
unsigned int index2 = seq_halfseg1.size() - 2;
|
|
// cout<<"index1 "<<index1<<" index2 "<<index2<<endl;
|
|
unsigned int index3 = seq_halfseg2.size() - 1;
|
|
unsigned int index4 = seq_halfseg2.size() - 2;
|
|
|
|
point_list.push_back(seq_halfseg1[index1].to);
|
|
point_list.push_back(seq_halfseg1[index1].from);
|
|
point_list.push_back(seq_halfseg1[index2].from);
|
|
if(seq_halfseg1.size() == seq_halfseg2.size()){
|
|
point_list.push_back(seq_halfseg2[index2].from);
|
|
point_list.push_back(seq_halfseg2[index1].from);
|
|
point_list.push_back(seq_halfseg2[index1].to);
|
|
}else{
|
|
point_list.push_back(seq_halfseg2[index4].from);
|
|
point_list.push_back(seq_halfseg2[index3].from);
|
|
point_list.push_back(seq_halfseg2[index3].to);
|
|
}
|
|
}
|
|
vector<MMRegion> regs;
|
|
sp->ComputeRegion(point_list,regs);
|
|
assert(regs.size() == 1);
|
|
delete sp;
|
|
|
|
CompTriangle* ct = new CompTriangle();
|
|
bool clock_wise = ct->GetClockwise(point_list);
|
|
if(clock_wise){
|
|
// cout<<"l1 "<<false<<"l2 "<<true<<endl;
|
|
direction_flag.push_back(false);
|
|
direction_flag.push_back(true);
|
|
}else{
|
|
// cout<<"l1 "<<true<<" l2 "<<false<<endl;
|
|
direction_flag.push_back(true);
|
|
direction_flag.push_back(false);
|
|
}
|
|
delete ct;
|
|
|
|
}
|
|
|
|
/*
|
|
set the up and down value for each bus stop
|
|
|
|
*/
|
|
void BusRoute::CreateBusStop5(int attr,int attr1,int attr2,
|
|
int attr3,int attr4, int attr5)
|
|
{
|
|
// cout<<"attr "<<attr<<"attr1 "<<attr1<<" attr2 "<<attr2
|
|
// <<" attr3 "<<attr3<<" attr4 "<<attr4<<" attr5 "<<attr5<<endl;
|
|
|
|
vector<bool> br_direction;
|
|
for(int i = 1;i <= rel1->GetNoTuples();i++){
|
|
Tuple* tuple_bus_route = rel1->GetTuple(i, false);
|
|
bool direction =
|
|
((CcBool*)tuple_bus_route->GetAttribute(attr))->GetBoolval();
|
|
br_direction.push_back(direction);
|
|
tuple_bus_route->DeleteIfAllowed();
|
|
}
|
|
|
|
// cout<<"direction size "<<br_direction.size()<<endl;
|
|
|
|
for(int i = 1;i <= rel2->GetNoTuples();i++){
|
|
Tuple* tuple_bus_stop = rel2->GetTuple(i, false);
|
|
int br_id = ((CcInt*)tuple_bus_stop->GetAttribute(attr1))->GetIntval();
|
|
int br_uid = ((CcInt*)tuple_bus_stop->GetAttribute(attr2))->GetIntval();
|
|
int stop_id = ((CcInt*)tuple_bus_stop->GetAttribute(attr3))->GetIntval();
|
|
Point* loc = (Point*)tuple_bus_stop->GetAttribute(attr4);
|
|
double pos = ((CcReal*)tuple_bus_stop->GetAttribute(attr5))->GetRealval();
|
|
assert(br_uid == br_id *2 - 1 || br_uid == br_id * 2);
|
|
|
|
bool direction = br_direction[br_uid - 1];
|
|
|
|
br_id_list.push_back(br_id);
|
|
br_uid_list.push_back(br_uid);
|
|
br_stop_id.push_back(stop_id);
|
|
start_gp.push_back(*loc);
|
|
bus_stop_loc_3.push_back(pos);
|
|
bus_stop_flag.push_back(direction);
|
|
|
|
tuple_bus_stop->DeleteIfAllowed();
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
create bus stops relations with the data type busstop
|
|
|
|
*/
|
|
void BusRoute::GetBusStops()
|
|
{
|
|
for(int i = 1;i <= rel2->GetNoTuples();i++){
|
|
Tuple* br_tuple = rel2->GetTuple(i, false);
|
|
int br_id =
|
|
((CcInt*)br_tuple->GetAttribute(RoadDenstiy::BR_ID6))->GetIntval();
|
|
bool direction =
|
|
((CcBool*)br_tuple->GetAttribute(RoadDenstiy::BR_DIRECTION))->GetBoolval();
|
|
|
|
int br_uid =
|
|
((CcInt*)br_tuple->GetAttribute(RoadDenstiy::BR_RUID))->GetIntval();
|
|
|
|
CcInt* search_id = new CcInt(true, br_id);
|
|
BTreeIterator* btree_iter = btree->ExactMatch(search_id);
|
|
int count = 0;
|
|
while(btree_iter->Next()){
|
|
Tuple* bs_tuple = rel1->GetTuple(btree_iter->GetId(), false);
|
|
bool d =
|
|
((CcBool*)bs_tuple->GetAttribute(RoadDenstiy::STOP_DIRECTION))->GetBoolval();
|
|
if(direction == d){
|
|
int br_id_s =
|
|
((CcInt*)bs_tuple->GetAttribute(RoadDenstiy::BR_ID4))->GetIntval();
|
|
|
|
int br_uid_s =
|
|
((CcInt*)bs_tuple->GetAttribute(RoadDenstiy::BR_UID))->GetIntval();
|
|
assert(br_id_s == br_id);
|
|
assert(br_uid == br_uid_s);
|
|
int s_id =
|
|
((CcInt*)bs_tuple->GetAttribute(RoadDenstiy::BUS_STOP_ID))->GetIntval();
|
|
Point* loc = (Point*)bs_tuple->GetAttribute(RoadDenstiy::BUS_LOC);
|
|
|
|
// cout<<"busstop_rid "<<br_id_s<<" stop id "<<s_id<<endl;
|
|
|
|
// bus_stop_list.push_back(Bus_Stop(true, br_id_s, s_id));
|
|
bus_stop_list.push_back(Bus_Stop(true, br_id_s, s_id, d));
|
|
bus_stop_geodata.push_back(*loc);
|
|
count++;
|
|
}
|
|
bs_tuple->DeleteIfAllowed();
|
|
}
|
|
delete btree_iter;
|
|
search_id->DeleteIfAllowed();
|
|
|
|
br_tuple->DeleteIfAllowed();
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
create bus routes represented by the data type busroute
|
|
|
|
*/
|
|
void BusRoute::GetBusRoutes()
|
|
{
|
|
for(int i = 1;i <= rel2->GetNoTuples();i++){
|
|
Tuple* br_tuple = rel2->GetTuple(i, false);
|
|
int br_id =
|
|
((CcInt*)br_tuple->GetAttribute(RoadDenstiy::BR_ID6))->GetIntval();
|
|
// cout<<"br_id "<<br_id<<endl;
|
|
|
|
bool direction =
|
|
((CcBool*)br_tuple->GetAttribute(RoadDenstiy::BR_DIRECTION))->GetBoolval();
|
|
|
|
bool small =
|
|
((CcBool*)br_tuple->GetAttribute(RoadDenstiy::BR_STARTSMALLER))->GetBoolval();
|
|
|
|
Line* l = (Line*)br_tuple->GetAttribute(RoadDenstiy::BR_GEODATA);
|
|
CcInt* search_id = new CcInt(true, br_id);
|
|
BTreeIterator* btree_iter = btree->ExactMatch(search_id);
|
|
vector<TupleId> tid_list;
|
|
while(btree_iter->Next()){
|
|
Tuple* bs_tuple = rel1->GetTuple(btree_iter->GetId(), false);
|
|
bool d =
|
|
((CcBool*)bs_tuple->GetAttribute(RoadDenstiy::STOP_DIRECTION))->GetBoolval();
|
|
if(direction == d){
|
|
tid_list.push_back(bs_tuple->GetTupleId());
|
|
}
|
|
bs_tuple->DeleteIfAllowed();
|
|
}
|
|
SimpleLine* sl = new SimpleLine(0);
|
|
sl->fromLine(*l);
|
|
|
|
CreateRoutes(tid_list, br_id, sl, small, direction);
|
|
|
|
sl->DeleteIfAllowed();
|
|
delete btree_iter;
|
|
search_id->DeleteIfAllowed();
|
|
|
|
br_tuple->DeleteIfAllowed();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
sort bus stops of one route by stop id
|
|
|
|
*/
|
|
bool CompareBusStopExt(const BusStop_Ext& bs1, const BusStop_Ext& bs2)
|
|
{
|
|
if(bs1.br_stop_id < bs2.br_stop_id) return true;
|
|
else return false;
|
|
|
|
}
|
|
|
|
/*
|
|
create a bus route consisting of a set of bus segments.
|
|
there is a restriction of bus routes.
|
|
before the first stop and after the last stop, there are also some bus segments
|
|
|
|
*/
|
|
void BusRoute::CreateRoutes(vector<TupleId>& tid_list, int br_id,
|
|
SimpleLine* sl, bool small, bool direction)
|
|
{
|
|
vector<BusStop_Ext> bslist;
|
|
for(unsigned int i = 0;i < tid_list.size();i++){
|
|
Tuple* bs_tuple = rel1->GetTuple(tid_list[i], false);
|
|
int bs_id =
|
|
((CcInt*)bs_tuple->GetAttribute(RoadDenstiy::BR_ID4))->GetIntval();
|
|
|
|
assert(bs_id == br_id);
|
|
|
|
double pos =
|
|
((CcReal*)bs_tuple->GetAttribute(RoadDenstiy::BUS_POS))->GetRealval();
|
|
|
|
Point* loc = (Point*)bs_tuple->GetAttribute(RoadDenstiy::BUS_LOC);
|
|
int s_id =
|
|
((CcInt*)bs_tuple->GetAttribute(RoadDenstiy::BUS_STOP_ID))->GetIntval();
|
|
|
|
BusStop_Ext bs(bs_id, s_id, pos, *loc, small);
|
|
bslist.push_back(bs);
|
|
bs_tuple->DeleteIfAllowed();
|
|
}
|
|
|
|
const double delta_dist = 0.001;
|
|
sort(bslist.begin(), bslist.end(), CompareBusStopExt);
|
|
Bus_Route* br = new Bus_Route(br_id, direction);
|
|
br->StartBulkLoad();
|
|
int count = 0;
|
|
|
|
SpacePartition* sp_pt = new SpacePartition();
|
|
vector<MyHalfSegment> mhs;
|
|
sp_pt->ReorderLine(sl, mhs);
|
|
delete sp_pt;
|
|
|
|
|
|
for(unsigned int i = 0;i < bslist.size() - 1;i++){//ordered by stop id
|
|
Point loc1 = bslist[i].loc;
|
|
Point loc2 = bslist[i + 1].loc;
|
|
|
|
// cout<<"br_id "<<br_id<<endl;
|
|
// cout<<"stop id1 "<<bslist[i].br_stop_id
|
|
// <<" stop id2 "<<bslist[i + 1].br_stop_id<<endl;
|
|
|
|
// cout<<"loc1 "<<bslist[i].loc<<" loc2 "<<bslist[i + 1].loc<<endl;
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
/////////numeric problem, use the new implementation//////////////
|
|
//////////////////////////////////////////////////////////////////
|
|
double pos1 = -1.0;
|
|
double pos2 = -1.0;
|
|
|
|
double newpos1, newpos2;
|
|
|
|
// GetPosOnSL(sl, loc1, newpos1);
|
|
// GetPosOnSL(sl, loc2, newpos2);
|
|
|
|
//////////////////////////////////////////////////
|
|
|
|
GetPosOnSL(sl, loc1, newpos1, mhs);
|
|
GetPosOnSL(sl, loc2, newpos2, mhs);
|
|
|
|
///////////////////////////////////////////
|
|
|
|
pos1 = newpos1;
|
|
pos2 = newpos2;
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
////////////////////////section before the first stop////////////////
|
|
/////////////////////////////////////////////////////////////////////
|
|
if(i == 0){
|
|
assert(pos1 > 0.0 && !AlmostEqual(pos1, sl->Length()));
|
|
|
|
double l1;
|
|
double l2;
|
|
if(pos1 > pos2){
|
|
l1 = pos1;
|
|
l2 = sl->Length();
|
|
}else{
|
|
l1 = 0.0;
|
|
l2 = pos1;
|
|
}
|
|
|
|
SimpleLine sub_line(0);
|
|
|
|
if(sl->GetStartSmaller())
|
|
sl->SubLine(l1, l2, sl->GetStartSmaller(), sub_line);
|
|
else
|
|
sl->SubLine(l2, l1, sl->GetStartSmaller(), sub_line);
|
|
|
|
assert(AlmostEqual(sub_line.Length(), l2 - l1));
|
|
|
|
Point p1, p2;
|
|
sub_line.AtPosition(0.0, sub_line.GetStartSmaller() ,p1);
|
|
sub_line.AtPosition(sub_line.Length(), sub_line.GetStartSmaller(), p2);
|
|
//bool startSmaller;
|
|
if(loc1.Distance(p1) < delta_dist){
|
|
// startSmaller = !sub_line.GetStartSmaller();
|
|
;
|
|
}else if(loc1.Distance(p2) < delta_dist){
|
|
//startSmaller = sub_line.GetStartSmaller();
|
|
;
|
|
}else assert(false);
|
|
|
|
br->Add(&sub_line, count);
|
|
count++;
|
|
}
|
|
//////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////
|
|
double len1, len2;
|
|
if(pos1 > pos2){
|
|
len1 = pos2;
|
|
len2 = pos1;
|
|
}else{
|
|
len1 = pos1;
|
|
len2 = pos2;
|
|
}
|
|
|
|
SimpleLine sub_l(0);
|
|
|
|
if(sl->GetStartSmaller()){
|
|
sl->SubLine(len1, len2, sl->GetStartSmaller(), sub_l);
|
|
}else{
|
|
sl->SubLine(len2, len1, sl->GetStartSmaller(), sub_l);
|
|
}
|
|
|
|
assert(AlmostEqual(sub_l.Length(), fabs(pos2 - pos1)));
|
|
Point sp, ep;
|
|
sub_l.AtPosition(0.0, sub_l.GetStartSmaller() ,sp);
|
|
sub_l.AtPosition(sub_l.Length(), sub_l.GetStartSmaller(), ep);
|
|
|
|
// cout<<"sp "<<sp<<" ep "<<ep<<endl<<endl;
|
|
|
|
// bool startSmaller;
|
|
if(loc1.Distance(sp) < delta_dist && loc2.Distance(ep) < delta_dist){
|
|
//startSmaller = sub_l.GetStartSmaller();
|
|
;
|
|
}else if(loc1.Distance(ep) < delta_dist &&
|
|
loc2.Distance(sp) < delta_dist){
|
|
//startSmaller = !sub_l.GetStartSmaller();
|
|
;
|
|
}else assert(false);
|
|
|
|
br->Add(&sub_l, count);
|
|
count++;
|
|
////////////////////////////////////////////////////////////////////////
|
|
////////////////////the segment after the last stop//////////////////////
|
|
/////////////////////////////////////////////////////////////////////////
|
|
if(i == bslist.size() - 2){
|
|
assert(pos2 > 0.0 && !AlmostEqual(pos2, sl->Length()));
|
|
double l1;
|
|
double l2;
|
|
if(pos1 > pos2){
|
|
l1 = 0.0;
|
|
l2 = pos2;
|
|
}else{
|
|
l1 = pos2;
|
|
l2 = sl->Length();
|
|
}
|
|
|
|
SimpleLine sub_line(0);
|
|
|
|
if(sl->GetStartSmaller())
|
|
sl->SubLine(l1, l2, sl->GetStartSmaller(), sub_line);
|
|
else
|
|
sl->SubLine(l2, l1, sl->GetStartSmaller(), sub_line);
|
|
|
|
assert(AlmostEqual(sub_line.Length(), l2 - l1));
|
|
|
|
Point p1, p2;
|
|
sub_line.AtPosition(0.0, sub_line.GetStartSmaller() ,p1);
|
|
sub_line.AtPosition(sub_line.Length(), sub_line.GetStartSmaller(), p2);
|
|
//bool startSmaller;
|
|
//for the last bus segment, the point corresponds to the start point
|
|
if(loc2.Distance(p1) < delta_dist){//the last segment is different
|
|
//startSmaller = sub_line.GetStartSmaller();
|
|
;
|
|
}else if(loc2.Distance(p2) < delta_dist){
|
|
//startSmaller = !sub_line.GetStartSmaller();
|
|
;
|
|
}else assert(false);
|
|
|
|
br->Add(&sub_line, count);
|
|
count++;
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
br->EndBulkLoad();
|
|
br_id_list.push_back(br_id);
|
|
bus_route_list.push_back(*br);
|
|
br->DeleteIfAllowed();
|
|
}
|
|
|
|
|
|
/*
|
|
due to numeric problem, use the following method to find pos for a point on
|
|
a sline
|
|
|
|
*/
|
|
void BusRoute::GetPosOnSL(SimpleLine* sl, Point loc, double& pos,
|
|
vector<MyHalfSegment>& mhs)
|
|
{
|
|
////////get the start point of sline /////////////
|
|
Point start_loc;
|
|
assert(sl->AtPosition(0.0, sl->StartsSmaller(), start_loc));
|
|
|
|
/////////convert to myhalfsegment/////////////////
|
|
SpacePartition* sp = new SpacePartition();
|
|
|
|
////////use getclosespoint//////////////////////
|
|
const double delta_d = 0.001;
|
|
if(mhs[0].from.Distance(start_loc) < delta_d){
|
|
double len = 0;
|
|
unsigned int i = 0;
|
|
for(;i < mhs.size();i++){
|
|
HalfSegment hs(true, mhs[i].from, mhs[i].to);
|
|
Point res;
|
|
sp->GetClosestPoint_New(hs, loc, res);
|
|
if(res.Distance(loc) < delta_d){
|
|
len += res.Distance(mhs[i].from);
|
|
pos = len;
|
|
break;
|
|
}else{
|
|
len += hs.Length();
|
|
}
|
|
}
|
|
if(i == mhs.size())assert(false);
|
|
|
|
|
|
}else if(mhs[mhs.size() - 1].to.Distance(start_loc) < delta_d){
|
|
|
|
double len = 0;
|
|
int i = mhs.size() - 1;
|
|
for(;i >= 0;i--){
|
|
HalfSegment hs(true, mhs[i].from, mhs[i].to);
|
|
Point res;
|
|
sp->GetClosestPoint_New(hs, loc, res);
|
|
if(res.Distance(loc) < delta_d){
|
|
len += res.Distance(mhs[i].to);
|
|
pos = len;
|
|
break;
|
|
}else{
|
|
len += hs.Length();
|
|
}
|
|
}
|
|
if(i < 0)assert(false);
|
|
|
|
}else{
|
|
cout<<"should not be here"<<endl;
|
|
assert(false);
|
|
}
|
|
|
|
delete sp;
|
|
|
|
//////////////////testing the result again////////////////
|
|
Point test;
|
|
assert(sl->AtPosition(pos,sl->StartsSmaller(), test));
|
|
assert(test.Distance(loc) < delta_d);
|
|
|
|
}
|
|
|
|
/*void BusRoute::GetPosOnSL(SimpleLine* sl, Point loc, double& pos)
|
|
{
|
|
////////get the start point of sline /////////////
|
|
Point start_loc;
|
|
assert(sl->AtPosition(0.0, sl->StartsSmaller(), start_loc));
|
|
|
|
/////////convert to myhalfsegment/////////////////
|
|
SpacePartition* sp = new SpacePartition();
|
|
vector<MyHalfSegment> mhs;
|
|
sp->ReorderLine(sl, mhs);
|
|
|
|
////////use getclosespoint//////////////////////
|
|
const double delta_d = 0.001;
|
|
if(mhs[0].from.Distance(start_loc) < delta_d){
|
|
double len = 0;
|
|
unsigned int i = 0;
|
|
for(;i < mhs.size();i++){
|
|
HalfSegment hs(true, mhs[i].from, mhs[i].to);
|
|
Point res;
|
|
sp->GetClosestPoint_New(hs, loc, res);
|
|
if(res.Distance(loc) < delta_d){
|
|
len += res.Distance(mhs[i].from);
|
|
pos = len;
|
|
break;
|
|
}else{
|
|
len += hs.Length();
|
|
}
|
|
}
|
|
if(i == mhs.size())assert(false);
|
|
|
|
|
|
}else if(mhs[mhs.size() - 1].to.Distance(start_loc) < delta_d){
|
|
|
|
double len = 0;
|
|
int i = mhs.size() - 1;
|
|
for(;i >= 0;i--){
|
|
HalfSegment hs(true, mhs[i].from, mhs[i].to);
|
|
Point res;
|
|
sp->GetClosestPoint_New(hs, loc, res);
|
|
if(res.Distance(loc) < delta_d){
|
|
len += res.Distance(mhs[i].to);
|
|
pos = len;
|
|
break;
|
|
}else{
|
|
len += hs.Length();
|
|
}
|
|
}
|
|
if(i < 0)assert(false);
|
|
|
|
}else{
|
|
cout<<"should not be here"<<endl;
|
|
assert(false);
|
|
}
|
|
|
|
delete sp;
|
|
|
|
//////////////////testing the result again////////////////
|
|
Point test;
|
|
assert(sl->AtPosition(pos,sl->StartsSmaller(), test));
|
|
assert(test.Distance(loc) < delta_d);
|
|
|
|
}*/
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// use the road density data to set time schedule for each bus route ///
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
string RoadDenstiy::bus_route_speed_typeinfo =
|
|
"(rel (tuple ((br_id int) (br_pos real) (speed_limit real)\
|
|
(route_segment line))))";
|
|
|
|
string RoadDenstiy::bus_stop_typeinfo =
|
|
"(rel (tuple ((Br_id int) (Br_uid int) (Bus_stop_id int) (Bus_stop point)\
|
|
(Bus_pos real) (Stop_direction bool))))";
|
|
|
|
|
|
string RoadDenstiy::night_sched_typeinfo =
|
|
"(rel (tuple ((br_id int) (duration1 periods) (duration2 periods) (br_interval\
|
|
real))))";
|
|
|
|
string RoadDenstiy::day_sched_typeinfo =
|
|
"(rel (tuple ((br_id int) (duration1 periods) (duration2 periods) (br_interval1\
|
|
real) (br_interval2 real))))";
|
|
|
|
string RoadDenstiy::mo_bus_typeinfo =
|
|
"(rel (tuple ((br_id int) (bus_direction bool) (bus_trip mpoint) (bus_type \
|
|
string) (bus_day string) (schedule_id int))))";
|
|
|
|
string RoadDenstiy::bus_route_typeinfo =
|
|
"(rel (tuple ((Br_id int) (Bus_route line) (Route_type int) (Br_uid int)\
|
|
(Bus_direction bool) (StartSmaller bool))))";
|
|
|
|
|
|
string RoadDenstiy::bus_route_old_typeinfo =
|
|
"(rel (tuple ((br_id int) (bus_route1 gline) (bus_route2 line)\
|
|
(start_loc point) (end_loc point) (route_type int))))";
|
|
|
|
|
|
/*
|
|
get night buses. use the network flow value.
|
|
for night bus, we don't dinstinguish Sunday and Workday
|
|
|
|
*/
|
|
|
|
void RoadDenstiy::GetNightRoutes(int attr1, int attr2, int attr_a,
|
|
int attr_b,Periods* peri1, Periods* peri2)
|
|
{
|
|
// cout<<"attr1 "<<attr1<<" attr2 "<<attr2
|
|
// <<"attr_a "<<attr_a<<" attr_b "<<attr_b<<endl;
|
|
// cout<<*peri1<<" "<<*peri2<<endl;
|
|
|
|
Interval<Instant> periods1;
|
|
Interval<Instant> periods2;
|
|
peri1->Get(0, periods1);
|
|
peri2->Get(0, periods2);
|
|
|
|
// cout<<periods1<<" "<<periods2<<endl;
|
|
|
|
for(int i = 1;i <= rel2->GetNoTuples();i++){
|
|
|
|
Tuple* tuple_bus_stop = rel2->GetTuple(i, false);
|
|
int br_id = ((CcInt*)tuple_bus_stop->GetAttribute(attr_a))->GetIntval();
|
|
GLine* gl = (GLine*)tuple_bus_stop->GetAttribute(attr_b);
|
|
|
|
// cout<<*gl<<endl;
|
|
|
|
BusRoute* br = new BusRoute(n,NULL,NULL);
|
|
|
|
vector<bool> start_from;
|
|
vector<SectTreeEntry> sec_list;
|
|
br->GetSectionList(gl, sec_list, start_from);
|
|
|
|
int traffic_num = 0;
|
|
|
|
Interval<Instant> time_span1 = periods1;
|
|
Interval<Instant> time_span2 = periods2;
|
|
|
|
for(unsigned int j = 0;j < sec_list.size();j++){
|
|
int secid = sec_list[j].secttid;
|
|
/////////////use btree to find the section/////////////////
|
|
CcInt* search_sec_id = new CcInt(true, secid);
|
|
BTreeIterator* btree_iter = btree->ExactMatch(search_sec_id);
|
|
while(btree_iter->Next()){
|
|
Tuple* tuple_traffic = rel1->GetTuple(btree_iter->GetId(), false);
|
|
MInt* flow = (MInt*)tuple_traffic->GetAttribute(attr2);
|
|
// cout<<*flow<<endl;
|
|
for(int k = 0;k < flow->GetNoComponents();k++){
|
|
UInt cur_uint;
|
|
flow->Get(k,cur_uint);
|
|
|
|
if(periods1.Intersects(cur_uint.timeInterval)){
|
|
// cout<<"1"<<endl;
|
|
// cur_uint.Print(cout);
|
|
traffic_num += cur_uint.constValue.GetValue();
|
|
|
|
if(cur_uint.timeInterval.start > time_span1.start &&
|
|
cur_uint.timeInterval.start < time_span1.end){
|
|
time_span1.start = cur_uint.timeInterval.start;
|
|
}
|
|
if(cur_uint.timeInterval.end < time_span1.end &&
|
|
cur_uint.timeInterval.end > time_span1.start)
|
|
time_span1.end = cur_uint.timeInterval.end;
|
|
}
|
|
|
|
if(periods2.Intersects(cur_uint.timeInterval)){
|
|
// cout<<"2"<<endl;
|
|
// cur_uint.Print(cout);
|
|
traffic_num += cur_uint.constValue.GetValue();
|
|
|
|
if(cur_uint.timeInterval.start > time_span2.start &&
|
|
cur_uint.timeInterval.start < time_span2.end)
|
|
time_span2.start = cur_uint.timeInterval.start;
|
|
if(cur_uint.timeInterval.end < time_span2.end &&
|
|
cur_uint.timeInterval.end > time_span2.start)
|
|
time_span2.end = cur_uint.timeInterval.end;
|
|
}
|
|
}
|
|
|
|
tuple_traffic->DeleteIfAllowed();
|
|
}
|
|
delete btree_iter;
|
|
search_sec_id->DeleteIfAllowed();
|
|
//////////////////////////////////////////////////////////
|
|
}
|
|
delete br;
|
|
|
|
tuple_bus_stop->DeleteIfAllowed();
|
|
|
|
br_id_list.push_back(br_id);
|
|
traffic_no.push_back(traffic_num);
|
|
|
|
Periods* p1 = new Periods(0);
|
|
p1->StartBulkLoad();
|
|
p1->MergeAdd(time_span1);
|
|
p1->EndBulkLoad();
|
|
duration1.push_back(*p1);
|
|
|
|
p1->DeleteIfAllowed();
|
|
|
|
Periods* p2 = new Periods(0);
|
|
p2->StartBulkLoad();
|
|
p2->MergeAdd(time_span2);
|
|
p2->EndBulkLoad();
|
|
duration2.push_back(*p2);
|
|
|
|
p2->DeleteIfAllowed();
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
create time interval for each night bus
|
|
it returns brid, time interval for each schedule and two intervals
|
|
each interval records the first and last schedule time instant of this route
|
|
|
|
*/
|
|
void RoadDenstiy::SetTSNightBus(int attr1,int attr2, int attr3,
|
|
Periods* peri1, Periods* peri2)
|
|
{
|
|
// cout<<"attr1 "<<attr1<<" attr2 "<<attr2<<" attr3 "<<attr3<<endl;
|
|
// cout<<*peri1<<" "<<*peri2<<endl;
|
|
|
|
for(int i = 1;i <= rel1->GetNoTuples();i++){
|
|
Tuple* tuple_bus_route = rel1->GetTuple(i, false);
|
|
int br_id = ((CcInt*)tuple_bus_route->GetAttribute(attr1))->GetIntval();
|
|
Periods* time1 = (Periods*)tuple_bus_route->GetAttribute(attr2);
|
|
Periods* time2 = (Periods*)tuple_bus_route->GetAttribute(attr3);
|
|
|
|
|
|
Interval<Instant> time_span1;
|
|
Interval<Instant> time_span2;
|
|
|
|
Interval<Instant> interval1;
|
|
Interval<Instant> interval2;
|
|
|
|
time1->Get(0, interval1);
|
|
time2->Get(0, interval2);
|
|
|
|
int h1 = interval1.start.GetHour();
|
|
int h2 = interval2.start.GetHour();
|
|
|
|
if(h1 > h2){
|
|
double m =
|
|
CalculateTimeSpan1(time1, peri1,time_span1,i);
|
|
CalculateTimeSpan2(peri2,time_span2,m);
|
|
}else{
|
|
double m =
|
|
CalculateTimeSpan1(time2, peri2,time_span2,i);
|
|
CalculateTimeSpan2(peri1,time_span1,m);
|
|
}
|
|
|
|
br_id_list.push_back(br_id);
|
|
|
|
// duration1.push_back(*time1);
|
|
// duration2.push_back(*time2);
|
|
|
|
// cout<<time_span1<<endl;
|
|
// cout<<time_span2<<endl;
|
|
|
|
Periods* p1 = new Periods(0);
|
|
p1->StartBulkLoad();
|
|
p1->MergeAdd(time_span1);
|
|
p1->EndBulkLoad();
|
|
duration1.push_back(*p1);
|
|
|
|
p1->DeleteIfAllowed();
|
|
|
|
Periods* p2 = new Periods(0);
|
|
p2->StartBulkLoad();
|
|
p2->MergeAdd(time_span2);
|
|
p2->EndBulkLoad();
|
|
duration2.push_back(*p2);
|
|
|
|
p2->DeleteIfAllowed();
|
|
|
|
time_interval.push_back(1.0/24.0); //1 means 1 day , 1.0/24.0 = 1 hour
|
|
tuple_bus_route->DeleteIfAllowed();
|
|
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
create time interval for each daytime bus
|
|
it returns brid, time interval for each schedule and two intervals
|
|
each interval records the first and last schedule time instant of this route
|
|
the time interval for Monday and Sunday is different
|
|
the start time for Monday and Sunday is also different
|
|
|
|
streets have high density are closeer to city and longer than those low density
|
|
streets
|
|
|
|
*/
|
|
void RoadDenstiy::SetTSDayTimeBus(int attr1,int attr2, int attr3,
|
|
Periods* peri1, Periods* peri2)
|
|
{
|
|
// cout<<"attr1 "<<attr1<<" attr2 "<<attr2<<" attr3 "<<attr3<<endl;
|
|
// cout<<*peri1<<" "<<*peri2<<endl;
|
|
|
|
const double factor = 0.3;
|
|
int num_high_freq = (int)(rel1->GetNoTuples() * factor);
|
|
|
|
//////////////////////////////////////////////////////
|
|
for(int i = 1;i <= rel1->GetNoTuples();i++){
|
|
Tuple* tuple_bus_route = rel1->GetTuple(i, false);
|
|
int br_id = ((CcInt*)tuple_bus_route->GetAttribute(attr1))->GetIntval();
|
|
// cout<<"br_id "<<br_id<<endl;
|
|
|
|
Periods* time1 = (Periods*)tuple_bus_route->GetAttribute(attr2);//Monday
|
|
Periods* time2 = (Periods*)tuple_bus_route->GetAttribute(attr3);//Sunday
|
|
double interval = 15.0/(24.0*60.0);//15 minutes
|
|
|
|
if(i > num_high_freq)
|
|
interval = 30.0/(24.0*60.0); //30 minutes
|
|
|
|
Interval<Instant> time_span1;//For Monday
|
|
// cout<<"Monday"<<endl;
|
|
CalculateTimeSpan3(time1, peri1, time_span1,i, interval);
|
|
|
|
Interval<Instant> time_span2;//For Sunday
|
|
// cout<<"Sunday"<<endl;
|
|
// cout<<*time2<<" "<<*peri2<<endl;
|
|
CalculateTimeSpan3(time2, peri2, time_span2, i, 2.0*interval);
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
br_id_list.push_back(br_id);
|
|
Periods* p1 = new Periods(0);
|
|
p1->StartBulkLoad();
|
|
p1->MergeAdd(time_span1);
|
|
p1->EndBulkLoad();
|
|
duration1.push_back(*p1);
|
|
|
|
p1->DeleteIfAllowed();
|
|
|
|
// cout<<time_span2<<endl;
|
|
|
|
Periods* p2 = new Periods(0);
|
|
p2->StartBulkLoad();
|
|
p2->MergeAdd(time_span2);
|
|
p2->EndBulkLoad();
|
|
duration2.push_back(*p2);
|
|
|
|
p2->DeleteIfAllowed();
|
|
time_interval.push_back(interval);
|
|
time_interval2.push_back(2.0*interval);
|
|
/////////////////////////////////////////////////////////////////////////
|
|
|
|
tuple_bus_route->DeleteIfAllowed();
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
calculate the first and end time schedule of bus route
|
|
if the start minute is larger than 30. we reduce the start hour by one
|
|
e.g., 21:57 ---> 20:57
|
|
else keep it e.g., 21:14 --> 21:14
|
|
|
|
*/
|
|
double RoadDenstiy::CalculateTimeSpan1(Periods* t, Periods* p,
|
|
Interval<Instant>& span,
|
|
int index)
|
|
{
|
|
const int bti = 60;
|
|
Interval<Instant> p1;
|
|
Interval<Instant> t1;
|
|
p->Get(0, p1);
|
|
t->Get(0, t1);
|
|
int m1 = t1.start.GetMinute();
|
|
// cout<<"start minute "<<m1<<endl;
|
|
if(m1 == 0){
|
|
// m1 = lrand48() % bti;
|
|
m1 = index % bti;
|
|
}
|
|
|
|
/////////////set the time for the first schedule //////////////////////////
|
|
Instant start = t1.start;
|
|
// cout<<"old "<<start<<endl;
|
|
if(m1 > bti/2){ // larger than half an hour
|
|
start = p1.start; // 1 means 1 day. 1.0/24.0 1 hour 1.0/(24*60) 1 minute
|
|
double d = start.ToDouble() - 1.0/24.0 + m1*1.0/(24.0*60);
|
|
start.ReadFrom(d);
|
|
}else{
|
|
start = p1.start;
|
|
double d = start.ToDouble() + m1*1.0/(24.0*60);
|
|
start.ReadFrom(d);
|
|
}
|
|
|
|
// cout<<"start "<<start;
|
|
/////////////set the time for the last schedule///////////////////////////
|
|
|
|
double d_s = start.ToDouble();
|
|
double d_e = p1.end.ToDouble();
|
|
double one_hour = 1/24.0;
|
|
while(d_s < d_e){
|
|
d_s += one_hour;
|
|
|
|
}
|
|
d_s -= one_hour;
|
|
Instant end = p1.end;//initialize value
|
|
end.ReadFrom(d_s);
|
|
// cout<<" end "<<end<<endl;
|
|
|
|
span.start = start;
|
|
span.lc = true;
|
|
span.end = end;
|
|
span.rc = false;
|
|
|
|
return m1*1.0/(24.0*60);//minute e.g., 20, 15
|
|
}
|
|
|
|
|
|
/*
|
|
calculate the first and end time schedule of bus route
|
|
use the minute in the last time span plus the hour 0:00
|
|
|
|
*/
|
|
void RoadDenstiy::CalculateTimeSpan2(Periods* p,
|
|
Interval<Instant>& span, double m)
|
|
{
|
|
Interval<Instant> p1;
|
|
p->Get(0, p1);
|
|
|
|
/////////////set the time for the first schedule //////////////////////////
|
|
Instant start = p1.start;
|
|
double d = start.ToDouble() + m;
|
|
start.ReadFrom(d);
|
|
|
|
// cout<<"start "<<start;
|
|
/////////////set the time for the last schedule///////////////////////////
|
|
|
|
double d_s = start.ToDouble();
|
|
double d_e = p1.end.ToDouble();
|
|
double one_hour = 1/24.0;
|
|
while(d_s < d_e){
|
|
d_s += one_hour;
|
|
|
|
}
|
|
d_s -= one_hour;
|
|
Instant end = p1.end;//initialize value
|
|
end.ReadFrom(d_s);
|
|
// cout<<" end "<<end<<endl;
|
|
|
|
span.start = start;
|
|
span.lc = true;
|
|
span.end = end;
|
|
span.rc = false;
|
|
|
|
}
|
|
|
|
/*
|
|
calculate the first and end time schedule of daytime bus route
|
|
if the start minute is larger than 30. we reduce the start hour by one
|
|
e.g., 21:57 ---> 20:57
|
|
else keep it e.g., 21:14 --> 21:14
|
|
For Monday
|
|
|
|
*/
|
|
void RoadDenstiy::CalculateTimeSpan3(Periods* t, Periods* p,
|
|
Interval<Instant>& span,
|
|
int index, double interval)
|
|
{
|
|
const int bti = 60;
|
|
|
|
Interval<Instant> p1;
|
|
Interval<Instant> t1;
|
|
p->Get(0, p1);
|
|
t->Get(0, t1);
|
|
int m1 = t1.start.GetMinute();
|
|
if(m1 == 0){
|
|
m1 = index % bti;
|
|
}
|
|
|
|
/////////////set the time for the first schedule //////////////////////////
|
|
Instant start = t1.start;
|
|
// cout<<"old "<<start<<endl;
|
|
if(m1 > bti/2){ // larger than half an hour
|
|
start = p1.start; // 1 means 1 day. 1.0/24.0 1 hour 1.0/(24*60) 1 minute
|
|
double d = start.ToDouble() - 1.0/24.0 + m1*1.0/(24.0*60);
|
|
start.ReadFrom(d);
|
|
}else{
|
|
start = p1.start;
|
|
double d = start.ToDouble() + m1*1.0/(24.0*60);
|
|
start.ReadFrom(d);
|
|
}
|
|
|
|
// cout<<"start "<<start;
|
|
/////////////set the time for the last schedule///////////////////////////
|
|
|
|
double d_s = start.ToDouble();
|
|
double d_e = p1.end.ToDouble();
|
|
while(d_s < d_e){
|
|
d_s += interval;
|
|
}
|
|
d_s -= interval;
|
|
Instant end = p1.end;//initialize value
|
|
end.ReadFrom(d_s);
|
|
// cout<<" end "<<end<<endl;
|
|
|
|
span.start = start;
|
|
span.lc = true;
|
|
span.end = end;
|
|
span.rc = false;
|
|
|
|
}
|
|
|
|
/*
|
|
set up the speed value for each bus route
|
|
|
|
*/
|
|
|
|
void RoadDenstiy::SetBRSpeed(int attr1, int attr2, int attr, int attr_sm)
|
|
{
|
|
///////////////collect the startsmaller value for each route//////////
|
|
vector<bool> sm_list;
|
|
for(int i = 1;i <= rel3->GetNoTuples();i+= 2){
|
|
Tuple* tuple_route1 = rel3->GetTuple(i, false);
|
|
bool sm1 = ((CcBool*)tuple_route1->GetAttribute(attr_sm))->GetBoolval();
|
|
sm_list.push_back(sm1);
|
|
Tuple* tuple_route2 = rel3->GetTuple(i + 1, false);
|
|
bool sm2 = ((CcBool*)tuple_route2->GetAttribute(attr_sm))->GetBoolval();
|
|
assert(sm1 == sm2);
|
|
tuple_route1->DeleteIfAllowed();
|
|
tuple_route2->DeleteIfAllowed();
|
|
}
|
|
|
|
|
|
// cout<<"attr1 "<<attr1<<" attr2 "<<attr2<<" attr "<<attr<<endl;
|
|
vector<double> route_speed;
|
|
//// take the speed limit value from the relation///////////////
|
|
for(int i = 1;i <= rel2->GetNoTuples();i++){
|
|
Tuple* tuple_route = rel2->GetTuple(i, false);
|
|
double speed_val = ((CcReal*)tuple_route->GetAttribute(attr))->GetRealval();
|
|
route_speed.push_back(speed_val);
|
|
tuple_route->DeleteIfAllowed();
|
|
}
|
|
|
|
// cout<<"size "<<route_speed.size()<<endl;
|
|
for(int i = 1;i <= rel1->GetNoTuples();i++){
|
|
|
|
// if(i > 3 ) continue;
|
|
|
|
Tuple* tuple_bus_route = rel1->GetTuple(i, false);
|
|
int br_id = ((CcInt*)tuple_bus_route->GetAttribute(attr1))->GetIntval();
|
|
GLine* gl = (GLine*)tuple_bus_route->GetAttribute(attr2);
|
|
|
|
///////////////collect all road sections/////////////////////////
|
|
///////////////get the route id and the corresponding speed value////////
|
|
BusRoute* br = new BusRoute(n,NULL,NULL);
|
|
|
|
vector<bool> start_from;
|
|
vector<SectTreeEntry> sec_list;
|
|
br->GetSectionList(gl, sec_list, start_from);
|
|
|
|
vector<Pos_Speed> pos_speed1;
|
|
double dist = 0.0;
|
|
for(unsigned int j = 0;j < sec_list.size();j++){
|
|
dist += fabs(sec_list[j].end - sec_list[j].start);
|
|
double s = route_speed[sec_list[j].rid - 1];
|
|
/////////////we define -1 --- 10km/h //////////////////////////
|
|
////////the street that is not valid for cars//////////////
|
|
if(s < 0.0) s = 10.0;
|
|
///////////////////////////////////////////////////////////
|
|
Pos_Speed* ps = new Pos_Speed(dist, s);
|
|
pos_speed1.push_back(*ps);
|
|
delete ps;
|
|
}
|
|
|
|
// cout<<" size "<<pos_speed1.size()<<endl;
|
|
|
|
delete br;
|
|
/////////////// merge value /////////////////////////////////
|
|
vector<Pos_Speed> pos_speed2;
|
|
pos_speed2.push_back(pos_speed1[0]);
|
|
// cout<<"before "<<endl;
|
|
for(unsigned int j = 1;j < pos_speed1.size();j++){
|
|
// pos_speed1[j].Print();
|
|
Pos_Speed ps1 = pos_speed1[j];
|
|
Pos_Speed ps2 = pos_speed2[pos_speed2.size() - 1];
|
|
if(AlmostEqual(ps1.speed_val, ps2.speed_val)){
|
|
pos_speed2[pos_speed2.size() - 1].pos = ps1.pos;
|
|
}else
|
|
pos_speed2.push_back(ps1);
|
|
}
|
|
|
|
// cout<<"after "<<endl;
|
|
|
|
Line* l = new Line(0);
|
|
gl->Gline2line(l);
|
|
SimpleLine* sl = new SimpleLine(0);
|
|
sl->fromLine(*l);
|
|
|
|
for(unsigned int j = 0;j < pos_speed2.size();j++){
|
|
// pos_speed2[j].Print();
|
|
br_id_list.push_back(br_id);
|
|
br_pos.push_back(pos_speed2[j].pos);
|
|
speed_limit.push_back(pos_speed2[j].speed_val);
|
|
|
|
/////////////get the sub line of the speed//////////////////////////
|
|
|
|
SimpleLine* sub_line = new SimpleLine(0);
|
|
double pos1, pos2;
|
|
if(j == 0){
|
|
pos1 = 0.0;;
|
|
pos2 = pos_speed2[j].pos;
|
|
}else{
|
|
pos1 = pos_speed2[j - 1].pos;
|
|
pos2 = pos_speed2[j].pos;
|
|
}
|
|
|
|
sl->SubLine(pos1, pos2, sm_list[br_id - 1] , *sub_line);
|
|
Line* sub_l = new Line(0);
|
|
sub_line->toLine(*sub_l);
|
|
br_subroute.push_back(*sub_l);
|
|
sub_l->DeleteIfAllowed();
|
|
sub_line->DeleteIfAllowed();
|
|
/////////////////////////////////////////////////////////////////////
|
|
}
|
|
sl->DeleteIfAllowed();
|
|
l->DeleteIfAllowed();
|
|
|
|
//////////////////////////////////////////////////////////////
|
|
tuple_bus_route->DeleteIfAllowed();
|
|
}
|
|
|
|
}
|
|
|
|
bool CompareBusStop(const BusStop_Ext& bs1, const BusStop_Ext& bs2)
|
|
{
|
|
if(bs1.rid < bs2.rid) return true;
|
|
else if(bs1.rid == bs2.rid){
|
|
if(bs1.pos < bs2.pos) return true;
|
|
else if(AlmostEqual(bs1.pos,bs2.pos))return true;
|
|
else return false;
|
|
|
|
}else return false;
|
|
|
|
}
|
|
|
|
/*
|
|
for each bus route segment, it sets the speed value
|
|
|
|
*/
|
|
void RoadDenstiy::CreateSegmentSpeed(int attr1, int attr2, int attr3, int attr4,
|
|
int attr_a, int attr_b)
|
|
{
|
|
// cout<<"attr1 "<<attr1<<" attr2 "<<attr2<<" attr3 "<<attr3
|
|
// <<" attr4 "<<attr4
|
|
// <<" attr_a "<<attr_a<<" attr_b "<<attr_b<<endl;
|
|
|
|
for(int i = 1;i <= rel1->GetNoTuples();i++){
|
|
Tuple* tuple_bus_route = rel1->GetTuple(i, false);
|
|
/////collect br id, line, up down, startSmaller value of each route/////
|
|
int br_id = ((CcInt*)tuple_bus_route->GetAttribute(attr1))->GetIntval();
|
|
|
|
|
|
/* if(br_id != 48){
|
|
tuple_bus_route->DeleteIfAllowed();
|
|
continue;
|
|
}*/
|
|
|
|
|
|
Line* l = (Line*)tuple_bus_route->GetAttribute(attr2);
|
|
bool up_down =
|
|
((CcBool*)tuple_bus_route->GetAttribute(attr3))->GetBoolval();
|
|
bool startsmaller =
|
|
((CcBool*)tuple_bus_route->GetAttribute(attr4))->GetBoolval();
|
|
|
|
// cout<<"br_id "<<br_id<<" up_down "<<up_down
|
|
// <<" smaller "<<startsmaller<<endl;
|
|
|
|
////////////////get the speed limit of this bus route ///////////////////
|
|
CcInt* search_speed_id = new CcInt(true, br_id);
|
|
BTreeIterator* btree_iter2 = btree_b->ExactMatch(search_speed_id);
|
|
vector<Pos_Speed> br_speed_list;
|
|
|
|
while(btree_iter2->Next()){
|
|
Tuple* tuple_bs = rel3->GetTuple(btree_iter2->GetId(), false);
|
|
double bs_pos =
|
|
((CcReal*)tuple_bs->GetAttribute(BR_POS))->GetRealval();
|
|
double speed_val =
|
|
((CcReal*)tuple_bs->GetAttribute(BR_SPEED))->GetRealval();
|
|
Pos_Speed* pos_speed = new Pos_Speed(bs_pos, speed_val);
|
|
br_speed_list.push_back(*pos_speed);
|
|
delete pos_speed;
|
|
tuple_bs->DeleteIfAllowed();
|
|
}
|
|
|
|
|
|
delete btree_iter2;
|
|
search_speed_id->DeleteIfAllowed();
|
|
|
|
/* cout<<"speed limit"<<endl;
|
|
for(unsigned int j = 0;j < br_speed_list.size();j++){
|
|
br_speed_list[j].Print();
|
|
}*/
|
|
|
|
/////////collect all bus stops of this route/////////////////////////////
|
|
|
|
CcInt* search_bs_id = new CcInt(true, br_id);
|
|
BTreeIterator* btree_iter1 = btree_a->ExactMatch(search_bs_id);
|
|
vector<BusStop_Ext> bus_stop_list;
|
|
|
|
while(btree_iter1->Next()){
|
|
Tuple* tuple_bs = rel2->GetTuple(btree_iter1->GetId(), false);
|
|
double bs_pos =
|
|
((CcReal*)tuple_bs->GetAttribute(attr_a))->GetRealval();
|
|
bool direction =
|
|
((CcBool*)tuple_bs->GetAttribute(attr_b))->GetBoolval();
|
|
//take bus stops on the same side of the route
|
|
if(direction == up_down){
|
|
Point p(true,0.0,0.0);
|
|
BusStop_Ext* bs_ext = new BusStop_Ext(br_id,0,bs_pos,p,direction);
|
|
bus_stop_list.push_back(*bs_ext);
|
|
delete bs_ext;
|
|
}
|
|
tuple_bs->DeleteIfAllowed();
|
|
}
|
|
delete btree_iter1;
|
|
search_bs_id->DeleteIfAllowed();
|
|
|
|
sort(bus_stop_list.begin(),bus_stop_list.end(),CompareBusStop);
|
|
|
|
/* cout<<"bus stop list "<<endl;
|
|
for(unsigned int j = 0;j < bus_stop_list.size();j++){
|
|
bus_stop_list[j].Print();
|
|
}*/
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
SimpleLine* sl = new SimpleLine(0);
|
|
sl->fromLine(*l);
|
|
|
|
|
|
CalculateRouteSegment(sl, br_speed_list, bus_stop_list, startsmaller);
|
|
|
|
sl->DeleteIfAllowed();
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
tuple_bus_route->DeleteIfAllowed();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
calculate the bus segment combined with speed limit value
|
|
the returned lines are already ordered in the same way as bus stops
|
|
from bus stop id small to big.
|
|
It also writes down the start location (point) of each bus route for each
|
|
direction
|
|
return segment id (start from 1)
|
|
bus stop id (starts from 1)
|
|
|
|
*/
|
|
void RoadDenstiy::CalculateRouteSegment(SimpleLine* sl,
|
|
vector<Pos_Speed> br_speed_list,
|
|
vector<BusStop_Ext> bus_stop_list, bool sm)
|
|
{
|
|
BusStop_Ext last_stop = bus_stop_list[0];
|
|
// last_stop.Print();
|
|
|
|
unsigned int index_speed = 0;
|
|
// cout<<"length "<<sl->Length()<<endl;
|
|
|
|
vector<SimpleLine> sub_line_list;
|
|
vector<double> speed_val_list;
|
|
vector<int> bus_segment_id_list;
|
|
|
|
for(unsigned int i = 1;i < bus_stop_list.size();i++){
|
|
BusStop_Ext cur_stop = bus_stop_list[i];
|
|
|
|
// cur_stop.Print();
|
|
|
|
////////////advance the index ///////////////////////////
|
|
while(br_speed_list[index_speed].pos < last_stop.pos ||
|
|
AlmostEqual(br_speed_list[index_speed].pos,last_stop.pos))
|
|
index_speed++;
|
|
|
|
//////////////////////////////////////////////////////////
|
|
if(cur_stop.pos < br_speed_list[index_speed].pos ||
|
|
AlmostEqual(cur_stop.pos,br_speed_list[index_speed].pos)){
|
|
SimpleLine* sub_line1 = new SimpleLine(0);
|
|
sl->SubLine(last_stop.pos,cur_stop.pos,sm,*sub_line1);
|
|
// cout<<"sub length1 "<<sub_line1->Length()<<endl;
|
|
sub_line_list.push_back(*sub_line1);
|
|
sub_line1->DeleteIfAllowed();
|
|
speed_val_list.push_back(br_speed_list[index_speed].speed_val);
|
|
bus_segment_id_list.push_back(i);
|
|
|
|
}else{
|
|
//between last stop and cur stop
|
|
assert(last_stop.pos < br_speed_list[index_speed].pos &&
|
|
br_speed_list[index_speed].pos < cur_stop.pos);
|
|
|
|
SimpleLine* sub_line2 = new SimpleLine(0);
|
|
sl->SubLine(last_stop.pos,br_speed_list[index_speed].pos,
|
|
sm,*sub_line2);
|
|
// cout<<"sub length2 "<<sub_line2->Length()<<endl;
|
|
sub_line_list.push_back(*sub_line2);
|
|
sub_line2->DeleteIfAllowed();
|
|
speed_val_list.push_back(br_speed_list[index_speed].speed_val);
|
|
bus_segment_id_list.push_back(i);
|
|
|
|
|
|
unsigned int index_speed_tmp = index_speed + 1;
|
|
while(index_speed_tmp < br_speed_list.size() &&
|
|
br_speed_list[index_speed_tmp].pos < cur_stop.pos){
|
|
|
|
SimpleLine* sub_line3 = new SimpleLine(0);
|
|
sl->SubLine(br_speed_list[index_speed].pos,
|
|
br_speed_list[index_speed_tmp].pos,
|
|
sm,*sub_line3);
|
|
// cout<<"sub length3 "<<sub_line3->Length()<<endl;
|
|
sub_line_list.push_back(*sub_line3);
|
|
sub_line3->DeleteIfAllowed();
|
|
speed_val_list.push_back(br_speed_list[index_speed_tmp].speed_val);
|
|
|
|
bus_segment_id_list.push_back(i);
|
|
|
|
index_speed = index_speed_tmp;
|
|
index_speed_tmp = index_speed + 1;
|
|
}
|
|
|
|
SimpleLine* sub_line4 = new SimpleLine(0);
|
|
sl->SubLine(br_speed_list[index_speed].pos,cur_stop.pos,
|
|
sm,*sub_line4);
|
|
// cout<<"sub length4 "<<sub_line4->Length()<<endl;
|
|
sub_line_list.push_back(*sub_line4);
|
|
sub_line4->DeleteIfAllowed();
|
|
|
|
if(index_speed_tmp < br_speed_list.size())
|
|
speed_val_list.push_back(br_speed_list[index_speed_tmp].speed_val);
|
|
else
|
|
speed_val_list.push_back(br_speed_list[index_speed].speed_val);
|
|
|
|
bus_segment_id_list.push_back(i);
|
|
|
|
}
|
|
last_stop = cur_stop;
|
|
}
|
|
|
|
BusStop_Ext temp_stop = bus_stop_list[0];
|
|
assert(speed_val_list.size() == sub_line_list.size());
|
|
assert(speed_val_list.size() == bus_segment_id_list.size());
|
|
|
|
////////////get start location ///////////////////
|
|
Point sp;
|
|
if(temp_stop.start_small){ //up and down bus stop
|
|
assert(sl->AtPosition(temp_stop.pos,sm,sp));
|
|
}else{
|
|
BusStop_Ext temp_stop_end = bus_stop_list[bus_stop_list.size() - 1];
|
|
assert(sl->AtPosition(temp_stop_end.pos,sm,sp));
|
|
}
|
|
|
|
//////////////////////////////////////////////////
|
|
for(unsigned int i = 0;i < sub_line_list.size();i++){
|
|
br_id_list.push_back(temp_stop.br_id);
|
|
br_direction.push_back(temp_stop.start_small);//!!actually up and down
|
|
|
|
Line* temp_l = new Line(0);
|
|
sub_line_list[i].toLine(*temp_l);
|
|
br_subroute.push_back(*temp_l);
|
|
temp_l->DeleteIfAllowed();
|
|
|
|
|
|
speed_limit.push_back(speed_val_list[i]);
|
|
startSmaller.push_back(sm);
|
|
|
|
//write down the location of first bus stop
|
|
start_loc_list.push_back(sp);
|
|
|
|
//segmend id starts from 1
|
|
segment_id_list.push_back(bus_segment_id_list[i]);
|
|
}
|
|
|
|
|
|
}
|
|
|
|
/*
|
|
create night moving bus. it has two time intervals 0-5 21-24
|
|
|
|
*/
|
|
void RoadDenstiy::CreateNightBus()
|
|
{
|
|
for(int i = 1; i <= rel1->GetNoTuples();i++){
|
|
Tuple* tuple_bus_ts = rel1->GetTuple(i, false);
|
|
int br_id= ((CcInt*)tuple_bus_ts->GetAttribute(BR_ID2))->GetIntval();
|
|
|
|
// if(br_id != 41){
|
|
// tuple_bus_ts->DeleteIfAllowed();
|
|
// continue;
|
|
// }
|
|
|
|
Periods* peri1 = (Periods*)tuple_bus_ts->GetAttribute(DURATION1);
|
|
Periods* peri2 = (Periods*)tuple_bus_ts->GetAttribute(DURATION2);
|
|
double time_interval =
|
|
((CcReal*)tuple_bus_ts->GetAttribute(BR_INTERVAL))->GetRealval();
|
|
|
|
// cout<<"br_id "<<br_id<<" Periods1 "<<*peri1
|
|
// <<" Periods2 "<<*peri2<<" interval "<<time_interval<<endl;
|
|
|
|
CreateMovingBus(br_id,peri1,time_interval, false);
|
|
CreateMovingBus(br_id,peri2,time_interval, false);
|
|
tuple_bus_ts->DeleteIfAllowed();
|
|
|
|
// break;
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
create moving objects during the time interval.peri
|
|
actually, it creates a set of moving objects. the start time deviation
|
|
between each two consequent schedule is time interval
|
|
70 km h 1166.67 m minute 19.44 m second
|
|
50 km h 8333.3m minute 13.89 m second
|
|
30 km h 500 m minute 8.33 m second
|
|
10 km h 166.67 m minute 2.78 m second
|
|
|
|
*/
|
|
void RoadDenstiy::CreateMovingBus(int br_id,Periods* peri,
|
|
double time_interval, bool daytime)
|
|
{
|
|
|
|
CreateUp(br_id, peri, time_interval, daytime);
|
|
CreateDown(br_id, peri, time_interval, daytime);
|
|
}
|
|
|
|
/*
|
|
create moving bus in up direction
|
|
|
|
*/
|
|
void RoadDenstiy::CreateUp(int br_id, Periods* peri,
|
|
double time_interval, bool daytime)
|
|
{
|
|
// cout<<"create bus trip: route "<<br_id<<" up "<<endl;
|
|
|
|
vector<SimpleLine> sub_sline_list;
|
|
vector<double> speed_list;
|
|
vector<int> seg_id_list;
|
|
|
|
//////////////////////collect all bus segments of up direction//////////////
|
|
CcInt* search_bs_id = new CcInt(true, br_id);
|
|
BTreeIterator* btree_iter = btree->ExactMatch(search_bs_id);
|
|
Point start_p;
|
|
while(btree_iter->Next()){
|
|
Tuple* tuple_bs = rel2->GetTuple(btree_iter->GetId(), false);
|
|
bool direction =
|
|
((CcBool*)tuple_bs->GetAttribute(BUS_DIRECTION))->GetBoolval();
|
|
if(direction){ //up direction
|
|
Line* l = (Line*)tuple_bs->GetAttribute(SUB_ROUTE_LINE);
|
|
double speed_val =
|
|
((CcReal*)tuple_bs->GetAttribute(SPEED_LIMIT))->GetRealval();
|
|
SimpleLine* sl = new SimpleLine(0);
|
|
sl->fromLine(*l);
|
|
sub_sline_list.push_back(*sl);
|
|
sl->DeleteIfAllowed();
|
|
speed_list.push_back(speed_val);
|
|
|
|
int segid = ((CcInt*)tuple_bs->GetAttribute(SEGMENT_ID))->GetIntval();
|
|
seg_id_list.push_back(segid);
|
|
|
|
////get the start point///
|
|
Point* p = (Point*)tuple_bs->GetAttribute(START_LOC);
|
|
start_p = *p;
|
|
}
|
|
tuple_bs->DeleteIfAllowed();
|
|
}
|
|
delete btree_iter;
|
|
search_bs_id->DeleteIfAllowed();
|
|
|
|
|
|
/////////////////create one bus trip movement///////////////////////////////
|
|
const double dist_delta = 0.01;
|
|
MPoint* bus_mo = new MPoint(0);
|
|
bus_mo->StartBulkLoad();
|
|
Interval<Instant> bus_periods;
|
|
peri->Get(0, bus_periods);
|
|
|
|
// cout<<"seg_id_list size "<<seg_id_list.size()
|
|
// <<"sub sline size "<<sub_sline_list.size()<<endl;
|
|
|
|
// for(unsigned int i = 0;i < seg_id_list.size();i++)
|
|
// cout<<"seg id "<<seg_id_list[i]<<endl;
|
|
|
|
|
|
// int last_seg_id = seg_id_list[0];
|
|
int last_seg_id = 0; //initialize, real segment starts from 1.
|
|
UPoint last_upoint;
|
|
|
|
for(unsigned int i = 0;i < sub_sline_list.size();i++){
|
|
SpacePartition* sp = new SpacePartition();
|
|
vector<MyHalfSegment> seq_halfseg; //reorder it from start to end
|
|
// cout<<sub_sline_list[i].Length()<<endl;
|
|
// cout<<"i "<<i<<"last_seg_id "<<last_seg_id
|
|
// <<"cur seg id "<<seg_id_list[i]<<endl;
|
|
|
|
if(!(sub_sline_list[i].Length() > 0.0)){
|
|
delete sp;
|
|
continue;
|
|
}
|
|
sp->ReorderLine(&sub_sline_list[i], seq_halfseg);
|
|
assert(seq_halfseg.size() > 0);
|
|
|
|
Point temp_sp1 = seq_halfseg[0].from;
|
|
Point temp_sp2 = seq_halfseg[seq_halfseg.size() - 1].to;
|
|
|
|
// cout<<"last start p "<<start_p
|
|
// <<"endpoint1 "<<temp_sp1
|
|
// <<" endpoint2 "<<temp_sp2<<endl;
|
|
|
|
//bool start;
|
|
double real_speed = speed_list[i] * 1000 / 60;// convert to meter minute
|
|
if(start_p.Distance(temp_sp1) < dist_delta){
|
|
////////moving bus moves to the bus stop and wait for a while//////
|
|
if(last_seg_id != seg_id_list[i]){
|
|
// cout<<"trip 1"
|
|
// <<"last_seg_id "<<last_seg_id
|
|
// <<"seg_id_list[i] "<<seg_id_list[i]
|
|
// <<"i "<<i<<endl;
|
|
|
|
last_seg_id = seg_id_list[i];
|
|
Interval<Instant> up_interval;
|
|
up_interval.start = bus_periods.start;
|
|
up_interval.lc = true;
|
|
Instant newend = bus_periods.start;
|
|
////////////////pause for 30 seconds /////////////////////////////
|
|
newend.ReadFrom(bus_periods.start.ToDouble() + 30.0/(24.0*60*60));
|
|
up_interval.end = newend;
|
|
up_interval.rc = false;
|
|
UPoint* up = new UPoint(up_interval,temp_sp1,temp_sp1);
|
|
bus_mo->Add(*up);
|
|
|
|
up->DeleteIfAllowed();
|
|
bus_periods.start = newend;
|
|
}
|
|
|
|
//start = true;
|
|
start_p = temp_sp2;
|
|
CreateBusTrip1(bus_mo, seq_halfseg, bus_periods.start,
|
|
real_speed, last_upoint);
|
|
}else if(start_p.Distance(temp_sp2) < dist_delta){
|
|
////////moving bus moves to the bus stop and wait for a while//////
|
|
if(last_seg_id != seg_id_list[i]){
|
|
// cout<<"trip 2"
|
|
// <<"last_seg_id "<<last_seg_id
|
|
// <<"seg_id_list[i] "<<seg_id_list[i]
|
|
// <<"i "<<i<<endl;
|
|
|
|
last_seg_id = seg_id_list[i];
|
|
Interval<Instant> up_interval;
|
|
up_interval.start = bus_periods.start;
|
|
up_interval.lc = true;
|
|
Instant newend = bus_periods.start;
|
|
////////////////pause for 30 seconds //////////////////////////
|
|
newend.ReadFrom(bus_periods.start.ToDouble() + 30.0/(24.0*60*60));
|
|
up_interval.end = newend;
|
|
up_interval.rc = false;
|
|
UPoint* up = new UPoint(up_interval,temp_sp2,temp_sp2);
|
|
bus_mo->Add(*up);
|
|
last_upoint = *up;
|
|
up->DeleteIfAllowed();
|
|
bus_periods.start = newend;
|
|
}
|
|
//start = false;
|
|
start_p = temp_sp1;
|
|
CreateBusTrip2(bus_mo, seq_halfseg, bus_periods.start,
|
|
real_speed, last_upoint);
|
|
}else assert(false);
|
|
|
|
delete sp;
|
|
}
|
|
////////////////add 30 seconds wait for the last bus stop/////////////////
|
|
Instant new_end = last_upoint.timeInterval.end;
|
|
last_upoint.timeInterval.start = new_end;
|
|
new_end.ReadFrom(new_end.ToDouble() + 30.0/(24.0*60*60));
|
|
last_upoint.timeInterval.end = new_end;
|
|
last_upoint.p0 = last_upoint.p1;
|
|
bus_mo->Add(last_upoint);
|
|
/////////////////////////////////////////////////////////////////////
|
|
bus_mo->EndBulkLoad();
|
|
///////////////////////////add to the result ///////////////////////
|
|
br_id_list.push_back(br_id);
|
|
br_direction.push_back(true); //UP direction
|
|
bus_trip.push_back(*bus_mo);
|
|
////////////////////////////////////////////////////////////////////
|
|
AddTypeandDay(bus_mo,daytime);
|
|
//////////////////////////////////////////////////////////////////
|
|
int schedule_id = 1;
|
|
schedule_id_list.push_back(schedule_id);
|
|
schedule_id++;
|
|
//////////////////copy the trip by time interval//////////////////////////
|
|
CopyBusTrip(br_id, true, bus_mo, peri, time_interval,daytime,schedule_id);
|
|
//////////////////////////////////////////////////////////////////////////
|
|
delete bus_mo;
|
|
}
|
|
|
|
/*
|
|
create moving bus units and add them into the trip,
|
|
it travers from index small to big in myhalfsegment list
|
|
use the maxspeed as bus speed
|
|
|
|
*/
|
|
|
|
void RoadDenstiy::CreateBusTrip1(MPoint* mo,
|
|
vector<MyHalfSegment> seq_halfseg,
|
|
Instant& start_time,
|
|
double speed_val, UPoint& last_up)
|
|
{
|
|
|
|
// cout<<"trip1 max speed "<<speed_val<<" start time "<<start_time<<endl;
|
|
|
|
const double dist_delta = 0.01;
|
|
|
|
Instant st = start_time;
|
|
Instant et = start_time;
|
|
Interval<Instant> up_interval;
|
|
for(unsigned int i = 0;i < seq_halfseg.size();i++){
|
|
Point from_loc = seq_halfseg[i].from;
|
|
Point to_loc = seq_halfseg[i].to;
|
|
|
|
double dist = from_loc.Distance(to_loc);
|
|
double time = dist/speed_val;
|
|
|
|
// cout<<"dist "<<dist<<" time "<<time<<endl;
|
|
// printf("%.10f, %.10f",dist, time);
|
|
//////////////////////////////////////////////////////////////
|
|
if(dist < dist_delta){//ignore such small segment
|
|
if((i + 1) < seq_halfseg.size()){
|
|
seq_halfseg[i+1].from = from_loc;
|
|
}
|
|
continue;
|
|
}
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
et.ReadFrom(st.ToDouble() + time*1.0/(24.0*60.0));//double 1.0 means 1 day
|
|
// cout<<st<<" "<<et<<endl;
|
|
|
|
int64_t time1 = st.ToDouble()*86400000.0;
|
|
int64_t time2 = et.ToDouble()*86400000.0;
|
|
if(time1 == time2){/////////time is equal, unit is not valid
|
|
if((i + 1) < seq_halfseg.size()){
|
|
seq_halfseg[i + 1].from = from_loc;
|
|
}
|
|
continue;
|
|
}
|
|
|
|
////////////////////create a upoint////////////////////////
|
|
up_interval.start = st;
|
|
up_interval.lc = true;
|
|
up_interval.end = et;
|
|
up_interval.rc = false;
|
|
UPoint* up = new UPoint(up_interval,from_loc,to_loc);
|
|
// cout<<*up<<endl;
|
|
mo->Add(*up);
|
|
last_up = *up;
|
|
up->DeleteIfAllowed();
|
|
//////////////////////////////////////////////////////////////
|
|
st = et;
|
|
}
|
|
|
|
start_time = et;
|
|
|
|
}
|
|
|
|
/*
|
|
create moving bus units and add them into the trip,
|
|
!!! it traverse from index big to small in myhalfsegment list
|
|
use the maxspeed as bus speed
|
|
|
|
*/
|
|
void RoadDenstiy::CreateBusTrip2(MPoint* mo,
|
|
vector<MyHalfSegment> seq_halfseg,
|
|
Instant& start_time,
|
|
double speed_val, UPoint& last_up)
|
|
{
|
|
const double dist_delta = 0.01;
|
|
// cout<<"trip2 max speed "<<speed_val<<" start time "<<start_time<<endl;
|
|
Instant st = start_time;
|
|
Instant et = start_time;
|
|
Interval<Instant> up_interval;
|
|
for(int i = seq_halfseg.size() - 1;i >= 0;i--){
|
|
Point from_loc = seq_halfseg[i].to;
|
|
Point to_loc = seq_halfseg[i].from;
|
|
double dist = from_loc.Distance(to_loc);
|
|
double time = dist/speed_val;
|
|
|
|
// cout<<"dist "<<dist<<" time "<<time<<endl;
|
|
///////////////////////////////////////////////////////////////////
|
|
if(dist < dist_delta){//ignore such small segment
|
|
if((i + 1) < (int) seq_halfseg.size()){
|
|
seq_halfseg[i+1].from = from_loc;
|
|
}
|
|
continue;
|
|
}
|
|
|
|
et.ReadFrom(st.ToDouble() + time*1.0/(24.0*60.0));//double 1.0 means 1 day
|
|
// cout<<st<<" "<<et<<endl;
|
|
|
|
|
|
int64_t time1 = st.ToDouble()*86400000.0;
|
|
int64_t time2 = et.ToDouble()*86400000.0;
|
|
if(time1 == time2){/////////time is equal, unit is not valid
|
|
if((i + 1) < (int)seq_halfseg.size()){
|
|
seq_halfseg[i + 1].from = from_loc;
|
|
}
|
|
continue;
|
|
}
|
|
|
|
////////////////////create a upoint////////////////////////
|
|
up_interval.start = st;
|
|
up_interval.lc = true;
|
|
up_interval.end = et;
|
|
up_interval.rc = false;
|
|
UPoint* up = new UPoint(up_interval,from_loc,to_loc);
|
|
mo->Add(*up);
|
|
last_up = *up;
|
|
up->DeleteIfAllowed();
|
|
//////////////////////////////////////////////////////////////
|
|
st = et;
|
|
}
|
|
|
|
start_time = et;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
create moving bus in down direction.
|
|
the bus moves from large bus stop id to small bus stop id
|
|
|
|
*/
|
|
void RoadDenstiy::CreateDown(int br_id, Periods* peri,
|
|
double time_interval, bool daytime)
|
|
{
|
|
|
|
// cout<<"create bus trip: route "<<br_id<<" down "<<endl;
|
|
|
|
vector<SimpleLine> sub_sline_list;
|
|
vector<double> speed_list;
|
|
vector<int> seg_id_list;
|
|
|
|
//////////////////////collect all bus segments of up direction//////////////
|
|
CcInt* search_bs_id = new CcInt(true, br_id);
|
|
BTreeIterator* btree_iter = btree->ExactMatch(search_bs_id);
|
|
Point start_p;
|
|
while(btree_iter->Next()){
|
|
Tuple* tuple_bs = rel2->GetTuple(btree_iter->GetId(), false);
|
|
bool direction =
|
|
((CcBool*)tuple_bs->GetAttribute(BUS_DIRECTION))->GetBoolval();
|
|
if(direction == false){ //down direction
|
|
Line* l = (Line*)tuple_bs->GetAttribute(SUB_ROUTE_LINE);
|
|
double speed_val =
|
|
((CcReal*)tuple_bs->GetAttribute(SPEED_LIMIT))->GetRealval();
|
|
SimpleLine* sl = new SimpleLine(0);
|
|
sl->fromLine(*l);
|
|
sub_sline_list.push_back(*sl);
|
|
sl->DeleteIfAllowed();
|
|
speed_list.push_back(speed_val);
|
|
|
|
int segid = ((CcInt*)tuple_bs->GetAttribute(SEGMENT_ID))->GetIntval();
|
|
seg_id_list.push_back(segid);
|
|
|
|
////get the start point///
|
|
Point* p = (Point*)tuple_bs->GetAttribute(START_LOC);
|
|
start_p = *p;
|
|
}
|
|
tuple_bs->DeleteIfAllowed();
|
|
}
|
|
delete btree_iter;
|
|
search_bs_id->DeleteIfAllowed();
|
|
|
|
|
|
/////////////////create one bus trip movement///////////////////////////////
|
|
const double dist_delta = 0.01;
|
|
MPoint* bus_mo = new MPoint(0);
|
|
bus_mo->StartBulkLoad();
|
|
Interval<Instant> bus_periods;
|
|
peri->Get(0, bus_periods);
|
|
|
|
// cout<<"seg_id_list size "<<seg_id_list.size()
|
|
// <<"sub sline size "<<sub_sline_list.size()<<endl;
|
|
|
|
// for(unsigned int i = 0;i < seg_id_list.size();i++)
|
|
// cout<<"seg id "<<seg_id_list[i]<<endl;
|
|
|
|
UPoint last_upoint;
|
|
// int last_seg_id = seg_id_list[seg_id_list.size() - 1]; //from the last
|
|
int last_seg_id = 0; //initialize, real segment starts from 1
|
|
|
|
for(int i = sub_sline_list.size() - 1;i >= 0 ;i--){
|
|
SpacePartition* sp = new SpacePartition();
|
|
vector<MyHalfSegment> seq_halfseg; //reorder it from start to end
|
|
// cout<<sub_sline_list[i].Length()<<endl;
|
|
// cout<<"i "<<i<<"last_seg_id "<<last_seg_id
|
|
// <<" cur seg id "<<seg_id_list[i]
|
|
// <<"length "<<sub_sline_list[i].Length()<<endl;
|
|
|
|
if(!(sub_sline_list[i].Length() > 0.0)){
|
|
delete sp;
|
|
continue;
|
|
}
|
|
|
|
sp->ReorderLine(&sub_sline_list[i], seq_halfseg);
|
|
assert(seq_halfseg.size() > 0);
|
|
|
|
Point temp_sp1 = seq_halfseg[0].from;
|
|
Point temp_sp2 = seq_halfseg[seq_halfseg.size() - 1].to;
|
|
|
|
double real_speed = speed_list[i] * 1000 / 60;// convert to meter minute
|
|
if(start_p.Distance(temp_sp1) < dist_delta){
|
|
////////moving bus moves to the bus stop and wait for a while//////
|
|
if(last_seg_id != seg_id_list[i]){
|
|
// cout<<"trip 1"
|
|
// <<"last_seg_id "<<last_seg_id
|
|
// <<"seg_id_list[i] "<<seg_id_list[i]
|
|
// <<"i "<<i<<endl;
|
|
|
|
last_seg_id = seg_id_list[i];
|
|
Interval<Instant> up_interval;
|
|
up_interval.start = bus_periods.start;
|
|
up_interval.lc = true;
|
|
Instant newend = bus_periods.start;
|
|
////////////////pause for 30 seconds /////////////////////////////
|
|
newend.ReadFrom(bus_periods.start.ToDouble() + 30.0/(24.0*60*60));
|
|
up_interval.end = newend;
|
|
up_interval.rc = false;
|
|
UPoint* up = new UPoint(up_interval,temp_sp1,temp_sp1);
|
|
bus_mo->Add(*up);
|
|
|
|
delete up;
|
|
bus_periods.start = newend;
|
|
}
|
|
|
|
|
|
start_p = temp_sp2;
|
|
CreateBusTrip1(bus_mo, seq_halfseg, bus_periods.start,
|
|
real_speed, last_upoint);
|
|
}else if(start_p.Distance(temp_sp2) < dist_delta){
|
|
////////moving bus moves to the bus stop and wait for a while//////
|
|
if(last_seg_id != seg_id_list[i]){
|
|
// cout<<"trip 2"
|
|
// <<"last_seg_id "<<last_seg_id
|
|
// <<"seg_id_list[i] "<<seg_id_list[i]
|
|
// <<"i "<<i<<endl;
|
|
|
|
last_seg_id = seg_id_list[i];
|
|
Interval<Instant> up_interval;
|
|
up_interval.start = bus_periods.start;
|
|
up_interval.lc = true;
|
|
Instant newend = bus_periods.start;
|
|
////////////////pause for 30 seconds //////////////////////////
|
|
newend.ReadFrom(bus_periods.start.ToDouble() + 30.0/(24.0*60*60));
|
|
up_interval.end = newend;
|
|
up_interval.rc = false;
|
|
UPoint* up = new UPoint(up_interval,temp_sp2,temp_sp2);
|
|
bus_mo->Add(*up);
|
|
|
|
delete up;
|
|
bus_periods.start = newend;
|
|
}
|
|
|
|
start_p = temp_sp1;
|
|
CreateBusTrip2(bus_mo, seq_halfseg, bus_periods.start,
|
|
real_speed, last_upoint);
|
|
}else assert(false);
|
|
|
|
delete sp;
|
|
}
|
|
////////////////add 30 seconds wait for the last bus stop/////////////////
|
|
Instant new_end = last_upoint.timeInterval.end;
|
|
last_upoint.timeInterval.start = new_end;
|
|
new_end.ReadFrom(new_end.ToDouble() + 30.0/(24.0*60*60));
|
|
last_upoint.timeInterval.end = new_end;
|
|
last_upoint.p0 = last_upoint.p1;
|
|
bus_mo->Add(last_upoint);
|
|
/////////////////////////////////////////////////////////////////////////
|
|
bus_mo->EndBulkLoad();
|
|
///////////////////////////add to the result ///////////////////////
|
|
br_id_list.push_back(br_id);
|
|
br_direction.push_back(false); //DOWN direction
|
|
bus_trip.push_back(*bus_mo);
|
|
////////////////////////////////////////////////////////////////////
|
|
AddTypeandDay(bus_mo, daytime);
|
|
///////////////////////add schedule counter/////////////////////////////
|
|
int schedule_id = 1;
|
|
schedule_id_list.push_back(schedule_id);
|
|
schedule_id++;
|
|
//////////////////copy the trip by time interval///////////////////////////
|
|
CopyBusTrip(br_id, false, bus_mo, peri, time_interval,daytime,schedule_id);
|
|
///////////////////////////////////////////////////////////////////////////
|
|
delete bus_mo;
|
|
}
|
|
|
|
/*
|
|
create a moving bus trip for every time interval
|
|
|
|
*/
|
|
void RoadDenstiy::CopyBusTrip(int br_id,bool direction,
|
|
MPoint* mo, Periods* peri,
|
|
double time_interval, bool daytime,
|
|
int schedule_id)
|
|
{
|
|
// cout<<"periods "<<*peri<<endl;
|
|
|
|
Interval<Instant> bus_periods;
|
|
peri->Get(0, bus_periods);
|
|
Instant st = bus_periods.start;
|
|
st.ReadFrom(st.ToDouble() + time_interval);
|
|
/////////////calculate the number of copies /////////////////////
|
|
unsigned int copy_no = 0;
|
|
while(st <= bus_periods.end){
|
|
copy_no++;
|
|
// cout<<"new st "<<st<<endl;
|
|
st.ReadFrom(st.ToDouble() + time_interval);
|
|
}
|
|
|
|
|
|
for(unsigned int i = 0;i < copy_no;i++){
|
|
MPoint* mo1 = new MPoint(0);
|
|
mo1->StartBulkLoad();
|
|
for(int j = 0;j < mo->GetNoComponents();j++){
|
|
UPoint up1;
|
|
mo->Get(j, up1);
|
|
Interval<Instant> up_interval;
|
|
|
|
Instant st = up1.timeInterval.start;
|
|
st.ReadFrom(st.ToDouble() + (i+1)*time_interval);
|
|
up_interval.start = st;
|
|
up_interval.lc = up1.timeInterval.lc;
|
|
|
|
|
|
Instant et = up1.timeInterval.end;
|
|
et.ReadFrom(et.ToDouble() + (i+1)*time_interval);
|
|
up_interval.end = et;
|
|
up_interval.rc = up1.timeInterval.rc;
|
|
|
|
|
|
UPoint* up2 = new UPoint(up_interval, up1.p0,up1.p1);
|
|
mo1->Add(*up2);
|
|
delete up2;
|
|
}
|
|
mo1->EndBulkLoad();
|
|
|
|
br_id_list.push_back(br_id);
|
|
br_direction.push_back(direction);
|
|
bus_trip.push_back(*mo1);
|
|
////////Sunday,Monday,Night,Daytime////////////////////
|
|
AddTypeandDay(mo1, daytime);
|
|
/////////Schedule ID//////////////////////////////////
|
|
schedule_id_list.push_back(schedule_id);
|
|
schedule_id++;
|
|
////////////////////////////////////////////////////////
|
|
mo1->DeleteIfAllowed();
|
|
}
|
|
//////////////////////////copy the trip one day more//////////////////////
|
|
if(daytime == false){ //only for night bus
|
|
for(unsigned int i = 0;i < copy_no + 1;i++){
|
|
MPoint* mo1 = new MPoint(0);
|
|
mo1->StartBulkLoad();
|
|
for(int j = 0;j < mo->GetNoComponents();j++){
|
|
UPoint up1;
|
|
mo->Get(j, up1);
|
|
Interval<Instant> up_interval;
|
|
|
|
Instant st = up1.timeInterval.start;
|
|
st.ReadFrom(st.ToDouble() + i*time_interval + 1.0);//1 day more
|
|
up_interval.start = st;
|
|
up_interval.lc = up1.timeInterval.lc;
|
|
|
|
|
|
Instant et = up1.timeInterval.end;
|
|
et.ReadFrom(et.ToDouble() + i*time_interval + 1.0);//1 day more
|
|
up_interval.end = et;
|
|
up_interval.rc = up1.timeInterval.rc;
|
|
|
|
|
|
UPoint* up2 = new UPoint(up_interval, up1.p0,up1.p1);
|
|
mo1->Add(*up2);
|
|
delete up2;
|
|
}
|
|
mo1->EndBulkLoad();
|
|
|
|
br_id_list.push_back(br_id);
|
|
br_direction.push_back(direction);
|
|
bus_trip.push_back(*mo1);
|
|
//////////Sunday,Monday,Night,Daytime///////////////////////
|
|
AddTypeandDay(mo1, daytime);
|
|
/////////Schedule ID////////////////////
|
|
schedule_id_list.push_back(schedule_id);
|
|
schedule_id++;
|
|
//////////////////////////////////////////////
|
|
mo1->DeleteIfAllowed();
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
add type of the bus: night or daytime
|
|
add whether it is Monday, Sunday or ...
|
|
|
|
*/
|
|
void RoadDenstiy::AddTypeandDay(MPoint* mo, bool daytime)
|
|
{
|
|
|
|
if(daytime)
|
|
trip_type.push_back("daytime");
|
|
else
|
|
trip_type.push_back("night");
|
|
|
|
assert(mo->GetNoComponents() > 0);
|
|
UPoint up;
|
|
mo->Get(0, up);
|
|
Instant st = up.timeInterval.start;
|
|
int d = st.GetWeekday();//0--Monday
|
|
// cout<<"start time "<<st<<"d "<<d<<endl;
|
|
string str;
|
|
switch(d){
|
|
case 0: str = "Monday";
|
|
break;
|
|
case 1: str = "Tuesday";
|
|
break;
|
|
case 2: str = "Wednesday";
|
|
break;
|
|
case 3: str = "Thursday";
|
|
break;
|
|
case 4: str = "Friday";
|
|
break;
|
|
case 5: str = "Saturday";
|
|
break;
|
|
case 6: str = "Sunday";
|
|
break;
|
|
default:str = " ";
|
|
break;
|
|
}
|
|
trip_day.push_back(str);
|
|
}
|
|
|
|
/*
|
|
create daytime moving bus. it has two types of movement: Monday and Sunday
|
|
different time intervals
|
|
|
|
*/
|
|
|
|
void RoadDenstiy::CreateDayTimeBus()
|
|
{
|
|
|
|
for(int i = 1; i <= rel1->GetNoTuples();i++){
|
|
Tuple* tuple_bus_ts = rel1->GetTuple(i, false);
|
|
int br_id= ((CcInt*)tuple_bus_ts->GetAttribute(BR_ID3))->GetIntval();
|
|
|
|
// cout<<"br_id "<<br_id<<endl;
|
|
|
|
// if(br_id != 1){
|
|
// tuple_bus_ts->DeleteIfAllowed();
|
|
// continue;
|
|
// }
|
|
|
|
Periods* peri1 = (Periods*)tuple_bus_ts->GetAttribute(DURATION1);
|
|
Periods* peri2 = (Periods*)tuple_bus_ts->GetAttribute(DURATION2);
|
|
double time_interval1 =
|
|
((CcReal*)tuple_bus_ts->GetAttribute(BR_INTERVAL1))->GetRealval();
|
|
double time_interval2 =
|
|
((CcReal*)tuple_bus_ts->GetAttribute(BR_INTERVAL2))->GetRealval();
|
|
|
|
// cout<<"br_id "<<br_id<<" Periods1 "<<*peri1
|
|
// <<" Periods2 "<<*peri2<<" interval "<<time_interval<<endl;
|
|
|
|
CreateMovingBus(br_id, peri1, time_interval1, true);
|
|
CreateMovingBus(br_id, peri2, time_interval2, true);
|
|
tuple_bus_ts->DeleteIfAllowed();
|
|
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
create time table at each spatial location. several bus stops from different
|
|
bus routes can locate at the same spatial location
|
|
Compact Storage:
|
|
loc:point lineid:int stopid:int direction:bool deftime:periods
|
|
locid:int scheduleinterval:double
|
|
|
|
for one route, one direction, one stop, it has at most four tuples
|
|
night1 night2 sunday monday
|
|
|
|
or only two tuples: sunday mondy
|
|
|
|
*/
|
|
void RoadDenstiy::CreateTimeTable_Compact(Periods* peri1, Periods* peri2)
|
|
{
|
|
////////////collect all bus stops /////////////////////////////////
|
|
vector<BusStop_Ext> bus_stop_list;
|
|
for(int i = 1;i <= rel1->GetNoTuples();i++){
|
|
Tuple* tuple_bus_stop = rel1->GetTuple(i, false);
|
|
int br_id = ((CcInt*)tuple_bus_stop->GetAttribute(BR_ID4))->GetIntval();
|
|
int stop_id =
|
|
((CcInt*)tuple_bus_stop->GetAttribute(BUS_STOP_ID))->GetIntval();
|
|
Point* loc = (Point*)tuple_bus_stop->GetAttribute(BUS_LOC);
|
|
bool start_small =
|
|
((CcBool*)tuple_bus_stop->GetAttribute(STOP_DIRECTION))->GetBoolval();
|
|
|
|
BusStop_Ext* bse = new BusStop_Ext(br_id,stop_id,0,*loc,start_small);
|
|
bus_stop_list.push_back(*bse);
|
|
delete bse;
|
|
tuple_bus_stop->DeleteIfAllowed();
|
|
}
|
|
|
|
sort(bus_stop_list.begin(), bus_stop_list.end());
|
|
// cout<<"bus_stop_list size "<<bus_stop_list.size()<<endl;
|
|
|
|
const double dist_delta = 0.01;
|
|
unsigned int temp_count = 1;
|
|
for(unsigned int i = 0;i < bus_stop_list.size();i++){
|
|
vector<BusStop_Ext> bus_stop_list_new;
|
|
|
|
bus_stop_list_new.push_back(bus_stop_list[i]);
|
|
|
|
////////collect all bus stops mapping to the same 2D point in space/////
|
|
unsigned int j = i + 1;
|
|
BusStop_Ext bse = bus_stop_list_new[0];
|
|
// bse.Print();
|
|
|
|
while(j < bus_stop_list.size() &&
|
|
bus_stop_list[j].loc.Distance(bse.loc) < dist_delta ){
|
|
bus_stop_list_new.push_back(bus_stop_list[j]);
|
|
j++;
|
|
}
|
|
i = j - 1;
|
|
///////////////////process bus stop list new ///////////////////////////
|
|
// cout<<"sub size "<<bus_stop_list_new.size()<<endl;
|
|
|
|
CreateLocTable_Compact(bus_stop_list_new,temp_count,peri1,peri2);
|
|
|
|
temp_count++;
|
|
|
|
// break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
get the time table for one spatial location
|
|
|
|
*/
|
|
void RoadDenstiy::CreateLocTable_Compact(vector<BusStop_Ext> bus_stop_list_new,
|
|
int count_id, Periods* peri1, Periods* peri2)
|
|
{
|
|
// cout<<"bus_stop_list_new size "<<bus_stop_list_new.size()<<endl;
|
|
|
|
Point loc = bus_stop_list_new[0].loc;
|
|
|
|
// cout<<"bus stop location "<<loc<<endl;
|
|
|
|
for(unsigned int i = 0;i < bus_stop_list_new.size();i++){
|
|
int br_id = bus_stop_list_new[i].br_id;
|
|
bool direction = bus_stop_list_new[i].start_small;
|
|
int stop_id = bus_stop_list_new[i].br_stop_id;
|
|
|
|
// if( !(br_id == 11 && direction)) continue;
|
|
|
|
// cout<<"br_id "<<br_id<<" direction "<<direction<<endl;
|
|
|
|
/////use btree to find all bus trips of this route ///////
|
|
CcInt* search_trip_id = new CcInt(true, br_id);
|
|
BTreeIterator* btree_iter = btree->ExactMatch(search_trip_id);
|
|
|
|
vector<MPoint> night_mo;
|
|
vector<MPoint> day_mo1; //Monday
|
|
vector<MPoint> day_mo2; //Sunday
|
|
|
|
while(btree_iter->Next()){
|
|
Tuple* tuple_trip = rel2->GetTuple(btree_iter->GetId(), false);
|
|
int br_trip_id =
|
|
((CcInt*)tuple_trip->GetAttribute(BR_ID5))->GetIntval();
|
|
bool trip_direction =
|
|
((CcBool*)tuple_trip->GetAttribute(MO_BUS_DIRECTION))->GetBoolval();
|
|
assert(br_id == br_trip_id);
|
|
if(direction == trip_direction){
|
|
MPoint* mo = (MPoint*)tuple_trip->GetAttribute(BUS_TRIP);
|
|
string busday =
|
|
((CcString*)tuple_trip->GetAttribute(BUS_DAY))->GetValue();
|
|
string bus_type =
|
|
((CcString*)tuple_trip->GetAttribute(BUS_TYPE))->GetValue();
|
|
UPoint up;
|
|
mo->Get(0, up);
|
|
////////////////////////////////////////////////////////////////////
|
|
//////// classify the buses into groups according to time ///////
|
|
//////////////////////////////////////////////////////////////////
|
|
|
|
if(bus_type.compare("night") == 0){// only need one day for night bus
|
|
if(SameDay(up,peri1))
|
|
night_mo.push_back(*mo);
|
|
}else{
|
|
if(busday.compare("Monday") == 0){
|
|
day_mo1.push_back(*mo);
|
|
}
|
|
else if(busday.compare("Sunday") == 0){
|
|
day_mo2.push_back(*mo);
|
|
}
|
|
else assert(false);
|
|
}
|
|
////////////////////////////////////////////////////////////
|
|
}
|
|
tuple_trip->DeleteIfAllowed();
|
|
}
|
|
delete btree_iter;
|
|
search_trip_id->DeleteIfAllowed();
|
|
////////////////////////////////////////////////////////////////////
|
|
// cout<<"night_mo "<<night_mo.size()<<endl;
|
|
// cout<<"workday_mo "<<day_mo1.size()<<endl;
|
|
// cout<<"weekend_mo "<<day_mo2.size()<<endl;
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
if(night_mo.size() > 0)
|
|
CreatTableAtStopNight(night_mo,loc,br_id,stop_id,direction,
|
|
peri1,peri2,count_id);
|
|
CreatTableAtStop(day_mo1,loc,br_id,stop_id,direction,count_id);
|
|
CreatTableAtStop(day_mo2,loc,br_id,stop_id,direction,count_id);
|
|
////////////////////////////////////////////////////////////////////
|
|
}
|
|
}
|
|
|
|
/*
|
|
check whether thay are in the same day
|
|
|
|
*/
|
|
bool RoadDenstiy::SameDay(UPoint& up, Periods* peri1)
|
|
{
|
|
Interval<Instant> periods1;
|
|
peri1->Get(0, periods1);
|
|
int day1 = up.timeInterval.start.GetDay();
|
|
int day2 = periods1.start.GetDay();
|
|
if(day1 == day2)return true;
|
|
else
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
create table at one location for night buses
|
|
|
|
*/
|
|
void RoadDenstiy::CreatTableAtStopNight(vector<MPoint>& mo_list, Point& loc,
|
|
int br_id, int stop_id, bool dir,
|
|
Periods* night1, Periods* night2,
|
|
int count_id)
|
|
{
|
|
Interval<Instant> periods1;
|
|
night1->Get(0, periods1);
|
|
Interval<Instant> periods2;
|
|
night2->Get(0, periods2);
|
|
|
|
// cout<<"peri1 "<<*night1<<" peri2 "<<*night2<<endl;
|
|
|
|
double e1 = periods1.end.ToDouble();
|
|
|
|
vector<MPoint> mo_list1;
|
|
vector<MPoint> mo_list2;
|
|
for(unsigned int i = 0;i < mo_list.size();i++){
|
|
MPoint mo = mo_list[i];
|
|
UPoint up;
|
|
mo.Get(0, up);
|
|
double s = up.timeInterval.start.ToDouble();
|
|
if( s < e1 || AlmostEqual(s, e1))
|
|
mo_list1.push_back(mo_list[i]);
|
|
else
|
|
mo_list2.push_back(mo_list[i]);
|
|
}
|
|
// cout<<"mo_list1 size "<<mo_list1.size()
|
|
// <<" mo_list2 size "<<mo_list2.size()<<endl;
|
|
|
|
CreatTableAtStop(mo_list1,loc,br_id,stop_id,dir,count_id);
|
|
CreatTableAtStop(mo_list2,loc,br_id,stop_id,dir,count_id);
|
|
}
|
|
|
|
/*
|
|
create time table for one location
|
|
|
|
*/
|
|
void RoadDenstiy::CreatTableAtStop(vector<MPoint> trip_list, Point& loc,
|
|
int br_id, int stop_id, bool dir,
|
|
int count_id)
|
|
{
|
|
|
|
assert(trip_list.size() >= 2);
|
|
|
|
MPoint start_mo_0 = trip_list[0];
|
|
UPoint up1;
|
|
start_mo_0.Get(0, up1);//the start time of first trip
|
|
Instant start_time_0 = up1.timeInterval.start;
|
|
Instant st = start_time_0;
|
|
GetTimeInstantStop(start_mo_0, loc,st);
|
|
|
|
/////////////cut second and millsecond /////////////////////////////
|
|
int second_val_s = st.GetSecond();
|
|
// int msecond_val_s = st.GetMillisecond();
|
|
// double double_s = st.ToDouble() -
|
|
// second_val_s/(24.0*60.0*60.0) -
|
|
// msecond_val_s/(24.0*60.0*60.0*1000.0);
|
|
|
|
double double_s = st.ToDouble();//we should consider second and millisecond
|
|
|
|
st.ReadFrom(double_s);
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
MPoint start_mo_1 = trip_list[1];
|
|
UPoint up2;
|
|
start_mo_1.Get(0, up1);//the start time of second trip
|
|
Instant start_time_1 = up1.timeInterval.start;
|
|
|
|
/////////// get time interval for schedule ///////////////////
|
|
double sch_interval = start_time_1.ToDouble() - start_time_0.ToDouble();
|
|
assert(sch_interval > 0.0);
|
|
// cout<<"schedule "<<sch_interval*24.0*60.0*60.0<<" seconds"<<endl;
|
|
|
|
////////////////last bus trip ////////////////////////////////////
|
|
MPoint end_mo = trip_list[trip_list.size() - 1];
|
|
UPoint up3;
|
|
end_mo.Get(0, up3);//the start time of last trip
|
|
Instant end_time = up3.timeInterval.start;
|
|
/////////////////cut second and millsecond ////////////////////////////////
|
|
Instant et = end_time;
|
|
|
|
GetTimeInstantStop(end_mo, loc, et);
|
|
|
|
int second_val_e = et.GetSecond();
|
|
/* int msecond_val_e = et.GetMillisecond();
|
|
double double_e = et.ToDouble() -
|
|
second_val_e/(24.0*60.0*60.0) -
|
|
msecond_val_e/(24.0*60.0*60.0*1000.0);*/
|
|
|
|
double double_e = et.ToDouble();//we should consider second and millisecond
|
|
|
|
et.ReadFrom(double_e);
|
|
////////////////////////////////////////////////////////////////////////////
|
|
assert(second_val_s == second_val_e);
|
|
Interval<Instant> time_span;
|
|
time_span.start = st;
|
|
time_span.lc = true;
|
|
time_span.end = et;
|
|
time_span.rc = true;
|
|
|
|
Periods* peri = new Periods(0);
|
|
peri->StartBulkLoad();
|
|
peri->MergeAdd(time_span);
|
|
peri->EndBulkLoad();
|
|
// duration.push_back(*peri);
|
|
// cout<<"periods "<<*peri<<endl;
|
|
|
|
|
|
bus_stop_loc.push_back(loc);
|
|
|
|
// br_id_list.push_back(br_id);
|
|
// bus_stop_id_list.push_back(stop_id);
|
|
// br_direction.push_back(dir);
|
|
|
|
Bus_Stop* bs = new Bus_Stop(true, br_id, stop_id, dir);
|
|
bs_list.push_back(*bs);
|
|
bs_uoid_list.push_back(bs->GetUOid());
|
|
delete bs;
|
|
|
|
|
|
duration1.push_back(*peri);
|
|
unique_id_list.push_back(count_id);
|
|
schedule_interval.push_back(sch_interval);
|
|
peri->DeleteIfAllowed();
|
|
|
|
|
|
//////////////////////// check time //////////////////////////////
|
|
for(unsigned int i = 0;i < trip_list.size();i++){
|
|
MPoint mo = trip_list[i];
|
|
Instant temp_instant;
|
|
GetTimeInstantStop(mo, loc, temp_instant);
|
|
int second_val = temp_instant.GetSecond();
|
|
assert(second_val == second_val_s);
|
|
}
|
|
////////////////////////////////////////////////////////////////////////
|
|
}
|
|
|
|
/*
|
|
get the time that the bus arrives at this point(stop)
|
|
|
|
*/
|
|
void RoadDenstiy::GetTimeInstantStop(MPoint& mo, Point loc, Instant& arrove_t)
|
|
{
|
|
const double dist_delta = 0.01;
|
|
const double stop_time = 30.0/(24.0*60.0*60.0); //30 seconds for buses
|
|
for(int j = 0;j < mo.GetNoComponents();j++){
|
|
UPoint up;
|
|
mo.Get(j, up);
|
|
Point loc1 = up.p0;
|
|
Point loc2 = up.p1;
|
|
|
|
if(loc1.Distance(loc2) < dist_delta &&
|
|
loc1.Distance(loc) < dist_delta){ //find the place
|
|
Instant st = up.timeInterval.start;
|
|
Instant et = up.timeInterval.end;
|
|
double d_st = st.ToDouble();
|
|
double d_et = et.ToDouble();
|
|
assert(AlmostEqual(fabs(d_st-d_et), stop_time));//check 30 seconds
|
|
arrove_t = st;
|
|
return;
|
|
}
|
|
}
|
|
assert(false);
|
|
}
|
|
|
|
bool CompareGP_P(const GP_Point& gp_p1, const GP_Point& gp_p2)
|
|
{
|
|
if(gp_p1.rid < gp_p2.rid) return true;
|
|
else{
|
|
if(gp_p1.rid > gp_p2.rid) return false;
|
|
else{
|
|
if(gp_p1.pos1 < gp_p2.pos1) return true;
|
|
else return false;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
create nodes relation for road graph jun id, gpoint, point
|
|
|
|
*/
|
|
|
|
void RoadDenstiy::GetRGNodes()
|
|
{
|
|
|
|
Relation* juns = n->GetJunctions();
|
|
|
|
vector<GP_Point> loc_list;
|
|
|
|
for(int i = 1;i <= juns->GetNoTuples();i++){
|
|
|
|
Tuple* jun_tuple = juns->GetTuple(i, false);
|
|
CcInt* rid1 = (CcInt*)jun_tuple->GetAttribute(JUNCTION_ROUTE1_ID);
|
|
CcInt* rid2 = (CcInt*)jun_tuple->GetAttribute(JUNCTION_ROUTE2_ID);
|
|
int id1 = rid1->GetIntval();
|
|
int id2 = rid2->GetIntval();
|
|
Point* junp = (Point*)jun_tuple->GetAttribute(JUNCTION_POS);
|
|
|
|
CcReal* meas1 = (CcReal*)jun_tuple->GetAttribute(JUNCTION_ROUTE1_MEAS);
|
|
CcReal* meas2 = (CcReal*)jun_tuple->GetAttribute(JUNCTION_ROUTE2_MEAS);
|
|
|
|
double pos1 = meas1->GetRealval();
|
|
double pos2 = meas2->GetRealval();
|
|
|
|
|
|
// unique_id_list.push_back(oid);
|
|
// oid++;
|
|
// gp_list.push_back(*gp1);
|
|
// jun_loc_list.push_back(*junp);
|
|
//
|
|
//
|
|
// unique_id_list.push_back(oid);
|
|
// oid++;
|
|
// gp_list.push_back(*gp2);
|
|
// jun_loc_list.push_back(*junp);
|
|
GP_Point gp_p1(id1, pos1, -1.0, *junp, *junp);
|
|
GP_Point gp_p2(id2, pos2, -1.0, *junp, *junp);
|
|
|
|
loc_list.push_back(gp_p1);
|
|
loc_list.push_back(gp_p2);
|
|
|
|
jun_tuple->DeleteIfAllowed();
|
|
}
|
|
|
|
juns->Delete();
|
|
|
|
|
|
int oid = 1;
|
|
|
|
sort(loc_list.begin(), loc_list.end(), CompareGP_P);
|
|
const double delta_dist = 0.001;
|
|
for(unsigned int i = 0;i < loc_list.size();i++){
|
|
// loc_list[i].Print();
|
|
if(oid == 1){
|
|
GPoint* gp = new GPoint(true, n->GetId(), loc_list[i].rid,
|
|
loc_list[i].pos1, None);
|
|
|
|
unique_id_list.push_back(oid);
|
|
oid++;
|
|
gp_list.push_back(*gp);
|
|
delete gp;
|
|
jun_loc_list.push_back(loc_list[i].loc1);
|
|
rid_list.push_back(loc_list[i].rid);
|
|
}else{
|
|
GPoint last_gp = gp_list[gp_list.size() - 1];
|
|
Point last_jun = jun_loc_list[jun_loc_list.size() - 1];
|
|
|
|
|
|
GPoint* gp = new GPoint(true, n->GetId(), loc_list[i].rid,
|
|
loc_list[i].pos1, None);
|
|
if(gp->GetRouteId() == last_gp.GetRouteId() &&
|
|
fabs(gp->GetPosition() - last_gp.GetPosition()) < delta_dist &&
|
|
last_jun.Distance(loc_list[i].loc1) < delta_dist){
|
|
delete gp;
|
|
continue;
|
|
}
|
|
|
|
unique_id_list.push_back(oid);
|
|
oid++;
|
|
gp_list.push_back(*gp);
|
|
delete gp;
|
|
jun_loc_list.push_back(loc_list[i].loc1);
|
|
rid_list.push_back(loc_list[i].rid);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
create one connection for road graph, two junction points having the same
|
|
spatial location
|
|
|
|
*/
|
|
void RoadDenstiy::GetRGEdges1(Relation* rel, R_Tree<2,TupleId>* rtree)
|
|
{
|
|
|
|
for(int i = 1;i <= rel->GetNoTuples();i++){
|
|
Tuple* jun_tuple = rel->GetTuple(i, false);
|
|
// int id = ((CcInt*)jun_tuple->GetAttribute(RG_N_JUN_ID))->GetIntval();
|
|
// Point* loc = (Point*)jun_tuple->GetAttribute(RG_N_P);
|
|
|
|
int id =
|
|
((CcInt*)jun_tuple->GetAttribute(RoadGraph::RG_JUN_ID))->GetIntval();
|
|
Point* loc = (Point*)jun_tuple->GetAttribute(RoadGraph::RG_JUN_P);
|
|
|
|
vector<int> neighbor_list;
|
|
|
|
DFTraverse(rel, rtree, rtree->RootRecordId(), *loc, neighbor_list);
|
|
for(unsigned int i = 0;i < neighbor_list.size();i++){
|
|
if(neighbor_list[i] == id)continue;
|
|
jun_id_list1.push_back(id);
|
|
jun_id_list2.push_back(neighbor_list[i]);
|
|
}
|
|
jun_tuple->DeleteIfAllowed();
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
traverse rtree to find the points that have the same spatial location as input
|
|
|
|
*/
|
|
void RoadDenstiy::DFTraverse(Relation* rel,R_Tree<2,TupleId>* rtree,
|
|
SmiRecordId adr,
|
|
Point& loc, vector<int>& oid_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 = rel->GetTuple(e.info, false);
|
|
// Point* q = (Point*)dg_tuple->GetAttribute(RG_N_P);
|
|
Point* q = (Point*)dg_tuple->GetAttribute(RoadGraph::RG_JUN_P);
|
|
if(q->Distance(loc) < delta_dist){
|
|
int id =
|
|
// ((CcInt*)dg_tuple->GetAttribute(RG_N_JUN_ID))->GetIntval();
|
|
((CcInt*)dg_tuple->GetAttribute(RoadGraph::RG_JUN_ID))->GetIntval();
|
|
oid_list.push_back(id);
|
|
}
|
|
dg_tuple->DeleteIfAllowed();
|
|
}else{
|
|
R_TreeInternalEntry<2> e =
|
|
(R_TreeInternalEntry<2>&)(*node)[j];
|
|
if(loc.Inside(e.box)){
|
|
DFTraverse(rel, rtree, e.pointer, loc, oid_list);
|
|
}
|
|
}
|
|
}
|
|
delete node;
|
|
|
|
}
|
|
|
|
/*
|
|
two junction points are connected by glines
|
|
converting gline to line takes a lot of time
|
|
because the junction point (gpoint ) is get from curve -- dual --TRUE
|
|
use simpline method 2 seconds for berlin roads
|
|
|
|
use gline2line method 27 seconds
|
|
|
|
*/
|
|
void RoadDenstiy::GetRGEdges2(Relation* rel)
|
|
{
|
|
vector<GP_Point> gp_p_list;
|
|
// int NetId;
|
|
int NetId = -1;
|
|
for(int i = 1;i <= rel->GetNoTuples();i++){
|
|
Tuple* jun_tuple = rel->GetTuple(i, false);
|
|
// int oid = ((CcInt*)jun_tuple->GetAttribute(RG_N_JUN_ID))->GetIntval();
|
|
// GPoint* gp = (GPoint*)jun_tuple->GetAttribute(RG_N_GP);
|
|
// Point* loc = (Point*)jun_tuple->GetAttribute(RG_N_P);
|
|
|
|
int oid =
|
|
((CcInt*)jun_tuple->GetAttribute(RoadGraph::RG_JUN_ID))->GetIntval();
|
|
GPoint* gp = (GPoint*)jun_tuple->GetAttribute(RoadGraph::RG_JUN_GP);
|
|
Point* loc = (Point*)jun_tuple->GetAttribute(RoadGraph::RG_JUN_P);
|
|
|
|
|
|
NetId = gp->GetNetworkId();
|
|
GP_Point gp_p(gp->GetRouteId(), gp->GetPosition(), oid, *loc, *loc);
|
|
gp_p_list.push_back(gp_p);
|
|
jun_tuple->DeleteIfAllowed();
|
|
}
|
|
sort(gp_p_list.begin(), gp_p_list.end(), CompareGP_P);
|
|
|
|
|
|
for(unsigned int i = 0;i < gp_p_list.size();i++){
|
|
|
|
// gp_p_list[i].Print();
|
|
vector<GP_Point> sub_list;
|
|
sub_list.push_back(gp_p_list[i]);
|
|
int rid = gp_p_list[i].rid;
|
|
unsigned int j = i + 1;
|
|
while(j < gp_p_list.size() &&
|
|
gp_p_list[j].rid == sub_list[sub_list.size() - 1].rid){
|
|
sub_list.push_back(gp_p_list[j]);
|
|
j++;
|
|
}
|
|
|
|
// cout<<"rid "<<rid<<" "<<sub_list.size()<<endl;
|
|
i = j - 1;
|
|
if(sub_list.size() > 1){
|
|
// cout<<"rid "<<rid<<endl;
|
|
|
|
Tuple* road_tuple = n->GetRoute(rid);
|
|
SimpleLine* sl = (SimpleLine*)road_tuple->GetAttribute(ROUTE_CURVE);
|
|
|
|
for(unsigned int k = 0;k < sub_list.size();k++){
|
|
if(k == 0){
|
|
jun_id_list1.push_back((int)sub_list[k].pos2);
|
|
jun_id_list2.push_back((int)sub_list[k + 1].pos2);
|
|
double pos1 = sub_list[k].pos1;
|
|
double pos2 = sub_list[k + 1].pos1;
|
|
|
|
GLine* gl = new GLine(0);
|
|
gl->SetNetworkId(NetId);
|
|
gl->AddRouteInterval(rid, pos1, pos2);
|
|
gl->SetDefined(true);
|
|
gl->SetSorted(false);
|
|
gl->TrimToSize();
|
|
|
|
gl_path_list.push_back(*gl);
|
|
|
|
SimpleLine* sub_l = new SimpleLine(0);
|
|
if(pos1 < pos2)
|
|
sl->SubLine(pos1, pos2, true, *sub_l);
|
|
else
|
|
sl->SubLine(pos2, pos1, true, *sub_l);
|
|
|
|
sline_path_list.push_back(*sub_l);
|
|
sub_l->DeleteIfAllowed();
|
|
|
|
|
|
gl->DeleteIfAllowed();
|
|
|
|
}else if(k == sub_list.size() - 1){
|
|
jun_id_list1.push_back((int)sub_list[k].pos2);
|
|
jun_id_list2.push_back((int)sub_list[k - 1].pos2);
|
|
|
|
double pos1 = sub_list[k].pos1;
|
|
double pos2 = sub_list[k - 1].pos1;
|
|
|
|
GLine* gl = new GLine(0);
|
|
gl->SetNetworkId(NetId);
|
|
gl->AddRouteInterval(rid, pos1, pos2);
|
|
|
|
gl->SetDefined(true);
|
|
gl->SetSorted(false);
|
|
gl->TrimToSize();
|
|
|
|
gl_path_list.push_back(*gl);
|
|
|
|
SimpleLine* sub_l = new SimpleLine(0);
|
|
if(pos2 < pos1)
|
|
sl->SubLine(pos2, pos1, true, *sub_l);
|
|
else
|
|
sl->SubLine(pos1, pos2, true, *sub_l);
|
|
|
|
sline_path_list.push_back(*sub_l);
|
|
sub_l->DeleteIfAllowed();
|
|
|
|
gl->DeleteIfAllowed();
|
|
|
|
}else{
|
|
jun_id_list1.push_back((int)sub_list[k].pos2);
|
|
jun_id_list2.push_back((int)sub_list[k - 1].pos2);
|
|
|
|
double pos1_1 = sub_list[k].pos1;
|
|
double pos1_2 = sub_list[k - 1].pos1;
|
|
|
|
jun_id_list1.push_back((int)sub_list[k].pos2);
|
|
jun_id_list2.push_back((int)sub_list[k + 1].pos2);
|
|
|
|
double pos2_1 = sub_list[k].pos1;
|
|
double pos2_2 = sub_list[k + 1].pos1;
|
|
|
|
|
|
GLine* gl1 = new GLine(0);
|
|
gl1->SetNetworkId(NetId);
|
|
gl1->AddRouteInterval(rid, pos1_1, pos1_2);
|
|
gl1->SetDefined(true);
|
|
gl1->SetSorted(false);
|
|
gl1->TrimToSize();
|
|
gl_path_list.push_back(*gl1);
|
|
|
|
|
|
SimpleLine* sub_l1 = new SimpleLine(0);
|
|
if(pos1_2 < pos1_1)
|
|
sl->SubLine(pos1_2, pos1_1, true, *sub_l1);
|
|
else
|
|
sl->SubLine(pos1_1, pos1_2, true, *sub_l1);
|
|
|
|
sline_path_list.push_back(*sub_l1);
|
|
sub_l1->DeleteIfAllowed();
|
|
|
|
|
|
gl1->DeleteIfAllowed();
|
|
|
|
|
|
GLine* gl2 = new GLine(0);
|
|
gl2->SetNetworkId(NetId);
|
|
gl2->AddRouteInterval(rid, pos2_1, pos2_2);
|
|
gl2->SetDefined(true);
|
|
gl2->SetSorted(false);
|
|
gl2->TrimToSize();
|
|
|
|
gl_path_list.push_back(*gl2);
|
|
|
|
SimpleLine* sub_l2 = new SimpleLine(0);
|
|
if(pos2_1 < pos2_2)
|
|
sl->SubLine(pos2_1, pos2_2, true, *sub_l2);
|
|
else
|
|
sl->SubLine(pos2_2, pos2_1, true, *sub_l2);
|
|
|
|
sline_path_list.push_back(*sub_l2);
|
|
sub_l2->DeleteIfAllowed();
|
|
|
|
gl2->DeleteIfAllowed();
|
|
}
|
|
|
|
}
|
|
|
|
road_tuple->DeleteIfAllowed();
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////
|
|
///////////////////Bus Stop///////////////////////////////////
|
|
//////////////////////////////////////////////////////////////
|
|
|
|
ListExpr BusStopProperty()
|
|
{
|
|
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("busstop"),
|
|
nl->StringAtom("(<brid, stopid, up>) (int int bool)"),
|
|
nl->StringAtom("((1 2 TRUE))"))));
|
|
}
|
|
|
|
/*
|
|
Output (brid, stopid)
|
|
|
|
*/
|
|
|
|
ListExpr OutBusStop( ListExpr typeInfo, Word value )
|
|
{
|
|
// cout<<"OutBusStop"<<endl;
|
|
Bus_Stop* bs = (Bus_Stop*)(value.addr);
|
|
if(!bs->IsDefined()){
|
|
return nl->SymbolAtom("undef");
|
|
}
|
|
|
|
ListExpr list1 = nl->TwoElemList(nl->StringAtom("Route Id:"),
|
|
nl->IntAtom(bs->GetId()));
|
|
|
|
ListExpr list2 = nl->TwoElemList(nl->StringAtom("Stop Id:"),
|
|
nl->IntAtom(bs->GetStopId()));
|
|
|
|
ListExpr list3 = nl->TwoElemList(nl->StringAtom("UP:"),
|
|
nl->BoolAtom(bs->GetUp()));
|
|
return nl->ThreeElemList(list1,list2, list3);
|
|
|
|
}
|
|
|
|
/*
|
|
In function
|
|
|
|
*/
|
|
Word InBusStop( const ListExpr typeInfo, const ListExpr instance,
|
|
const int errorPos, ListExpr& errorInfo, bool& correct )
|
|
{
|
|
|
|
// cout<<"length "<<nl->ListLength(instance)<<endl;
|
|
|
|
if( !nl->IsAtom( instance ) ){
|
|
|
|
if(nl->ListLength(instance) != 3){
|
|
cout<<"length should be 3"<<endl;
|
|
correct = false;
|
|
return SetWord(Address(0));
|
|
}
|
|
ListExpr first = nl->First(instance);
|
|
if(!nl->IsAtom(first) || nl->AtomType(first) != IntType){
|
|
cout<< "busstop(): brid must be int type"<<endl;
|
|
correct = false;
|
|
return SetWord(Address(0));
|
|
}
|
|
unsigned int id1 = nl->IntValue(first);
|
|
|
|
ListExpr second = nl->Second(instance);
|
|
if(!nl->IsAtom(second) || nl->AtomType(second) != IntType){
|
|
cout<< "busstop(): stop id must be int type"<<endl;
|
|
correct = false;
|
|
return SetWord(Address(0));
|
|
}
|
|
unsigned int id2 = nl->IntValue(second);
|
|
|
|
ListExpr third = nl->Third(instance);
|
|
if(!nl->IsAtom(third) || nl->AtomType(third) != BoolType){
|
|
cout<< "busstop(): up/down must be bool type"<<endl;
|
|
correct = false;
|
|
return SetWord(Address(0));
|
|
}
|
|
bool d = nl->BoolValue(third);
|
|
|
|
////////////////very important /////////////////////////////
|
|
correct = true;
|
|
///////////////////////////////////////////////////////////
|
|
Bus_Stop* bs = new Bus_Stop(true, id1, id2, d);
|
|
return SetWord(bs);
|
|
}
|
|
|
|
correct = false;
|
|
return SetWord(Address(0));
|
|
}
|
|
|
|
/*
|
|
Open an reference object
|
|
|
|
*/
|
|
bool OpenBusStop(SmiRecord& valueRecord, size_t& offset,
|
|
const ListExpr typeInfo, Word& value)
|
|
{
|
|
// cout<<"OpenBusStop()"<<endl;
|
|
|
|
Bus_Stop* bs = (Bus_Stop*)Attribute::Open(valueRecord, offset, typeInfo);
|
|
value = SetWord(bs);
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
Save an reference object
|
|
|
|
*/
|
|
bool SaveBusStop(SmiRecord& valueRecord, size_t& offset,
|
|
const ListExpr typeInfo, Word& value)
|
|
{
|
|
// cout<<"SaveBusStop"<<endl;
|
|
Bus_Stop* bs = (Bus_Stop*)value.addr;
|
|
Attribute::Save(valueRecord, offset, typeInfo, bs);
|
|
return true;
|
|
}
|
|
|
|
Word CreateBusStop(const ListExpr typeInfo)
|
|
{
|
|
// cout<<"CreateBusStop()"<<endl;
|
|
return SetWord (new Bus_Stop(false));
|
|
}
|
|
|
|
|
|
void DeleteBusStop(const ListExpr typeInfo, Word& w)
|
|
{
|
|
// cout<<"DeleteBusStop()"<<endl;
|
|
Bus_Stop* bs = (Bus_Stop*)w.addr;
|
|
delete bs;
|
|
w.addr = NULL;
|
|
}
|
|
|
|
|
|
void CloseBusStop( const ListExpr typeInfo, Word& w )
|
|
{
|
|
// cout<<"CloseBusStop"<<endl;
|
|
((Bus_Stop*)w.addr)->DeleteIfAllowed();
|
|
w.addr = 0;
|
|
}
|
|
|
|
Word CloneBusStop( const ListExpr typeInfo, const Word& w )
|
|
{
|
|
// cout<<"CloneBusStop"<<endl;
|
|
return SetWord( new Bus_Stop( *((Bus_Stop*)w.addr) ) );
|
|
}
|
|
|
|
int SizeOfBusStop()
|
|
{
|
|
// cout<<"SizeOfBusStop"<<endl;
|
|
return sizeof(Bus_Stop);
|
|
}
|
|
|
|
bool CheckBusStop( ListExpr type, ListExpr& errorInfo )
|
|
{
|
|
// cout<<"CheckBusStop"<<endl;
|
|
return (nl->IsEqual( type, "busstop" ));
|
|
}
|
|
|
|
/*
|
|
type constructure functions
|
|
|
|
*/
|
|
Bus_Stop::Bus_Stop():Attribute(){}
|
|
|
|
Bus_Stop::Bus_Stop(bool def, unsigned int id1, unsigned int id2, bool d):
|
|
Attribute(def), br_id(id1), stop_id(id2), up_down(d)
|
|
{
|
|
SetDefined(def);
|
|
}
|
|
Bus_Stop::Bus_Stop(const Bus_Stop& bs):
|
|
Attribute(bs.IsDefined()), br_id(bs.br_id),
|
|
stop_id(bs.stop_id), up_down(bs.up_down)
|
|
{
|
|
SetDefined(bs.IsDefined());
|
|
}
|
|
|
|
Bus_Stop& Bus_Stop::operator=(const Bus_Stop& bs)
|
|
{
|
|
SetDefined(bs.IsDefined());
|
|
if(IsDefined()){
|
|
br_id = bs.GetId();
|
|
stop_id = bs.GetStopId();
|
|
up_down = bs.up_down;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
|
|
void* Bus_Stop::Cast(void* addr)
|
|
{
|
|
return new (addr)Bus_Stop;
|
|
|
|
}
|
|
|
|
ostream& operator<<(ostream& o, const Bus_Stop& bs)
|
|
{
|
|
if(bs.IsDefined()){
|
|
o<<"br_id "<< bs.GetId()<<" "
|
|
<<"stop id "<<bs.GetStopId()<<" "
|
|
<<"direction "<<bs.GetUp();
|
|
}else
|
|
o<<"undef"<<endl;
|
|
|
|
return o;
|
|
}
|
|
|
|
/*
|
|
for each bus stop, we assign a unique number.
|
|
the number is constrcuted by: brid + stopid + up
|
|
a number has three parts (string to int)
|
|
not correct 1 11 1----11 1 1
|
|
|
|
*/
|
|
int Bus_Stop::GetUOid()
|
|
{
|
|
if(!IsDefined()) return 0;
|
|
|
|
char buf1[256], buf2[256], buf3[2];
|
|
|
|
sprintf(buf1, "%d", br_id * 10);
|
|
sprintf(buf2, "%d", stop_id);
|
|
if(up_down)
|
|
sprintf(buf3, "%d", 1);
|
|
else
|
|
sprintf(buf3, "%d", 0);
|
|
|
|
strcat (buf1, buf2);
|
|
strcat (buf1, buf3);
|
|
|
|
int uoid = atoi(buf1);
|
|
// cout<<" uoid "<<uoid<<endl;
|
|
assert(uoid > 0);
|
|
return uoid;
|
|
|
|
}
|
|
|
|
bool Bus_Stop::operator==(const Bus_Stop& bs)
|
|
{
|
|
if(!IsDefined() || !bs.IsDefined()) return false;
|
|
if(br_id == bs.GetId() && stop_id == bs.GetStopId() && up_down == bs.GetUp())
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
ostream& Bus_Stop::Print(ostream& os) const
|
|
{
|
|
return os<<*this;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////
|
|
//////////////////////bus route///////////////////////////////
|
|
//////////////////////////////////////////////////////////////
|
|
ListExpr BusRouteProperty()
|
|
{
|
|
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("busroute"),
|
|
nl->StringAtom("((id, up) (<segment list>*))"),
|
|
nl->StringAtom("((1 true)((((2.0 2.0 3.0 3.0)))))"))));
|
|
}
|
|
|
|
/*
|
|
Open an reference object
|
|
|
|
*/
|
|
bool OpenBusRoute(SmiRecord& valueRecord, size_t& offset,
|
|
const ListExpr typeInfo, Word& value)
|
|
{
|
|
// cout<<"OpenBusRoute()"<<endl;
|
|
|
|
Bus_Route* br = (Bus_Route*)Attribute::Open(valueRecord, offset, typeInfo);
|
|
value = SetWord(br);
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
Save an reference object
|
|
|
|
*/
|
|
bool SaveBusRoute(SmiRecord& valueRecord, size_t& offset,
|
|
const ListExpr typeInfo, Word& value)
|
|
{
|
|
// cout<<"SaveBusRoute"<<endl;
|
|
Bus_Route* br = (Bus_Route*)value.addr;
|
|
Attribute::Save(valueRecord, offset, typeInfo, br);
|
|
return true;
|
|
}
|
|
|
|
Word CreateBusRoute(const ListExpr typeInfo)
|
|
{
|
|
// cout<<"CreateBusRoute()"<<endl;
|
|
return SetWord (new Bus_Route(0));
|
|
}
|
|
|
|
|
|
void DeleteBusRoute(const ListExpr typeInfo, Word& w)
|
|
{
|
|
// cout<<"DeleteBusRoute()"<<endl;
|
|
Bus_Route* br = (Bus_Route*)w.addr;
|
|
delete br;
|
|
w.addr = NULL;
|
|
}
|
|
|
|
|
|
void CloseBusRoute( const ListExpr typeInfo, Word& w )
|
|
{
|
|
// cout<<"CloseBusRoute"<<endl;
|
|
((Bus_Route*)w.addr)->DeleteIfAllowed();
|
|
w.addr = 0;
|
|
}
|
|
|
|
Word CloneBusRoute( const ListExpr typeInfo, const Word& w )
|
|
{
|
|
// cout<<"CloneBusRoute"<<endl;
|
|
return SetWord( new Bus_Route( *((Bus_Route*)w.addr) ) );
|
|
}
|
|
|
|
int SizeOfBusRoute()
|
|
{
|
|
// cout<<"SizeOfBusRoute"<<endl;
|
|
return sizeof(Bus_Route);
|
|
}
|
|
|
|
bool CheckBusRoute( ListExpr type, ListExpr& errorInfo )
|
|
{
|
|
// cout<<"CheckBusRoute"<<endl;
|
|
return (nl->IsEqual( type, "busroute" ));
|
|
}
|
|
|
|
/*
|
|
In function
|
|
|
|
*/
|
|
Word InBusRoute( const ListExpr typeInfo, const ListExpr instance,
|
|
const int errorPos, ListExpr& errorInfo, bool& correct )
|
|
{
|
|
|
|
// cout<<"length "<<nl->ListLength(instance)<<endl;
|
|
|
|
if( !nl->IsAtom( instance ) ){
|
|
|
|
if(nl->ListLength(instance) != 2){
|
|
cout<<"length should be 2"<<endl;
|
|
correct = false;
|
|
return SetWord(Address(0));
|
|
}
|
|
ListExpr first = nl->First(instance);
|
|
if(nl->ListLength(first) != 2){
|
|
cout<< "busroute(): the first part should have two parameters"<<endl;
|
|
correct = false;
|
|
return SetWord(Address(0));
|
|
}
|
|
|
|
ListExpr first1 = nl->First(first);
|
|
if(!nl->IsAtom(first1) || nl->AtomType(first1) != IntType){
|
|
cout<< "busroute(): bus route id must be int type"<<endl;
|
|
correct = false;
|
|
return SetWord(Address(0));
|
|
}
|
|
unsigned int br_id = nl->IntValue(first1);
|
|
|
|
ListExpr first2 = nl->Second(first);
|
|
if(!nl->IsAtom(first2) || nl->AtomType(first2) != BoolType){
|
|
cout<< "busroute(): bus route up/down must be bool type"<<endl;
|
|
correct = false;
|
|
return SetWord(Address(0));
|
|
}
|
|
bool d = nl->BoolValue(first2);
|
|
|
|
Bus_Route* br = new Bus_Route(br_id, d);
|
|
|
|
|
|
ListExpr geo_list = nl->Second(instance);
|
|
br->StartBulkLoad();
|
|
int count = 0;
|
|
while(!nl->IsEmpty(geo_list)){
|
|
ListExpr geo_first = nl->First(geo_list);
|
|
geo_list = nl->Rest(geo_list);
|
|
if(nl->ListLength(geo_first) != 1){
|
|
cout<< "busroute(): segment list should have length 1"<<endl;
|
|
correct = false;
|
|
return SetWord(Address(0));
|
|
}
|
|
|
|
SimpleLine* sl = (SimpleLine*)InSimpleLine(typeInfo,
|
|
nl->First(geo_first), errorPos, errorInfo, correct).addr;
|
|
// cout<<s<<" "<<sl->Length()<<endl;
|
|
br->Add(sl, count);
|
|
count++;
|
|
}
|
|
br->EndBulkLoad();
|
|
////////////////very important /////////////////////////////
|
|
correct = true;
|
|
///////////////////////////////////////////////////////////
|
|
return SetWord(br);
|
|
}
|
|
|
|
correct = false;
|
|
return SetWord(Address(0));
|
|
}
|
|
|
|
|
|
/*
|
|
Output a sequence of bus segments
|
|
|
|
*/
|
|
|
|
ListExpr OutBusRoute( ListExpr typeInfo, Word value )
|
|
{
|
|
// cout<<"OutBusRoute"<<endl;
|
|
Bus_Route* br = (Bus_Route*)(value.addr);
|
|
if(!br->IsDefined()){
|
|
return nl->SymbolAtom("undef");
|
|
}
|
|
|
|
ListExpr list1 = nl->TwoElemList(
|
|
nl->IntAtom(br->GetId()), nl->BoolAtom(br->GetUp()));
|
|
ListExpr list2 = nl->TheEmptyList();
|
|
if(!br->IsEmpty()){
|
|
|
|
ListExpr last = list2;
|
|
bool first = true;
|
|
for(int i = 0;i < br->Size();i++){
|
|
SimpleLine sl(0);
|
|
br->Get(i, sl);
|
|
|
|
ListExpr geo_list = OutSimpleLine(nl->TheEmptyList(), SetWord(&sl));
|
|
ListExpr flatseg = nl->OneElemList(geo_list);
|
|
|
|
if(first == true){
|
|
list2 = nl->OneElemList( flatseg );
|
|
last = list2;
|
|
first = false;
|
|
}else{
|
|
last = nl->Append( last, flatseg );
|
|
}
|
|
}
|
|
}
|
|
|
|
return nl->TwoElemList(list1,list2);
|
|
|
|
}
|
|
|
|
Bus_Route::Bus_Route()
|
|
{
|
|
|
|
}
|
|
|
|
Bus_Route::Bus_Route(const Bus_Route& br):
|
|
StandardSpatialAttribute<2>(br.IsDefined()), elem_list(0), seg_list(0),
|
|
br_id(br.GetId()), up_down(br.GetUp())
|
|
{
|
|
if(IsDefined()){
|
|
elem_list.clean();
|
|
seg_list.clean();
|
|
Bus_Route* b_r = const_cast<Bus_Route*>(&br);
|
|
for(int i = 0;i < b_r->Size();i++){
|
|
BR_Elem elem;
|
|
b_r->GetElem(i, elem);
|
|
elem_list.Append(elem);
|
|
|
|
}
|
|
|
|
for(int i = 0;i < b_r->SegSize();i++){
|
|
HalfSegment hs;
|
|
b_r->GetSeg(i, hs);
|
|
seg_list.Append(hs);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
Bus_Route& Bus_Route::operator=(const Bus_Route& br)
|
|
{
|
|
if(!br.IsDefined()) return *this;
|
|
|
|
br_id = br.GetId();
|
|
up_down = br.GetUp();
|
|
|
|
elem_list.clean();
|
|
seg_list.clean();
|
|
|
|
Bus_Route* b_r = const_cast<Bus_Route*>(&br);
|
|
for(int i = 0;i < b_r->Size();i++){
|
|
BR_Elem elem;
|
|
b_r->GetElem(i, elem);
|
|
elem_list.Append(elem);
|
|
|
|
}
|
|
|
|
for(int i = 0;i < b_r->SegSize();i++){
|
|
HalfSegment hs;
|
|
b_r->GetSeg(i, hs);
|
|
seg_list.Append(hs);
|
|
}
|
|
|
|
SetDefined(true);
|
|
return *this;
|
|
}
|
|
|
|
void Bus_Route::GetElem(int i, BR_Elem& elem)
|
|
{
|
|
assert(0 <= i && i < elem_list.Size());
|
|
elem_list.Get(i, elem);
|
|
|
|
}
|
|
void Bus_Route::GetSeg(int i, HalfSegment& hs)
|
|
{
|
|
assert(0 <= i && i < seg_list.Size());
|
|
seg_list.Get(i, hs);
|
|
}
|
|
|
|
void* Bus_Route::Cast(void* addr)
|
|
{
|
|
return new (addr)Bus_Route;
|
|
|
|
}
|
|
|
|
|
|
const Rectangle<2> Bus_Route::BoundingBox(const Geoid* geoid) const
|
|
{
|
|
Rectangle<2> bbox;
|
|
for( int i = 0; seg_list.Size(); i++ ){
|
|
HalfSegment hs ;
|
|
seg_list.Get(i, hs);
|
|
if( i == 0 ){
|
|
bbox = hs.BoundingBox();
|
|
}else
|
|
bbox = bbox.Union(hs.BoundingBox());
|
|
}
|
|
return bbox;
|
|
}
|
|
|
|
/*
|
|
add a new element to the result
|
|
|
|
*/
|
|
void Bus_Route::Add(SimpleLine* sl, int count)
|
|
{
|
|
BR_Elem br_elem;
|
|
br_elem.br_seg_id = count;
|
|
br_elem.start_pos = seg_list.Size();
|
|
int no = 0;
|
|
for(int i = 0;i < sl->Size();i++){
|
|
HalfSegment hs;
|
|
sl->Get(i, hs);
|
|
if(!hs.IsLeftDomPoint()) continue;
|
|
seg_list.Append(hs);
|
|
no++;
|
|
}
|
|
br_elem.no = no;
|
|
elem_list.Append(br_elem);
|
|
}
|
|
|
|
/*
|
|
add a new element to the result, only a segment
|
|
|
|
*/
|
|
|
|
void Bus_Route::Add2(HalfSegment hs, int count)
|
|
{
|
|
BR_Elem br_elem;
|
|
br_elem.br_seg_id = count;
|
|
br_elem.start_pos = seg_list.Size();
|
|
int no = 0;
|
|
|
|
seg_list.Append(hs);
|
|
no++;
|
|
|
|
br_elem.no = no;
|
|
elem_list.Append(br_elem);
|
|
}
|
|
|
|
/*
|
|
get a bus segment from the dbarray
|
|
|
|
*/
|
|
void Bus_Route::Get(int i, SimpleLine& sl)
|
|
{
|
|
// cout<<i<<" "<<elem_list.Size()<<endl;
|
|
assert(0 <= i && i < elem_list.Size());
|
|
|
|
BR_Elem br_elem;
|
|
elem_list.Get(i, br_elem);
|
|
|
|
sl.StartBulkLoad();
|
|
|
|
for(unsigned int j = br_elem.start_pos; j < br_elem.start_pos + br_elem.no;
|
|
j++){
|
|
HalfSegment hs;
|
|
seg_list.Get(j ,hs);
|
|
sl += hs;
|
|
hs.SetLeftDomPoint(!hs.IsLeftDomPoint());
|
|
sl += hs;
|
|
}
|
|
sl.EndBulkLoad();
|
|
|
|
}
|
|
|
|
/*
|
|
get the geometrical line of a bus route
|
|
|
|
*/
|
|
void Bus_Route::GetGeoData(SimpleLine& sl)
|
|
{
|
|
sl.StartBulkLoad();
|
|
int edgeno = 0;
|
|
for(int i = 0;i < seg_list.Size();i++){
|
|
HalfSegment hs1;
|
|
seg_list.Get(i, hs1);
|
|
|
|
HalfSegment hs2(true, hs1.GetLeftPoint(), hs1.GetRightPoint());
|
|
hs2.attr.edgeno = edgeno++;
|
|
sl += hs2;
|
|
hs2.SetLeftDomPoint(!hs2.IsLeftDomPoint());
|
|
sl += hs2;
|
|
}
|
|
sl.EndBulkLoad();
|
|
}
|
|
|
|
/*
|
|
get the point of a bus stop. it is the end point of last segment and the
|
|
start point of next segment
|
|
|
|
*/
|
|
void Bus_Route::GetBusStopGeoData(Bus_Stop* bs, Point* p)
|
|
{
|
|
if(GetId() != bs->GetId()){
|
|
cout<<"route id is different for the bus stop and route"<<endl;
|
|
p->SetDefined(false);
|
|
return;
|
|
}
|
|
if(bs->GetStopId() < 1 || (int)bs->GetStopId() > Size()){
|
|
cout<<"invalid bus stop id"<<endl;
|
|
p->SetDefined(false);
|
|
return;
|
|
}
|
|
|
|
if(bs->GetUp() != GetUp()){
|
|
cout<<"bus stop and bus route have different directions"<<endl;
|
|
p->SetDefined(false);
|
|
return;
|
|
}
|
|
|
|
SimpleLine sl1(0);
|
|
Get(bs->GetStopId() - 1, sl1);
|
|
SimpleLine sl2(0);
|
|
Get(bs->GetStopId(), sl2);
|
|
|
|
Point sp1, sp2, ep1, ep2;
|
|
assert(sl1.AtPosition(0.0, sl1.GetStartSmaller(), sp1));
|
|
assert(sl1.AtPosition(sl1.Length(), sl1.GetStartSmaller(), ep1));
|
|
assert(sl2.AtPosition(0.0, sl2.GetStartSmaller(), sp2));
|
|
assert(sl2.AtPosition(sl2.Length(), sl2.GetStartSmaller(), ep2));
|
|
if(AlmostEqual(sp1, sp2) || AlmostEqual(sp1, ep2)){
|
|
*p = sp1;
|
|
}else if(AlmostEqual(ep1, sp2) || AlmostEqual(ep1, ep2)){
|
|
*p = ep1;
|
|
}else assert(false);
|
|
|
|
}
|
|
|
|
/*
|
|
get the point of a metro stop
|
|
it is different from the bus route. in metro network, the up and down direction
|
|
have the same route (geometry). the segment connecting two endpoints
|
|
|
|
*/
|
|
void Bus_Route::GetMetroStopGeoData(Bus_Stop* ms, Point* p)
|
|
{
|
|
if(GetId() != ms->GetId()){
|
|
cout<<"route id is different for the bus stop and route"<<endl;
|
|
p->SetDefined(false);
|
|
return;
|
|
}
|
|
if(ms->GetStopId() < 1 || (int) ms->GetStopId() > Size() + 2 ){
|
|
cout<<"invalid bus stop id"<<endl;
|
|
p->SetDefined(false);
|
|
return;
|
|
}
|
|
|
|
if(ms->GetUp() != GetUp()){
|
|
cout<<"bus stop and bus route have different directions"<<endl;
|
|
p->SetDefined(false);
|
|
return;
|
|
}
|
|
|
|
HalfSegment hs1, hs2;
|
|
if(ms->GetStopId() == 1){
|
|
|
|
if(ms->GetUp()){
|
|
GetSeg(0, hs1);
|
|
GetSeg(1, hs2);
|
|
}else{
|
|
GetSeg(SegSize() - 1, hs1);
|
|
GetSeg(SegSize() - 2, hs2);
|
|
}
|
|
|
|
Point lp1 = hs1.GetLeftPoint();
|
|
Point rp1 = hs1.GetRightPoint();
|
|
Point lp2 = hs2.GetLeftPoint();
|
|
Point rp2 = hs2.GetRightPoint();
|
|
|
|
if(AlmostEqual(lp1, lp2) || AlmostEqual(lp1, rp2)){
|
|
*p = rp1;
|
|
}else if(AlmostEqual(rp1, lp2) || AlmostEqual(rp1, rp2)){
|
|
*p = lp1;
|
|
}else assert(false);
|
|
|
|
}else if ((int)ms->GetStopId() == SegSize() + 1){
|
|
|
|
if(ms->GetUp()){
|
|
GetSeg(SegSize() - 1, hs1);
|
|
GetSeg(SegSize() - 2, hs2);
|
|
}else{
|
|
GetSeg(0, hs1);
|
|
GetSeg(1, hs2);
|
|
}
|
|
|
|
Point lp1 = hs1.GetLeftPoint();
|
|
Point rp1 = hs1.GetRightPoint();
|
|
Point lp2 = hs2.GetLeftPoint();
|
|
Point rp2 = hs2.GetRightPoint();
|
|
|
|
if(AlmostEqual(lp1, lp2) || AlmostEqual(lp1, rp2)){
|
|
*p = rp1;
|
|
}else if(AlmostEqual(rp1, lp2) || AlmostEqual(rp1, rp2)){
|
|
*p = lp1;
|
|
}else assert(false);
|
|
|
|
}
|
|
else{
|
|
|
|
if(ms->GetUp()){
|
|
int index1 = ms->GetStopId() - 2;
|
|
int index2 = ms->GetStopId() - 1;
|
|
GetSeg(index1, hs1);
|
|
GetSeg(index2, hs2);
|
|
}else{
|
|
int index1 = ms->GetStopId();
|
|
int index2 = ms->GetStopId() - 1;
|
|
GetSeg(SegSize() - index1, hs1);
|
|
GetSeg(SegSize() - index2, hs2);
|
|
}
|
|
|
|
Point lp1 = hs1.GetLeftPoint();
|
|
Point rp1 = hs1.GetRightPoint();
|
|
Point lp2 = hs2.GetLeftPoint();
|
|
Point rp2 = hs2.GetRightPoint();
|
|
|
|
if(AlmostEqual(lp1, lp2) || AlmostEqual(lp1, rp2)){
|
|
*p = lp1;
|
|
}else if(AlmostEqual(rp1, lp2) || AlmostEqual(rp1, rp2)){
|
|
*p = rp1;
|
|
}else assert(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
double Bus_Route::Length()
|
|
{
|
|
if(!IsDefined() || IsEmpty() == true) return 0.0;
|
|
|
|
double l = 0.0;
|
|
for(int i = 0;i < seg_list.Size();i++){
|
|
HalfSegment hs;
|
|
seg_list.Get(i, hs);
|
|
l += hs.Length();
|
|
}
|
|
return l;
|
|
}
|
|
|
|
|
|
void Bus_Route::StartBulkLoad()
|
|
{
|
|
|
|
}
|
|
|
|
/*
|
|
check whether two consequent segments are connected
|
|
|
|
*/
|
|
void Bus_Route::EndBulkLoad()
|
|
{
|
|
for(int i = 0;i < Size() - 1;i++){
|
|
|
|
SimpleLine sl1(0), sl2(0);
|
|
Get(i, sl1);
|
|
Get(i + 1, sl2);
|
|
////////////check the end point of the first bus segment///////.
|
|
////////////and the start point of the second bus segment//////
|
|
Point sp1, ep1;
|
|
Point sp2, ep2;
|
|
assert(sl1.AtPosition(0.0, sl1.GetStartSmaller(), sp1));
|
|
assert(sl1.AtPosition(sl1.Length(), sl1.GetStartSmaller(), ep1));
|
|
assert(sl2.AtPosition(0.0, sl2.GetStartSmaller(), sp2));
|
|
assert(sl2.AtPosition(sl2.Length(), sl2.GetStartSmaller(), ep2));
|
|
// cout<<" sp1 "<<sp1<<" ep1 "<<ep1<<" sp2 "<<sp2<<" ep2 "<<ep2<<endl;
|
|
if(!(AlmostEqual(sp1, sp2)|| AlmostEqual(sp1, ep2) ||
|
|
AlmostEqual(ep1, sp2)|| AlmostEqual(ep1, ep2))){
|
|
cout<<"not valid bus segments"<<endl;
|
|
cout<<"the end point of the first segment should be equal to \
|
|
the start point of the second segment"<<endl;
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
//////////////////////////////////////////////////////////////////
|
|
//////////////// Bus Network //////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////
|
|
string BusNetwork::BusStopsTypeInfo =
|
|
"(rel (tuple ((Bus_stop busstop) (Stop_geodata point))))";
|
|
string BusNetwork::BusRoutesTypeInfo =
|
|
"(rel (tuple ((Br_id int)(Bus_route busroute)(Oid int))))";
|
|
string BusNetwork::BusStopsInternalTypeInfo =
|
|
"(rel (tuple ((Br_id int)(Bus_stop busstop)(U_oid int)(Geodata point))))";
|
|
string BusNetwork::BusStopsBTreeTypeInfo =
|
|
"(btree (tuple ((Br_id int)(Bus_stop busstop)(U_oid int)(Geodata point))) int)";
|
|
string BusNetwork::BusStopsRTreeTypeInfo = "(rtree (tuple ((Br_id int)\
|
|
(Bus_stop busstop)(U_oid int)(Geodata point))) point FALSE)";
|
|
|
|
string BusNetwork::BusRoutesBTreeTypeInfo =
|
|
"(btree (tuple ((Br_id int)(Bus_route busroute)(Oid int))) int)";
|
|
|
|
string BusNetwork::BusRoutesBTreeUOidTypeInfo =
|
|
"(btree (tuple ((Br_id int)(Bus_route busroute)(Oid int))) int)";
|
|
|
|
string BusNetwork::BusTripsTypeInfo =
|
|
"(rel (tuple ((Bustrip1 genmo) (Bustrip2 mpoint) (Br_id int)(Oid int))))";
|
|
|
|
string BusNetwork::BusTripBTreeTypeInfo =
|
|
"(btree (tuple ((Bustrip1 genmo) (Bustrip2 mpoint) (Br_id int)(Oid int))) int)";
|
|
|
|
|
|
ListExpr BusNetworkProperty()
|
|
{
|
|
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("busnetwork"),
|
|
nl->StringAtom("((def, id))"),
|
|
nl->StringAtom("((TRUE 1))"))));
|
|
}
|
|
|
|
/*
|
|
output the bus network
|
|
|
|
*/
|
|
ListExpr OutBusNetwork( ListExpr typeInfo, Word value )
|
|
{
|
|
// cout<<"OutBusNetwork"<<endl;
|
|
BusNetwork* bn = (BusNetwork*)(value.addr);
|
|
if(!bn->IsDefined()){
|
|
return nl->SymbolAtom("undef");
|
|
}
|
|
|
|
ListExpr list1 = nl->TwoElemList(
|
|
nl->StringAtom("Bus Network Id:"),
|
|
nl->IntAtom(bn->GetId()));
|
|
// return nl->OneElemList(list1);
|
|
|
|
////////////////out put bus stops relation////////////////////////////////
|
|
ListExpr bs_list = nl->TheEmptyList();
|
|
Relation* bs_rel = bn->GetBS_Rel();
|
|
|
|
if(bs_rel != NULL){
|
|
bool bFirst = true;
|
|
ListExpr xNext = nl->TheEmptyList();
|
|
ListExpr xLast = nl->TheEmptyList();
|
|
for(int i = 1;i <= bs_rel->GetNoTuples();i++){
|
|
Tuple* node_tuple = bs_rel->GetTuple(i, false);
|
|
Bus_Stop* bs = (Bus_Stop*)node_tuple->GetAttribute(BusNetwork::BN_BS);
|
|
|
|
ListExpr stop_list = OutBusStop(nl->TheEmptyList(),SetWord(bs));
|
|
xNext = stop_list;
|
|
if(bFirst){
|
|
bs_list = nl->OneElemList(xNext);
|
|
xLast = bs_list;
|
|
bFirst = false;
|
|
}else
|
|
xLast = nl->Append(xLast,xNext);
|
|
node_tuple->DeleteIfAllowed();
|
|
}
|
|
}
|
|
// return nl->TwoElemList(list1, bs_list);
|
|
//////////////////////output bus routes relation///////////////////////////
|
|
ListExpr br_list = nl->TheEmptyList();
|
|
Relation* br_rel = bn->GetBR_Rel();
|
|
|
|
if(br_rel != NULL){
|
|
bool bFirst = true;
|
|
ListExpr xNext = nl->TheEmptyList();
|
|
ListExpr xLast = nl->TheEmptyList();
|
|
for(int i = 1;i <= br_rel->GetNoTuples();i++){
|
|
Tuple* node_tuple = br_rel->GetTuple(i, false);
|
|
Bus_Route* br = (Bus_Route*)node_tuple->GetAttribute(BusNetwork::BN_BR);
|
|
|
|
ListExpr stop_list = OutBusRoute(nl->TheEmptyList(),SetWord(br));
|
|
xNext = stop_list;
|
|
if(bFirst){
|
|
br_list = nl->OneElemList(xNext);
|
|
xLast = br_list;
|
|
bFirst = false;
|
|
}else
|
|
xLast = nl->Append(xLast,xNext);
|
|
node_tuple->DeleteIfAllowed();
|
|
}
|
|
}
|
|
////////////////////////////////////////////////////////////////////////
|
|
////////////////no output bus trips relation: too much data///////////////
|
|
//////////////////////////////////////////////////////////////////////////
|
|
return nl->ThreeElemList(list1, bs_list, br_list);
|
|
|
|
}
|
|
|
|
/*
|
|
In function. there is not nested list expression here.
|
|
|
|
*/
|
|
Word InBusNetwork( const ListExpr typeInfo, const ListExpr instance,
|
|
const int errorPos, ListExpr& errorInfo, bool& correct )
|
|
{
|
|
|
|
// cout<<"length "<<nl->ListLength(instance)<<endl;
|
|
|
|
if( !nl->IsAtom( instance ) ){
|
|
|
|
if(nl->ListLength(instance) != 2){
|
|
cout<<"length should be 2"<<endl;
|
|
correct = false;
|
|
return SetWord(Address(0));
|
|
}
|
|
ListExpr first = nl->First(instance);
|
|
ListExpr second = nl->Second(instance);
|
|
|
|
if(!nl->IsAtom(first) || nl->AtomType(first) != BoolType){
|
|
cout<< "busnetwork(): definition must be bool type"<<endl;
|
|
correct = false;
|
|
return SetWord(Address(0));
|
|
}
|
|
bool d = nl->BoolValue(first);
|
|
|
|
|
|
if(!nl->IsAtom(second) || nl->AtomType(second) != IntType){
|
|
cout<< "busnetwork(): bus network id must be int type"<<endl;
|
|
correct = false;
|
|
return SetWord(Address(0));
|
|
}
|
|
unsigned int id = nl->IntValue(second);
|
|
|
|
BusNetwork* bn = new BusNetwork(d, id);
|
|
|
|
////////////////very important /////////////////////////////
|
|
correct = true;
|
|
///////////////////////////////////////////////////////////
|
|
return SetWord(bn);
|
|
}
|
|
|
|
correct = false;
|
|
return SetWord(Address(0));
|
|
}
|
|
|
|
bool SaveBusNetwork(SmiRecord& valueRecord, size_t& offset,
|
|
const ListExpr typeInfo, Word& value)
|
|
{
|
|
BusNetwork* bn = (BusNetwork*)value.addr;
|
|
return bn->Save(valueRecord, offset, typeInfo);
|
|
}
|
|
|
|
BusNetwork* BusNetwork::Open(SmiRecord& valueRecord, size_t& offset,
|
|
const ListExpr typeInfo)
|
|
{
|
|
return new BusNetwork(valueRecord, offset, typeInfo);
|
|
|
|
}
|
|
|
|
bool OpenBusNetwork(SmiRecord& valueRecord, size_t& offset,
|
|
const ListExpr typeInfo, Word& value)
|
|
{
|
|
value.addr = BusNetwork::Open(valueRecord, offset, typeInfo);
|
|
return value.addr != NULL;
|
|
}
|
|
|
|
|
|
Word CreateBusNetwork(const ListExpr typeInfo)
|
|
{
|
|
// cout<<"CreateBusNetwork()"<<endl;
|
|
return SetWord (new BusNetwork());
|
|
}
|
|
|
|
|
|
void DeleteBusNetwork(const ListExpr typeInfo, Word& w)
|
|
{
|
|
// cout<<"DeleteBusNetwork()"<<endl;
|
|
BusNetwork* bn = (BusNetwork*)w.addr;
|
|
delete bn;
|
|
w.addr = NULL;
|
|
}
|
|
|
|
|
|
void CloseBusNetwork( const ListExpr typeInfo, Word& w )
|
|
{
|
|
// cout<<"CloseBusNetwork"<<endl;
|
|
delete static_cast<BusNetwork*>(w.addr);
|
|
w.addr = 0;
|
|
}
|
|
|
|
Word CloneBusNetwork( const ListExpr typeInfo, const Word& w )
|
|
{
|
|
// cout<<"CloneBusNetwork"<<endl;
|
|
return SetWord( new Address(0));
|
|
}
|
|
|
|
void* BusNetwork::Cast(void* addr)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
int SizeOfBusNetwork()
|
|
{
|
|
// cout<<"SizeOfBusNetwork"<<endl;
|
|
return sizeof(BusNetwork);
|
|
}
|
|
|
|
bool CheckBusNetwork( ListExpr type, ListExpr& errorInfo )
|
|
{
|
|
// cout<<"CheckBusNetwork"<<endl;
|
|
return (nl->IsEqual( type, "busnetwork" ));
|
|
}
|
|
|
|
BusNetwork::BusNetwork():
|
|
def(false), bn_id(0), graph_init(false), graph_id(0), max_bus_speed(0),
|
|
min_br_oid(0), min_bt_oid(0), start_time(0), end_time(0),
|
|
stops_rel(NULL), btree_bs(NULL),
|
|
routes_rel(NULL), btree_br(NULL), btree_bs_uoid(NULL), rtree_bs(NULL),
|
|
btree_br_uoid(NULL), bustrips_rel(NULL), btree_trip_oid(NULL),
|
|
btree_trip_br_id(NULL)
|
|
{
|
|
|
|
|
|
}
|
|
|
|
BusNetwork::BusNetwork(bool d, unsigned int i): def(d), bn_id(i),
|
|
graph_init(false), graph_id(0), max_bus_speed(0),
|
|
min_br_oid(0), min_bt_oid(0), start_time(0), end_time(0),
|
|
stops_rel(NULL), btree_bs(NULL), routes_rel(NULL), btree_br(NULL),
|
|
btree_bs_uoid(NULL), rtree_bs(NULL), btree_br_uoid(NULL), bustrips_rel(NULL),
|
|
btree_trip_oid(NULL), btree_trip_br_id(NULL)
|
|
{
|
|
|
|
}
|
|
|
|
/*
|
|
read the data from record
|
|
|
|
*/
|
|
BusNetwork::BusNetwork(SmiRecord& valueRecord, size_t& offset,
|
|
const ListExpr typeInfo):
|
|
def(false), bn_id(0), graph_init(false), graph_id(0), max_bus_speed(0),
|
|
min_br_oid(0), min_bt_oid(0), start_time(0), end_time(0),
|
|
stops_rel(NULL), btree_bs(NULL),
|
|
routes_rel(NULL), btree_br(NULL), btree_bs_uoid(NULL), rtree_bs(NULL),
|
|
btree_br_uoid(NULL), bustrips_rel(NULL), btree_trip_oid(NULL),
|
|
btree_trip_br_id(NULL)
|
|
{
|
|
valueRecord.Read(&def, sizeof(bool), offset);
|
|
offset += sizeof(bool);
|
|
|
|
valueRecord.Read(&bn_id, sizeof(unsigned int), offset);
|
|
offset += sizeof(unsigned int);
|
|
|
|
valueRecord.Read(&graph_init, sizeof(bool), offset);
|
|
offset += sizeof(bool);
|
|
|
|
valueRecord.Read(&graph_id, sizeof(unsigned int), offset);
|
|
offset += sizeof(unsigned int);
|
|
|
|
valueRecord.Read(&max_bus_speed, sizeof(double), offset);
|
|
offset += sizeof(double);
|
|
|
|
valueRecord.Read(&min_br_oid, sizeof(unsigned int), offset);
|
|
offset += sizeof(unsigned int);
|
|
|
|
valueRecord.Read(&min_bt_oid, sizeof(unsigned int), offset);
|
|
offset += sizeof(unsigned int);
|
|
|
|
valueRecord.Read(&start_time, sizeof(double), offset);
|
|
offset += sizeof(double);
|
|
|
|
valueRecord.Read(&end_time, sizeof(double), offset);
|
|
offset += sizeof(double);
|
|
|
|
ListExpr xType;
|
|
ListExpr xNumericType;
|
|
/***********************Open relation for busstops*********************/
|
|
nl->ReadFromString(BusStopsInternalTypeInfo,xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
stops_rel = Relation::Open(valueRecord, offset, xNumericType);
|
|
if(!stops_rel) {
|
|
return;
|
|
}
|
|
///////////////////btree on bus stops on brid///////////////////////////////
|
|
nl->ReadFromString(BusStopsBTreeTypeInfo,xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
btree_bs = BTree::Open(valueRecord, offset, xNumericType);
|
|
if(!btree_bs) {
|
|
stops_rel->Delete();
|
|
return;
|
|
}
|
|
|
|
/***********************Open relation for busroutes*********************/
|
|
nl->ReadFromString(BusRoutesTypeInfo,xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
routes_rel = Relation::Open(valueRecord, offset, xNumericType);
|
|
if(!routes_rel) {
|
|
stops_rel->Delete();
|
|
delete btree_bs;
|
|
return;
|
|
}
|
|
|
|
///////////////////btree on bus routes//////////////////////////////////
|
|
nl->ReadFromString(BusRoutesBTreeTypeInfo,xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
btree_br = BTree::Open(valueRecord, offset, xNumericType);
|
|
if(!btree_br) {
|
|
stops_rel->Delete();
|
|
delete btree_bs;
|
|
routes_rel->Delete();
|
|
return;
|
|
}
|
|
|
|
///////////////////btree on bus stops on uoid//////////////////////////////
|
|
nl->ReadFromString(BusStopsBTreeTypeInfo,xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
btree_bs_uoid = BTree::Open(valueRecord, offset, xNumericType);
|
|
if(!btree_bs_uoid) {
|
|
stops_rel->Delete();
|
|
delete btree_bs;
|
|
routes_rel->Delete();
|
|
delete btree_br;
|
|
return;
|
|
}
|
|
|
|
///////////////////rtree on bus stops //////////////////////////////
|
|
Word xValue;
|
|
if(!(rtree_bs->Open(valueRecord,offset, BusStopsRTreeTypeInfo,xValue))){
|
|
stops_rel->Delete();
|
|
delete btree_bs;
|
|
routes_rel->Delete();
|
|
delete btree_br;
|
|
delete btree_bs_uoid;
|
|
return;
|
|
}
|
|
|
|
rtree_bs = ( R_Tree<2,TupleId>* ) xValue.addr;
|
|
|
|
|
|
///////////////////btree on bus routes unique id////////////////////////////
|
|
nl->ReadFromString(BusRoutesBTreeUOidTypeInfo,xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
btree_br_uoid = BTree::Open(valueRecord, offset, xNumericType);
|
|
if(!btree_br_uoid) {
|
|
stops_rel->Delete();
|
|
delete btree_bs;
|
|
routes_rel->Delete();
|
|
delete btree_br;
|
|
delete btree_bs_uoid;
|
|
delete rtree_bs;
|
|
return;
|
|
}
|
|
|
|
///////////////open relation storing bus trips//////////////////////
|
|
nl->ReadFromString(BusTripsTypeInfo,xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
bustrips_rel = Relation::Open(valueRecord, offset, xNumericType);
|
|
if(!bustrips_rel) {
|
|
stops_rel->Delete();
|
|
delete btree_bs;
|
|
routes_rel->Delete();
|
|
delete btree_br;
|
|
delete btree_bs_uoid;
|
|
delete rtree_bs;
|
|
delete btree_br_uoid;
|
|
return;
|
|
}
|
|
|
|
///////////////////btree on bus trips unique id////////////////////////////
|
|
nl->ReadFromString(BusTripBTreeTypeInfo, xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
btree_trip_oid = BTree::Open(valueRecord, offset, xNumericType);
|
|
if(!btree_trip_oid) {
|
|
stops_rel->Delete();
|
|
delete btree_bs;
|
|
routes_rel->Delete();
|
|
delete btree_br;
|
|
delete btree_bs_uoid;
|
|
delete rtree_bs;
|
|
delete btree_br_uoid;
|
|
bustrips_rel->Delete();
|
|
return;
|
|
}
|
|
///////////////////btree on bus trips bus route id/////////////////////////
|
|
nl->ReadFromString(BusTripBTreeTypeInfo, xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
btree_trip_br_id = BTree::Open(valueRecord, offset, xNumericType);
|
|
if(!btree_trip_br_id) {
|
|
stops_rel->Delete();
|
|
delete btree_bs;
|
|
routes_rel->Delete();
|
|
delete btree_br;
|
|
delete btree_bs_uoid;
|
|
delete rtree_bs;
|
|
delete btree_br_uoid;
|
|
bustrips_rel->Delete();
|
|
delete btree_trip_oid;
|
|
return;
|
|
}
|
|
|
|
}
|
|
|
|
BusNetwork::~BusNetwork()
|
|
{
|
|
if(stops_rel != NULL) stops_rel->Close();
|
|
if(btree_bs != NULL) delete btree_bs;
|
|
if(routes_rel != NULL) routes_rel->Close();
|
|
if(btree_br != NULL) delete btree_br;
|
|
if(btree_bs_uoid != NULL) delete btree_bs_uoid;
|
|
if(rtree_bs != NULL) delete rtree_bs;
|
|
if(btree_br_uoid != NULL) delete btree_br_uoid;
|
|
if(bustrips_rel != NULL) bustrips_rel->Close();
|
|
if(btree_trip_oid != NULL) delete btree_trip_oid;
|
|
if(btree_trip_br_id != NULL) delete btree_trip_br_id;
|
|
|
|
}
|
|
|
|
bool BusNetwork::Save(SmiRecord& valueRecord, size_t& offset,
|
|
const ListExpr typeInfo)
|
|
{
|
|
|
|
// cout<<"BusNetwork::Save"<<endl;
|
|
|
|
valueRecord.Write(&def, sizeof(bool), offset);
|
|
offset += sizeof(bool);
|
|
|
|
valueRecord.Write(&bn_id, sizeof(unsigned int), offset);
|
|
offset += sizeof(unsigned int);
|
|
|
|
valueRecord.Write(&graph_init, sizeof(bool), offset);
|
|
offset += sizeof(bool);
|
|
|
|
valueRecord.Write(&graph_id, sizeof(unsigned int), offset);
|
|
offset += sizeof(unsigned int);
|
|
|
|
valueRecord.Write(&max_bus_speed, sizeof(double), offset);
|
|
offset += sizeof(double);
|
|
|
|
valueRecord.Write(&min_br_oid, sizeof(unsigned int), offset);
|
|
offset += sizeof(unsigned int);
|
|
|
|
valueRecord.Write(&min_bt_oid, sizeof(unsigned int), offset);
|
|
offset += sizeof(unsigned int);
|
|
|
|
valueRecord.Write(&start_time, sizeof(double), offset);
|
|
offset += sizeof(double);
|
|
|
|
valueRecord.Write(&end_time, sizeof(double), offset);
|
|
offset += sizeof(double);
|
|
|
|
ListExpr xType;
|
|
ListExpr xNumericType;
|
|
|
|
////////////////////bus stops relation/////////////////////////////
|
|
nl->ReadFromString(BusStopsInternalTypeInfo,xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
if(!stops_rel->Save(valueRecord,offset,xNumericType))
|
|
return false;
|
|
|
|
///////////////////////btree on bus stops on brid/////////////////////////
|
|
nl->ReadFromString(BusStopsBTreeTypeInfo,xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
if(!btree_bs->Save(valueRecord,offset,xNumericType))
|
|
return false;
|
|
|
|
///////////////////bus routes relation/////////////////////////////
|
|
nl->ReadFromString(BusRoutesTypeInfo,xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
if(!routes_rel->Save(valueRecord,offset,xNumericType))
|
|
return false;
|
|
|
|
///////////////////////btree on bus routes////////////////////////////
|
|
nl->ReadFromString(BusRoutesBTreeTypeInfo,xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
if(!btree_br->Save(valueRecord,offset,xNumericType))
|
|
return false;
|
|
|
|
///////////////////////btree on bus stops on uoid///////////////////////
|
|
nl->ReadFromString(BusStopsBTreeTypeInfo,xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
if(!btree_bs_uoid->Save(valueRecord,offset,xNumericType))
|
|
return false;
|
|
|
|
///////////////////////rtree on bus stops ///////////////////////
|
|
if(!rtree_bs->Save(valueRecord, offset)){
|
|
return false;
|
|
}
|
|
|
|
///////////////////////btree on bus routes on unique id//////////////////////
|
|
nl->ReadFromString(BusRoutesBTreeUOidTypeInfo,xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
if(!btree_br_uoid->Save(valueRecord,offset,xNumericType))
|
|
return false;
|
|
|
|
///////////////////bus trips relation/////////////////////////////
|
|
nl->ReadFromString(BusTripsTypeInfo, xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
if(!bustrips_rel->Save(valueRecord,offset,xNumericType))
|
|
return false;
|
|
|
|
///////////////////////btree on bus trips on unique id//////////////////////
|
|
nl->ReadFromString(BusTripBTreeTypeInfo,xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
if(!btree_trip_oid->Save(valueRecord,offset,xNumericType))
|
|
return false;
|
|
|
|
//////////////////btree on bus trips on bus route id//////////////////////
|
|
nl->ReadFromString(BusTripBTreeTypeInfo,xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
if(!btree_trip_br_id->Save(valueRecord,offset,xNumericType))
|
|
return false;
|
|
|
|
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
store bus stops relation and the index
|
|
|
|
*/
|
|
void BusNetwork::LoadStops(Relation* r1)
|
|
{
|
|
ListExpr xTypeInfo;
|
|
nl->ReadFromString(BusStopsInternalTypeInfo, xTypeInfo);
|
|
ListExpr xNumType = SecondoSystem::GetCatalog()->NumericType(xTypeInfo);
|
|
Relation* s_rel = new Relation(xNumType, true);
|
|
for(int i = 1;i <= r1->GetNoTuples();i++){
|
|
Tuple* bs_tuple = r1->GetTuple(i, false);
|
|
if(bs_tuple->GetNoAttributes() != 2){
|
|
cout<<"bus stops relation schema is wrong"<<endl;
|
|
bs_tuple->DeleteIfAllowed();
|
|
break;
|
|
}
|
|
Bus_Stop* bs = (Bus_Stop*)bs_tuple->GetAttribute(NODE_BS1);
|
|
int id = bs->GetId();
|
|
|
|
Tuple* new_bs_tuple = new Tuple(nl->Second(xNumType));
|
|
new_bs_tuple->PutAttribute(BN_ID1, new CcInt(true, id));
|
|
new_bs_tuple->PutAttribute(BN_BS, new Bus_Stop(*bs));
|
|
new_bs_tuple->PutAttribute(BS_U_OID, new CcInt(true, bs->GetUOid()));
|
|
|
|
Point* bs_loc = (Point*)bs_tuple->GetAttribute(NODE_BS2);
|
|
// cout<<*bs_loc<<endl;
|
|
new_bs_tuple->PutAttribute(BS_GEO, new Point(*bs_loc));
|
|
|
|
s_rel->AppendTuple(new_bs_tuple);
|
|
new_bs_tuple->DeleteIfAllowed();
|
|
bs_tuple->DeleteIfAllowed();
|
|
}
|
|
// cout<<s_rel->GetNoTuples()<<endl;
|
|
|
|
|
|
ListExpr ptrList1 = listutils::getPtrList(s_rel);
|
|
|
|
string strQuery = "(consume(feed(" + BusStopsInternalTypeInfo +
|
|
"(ptr " + nl->ToString(ptrList1) + "))))";
|
|
|
|
// cout<<strQuery<<endl;
|
|
|
|
Word xResult;
|
|
int QueryExecuted = QueryProcessor::ExecuteQuery(strQuery, xResult);
|
|
assert(QueryExecuted);
|
|
stops_rel = (Relation*)xResult.addr;
|
|
s_rel->Delete();
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
//////////////////////btree on bus stops br id/////////////////////
|
|
///////////////////////////////////////////////////////////////////
|
|
ListExpr ptrList2 = listutils::getPtrList(stops_rel);
|
|
|
|
strQuery = "(createbtree (" + BusStopsInternalTypeInfo +
|
|
"(ptr " + nl->ToString(ptrList2) + "))" + "Br_id)";
|
|
|
|
QueryExecuted = QueryProcessor::ExecuteQuery(strQuery,xResult);
|
|
assert(QueryExecuted);
|
|
btree_bs = (BTree*)xResult.addr;
|
|
|
|
|
|
//////////////////////btree on bus stops uoid/////////////////////
|
|
ListExpr ptrList3 = listutils::getPtrList(stops_rel);
|
|
|
|
strQuery = "(createbtree (" + BusStopsInternalTypeInfo +
|
|
"(ptr " + nl->ToString(ptrList3) + "))" + "U_oid)";
|
|
|
|
QueryExecuted = QueryProcessor::ExecuteQuery(strQuery,xResult);
|
|
assert(QueryExecuted);
|
|
btree_bs_uoid = (BTree*)xResult.addr;
|
|
|
|
//////////////////////rtree on bus stops//////////////////////////
|
|
ListExpr ptrList4 = listutils::getPtrList(stops_rel);
|
|
|
|
strQuery = "(bulkloadrtree(sortby(addid(feed (" + BusStopsInternalTypeInfo +
|
|
" (ptr " + nl->ToString(ptrList4) + "))))((Geodata asc))) Geodata)";
|
|
QueryExecuted = QueryProcessor::ExecuteQuery ( strQuery, xResult );
|
|
assert ( QueryExecuted );
|
|
rtree_bs = ( R_Tree<2,TupleId>* ) xResult.addr;
|
|
|
|
}
|
|
|
|
/*
|
|
store bus routes relation as well as some indices
|
|
|
|
*/
|
|
void BusNetwork:: LoadRoutes(Relation* r2)
|
|
{
|
|
|
|
ListExpr ptrList1 = listutils::getPtrList(r2);
|
|
|
|
string strQuery = "(consume(feed(" + BusRoutesTypeInfo +
|
|
"(ptr " + nl->ToString(ptrList1) + "))))";
|
|
|
|
// cout<<strQuery<<endl;
|
|
|
|
Word xResult;
|
|
int QueryExecuted = QueryProcessor::ExecuteQuery(strQuery, xResult);
|
|
assert(QueryExecuted);
|
|
routes_rel = (Relation*)xResult.addr;
|
|
|
|
///////////////////get the minimum bus route oid//////////////////////////
|
|
int temp_id = numeric_limits<int>::max();
|
|
for(int i = 1;i <= routes_rel->GetNoTuples();i++){
|
|
Tuple* br_tuple = routes_rel->GetTuple(i, false);
|
|
int id = ((CcInt*)br_tuple->GetAttribute(BN_BR_OID))->GetIntval();
|
|
if(id < temp_id) temp_id = id;
|
|
br_tuple->DeleteIfAllowed();
|
|
}
|
|
min_br_oid = temp_id;
|
|
// cout<<"min br oid "<<min_br_oid<<endl;
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
//////////////////////btree on bus routes brid/////////////////////
|
|
//////////////////////////////////////////////////////////////////
|
|
|
|
ListExpr ptrList2 = listutils::getPtrList(routes_rel);
|
|
|
|
strQuery = "(createbtree (" + BusRoutesTypeInfo +
|
|
"(ptr " + nl->ToString(ptrList2) + "))" + "Br_id)";
|
|
// cout<<strQuery<<endl;
|
|
QueryExecuted = QueryProcessor::ExecuteQuery(strQuery,xResult);
|
|
assert(QueryExecuted);
|
|
btree_br = (BTree*)xResult.addr;
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
//////////////////////btree on bus routes unique oid///////////////
|
|
//////////////////////////////////////////////////////////////////
|
|
|
|
ListExpr ptrList3 = listutils::getPtrList(routes_rel);
|
|
|
|
strQuery = "(createbtree (" + BusRoutesTypeInfo +
|
|
"(ptr " + nl->ToString(ptrList3) + "))" + "Oid)";
|
|
|
|
QueryExecuted = QueryProcessor::ExecuteQuery(strQuery,xResult);
|
|
assert(QueryExecuted);
|
|
btree_br_uoid = (BTree*)xResult.addr;
|
|
|
|
}
|
|
|
|
/*
|
|
store moving buses and the maximum speed of all buses
|
|
(for query processing of bus graph)
|
|
|
|
*/
|
|
void BusNetwork:: LoadBuses(Relation* r3)
|
|
{
|
|
|
|
ListExpr ptrList1 = listutils::getPtrList(r3);
|
|
|
|
string strQuery = "(consume(feed(" + BusTripsTypeInfo +
|
|
"(ptr " + nl->ToString(ptrList1) + "))))";
|
|
|
|
// cout<<strQuery<<endl;
|
|
|
|
Word xResult;
|
|
int QueryExecuted = QueryProcessor::ExecuteQuery(strQuery, xResult);
|
|
assert(QueryExecuted);
|
|
bustrips_rel = (Relation*)xResult.addr;
|
|
|
|
// cout<<"size "<<bustrips_rel->GetNoTuples()<<endl;
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
//////////////////////set maximum bus speed///////////////////////////
|
|
/////////////////////////////////////////////////////////////////////
|
|
int temp_id = numeric_limits<int>::max();
|
|
|
|
for(int i = 1;i <= bustrips_rel->GetNoTuples();i++){
|
|
Tuple* bus_tuple = bustrips_rel->GetTuple(i, false);
|
|
GenMO* mo = (GenMO*)bus_tuple->GetAttribute(BN_BUSTRIP);
|
|
|
|
/////////////get the start and end time of all bus trips//////////////
|
|
Periods* peri = new Periods(0);
|
|
mo->DefTime(*peri);
|
|
Interval<Instant> time_span;
|
|
peri->Get(0, time_span);
|
|
// cout<<time_span.start<<" "<<time_span.end<<endl;
|
|
if(i == 1){
|
|
start_time = time_span.start.ToDouble();
|
|
end_time = time_span.end.ToDouble();
|
|
}else{
|
|
if(time_span.start.ToDouble() < start_time)
|
|
start_time = time_span.start.ToDouble();
|
|
if(time_span.end.ToDouble() > end_time)
|
|
end_time = time_span.end.ToDouble();
|
|
}
|
|
peri->DeleteIfAllowed();
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
for( int j = 0; j < mo->GetNoComponents(); j++ ){
|
|
UGenLoc unit;
|
|
mo->Get( j, unit );
|
|
double pos1 = unit.gloc1.GetLoc().loc1;
|
|
double pos2 = unit.gloc2.GetLoc().loc1;
|
|
if(fabs(pos1 - pos2) > 1.0){
|
|
double t =
|
|
unit.timeInterval.end.ToDouble()*86400.0 -
|
|
unit.timeInterval.start.ToDouble()*86400.0;
|
|
double speed = fabs(pos1 - pos2)/t;
|
|
/* cout<<"dist "<<fabs(pos1 - pos2)<<" t "<<t
|
|
<<" speed "<<speed<<endl;*/
|
|
if(speed > max_bus_speed){
|
|
max_bus_speed = speed;
|
|
}
|
|
}
|
|
}
|
|
int id = ((CcInt*)bus_tuple->GetAttribute(BN_BUS_OID))->GetIntval();
|
|
if(id < temp_id) temp_id = id;
|
|
|
|
bus_tuple->DeleteIfAllowed();
|
|
|
|
}
|
|
min_bt_oid = temp_id;
|
|
// cout<<"max bus speed "<<max_bus_speed*60*60/1000.0<<"km/h "<<endl;
|
|
// cout<<"min bus trip oid "<<min_bt_oid<<endl;
|
|
|
|
////////////////btree on bus trips oid///////////////////////////
|
|
|
|
ListExpr ptrList2 = listutils::getPtrList(bustrips_rel);
|
|
|
|
strQuery = "(createbtree (" + BusTripsTypeInfo +
|
|
"(ptr " + nl->ToString(ptrList2) + "))" + "Oid)";
|
|
|
|
QueryExecuted = QueryProcessor::ExecuteQuery(strQuery,xResult);
|
|
assert(QueryExecuted);
|
|
btree_trip_oid = (BTree*)xResult.addr;
|
|
|
|
|
|
////////////////btree on bus trips bus route///////////////////////////
|
|
|
|
ListExpr ptrList3 = listutils::getPtrList(bustrips_rel);
|
|
|
|
strQuery = "(createbtree (" + BusTripsTypeInfo +
|
|
"(ptr " + nl->ToString(ptrList3) + "))" + "Br_id)";
|
|
|
|
QueryExecuted = QueryProcessor::ExecuteQuery(strQuery,xResult);
|
|
assert(QueryExecuted);
|
|
btree_trip_br_id = (BTree*)xResult.addr;
|
|
|
|
|
|
// Instant t1(start_time);
|
|
// Instant t2(end_time);
|
|
|
|
// cout<<t1<<" "<<t2<<endl;
|
|
|
|
}
|
|
|
|
/*
|
|
create a bus network by bus stops relation and bus routes relation
|
|
|
|
*/
|
|
void BusNetwork::Load(unsigned int i, Relation* r1, Relation* r2, Relation* r3)
|
|
{
|
|
if(i < 1){
|
|
def = false;
|
|
return;
|
|
}
|
|
bn_id = i;
|
|
|
|
LoadStops(r1); /////to get 2D points in space
|
|
LoadRoutes(r2); //first load bus routes because bus stops access bus routes
|
|
LoadBuses(r3); //first load bus routes because bus stops access bus routes
|
|
|
|
def = true;
|
|
}
|
|
|
|
/*
|
|
get the point of a bus stop by: busstop x busnetwork
|
|
|
|
*/
|
|
void BusNetwork::GetBusStopGeoData(Bus_Stop* bs, Point* p)
|
|
{
|
|
int id = bs->GetId();
|
|
if(id < 1){
|
|
cout<<"invalid bus stop"<<endl;
|
|
return;
|
|
}
|
|
|
|
CcInt* search_id = new CcInt(true, id);
|
|
BTreeIterator* btree_iter = btree_br->ExactMatch(search_id);
|
|
while(btree_iter->Next()){
|
|
Tuple* tuple = routes_rel->GetTuple(btree_iter->GetId(), false);
|
|
Bus_Route* br = (Bus_Route*)tuple->GetAttribute(BN_BR);
|
|
if(br->GetUp() == bs->GetUp()){
|
|
br->GetBusStopGeoData(bs, p);
|
|
tuple->DeleteIfAllowed();
|
|
break;
|
|
}
|
|
tuple->DeleteIfAllowed();
|
|
}
|
|
delete btree_iter;
|
|
search_id->DeleteIfAllowed();
|
|
}
|
|
|
|
/*
|
|
set the bus graph id for bus network
|
|
|
|
*/
|
|
void BusNetwork::SetGraphId(int g_id)
|
|
{
|
|
graph_id = g_id;
|
|
graph_init = true;
|
|
}
|
|
|
|
/*
|
|
get the bus graph in bus network
|
|
|
|
*/
|
|
BusGraph* BusNetwork::GetBusGraph()
|
|
{
|
|
if(graph_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) == "busgraph"){
|
|
// Get name of the bus graph
|
|
ListExpr xObjectName = nl->Second(xCurrent);
|
|
string strObjectName = nl->SymbolValue(xObjectName);
|
|
|
|
// Load object to find out the id of the network.
|
|
Word xValue;
|
|
bool bDefined;
|
|
bool bOk = SecondoSystem::GetCatalog()->GetObject(strObjectName,
|
|
xValue,
|
|
bDefined);
|
|
if(!bDefined || !bOk)
|
|
{
|
|
// Undefined
|
|
continue;
|
|
}
|
|
BusGraph* bg = (BusGraph*)xValue.addr;
|
|
if(bg->bg_id == graph_id){
|
|
// This is the bus graph we have been looking for
|
|
return bg;
|
|
}
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
close the bus graph
|
|
|
|
*/
|
|
void BusNetwork::CloseBusGraph(BusGraph* bg)
|
|
{
|
|
if(bg == NULL) return;
|
|
Word xValue;
|
|
xValue.addr = bg;
|
|
SecondoSystem::GetCatalog()->CloseObject(nl->SymbolAtom( "busgraph" ),
|
|
xValue);
|
|
}
|
|
|
|
/*
|
|
given a bus stop and time, it returns oid of the moving bus belonging to
|
|
that bus route and direction as well as coving the time
|
|
|
|
*/
|
|
struct Id_Time{
|
|
int oid;
|
|
double time;
|
|
Id_Time(){}
|
|
Id_Time(int id, double t):oid(id), time(t){}
|
|
Id_Time(const Id_Time& id_t):oid(id_t.oid), time(id_t.time){}
|
|
Id_Time& operator=(const Id_Time& id_time)
|
|
{
|
|
oid = id_time.oid;
|
|
time = id_time.time;
|
|
return *this;
|
|
}
|
|
bool operator<(const Id_Time& id_time) const
|
|
{
|
|
return time < id_time.time;
|
|
}
|
|
void Print()
|
|
{
|
|
cout<<"oid "<<oid<<"cost "<<time<<endl;
|
|
}
|
|
};
|
|
|
|
int BusNetwork::GetMOBus_Oid(Bus_Stop* bs, Point* bs_loc, Instant& t)
|
|
{
|
|
// cout<<"instant "<<t<<endl;
|
|
int br_id = bs->GetId();
|
|
//////////////////////////////////////////////////////////////////
|
|
////////////get the unique id for the bus route/////////////////
|
|
//////////////////////////////////////////////////////////////////
|
|
CcInt* search_id1 = new CcInt(true, br_id);
|
|
BTreeIterator* btree_iter1 = btree_br->ExactMatch(search_id1);
|
|
int br_uoid = 0;
|
|
while(btree_iter1->Next()){
|
|
Tuple* tuple = routes_rel->GetTuple(btree_iter1->GetId(), false);
|
|
Bus_Route* br = (Bus_Route*)tuple->GetAttribute(BusNetwork::BN_BR);
|
|
if(br->GetUp() == bs->GetUp()){
|
|
br_uoid =
|
|
((CcInt*)tuple->GetAttribute(BusNetwork::BN_BR_OID))->GetIntval();
|
|
tuple->DeleteIfAllowed();
|
|
break;
|
|
}
|
|
tuple->DeleteIfAllowed();
|
|
}
|
|
delete btree_iter1;
|
|
search_id1->DeleteIfAllowed();
|
|
assert(br_uoid > 0);
|
|
|
|
// cout<<"br_uoid "<<br_uoid<<endl;
|
|
///////////////////////////////////////////////////////////////
|
|
///////////////get moving buses moving on the route///////////
|
|
///////////////////////////////////////////////////////////////
|
|
int bus_oid = 0;
|
|
CcInt* search_id2 = new CcInt(true, br_uoid);
|
|
BTreeIterator* btree_iter2 = btree_trip_br_id->ExactMatch(search_id2);
|
|
const double delta_dist = 0.01;
|
|
vector<Id_Time> res_list;
|
|
|
|
while(btree_iter2->Next()){
|
|
Tuple* tuple = bustrips_rel->GetTuple(btree_iter2->GetId(), false);
|
|
int brid =
|
|
((CcInt*)tuple->GetAttribute(BN_REFBR_OID))->GetIntval();
|
|
assert(brid == br_uoid);
|
|
MPoint* mo_bus = (MPoint*)tuple->GetAttribute(BN_BUSTRIP_MP);
|
|
Periods* peri = new Periods(0);
|
|
mo_bus->DefTime(*peri);
|
|
// cout<<"periods "<<*peri<<endl;
|
|
if(peri->Contains(t)){
|
|
// cout<<"periods containt instant "<<endl;
|
|
|
|
for(int i = 0;i < mo_bus->GetNoComponents();i++){
|
|
UPoint unit;
|
|
mo_bus->Get(i, unit);
|
|
Point p0 = unit.p0;
|
|
Point p1 = unit.p1;
|
|
|
|
// cout<<unit.timeInterval<<" dist "<<bs_loc->Distance(p0)<<endl;
|
|
// cout<<"dist1 "<<bs_loc->Distance(p0)
|
|
// <<" dist2 "<<bs_loc->Distance(p1)<<endl;
|
|
|
|
if(bs_loc->Distance(p0) < delta_dist &&
|
|
bs_loc->Distance(p1) < delta_dist){
|
|
bus_oid = ((CcInt*)tuple->GetAttribute(BN_BUS_OID))->GetIntval();
|
|
double delta_t =
|
|
fabs(unit.timeInterval.start.ToDouble() - t.ToDouble());
|
|
Id_Time* id_time = new Id_Time(bus_oid, delta_t);
|
|
res_list.push_back(*id_time);
|
|
delete id_time;
|
|
}
|
|
}
|
|
}
|
|
peri->DeleteIfAllowed();
|
|
tuple->DeleteIfAllowed();
|
|
}
|
|
delete btree_iter2;
|
|
search_id2->DeleteIfAllowed();
|
|
sort(res_list.begin(), res_list.end());
|
|
// for(unsigned int i = 0;i < res_list.size();i++)
|
|
// res_list[i].Print();
|
|
// cout<<"res_list size "<<res_list.size()<<endl;
|
|
assert(res_list.size() > 0);
|
|
bus_oid = res_list[0].oid;
|
|
|
|
assert(bus_oid > 0);
|
|
return bus_oid;
|
|
}
|
|
|
|
/*
|
|
given a bus stop and time, it returns mpoint of the moving bus belonging to
|
|
that bus route and direction as well as coving the time
|
|
|
|
*/
|
|
int BusNetwork::GetMOBus_MP(Bus_Stop* bs, Point* bs_loc, Instant t, MPoint& mp)
|
|
{
|
|
// cout<<"GetMOBus_MP() bs "<<*bs<<endl;
|
|
int br_id = bs->GetId();
|
|
//////////////////////////////////////////////////////////////////
|
|
////////////get the unique id for the bus route/////////////////
|
|
//////////////////////////////////////////////////////////////////
|
|
CcInt* search_id1 = new CcInt(true, br_id);
|
|
BTreeIterator* btree_iter1 = btree_br->ExactMatch(search_id1);
|
|
int br_uoid = 0;
|
|
while(btree_iter1->Next()){
|
|
Tuple* tuple = routes_rel->GetTuple(btree_iter1->GetId(), false);
|
|
Bus_Route* br = (Bus_Route*)tuple->GetAttribute(BusNetwork::BN_BR);
|
|
if(br->GetUp() == bs->GetUp()){
|
|
br_uoid =
|
|
((CcInt*)tuple->GetAttribute(BusNetwork::BN_BR_OID))->GetIntval();
|
|
tuple->DeleteIfAllowed();
|
|
break;
|
|
}
|
|
tuple->DeleteIfAllowed();
|
|
}
|
|
delete btree_iter1;
|
|
search_id1->DeleteIfAllowed();
|
|
assert(br_uoid > 0);
|
|
|
|
// cout<<"br_uoid "<<br_uoid<<endl;
|
|
// cout<<"time "<<t<<endl;
|
|
///////////////////////////////////////////////////////////////
|
|
///////////////get moving buses moving on the route///////////
|
|
///////////////////////////////////////////////////////////////
|
|
int bus_oid = 0;
|
|
CcInt* search_id2 = new CcInt(true, br_uoid);
|
|
BTreeIterator* btree_iter2 = btree_trip_br_id->ExactMatch(search_id2);
|
|
bool found = false;
|
|
const double delta_dist = 0.01;
|
|
vector<Id_Time> res_list;
|
|
|
|
while(btree_iter2->Next() && found == false){
|
|
Tuple* tuple = bustrips_rel->GetTuple(btree_iter2->GetId(), false);
|
|
int brid =
|
|
((CcInt*)tuple->GetAttribute(BN_REFBR_OID))->GetIntval();
|
|
assert(brid == br_uoid);
|
|
MPoint* mo_bus = (MPoint*)tuple->GetAttribute(BN_BUSTRIP_MP);
|
|
Periods* peri = new Periods(0);
|
|
mo_bus->DefTime(*peri);
|
|
// cout<<"periods "<<*peri<<endl;
|
|
if(peri->Contains(t)){
|
|
// cout<<"periods "<<*peri<<endl;
|
|
for(int i = 0;i < mo_bus->GetNoComponents();i++){
|
|
UPoint unit;
|
|
mo_bus->Get(i, unit);
|
|
Point p0 = unit.p0;
|
|
Point p1 = unit.p1;
|
|
|
|
if(bs_loc->Distance(p0) < delta_dist &&
|
|
unit.timeInterval.Contains(t)){
|
|
mp = *mo_bus;
|
|
bus_oid = ((CcInt*)tuple->GetAttribute(BN_BUS_OID))->GetIntval();
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
peri->DeleteIfAllowed();
|
|
tuple->DeleteIfAllowed();
|
|
}
|
|
|
|
if(bus_oid <= 0) cout<<"time "<<t<<" br_uoid "<<br_uoid<<endl;
|
|
|
|
delete btree_iter2;
|
|
search_id2->DeleteIfAllowed();
|
|
assert(bus_oid > 0);
|
|
return bus_oid;
|
|
}
|
|
|
|
/*
|
|
find the bus trip by input oid
|
|
|
|
*/
|
|
void BusNetwork::GetMOBUS(int trip_id, MPoint& mp, int& br_uid)
|
|
{
|
|
|
|
CcInt* search_id = new CcInt(true, trip_id);
|
|
BTreeIterator* btree_iter = btree_trip_oid->ExactMatch(search_id);
|
|
while(btree_iter->Next()){
|
|
Tuple* tuple = bustrips_rel->GetTuple(btree_iter->GetId(), false);
|
|
MPoint* bus_trip = (MPoint*)tuple->GetAttribute(BN_BUSTRIP_MP);
|
|
int id = ((CcInt*)tuple->GetAttribute(BN_BUS_OID))->GetIntval();
|
|
assert(id == trip_id);
|
|
br_uid = ((CcInt*)tuple->GetAttribute(BN_REFBR_OID))->GetIntval();
|
|
mp = *bus_trip;
|
|
tuple->DeleteIfAllowed();
|
|
}
|
|
delete btree_iter;
|
|
search_id->DeleteIfAllowed();
|
|
assert(br_uid > 0);
|
|
}
|
|
|
|
/*
|
|
from the input bus route unique id, find its geo data
|
|
|
|
*/
|
|
void BusNetwork::GetBusRouteGeoData(int br_uoid, SimpleLine& sl)
|
|
{
|
|
CcInt* search_id = new CcInt(true, br_uoid);
|
|
BTreeIterator* btree_iter = btree_br_uoid->ExactMatch(search_id);
|
|
while(btree_iter->Next()){
|
|
Tuple* tuple = routes_rel->GetTuple(btree_iter->GetId(), false);
|
|
Bus_Route* br = (Bus_Route*)tuple->GetAttribute(BN_BR);
|
|
br->GetGeoData(sl);
|
|
tuple->DeleteIfAllowed();
|
|
}
|
|
delete btree_iter;
|
|
search_id->DeleteIfAllowed();
|
|
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
string BN::BusStopsPaveTypeInfo =
|
|
"(rel (tuple ((Bus_stop busstop) (Pave_loc1 genloc)\
|
|
(Pave_loc2 point)(Bus_stop_loc point))))";
|
|
|
|
string BN::BusTimeTableTypeInfo =
|
|
"(rel (tuple ((stop_loc point) (bus_stop busstop) (whole_time periods) \
|
|
(schedule_interval real) (loc_id int) (bus_uoid int))))";
|
|
|
|
string BN::RTreeBusStopsPaveTypeInfo =
|
|
"(rtree (tuple ((Bus_stop busstop) (Pave_loc1 genloc)\
|
|
(Pave_loc2 point)(Bus_stop_loc point))) point FALSE)";
|
|
|
|
BN::BN(BusNetwork* n):bn(n), count(0), resulttype(NULL)
|
|
{
|
|
}
|
|
BN::~BN()
|
|
{
|
|
if(resulttype != NULL) delete resulttype;
|
|
}
|
|
|
|
void BN::GetStops()
|
|
{
|
|
Relation* rel = bn->GetBS_Rel();
|
|
if(rel == NULL || rel->GetNoTuples() == 0) return;
|
|
for(int i = 1; i <= rel->GetNoTuples();i++){
|
|
Tuple* bs_tuple = rel->GetTuple(i, false);
|
|
Bus_Stop* bs = (Bus_Stop*)bs_tuple->GetAttribute(BusNetwork::BN_BS);
|
|
bs_list.push_back(*bs);
|
|
bs_tuple->DeleteIfAllowed();
|
|
}
|
|
}
|
|
|
|
/*
|
|
copy bus routes from busnetwork
|
|
|
|
*/
|
|
void BN::GetRoutes()
|
|
{
|
|
Relation* rel = bn->GetBR_Rel();
|
|
if(rel == NULL || rel->GetNoTuples() == 0) return;
|
|
for(int i = 1; i <= rel->GetNoTuples();i++){
|
|
Tuple* br_tuple = rel->GetTuple(i, false);
|
|
Bus_Route* br = (Bus_Route*)br_tuple->GetAttribute(BusNetwork::BN_BR);
|
|
br_list.push_back(*br);
|
|
br_tuple->DeleteIfAllowed();
|
|
}
|
|
}
|
|
|
|
|
|
bool BSCompare(const Bus_Stop& bs1, const Bus_Stop& bs2)
|
|
{
|
|
if(bs1.GetId() < bs2.GetId()) return true;
|
|
else if(bs1.GetId() == bs2.GetId()){
|
|
if(bs1.GetStopId() < bs2.GetStopId()){
|
|
return true;
|
|
}else
|
|
return false;
|
|
}else
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
map bus stops to the pavements
|
|
|
|
*/
|
|
|
|
void BN::MapBSToPavements(R_Tree<2,TupleId>* rtree, Relation* pave_rel,
|
|
int w, float para)
|
|
{
|
|
// if(type == "Berlin") w = 2*w;
|
|
// else if(type == "Houston") w = 4*w;
|
|
// else{
|
|
// cout<<"invalid value "<<type<<endl;
|
|
// assert(false);
|
|
// }
|
|
|
|
w = ((int)para)*w;
|
|
|
|
vector<Bus_Stop> stop_list;
|
|
|
|
for(int i = 1;i <= bn->GetBS_Rel()->GetNoTuples();i++){
|
|
Tuple* bs_tuple = bn->GetBS_Rel()->GetTuple(i, false);
|
|
Bus_Stop* bs = (Bus_Stop*)bs_tuple->GetAttribute(BusNetwork::BN_BS);
|
|
stop_list.push_back(*bs);
|
|
bs_tuple->DeleteIfAllowed();
|
|
}
|
|
|
|
// cout<<stop_list.size()<<endl;
|
|
|
|
sort(stop_list.begin(), stop_list.end(), BSCompare);
|
|
|
|
|
|
for(unsigned int i = 0;i < stop_list.size();){
|
|
Bus_Stop bs1 = stop_list[i];
|
|
Bus_Stop bs2 = stop_list[i + 1];
|
|
assert(bs1.GetId() == bs2.GetId() && bs1.GetStopId() == bs2.GetStopId());
|
|
i += 2;
|
|
MapToPavment(bs1, bs2, rtree, pave_rel, w);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
map a bus stop to a point in the pavement. It creates a line connecting the two
|
|
bus stops and extends the line. Then, it gets the intersection points of the
|
|
line and pavements.
|
|
|
|
*/
|
|
void BN::MapToPavment(Bus_Stop& bs1, Bus_Stop& bs2, R_Tree<2,TupleId>* rtree,
|
|
Relation* pave_rel, int w)
|
|
{
|
|
// w = 2*w;
|
|
// if(type == "Berlin") w = 2*w;
|
|
// else if(type == "Houston") w = 4*w;
|
|
// else{
|
|
// cout<<"invalid value "<<type<<endl;
|
|
// assert(false);
|
|
// }
|
|
////////////////construct a line connecting the two bus stops//////
|
|
Point p1;
|
|
bn->GetBusStopGeoData(&bs1, &p1);
|
|
|
|
Point p2;
|
|
bn->GetBusStopGeoData(&bs2, &p2);
|
|
|
|
// cout<<"bs1 "<<bs1<<" bs2 "<<bs2<<endl;
|
|
// cout<<"loc1 "<<p1<<" loc2 "<<p2<<endl;
|
|
|
|
Line* l = new Line(0);
|
|
l->StartBulkLoad();
|
|
if(AlmostEqual(p1.GetX(), p2.GetX())){
|
|
double miny = MIN(p1.GetY(), p2.GetY());
|
|
double maxy = MAX(p1.GetY(), p2.GetY());
|
|
Point lp(true, p1.GetX(), miny - w);
|
|
Point rp(true, p1.GetX(), maxy + w);
|
|
HalfSegment hs(true, lp, rp);
|
|
hs.attr.edgeno = 0;
|
|
*l += hs;
|
|
hs.SetLeftDomPoint(!hs.IsLeftDomPoint());
|
|
*l += hs;
|
|
}else if(AlmostEqual(p1.GetY(), p2.GetY())){
|
|
double minx = MIN(p1.GetX(), p2.GetX());
|
|
double maxx = MAX(p1.GetX(), p2.GetX());
|
|
Point lp(true, minx - w, p1.GetY());
|
|
Point rp(true, maxx + w, p1.GetY());
|
|
HalfSegment hs(true, lp, rp);
|
|
hs.attr.edgeno = 0;
|
|
*l += hs;
|
|
hs.SetLeftDomPoint(!hs.IsLeftDomPoint());
|
|
*l += hs;
|
|
}else{
|
|
double a = (p1.GetY() - p2.GetY())/(p1.GetX() - p2.GetX());
|
|
double b = p1.GetY() - a*p1.GetX();
|
|
double minx = MIN(p1.GetX(), p2.GetX());
|
|
double maxx = MAX(p1.GetX(), p2.GetX());
|
|
minx -= w;
|
|
maxx += w;
|
|
Point lp(true, minx, a*minx + b);
|
|
Point rp(true, maxx, a*maxx + b);
|
|
HalfSegment hs(true, lp, rp);
|
|
hs.attr.edgeno = 0;
|
|
*l += hs;
|
|
hs.SetLeftDomPoint(!hs.IsLeftDomPoint());
|
|
*l += hs;
|
|
}
|
|
|
|
l->EndBulkLoad();
|
|
////////////////////////////////////////////////////////////////////////////
|
|
////////////////get the intersection point of the line and pavements///////
|
|
////////////////////////////////////////////////////////////////////////////
|
|
// cout<<"l length: "<<l->Length()<<" dist p1 p2 "<<p1.Distance(p2)<<endl;
|
|
|
|
vector<MyPoint_Tid> it_p_list;
|
|
|
|
SmiRecordId adr = rtree->RootRecordId();
|
|
DFTraverse(rtree, pave_rel, adr, l, it_p_list);
|
|
l->DeleteIfAllowed();
|
|
|
|
// cout<<it_p_list.size()<<endl;
|
|
|
|
assert(it_p_list.size() >= 2);
|
|
Point midp(true, (p1.GetX() + p2.GetX())/2, (p1.GetY() + p2.GetY())/2);
|
|
|
|
/* for(unsigned int i = 0;i < it_p_list.size();i++){
|
|
bs_list.push_back(bs1);
|
|
Loc loc(0.0, 0.0);
|
|
GenLoc genloc(1, loc);
|
|
genloc_list.push_back(genloc);
|
|
geo_list.push_back(it_p_list[i].loc);
|
|
}*/
|
|
|
|
////////////get the two closest points ////////////////////////////
|
|
for(unsigned int i = 0;i < it_p_list.size();i++){
|
|
it_p_list[i].dist = it_p_list[i].loc.Distance(midp);
|
|
|
|
}
|
|
|
|
vector<MyPoint_Tid> it_p_list1;
|
|
vector<MyPoint_Tid> it_p_list2;
|
|
|
|
if(AlmostEqual(p1.GetX(), p2.GetX())){
|
|
for(unsigned int i = 0;i < it_p_list.size();i++){
|
|
if(it_p_list[i].loc.GetY() > midp.GetY()){
|
|
it_p_list1.push_back(it_p_list[i]);
|
|
}else
|
|
it_p_list2.push_back(it_p_list[i]);
|
|
}
|
|
}else{
|
|
for(unsigned int i = 0;i < it_p_list.size();i++){
|
|
if(it_p_list[i].loc.GetX() > midp.GetX()){
|
|
it_p_list1.push_back(it_p_list[i]);
|
|
}else
|
|
it_p_list2.push_back(it_p_list[i]);
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
///////////////map each point to its corresponding bus stop///////////////
|
|
/////////////////////////////////////////////////////////////////////////
|
|
// cout<<p1<<" "<<p2<<endl;
|
|
// cout<<it_p_list1.size()<<" "<<it_p_list2.size()<<endl;
|
|
if(it_p_list1.size() == 0 || it_p_list2.size() == 0){
|
|
cout<<"road width should be enlarged"<<endl;
|
|
assert(false);
|
|
|
|
}
|
|
|
|
sort(it_p_list1.begin(), it_p_list1.end());
|
|
sort(it_p_list2.begin(), it_p_list2.end());
|
|
|
|
// it_p_list1[0].Print();
|
|
// it_p_list2[0].Print();
|
|
|
|
double d1 = it_p_list1[0].loc.Distance(p1);
|
|
double d2 = it_p_list1[0].loc.Distance(p2);
|
|
|
|
if(d1 < d2){
|
|
// it_p_list1[0] -- p1 bs1, it_p_list2[0] -- p2 bs2
|
|
Tuple* pave_tuple1 = pave_rel->GetTuple(it_p_list1[0].tid, false);
|
|
int oid1 =
|
|
((CcInt*)pave_tuple1->GetAttribute(DualGraph::OID))->GetIntval();
|
|
Region* reg1 = (Region*)pave_tuple1->GetAttribute(DualGraph::PAVEMENT);
|
|
Point q1 = it_p_list1[0].loc;
|
|
|
|
Loc loc1(q1.GetX() - reg1->BoundingBox().MinD(0),
|
|
q1.GetY() - reg1->BoundingBox().MinD(1));
|
|
|
|
GenLoc genloc1(oid1, loc1);
|
|
assert(q1.Inside(*reg1));
|
|
// if(q1.Inside(*reg1) == false){
|
|
// cout<<"oid1 "<<"q1 "<<endl;
|
|
// cout<<bs1<<" "<<bs2<<endl;
|
|
// }
|
|
|
|
pave_tuple1->DeleteIfAllowed();
|
|
bs_list.push_back(bs1);
|
|
genloc_list.push_back(genloc1);
|
|
geo_list.push_back(it_p_list1[0].loc);
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
Tuple* pave_tuple2 = pave_rel->GetTuple(it_p_list2[0].tid, false);
|
|
int oid2 =
|
|
((CcInt*)pave_tuple2->GetAttribute(DualGraph::OID))->GetIntval();
|
|
Region* reg2 = (Region*)pave_tuple2->GetAttribute(DualGraph::PAVEMENT);
|
|
Point q2 = it_p_list2[0].loc;
|
|
|
|
Loc loc2(q2.GetX() - reg2->BoundingBox().MinD(0),
|
|
q2.GetY() - reg2->BoundingBox().MinD(1));
|
|
|
|
GenLoc genloc2(oid2, loc2);
|
|
assert(q2.Inside(*reg2));
|
|
// if(q2.Inside(*reg2) == false){
|
|
// cout<<"oid2 "<<oid2<<" q2 "<<q2<<endl;
|
|
// cout<<bs1<<" "<<bs2<<endl;
|
|
// }
|
|
|
|
pave_tuple2->DeleteIfAllowed();
|
|
|
|
bs_list.push_back(bs2);
|
|
genloc_list.push_back(genloc2);
|
|
geo_list.push_back(it_p_list2[0].loc);
|
|
|
|
// cout<<"tid1 "<<it_p_list1[0].tid<<" tid2 "<<it_p_list2[0].tid<<endl;
|
|
|
|
}else{
|
|
//it_p_list1[0] -- p2 bs2, it_p_list2[0] -- p1 bs1
|
|
|
|
Tuple* pave_tuple1 = pave_rel->GetTuple(it_p_list1[0].tid, false);
|
|
int oid1 =
|
|
((CcInt*)pave_tuple1->GetAttribute(DualGraph::OID))->GetIntval();
|
|
Region* reg1 = (Region*)pave_tuple1->GetAttribute(DualGraph::PAVEMENT);
|
|
Point q1 = it_p_list1[0].loc;
|
|
|
|
|
|
Loc loc1(q1.GetX() - reg1->BoundingBox().MinD(0),
|
|
q1.GetY() - reg1->BoundingBox().MinD(1));
|
|
|
|
|
|
GenLoc genloc1(oid1, loc1);
|
|
assert(q1.Inside(*reg1));
|
|
// if(q1.Inside(*reg1) == false){
|
|
// cout<<"oid1 "<<oid1<<" q1"<<q1<<endl;
|
|
// cout<<bs1<<" "<<bs2<<endl;
|
|
// }
|
|
|
|
pave_tuple1->DeleteIfAllowed();
|
|
bs_list.push_back(bs2);
|
|
genloc_list.push_back(genloc1);
|
|
geo_list.push_back(it_p_list1[0].loc);
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
Tuple* pave_tuple2 = pave_rel->GetTuple(it_p_list2[0].tid, false);
|
|
int oid2 =
|
|
((CcInt*)pave_tuple2->GetAttribute(DualGraph::OID))->GetIntval();
|
|
Region* reg2 = (Region*)pave_tuple2->GetAttribute(DualGraph::PAVEMENT);
|
|
Point q2 = it_p_list2[0].loc;
|
|
|
|
Loc loc2(q2.GetX() - reg2->BoundingBox().MinD(0),
|
|
q2.GetY() - reg2->BoundingBox().MinD(1));
|
|
|
|
GenLoc genloc2(oid2, loc2);
|
|
assert(q2.Inside(*reg2));
|
|
// if(q2.Inside(*reg2) == false){
|
|
// cout<<"oid2 "<<oid2<<" q2 "<<q2<<endl;
|
|
// cout<<bs1<<" "<<bs2<<endl;
|
|
// }
|
|
|
|
pave_tuple2->DeleteIfAllowed();
|
|
|
|
bs_list.push_back(bs1);
|
|
genloc_list.push_back(genloc2);
|
|
geo_list.push_back(it_p_list2[0].loc);
|
|
|
|
// cout<<"tid1 "<<it_p_list1[0].tid<<" tid2 "<<it_p_list2[0].tid<<endl;
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
Using depth first method to travese the R-tree to find all pavements intersect
|
|
the line and get the intersection points
|
|
|
|
*/
|
|
void BN::DFTraverse(R_Tree<2,TupleId>* rtree, Relation* rel,
|
|
SmiRecordId adr, Line* l,
|
|
vector<MyPoint_Tid>& it_p_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 = rel->GetTuple(e.info,false);
|
|
Region* candi_reg =
|
|
(Region*)dg_tuple2->GetAttribute(DualGraph::PAVEMENT);
|
|
// if(l->Intersects(candi_reg->BoundingBox())){
|
|
if(l->Intersects(Region(candi_reg->BoundingBox()))){
|
|
/* Line* l1 = new Line(0);
|
|
candi_reg->Boundary(l1);
|
|
Points* ps = new Points(0);
|
|
l->Crossings(*l1, *ps);
|
|
for(int i = 0;i < ps->Size();i++){
|
|
Point p;
|
|
ps->Get(i, p);
|
|
MyPoint_Tid mpt(p, 0.0, e.info);
|
|
it_p_list.push_back(mpt);
|
|
// assert(p.Inside(*candi_reg));
|
|
}
|
|
delete ps;
|
|
delete l1;*/
|
|
|
|
for(int i1 = 0;i1 < l->Size();i1++){
|
|
HalfSegment hs1;
|
|
l->Get(i1, hs1);
|
|
if(hs1.IsLeftDomPoint() == false) continue;
|
|
for(int i2 = 0;i2 < candi_reg->Size();i2++){
|
|
HalfSegment hs2;
|
|
candi_reg->Get(i2, hs2);
|
|
if(hs2.IsLeftDomPoint() == false) continue;
|
|
Point p;
|
|
if(hs1.Intersection(hs2, p)){
|
|
if(p.Inside(*candi_reg)){
|
|
MyPoint_Tid mpt(p, 0.0, e.info);
|
|
it_p_list.push_back(mpt);
|
|
}
|
|
// MyPoint_Tid mpt(p, 0.0, e.info);
|
|
// it_p_list.push_back(mpt);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
dg_tuple2->DeleteIfAllowed();
|
|
}else{
|
|
R_TreeInternalEntry<2> e =
|
|
(R_TreeInternalEntry<2>&)(*node)[j];
|
|
// if(l->Intersects(e.box)){
|
|
if(l->Intersects(Region(e.box))){
|
|
DFTraverse(rtree, rel, e.pointer, l, it_p_list);
|
|
}
|
|
}
|
|
}
|
|
delete node;
|
|
}
|
|
|
|
|
|
/*
|
|
for each bus stop, we find its neighbor bus stops. the distance between them
|
|
in the pavement area is smaller than a threshold value. e,g., 100m
|
|
|
|
*/
|
|
void BN::BsNeighbors1(DualGraph* dg, VisualGraph* vg, Relation* rel1,
|
|
Relation* rel2, R_Tree<2,TupleId>* rtree)
|
|
{
|
|
// const double neighbor_dist = 200.0;
|
|
const double neighbor_dist = 100.0;
|
|
|
|
SmiRecordId adr = rtree->RootRecordId();
|
|
/////for each bus stop, find the neighbor candidates where the distance///
|
|
/////between them is smaller than D in Euclidean space/////////////////
|
|
////////////this is done by traversing the RTree//////////////////////
|
|
for(int i = 1;i <= rel2->GetNoTuples();i++){
|
|
Tuple* bs_pave_tuple = rel2->GetTuple(i, false);
|
|
Point* loc = (Point*)bs_pave_tuple->GetAttribute(BN_PAVE_LOC2);
|
|
Bus_Stop* bs1 = (Bus_Stop*)bs_pave_tuple->GetAttribute(BN_BUSSTOP);
|
|
vector<int> neighbor_list;
|
|
////////////Euclidean distance as a bound///////////////////////
|
|
DFTraverse2(rtree, rel2, adr , loc, neighbor_list, neighbor_dist);
|
|
// cout<<"bs "<<*bs<<" "<<neighbor_list.size()<<endl;
|
|
|
|
int neighbor_no = 0;
|
|
for(unsigned int j = 0;j < neighbor_list.size();j++){
|
|
if(neighbor_list[j] != i){
|
|
|
|
Line* path = new Line(0);
|
|
if(FindNeighbor(i, neighbor_list[j], dg, vg, rel1,
|
|
rel2, neighbor_dist, path)){
|
|
// cout<<"a neighbor "<<endl;
|
|
// cout<<"tid1 "<<i<<" tid2 "<<neighbor_list[j]<<endl;
|
|
|
|
|
|
Tuple* tuple2 = rel2->GetTuple(neighbor_list[j], false);
|
|
Bus_Stop* bs2 = (Bus_Stop*)tuple2->GetAttribute(BN_BUSSTOP);
|
|
|
|
if(bs1->GetId() != bs2->GetId()){ //different bus routes
|
|
bs_list1.push_back(*bs1);
|
|
bs_list2.push_back(*bs2);
|
|
SimpleLine* sl = new SimpleLine(0);
|
|
sl->fromLine(*path);
|
|
path_sl_list.push_back(*sl);
|
|
|
|
|
|
// cout<<path->Length()<<endl;
|
|
//////////////////////////////////////////////////////////////
|
|
/////connection between bus stops and their mapping points ///
|
|
///////////////in the pavement///////////////////////////////
|
|
//////this is a special connection, I defint it does not /////
|
|
/////////belong to pavement area///////////////////////////////
|
|
///////////////////////////////////////////////////////////////
|
|
Point* bus_loc1 =
|
|
(Point*)bs_pave_tuple->GetAttribute(BN_BUSLOC);
|
|
Point* bus_loc2 = (Point*)tuple2->GetAttribute(BN_BUSLOC);
|
|
Point sl_sp;
|
|
assert(sl->AtPosition(0.0, true, sl_sp));
|
|
double d1 = sl_sp.Distance(*bus_loc1);
|
|
double d2 = sl_sp.Distance(*bus_loc2);
|
|
// cout<<"d1 "<<d1<<" d2 "<<d2<<endl;
|
|
|
|
|
|
if(d1 < d2){
|
|
Point sl_ep;
|
|
assert(sl->AtPosition(sl->Length(), true, sl_ep));
|
|
HalfSegment hs1(true, *bus_loc1, sl_sp);
|
|
HalfSegment hs2(true, *bus_loc2, sl_ep);
|
|
|
|
|
|
SimpleLine* sub_sl1 = new SimpleLine(0);
|
|
sub_sl1->StartBulkLoad();
|
|
hs1.attr.edgeno = 0;
|
|
*sub_sl1 += hs1;
|
|
hs1.SetLeftDomPoint(!hs1.IsLeftDomPoint());
|
|
*sub_sl1 += hs1;
|
|
sub_sl1->EndBulkLoad();
|
|
sub_path1.push_back(*sub_sl1);
|
|
|
|
SimpleLine* sub_sl2 = new SimpleLine(0);
|
|
sub_sl2->StartBulkLoad();
|
|
hs2.attr.edgeno = 0;
|
|
*sub_sl2 += hs2;
|
|
hs2.SetLeftDomPoint(!hs2.IsLeftDomPoint());
|
|
*sub_sl2 += hs2;
|
|
sub_sl2->EndBulkLoad();
|
|
sub_path2.push_back(*sub_sl2);
|
|
|
|
///////////////////construct the whole path////////////////////
|
|
SimpleLine* sl2 = new SimpleLine(0);
|
|
sl2->StartBulkLoad();
|
|
int edgeno = 0;
|
|
HalfSegment hs_1(true, *bus_loc1, sl_sp);
|
|
HalfSegment hs_2(true, *bus_loc2, sl_ep);
|
|
|
|
hs_1.attr.edgeno = edgeno++;
|
|
*sl2 += hs_1;
|
|
hs1.SetLeftDomPoint(!hs1.IsLeftDomPoint());
|
|
*sl2 += hs_1;
|
|
hs_2.attr.edgeno = edgeno++;
|
|
*sl2 += hs_2;
|
|
hs2.SetLeftDomPoint(!hs2.IsLeftDomPoint());
|
|
*sl2 += hs_2;
|
|
for(int k = 0;k < sl->Size();k++){
|
|
HalfSegment hs;
|
|
sl->Get(k, hs);
|
|
if(!hs.IsLeftDomPoint()) continue;
|
|
HalfSegment new_hs(true, hs.GetLeftPoint(),
|
|
hs.GetRightPoint());
|
|
new_hs.attr.edgeno = edgeno++;
|
|
*sl2 += new_hs;
|
|
new_hs.SetLeftDomPoint(!new_hs.IsLeftDomPoint());
|
|
*sl2 += new_hs;
|
|
}
|
|
sl2->EndBulkLoad();
|
|
path2_sl_list.push_back(*sl2);
|
|
sl2->DeleteIfAllowed();
|
|
//////////////////////////////////////////////////////////////
|
|
|
|
sub_sl1->DeleteIfAllowed();
|
|
sub_sl2->DeleteIfAllowed();
|
|
|
|
}else{
|
|
Point sl_ep;
|
|
assert(sl->AtPosition(sl->Length(), true, sl_ep));
|
|
HalfSegment hs1(true, *bus_loc2, sl_sp);
|
|
HalfSegment hs2(true, *bus_loc1, sl_ep);
|
|
|
|
SimpleLine* sub_sl1 = new SimpleLine(0);
|
|
sub_sl1->StartBulkLoad();
|
|
hs1.attr.edgeno = 0;
|
|
*sub_sl1 += hs1;
|
|
hs1.SetLeftDomPoint(!hs1.IsLeftDomPoint());
|
|
*sub_sl1 += hs1;
|
|
sub_sl1->EndBulkLoad();
|
|
sub_path1.push_back(*sub_sl1);
|
|
|
|
|
|
SimpleLine* sub_sl2 = new SimpleLine(0);
|
|
sub_sl2->StartBulkLoad();
|
|
hs2.attr.edgeno = 0;
|
|
*sub_sl2 += hs2;
|
|
hs2.SetLeftDomPoint(!hs2.IsLeftDomPoint());
|
|
*sub_sl2 += hs2;
|
|
sub_sl2->EndBulkLoad();
|
|
sub_path2.push_back(*sub_sl2);
|
|
|
|
///////////////////construct the whole path////////////////////
|
|
SimpleLine* sl2 = new SimpleLine(0);
|
|
sl2->StartBulkLoad();
|
|
int edgeno = 0;
|
|
HalfSegment hs_1(true, *bus_loc2, sl_sp);
|
|
HalfSegment hs_2(true, *bus_loc1, sl_ep);
|
|
|
|
hs_1.attr.edgeno = edgeno++;
|
|
*sl2 += hs_1;
|
|
hs1.SetLeftDomPoint(!hs1.IsLeftDomPoint());
|
|
*sl2 += hs_1;
|
|
hs_2.attr.edgeno = edgeno++;
|
|
*sl2 += hs_2;
|
|
hs2.SetLeftDomPoint(!hs2.IsLeftDomPoint());
|
|
*sl2 += hs_2;
|
|
for(int k = 0;k < sl->Size();k++){
|
|
HalfSegment hs;
|
|
sl->Get(k, hs);
|
|
if(!hs.IsLeftDomPoint()) continue;
|
|
HalfSegment new_hs(true, hs.GetLeftPoint(),
|
|
hs.GetRightPoint());
|
|
new_hs.attr.edgeno = edgeno++;
|
|
*sl2 += new_hs;
|
|
new_hs.SetLeftDomPoint(!new_hs.IsLeftDomPoint());
|
|
*sl2 += new_hs;
|
|
}
|
|
sl2->EndBulkLoad();
|
|
path2_sl_list.push_back(*sl2);
|
|
sl2->DeleteIfAllowed();
|
|
//////////////////////////////////////////////////////////////
|
|
|
|
sub_sl1->DeleteIfAllowed();
|
|
sub_sl2->DeleteIfAllowed();
|
|
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////
|
|
|
|
bs_uoid_list.push_back(bs1->GetUOid());
|
|
sl->DeleteIfAllowed();
|
|
}
|
|
neighbor_no++;
|
|
tuple2->DeleteIfAllowed();
|
|
}
|
|
|
|
path->DeleteIfAllowed();
|
|
|
|
}
|
|
}
|
|
|
|
bs_pave_tuple->DeleteIfAllowed();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
traverse R-tree to find neighbor points (bus stops), but does not include the
|
|
bus stops that have the same spatial location in space. because this kinds of
|
|
connection will be discovered later by another edge in bus network graph.
|
|
|
|
*/
|
|
void BN::DFTraverse2(R_Tree<2,TupleId>* rtree, Relation* rel,
|
|
SmiRecordId adr, Point* loc, vector<int>& neighbor_list,
|
|
double dist)
|
|
{
|
|
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_tuple2 = rel->GetTuple(e.info,false);
|
|
Point* bus_loc = (Point*)dg_tuple2->GetAttribute(BN_PAVE_LOC2);
|
|
double d = loc->Distance(*bus_loc);
|
|
if( d < dist && d > delta_dist){
|
|
neighbor_list.push_back(e.info);
|
|
}
|
|
dg_tuple2->DeleteIfAllowed();
|
|
}else{
|
|
R_TreeInternalEntry<2> e =
|
|
(R_TreeInternalEntry<2>&)(*node)[j];
|
|
if(loc->Distance(e.box) < dist){
|
|
DFTraverse2(rtree, rel, e.pointer, loc, neighbor_list, dist);
|
|
}
|
|
}
|
|
}
|
|
delete node;
|
|
|
|
|
|
}
|
|
|
|
/*
|
|
calculate the obstructed distance between the two bus stops.
|
|
rel1: triangle relation
|
|
rel2: bus stops and pavements location relation
|
|
use the same procedure in PaveGraph.cpp WalkSP ShortestPath
|
|
(calculate the shortest path between two locations on the pavements)
|
|
|
|
*/
|
|
bool BN::FindNeighbor(int tid1, int tid2, DualGraph* dg, VisualGraph* vg,
|
|
Relation* rel1, Relation* rel2,
|
|
double dist, Line* res)
|
|
{
|
|
// cout<<"tid1 "<<tid1<<" tid2 "<<tid2<<endl;
|
|
|
|
Tuple* tuple1 = rel2->GetTuple(tid1, false);
|
|
GenLoc* genloc1 = (GenLoc*)tuple1->GetAttribute(BN_PAVE_LOC1);
|
|
Point* loc_1 = (Point*)tuple1->GetAttribute(BN_PAVE_LOC2);
|
|
|
|
Tuple* tuple2 = rel2->GetTuple(tid2, false);
|
|
GenLoc* genloc2 = (GenLoc*)tuple2->GetAttribute(BN_PAVE_LOC1);
|
|
Point* loc_2 = (Point*)tuple2->GetAttribute(BN_PAVE_LOC2);
|
|
|
|
Point loc1 = *loc_1;
|
|
Point loc2 = *loc_2;
|
|
|
|
// GenLoc gloc1 = *genloc1;
|
|
// GenLoc gloc2 = *genloc2;
|
|
GenLoc gloc1(genloc1->GetOid(), genloc1->GetLoc());
|
|
GenLoc gloc2(genloc2->GetOid(), genloc2->GetLoc());
|
|
|
|
tuple1->DeleteIfAllowed();
|
|
tuple2->DeleteIfAllowed();
|
|
|
|
// cout<<gloc1<<" "<<gloc2<<endl;
|
|
///////////////////////////////////////////////////////////////////////////
|
|
/////////////////calculate the distance between the two bus stops//////////
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
int no_node_graph = dg->No_Of_Node();
|
|
int oid1 = gloc1.GetOid();
|
|
int oid2 = gloc2.GetOid();
|
|
oid1 -= dg->min_tri_oid_1;
|
|
oid2 -= dg->min_tri_oid_1;
|
|
|
|
if(oid1 < 1 || oid1 > no_node_graph){
|
|
cout<<"loc1 does not exist"<<endl;
|
|
return false;
|
|
}
|
|
if(oid2 < 1 || oid2 > no_node_graph){
|
|
cout<<"loc2 does not exist"<<endl;
|
|
return false;
|
|
}
|
|
|
|
/////////this kind of connection will be found by another edge in the ///
|
|
///////////////bus network graph////////////////////////////////////////
|
|
if(AlmostEqual(loc1,loc2)){
|
|
// return true;
|
|
return false;
|
|
}
|
|
|
|
Tuple* tuple_1 = dg->GetNodeRel()->GetTuple(oid1, false);
|
|
Region* reg1 = (Region*)tuple_1->GetAttribute(DualGraph::PAVEMENT);
|
|
|
|
if(loc1.Inside(*reg1) == false){
|
|
tuple_1->DeleteIfAllowed();
|
|
cout<<"point1 is not inside the polygon"<<endl;
|
|
return false;
|
|
}
|
|
Tuple* tuple_2 = dg->GetNodeRel()->GetTuple(oid2, false);
|
|
Region* reg2 = (Region*)tuple_2->GetAttribute(DualGraph::PAVEMENT);
|
|
|
|
if(loc2.Inside(*reg2) == false){
|
|
tuple_1->DeleteIfAllowed();
|
|
tuple_2->DeleteIfAllowed();
|
|
cout<<"point2 is not inside the polygon"<<endl;
|
|
return false;
|
|
}
|
|
tuple_1->DeleteIfAllowed();
|
|
tuple_2->DeleteIfAllowed();
|
|
////////////////////////////////////////////////////////////////
|
|
////////////////find all visibility nodes to start node/////////
|
|
///////connect them to the visibility graph/////////////////////
|
|
|
|
priority_queue<WPath_elem> path_queue;
|
|
vector<WPath_elem> expand_path;
|
|
|
|
VGraph* vg1 = new VGraph(dg, NULL, rel1, 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;
|
|
|
|
for(unsigned int i = 0;i < vg1->oids1.size();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, rel1, 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
|
|
|
|
Points* neighbor_end = new Points(0);
|
|
neighbor_end->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<bool> 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(top.real_w > dist){ //already larger than the threshold distance
|
|
neighbor_end->DeleteIfAllowed();
|
|
delete vg2;
|
|
return false;
|
|
}
|
|
|
|
if(AlmostEqual(top.loc, loc2)){
|
|
find = true;
|
|
dest = top;
|
|
break;
|
|
}
|
|
//do not consider the start point
|
|
//if it does not equal to the triangle vertex
|
|
//its adjacent nodes have been found already and put into the queue
|
|
if(top.tri_index > 0 && mark_flag[top.tri_index - 1] == false){
|
|
vector<int> 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;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
///////////////////////////////////////////////////////////////
|
|
}
|
|
|
|
neighbor_end->DeleteIfAllowed();
|
|
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();
|
|
}
|
|
if(len < dist) return true;
|
|
else return false;
|
|
}
|
|
|
|
/*
|
|
for each bus stop, find the bus stops that have the same spatial location but
|
|
belong to different bus routes. these are the places that people can do
|
|
transfer. we also return the unique id of the first bus stop
|
|
|
|
*/
|
|
void BN::BsNeighbors2()
|
|
{
|
|
|
|
R_Tree<2,TupleId>* rtree = bn->GetBS_RTree();
|
|
|
|
SmiRecordId adr = rtree->RootRecordId();
|
|
|
|
Relation* bs_rel = bn->GetBS_Rel();
|
|
for(int i = 1;i <= bs_rel->GetNoTuples();i++){
|
|
Tuple* bs_tuple = bs_rel->GetTuple(i, false);
|
|
Bus_Stop* bs = (Bus_Stop*)bs_tuple->GetAttribute(BusNetwork::BN_BS);
|
|
Point* bs_loc = (Point*)bs_tuple->GetAttribute(BusNetwork::BS_GEO);
|
|
vector<int> neighbor_tid;
|
|
DFTraverse3(rtree, bs_rel, adr, bs_loc,neighbor_tid);
|
|
|
|
// cout<<"bs "<<*bs<<" neighbor size "<<neighbor_tid.size()<<endl;
|
|
for(unsigned int j = 0;j < neighbor_tid.size();j++){
|
|
if(i != neighbor_tid[j]){
|
|
|
|
Tuple* bs_tuple2 = bs_rel->GetTuple(neighbor_tid[j], false);
|
|
Bus_Stop* bs2 = (Bus_Stop*)bs_tuple2->GetAttribute(BusNetwork::BN_BS);
|
|
// cout<<"neighbor "<<*bs2<<endl;
|
|
|
|
bs_list1.push_back(*bs);
|
|
bs_list2.push_back(*bs2);
|
|
bs_uoid_list.push_back(bs->GetUOid());
|
|
bs_tuple2->DeleteIfAllowed();
|
|
}
|
|
|
|
}
|
|
|
|
bs_tuple->DeleteIfAllowed();
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
find bus stops that map to the same spatial point
|
|
|
|
*/
|
|
void BN::DFTraverse3(R_Tree<2,TupleId>* rtree, Relation* rel,
|
|
SmiRecordId adr, Point* loc, vector<int>& neighbor_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_tuple2 = rel->GetTuple(e.info,false);
|
|
Point* bus_loc =
|
|
(Point*)dg_tuple2->GetAttribute(BusNetwork::BS_GEO);
|
|
double d = loc->Distance(*bus_loc);
|
|
if(d < delta_dist){
|
|
neighbor_list.push_back(e.info);
|
|
}
|
|
dg_tuple2->DeleteIfAllowed();
|
|
}else{
|
|
R_TreeInternalEntry<2> e =
|
|
(R_TreeInternalEntry<2>&)(*node)[j];
|
|
if(loc->Distance(e.box) < delta_dist){
|
|
DFTraverse3(rtree, rel, e.pointer, loc, neighbor_list);
|
|
}
|
|
}
|
|
}
|
|
delete node;
|
|
}
|
|
|
|
/*
|
|
find all adjacent nodes of the given node id
|
|
|
|
*/
|
|
void BN::GetAdjNodeBG1(BusGraph* bg, int nodeid)
|
|
{
|
|
if(bg->node_rel == NULL){
|
|
cout<<"no bus graph node rel"<<endl;
|
|
return;
|
|
}
|
|
if(nodeid < 1 || nodeid > bg->node_rel->GetNoTuples()){
|
|
cout<<"invalid node id "<<endl;
|
|
return;
|
|
}
|
|
|
|
cout<<"total "<<bg->node_rel->GetNoTuples()<<" nodes "<<endl;
|
|
cout<<"total "<<bg->edge_rel1->GetNoTuples() +
|
|
bg->edge_rel2->GetNoTuples() +
|
|
bg->edge_rel3->GetNoTuples() <<" edges "<<endl;
|
|
|
|
|
|
Tuple* bs_tuple = bg->node_rel->GetTuple(nodeid, false);
|
|
Bus_Stop* bs1 = (Bus_Stop*)bs_tuple->GetAttribute(BusGraph::BG_NODE);
|
|
// cout<<*bs1<<endl;
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
///////////////the first kind of connection by pavements/////////////////
|
|
/////////////////////////////////////////////////////////////////////////
|
|
vector<int> tid_list1;
|
|
bg->FindAdj1(nodeid, tid_list1);
|
|
for(unsigned int i = 0;i < tid_list1.size();i++){
|
|
Tuple* edge_tuple = bg->edge_rel1->GetTuple(tid_list1[i], false);
|
|
Bus_Stop* bs2 = (Bus_Stop*)edge_tuple->GetAttribute(BusGraph::BG_E_BS2);
|
|
SimpleLine* path =
|
|
(SimpleLine*)edge_tuple->GetAttribute(BusGraph::BG_PATH1);
|
|
bs_list1.push_back(*bs1);
|
|
bs_list2.push_back(*bs2);
|
|
path_sl_list.push_back(*path);
|
|
|
|
edge_tuple->DeleteIfAllowed();
|
|
type_list.push_back(1);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//////the second kind of connection (no path; the same spatial location)////
|
|
////////////////////////////////////////////////////////////////////////////
|
|
vector<int> tid_list2;
|
|
bg->FindAdj2(nodeid, tid_list2);
|
|
for(unsigned int i = 0;i < tid_list2.size();i++){
|
|
Tuple* edge_tuple = bg->edge_rel2->GetTuple(tid_list2[i], false);
|
|
Bus_Stop* bs2 = (Bus_Stop*)edge_tuple->GetAttribute(BusGraph::BG_E2_BS2);
|
|
SimpleLine* path = new SimpleLine(0);
|
|
path->StartBulkLoad();
|
|
path->EndBulkLoad();
|
|
bs_list1.push_back(*bs1);
|
|
bs_list2.push_back(*bs2);
|
|
path_sl_list.push_back(*path);
|
|
path->DeleteIfAllowed();
|
|
edge_tuple->DeleteIfAllowed();
|
|
type_list.push_back(2);
|
|
}
|
|
////////////////////////////////////////////////////////////////////
|
|
//////the third kind of connection (connected by moving buses)//////
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
vector<int> tid_list3;
|
|
bg->FindAdj3(nodeid, tid_list3);
|
|
// cout<<"connection 3 size: "<<tid_list3.size()<<endl;
|
|
for(unsigned int i = 0;i < tid_list3.size();i++){
|
|
Tuple* edge_tuple = bg->edge_rel3->GetTuple(tid_list3[i], false);
|
|
Bus_Stop* bs2 = (Bus_Stop*)edge_tuple->GetAttribute(BusGraph::BG_E3_BS2);
|
|
SimpleLine* path =
|
|
(SimpleLine*)edge_tuple->GetAttribute(BusGraph::BG_PATH3);
|
|
bs_list1.push_back(*bs1);
|
|
bs_list2.push_back(*bs2);
|
|
path_sl_list.push_back(*path);
|
|
|
|
edge_tuple->DeleteIfAllowed();
|
|
type_list.push_back(3);
|
|
}
|
|
|
|
bs_tuple->DeleteIfAllowed();
|
|
|
|
// /* test adjacency list1*/
|
|
// for(int i = 1;i <= bg->node_rel->GetNoTuples();i++){
|
|
// Tuple* node_tuple = bg->node_rel->GetTuple(i, false);
|
|
// cout<<*node_tuple<<endl;
|
|
// vector<int> tid_list;
|
|
// bg->FindAdj1(i, tid_list);
|
|
// for(unsigned int j = 0;j < tid_list.size();j++){
|
|
// Tuple* edge_tuple = bg->edge_rel1->GetTuple(tid_list[j], false);
|
|
// Bus_Stop* bs2 = (Bus_Stop*)edge_tuple->GetAttribute(BusGraph::BG_E_BS2);
|
|
// SimpleLine* path =
|
|
// (SimpleLine*)edge_tuple->GetAttribute(BusGraph::BG_PATH1);
|
|
// cout<<i<<" "<<path->Length()<<endl;
|
|
//
|
|
// edge_tuple->DeleteIfAllowed();
|
|
// }
|
|
// node_tuple->DeleteIfAllowed();
|
|
// }
|
|
|
|
/*test btree built on node relation*/
|
|
|
|
// for(int i = 1;i <= bg->node_rel->GetNoTuples();i++){
|
|
// Tuple* node_tuple = bg->node_rel->GetTuple(i, false);
|
|
// Bus_Stop* bs = (Bus_Stop*)node_tuple->GetAttribute(BusGraph::BG_NODE);
|
|
//
|
|
// CcInt* search_id = new CcInt(true, bs->GetUOid());
|
|
// BTreeIterator* btree_iter = bg->btree_node->ExactMatch(search_id);
|
|
//
|
|
// while(btree_iter->Next()){
|
|
// cout<<"tid1 "<<node_tuple->GetTupleId()
|
|
// <<"tid2 "<<btree_iter->GetId()<<endl;
|
|
// }
|
|
// delete btree_iter;
|
|
// delete search_id;
|
|
//
|
|
// node_tuple->DeleteIfAllowed();
|
|
// }
|
|
|
|
|
|
// /* test adjacency list2*/
|
|
// for(int i = 1;i <= bg->node_rel->GetNoTuples();i++){
|
|
// Tuple* node_tuple = bg->node_rel->GetTuple(i, false);
|
|
//
|
|
// vector<int> tid_list;
|
|
// bg->FindAdj2(i, tid_list);
|
|
// for(unsigned int j = 0;j < tid_list.size();j++){
|
|
// Tuple* edge_tuple = bg->edge_rel2->GetTuple(tid_list[j], false);
|
|
// Bus_Stop* bs2 = (Bus_Stop*)edge_tuple->GetAttribute(BusGraph::BG_E_BS2);
|
|
// edge_tuple->DeleteIfAllowed();
|
|
// }
|
|
//
|
|
// if(tid_list.size() > 0){
|
|
// cout<<*node_tuple<<" neighbor size "<<tid_list.size()<<endl;
|
|
// }
|
|
// node_tuple->DeleteIfAllowed();
|
|
// }
|
|
|
|
// /* test adjacency list3*/
|
|
// for(int i = 1;i <= bg->node_rel->GetNoTuples();i++){
|
|
// Tuple* node_tuple = bg->node_rel->GetTuple(i, false);
|
|
//
|
|
// vector<int> tid_list;
|
|
// bg->FindAdj3(i, tid_list);
|
|
// for(unsigned int j = 0;j < tid_list.size();j++){
|
|
// Tuple* edge_tuple = bg->edge_rel3->GetTuple(tid_list[j], false);
|
|
// edge_tuple->DeleteIfAllowed();
|
|
// }
|
|
//
|
|
// if(tid_list.size() > 0){
|
|
// cout<<" neighbor size "<<tid_list.size()<<endl;
|
|
// }
|
|
// node_tuple->DeleteIfAllowed();
|
|
// }
|
|
|
|
}
|
|
|
|
/*
|
|
get the neighbor nodes of a given bus stop
|
|
notes: the result may have the same value (type 3). this is becuase some bus
|
|
routes have night schedule (day schedule (workday and weekend))
|
|
(night schedule (0:00-5:00 20:00-24:00))
|
|
there can be 4 tuples having the same value
|
|
|
|
*/
|
|
void BN::GetAdjNodeBG2(BusGraph* bg, Bus_Stop* bs)
|
|
{
|
|
int bs_tid = -1;
|
|
CcInt* search_id = new CcInt(true, bs->GetUOid());
|
|
BTreeIterator* btree_iter = bg->btree_node->ExactMatch(search_id);
|
|
|
|
while(btree_iter->Next()){
|
|
bs_tid = btree_iter->GetId();
|
|
}
|
|
delete btree_iter;
|
|
search_id->DeleteIfAllowed();
|
|
if(!(1 <= bs_tid && bs_tid <= bg->node_rel->GetNoTuples())){
|
|
cout<<"invalid bus stop "<<*bs<<endl;
|
|
return;
|
|
}
|
|
|
|
GetAdjNodeBG1(bg, bs_tid);
|
|
}
|
|
|
|
/*
|
|
find connections of two adjacent bus stops in one route.
|
|
they are connected by the bus
|
|
|
|
*/
|
|
void BN::BsNeighbors3(Relation* table_rel, Relation* mo_rel, BTree* btree_mo)
|
|
{
|
|
// int count = 0;
|
|
for(int i = 1;i <= table_rel->GetNoTuples();i++){
|
|
Tuple* bs_table_tuple = table_rel->GetTuple(i, false);
|
|
int bs_uoid =
|
|
((CcInt*)bs_table_tuple->GetAttribute(BN_T_BUS_UOID))->GetIntval();
|
|
vector<int> tid_list;
|
|
tid_list.push_back(i);
|
|
int j = i + 1;
|
|
while(j <= table_rel->GetNoTuples()){
|
|
Tuple* tuple = table_rel->GetTuple(j, false);
|
|
int bs_uoid2 = ((CcInt*)tuple->GetAttribute(BN_T_BUS_UOID))->GetIntval();
|
|
tuple->DeleteIfAllowed();
|
|
if(bs_uoid2 == bs_uoid){
|
|
tid_list.push_back(j);
|
|
j++;
|
|
}else{
|
|
i = j - 1;
|
|
break;
|
|
}
|
|
}
|
|
// cout<<tid_list.size()<<endl;
|
|
////////////////////////////////////////////
|
|
// count += tid_list.size();
|
|
ConnectionOneRoute(table_rel, tid_list, mo_rel, btree_mo);
|
|
////////////////////////////////////////////
|
|
|
|
if(j > table_rel->GetNoTuples()){
|
|
bs_table_tuple->DeleteIfAllowed();
|
|
break;
|
|
}
|
|
|
|
}
|
|
// cout<<count<<endl;
|
|
|
|
}
|
|
|
|
/*
|
|
for a bus stop, find the connection to its consecutive bus stop in one route
|
|
for the last stop(no connection),
|
|
we can set the length of the path (empty) as zero
|
|
|
|
*/
|
|
void BN::ConnectionOneRoute(Relation* table_rel, vector<int> tid_list,
|
|
Relation* mo_rel, BTree* btree_mo)
|
|
{
|
|
const double delta_dist = 0.01;
|
|
for(unsigned int i = 0;i < tid_list.size();i++){
|
|
Tuple* table_tuple = table_rel->GetTuple(tid_list[i], false);
|
|
Point* bs_loc = (Point*)table_tuple->GetAttribute(BN_T_GEOBS);
|
|
Bus_Stop* bs = (Bus_Stop*)table_tuple->GetAttribute(BN_T_BS);
|
|
Periods* peri = (Periods*)table_tuple->GetAttribute(BN_T_P);
|
|
double schedu = ((CcReal*)table_tuple->GetAttribute(BN_T_S))->GetRealval();
|
|
int bs_uoid =
|
|
((CcInt*)table_tuple->GetAttribute(BN_T_BUS_UOID))->GetIntval();
|
|
|
|
|
|
/////////////////find the bus trip./////////////////////////////////
|
|
/////////////////get the path to the next bus stop if exists////////////
|
|
// int count = 0;
|
|
CcInt* search_id = new CcInt(true, bs->GetId());
|
|
BTreeIterator* btree_iter = btree_mo->ExactMatch(search_id);
|
|
while(btree_iter->Next()){
|
|
Tuple* mo_tuple = mo_rel->GetTuple(btree_iter->GetId(), false);
|
|
unsigned int bus_r_id =
|
|
((CcInt*)mo_tuple->GetAttribute(RoadDenstiy::BR_ID5))->GetIntval();
|
|
assert(bus_r_id == bs->GetId());
|
|
bool dir = ((CcBool*)mo_tuple->GetAttribute(
|
|
RoadDenstiy::MO_BUS_DIRECTION))->GetBoolval();
|
|
|
|
bool find = false;
|
|
if(dir == bs->GetUp()){ //the same direction
|
|
MPoint* mo = (MPoint*)mo_tuple->GetAttribute(RoadDenstiy::BUS_TRIP);
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
////////////////find the bus stop in units///////////////////////
|
|
////////////////////////////////////////////////////////////////
|
|
int j = 0;
|
|
for(;j < mo->GetNoComponents();j++){
|
|
UPoint up;
|
|
mo->Get(j, up);
|
|
Point lp = up.p0;
|
|
Point rp = up.p1;
|
|
|
|
if(bs_loc->Distance(lp) < delta_dist &&
|
|
bs_loc->Distance(rp) < delta_dist){
|
|
// count++;
|
|
break;
|
|
}
|
|
}
|
|
assert(j < mo->GetNoComponents());
|
|
|
|
if(j == mo->GetNoComponents() - 1){///last stop in the route
|
|
// cout<<"the last bus stop"<<endl;
|
|
}else{
|
|
MPoint sub_move(0);
|
|
sub_move.StartBulkLoad();
|
|
|
|
double time_move = 0.0;
|
|
//////the leaving time of the bus, not arrival time
|
|
for(j++;j < mo->GetNoComponents();j++){//start from the next unit
|
|
UPoint up;
|
|
mo->Get(j, up);
|
|
Point lp = up.p0;
|
|
Point rp = up.p1;
|
|
|
|
if(lp.Distance(rp) < delta_dist)//next bus stop
|
|
break;
|
|
else{
|
|
sub_move.Add(up);
|
|
time_move += up.timeInterval.end.ToDouble() -
|
|
up.timeInterval.start.ToDouble();
|
|
}
|
|
}
|
|
sub_move.EndBulkLoad();
|
|
|
|
|
|
// cout<<sl->Length()<<endl;
|
|
if(dir){
|
|
Bus_Stop* neighbor_bs =
|
|
new Bus_Stop(true, bs->GetId(), bs->GetStopId() + 1, bs->GetUp());
|
|
/////////////////////////////////////////////////////////////////
|
|
///////////////////////store the result -2///////////////////////
|
|
////////////////////////////////////////////////////////////////
|
|
bs_uoid_list.push_back(bs_uoid);
|
|
bs_list1.push_back(*bs);
|
|
bs_list2.push_back(*neighbor_bs);
|
|
// bus_trip_list.push_back(sub_move);
|
|
duration.push_back(*peri);
|
|
schedule_interval.push_back(schedu);
|
|
|
|
Line traj(0);
|
|
sub_move.Trajectory(traj);
|
|
SimpleLine sl_traj(0);
|
|
sl_traj.fromLine(traj);
|
|
path_sl_list.push_back(sl_traj);
|
|
delete neighbor_bs;
|
|
time_cost_list.push_back(time_move);
|
|
}else{
|
|
Bus_Stop* neighbor_bs =
|
|
new Bus_Stop(true, bs->GetId(), bs->GetStopId() - 1, bs->GetUp());
|
|
/////////////////////////////////////////////////////////////////
|
|
///////////////////////store the result -3///////////////////////
|
|
////////////////////////////////////////////////////////////////
|
|
bs_uoid_list.push_back(bs_uoid);
|
|
bs_list1.push_back(*bs);
|
|
bs_list2.push_back(*neighbor_bs);
|
|
// bus_trip_list.push_back(sub_move);
|
|
duration.push_back(*peri);
|
|
schedule_interval.push_back(schedu);
|
|
|
|
Line traj(0);
|
|
sub_move.Trajectory(traj);
|
|
SimpleLine sl_traj(0);
|
|
sl_traj.fromLine(traj);
|
|
path_sl_list.push_back(sl_traj);
|
|
delete neighbor_bs;
|
|
time_cost_list.push_back(time_move);
|
|
}
|
|
|
|
assert(j < mo->GetNoComponents());
|
|
|
|
}
|
|
///////////////////////////////////////////////////////////////////
|
|
find = true;
|
|
}
|
|
mo_tuple->DeleteIfAllowed();
|
|
if(find)break;
|
|
}
|
|
delete btree_iter;
|
|
search_id->DeleteIfAllowed();
|
|
/////////////////////////////////////////////////////////////////////
|
|
/* cout<<"count "<<count<<endl;
|
|
cout<<*bs<<endl;
|
|
assert(count == 1);*/
|
|
|
|
table_tuple->DeleteIfAllowed();
|
|
|
|
}
|
|
}
|
|
/*
|
|
decompose a bus route into a set of segments. the result is a stream of values
|
|
(1) a segment; (2) the union of two segments each of which is from its bus route
|
|
a bus route has up and down routes
|
|
|
|
*/
|
|
void BN::DecomposeBR(Line* l1, Line* l2)
|
|
{
|
|
// cout<<"decompose a bus route"<<endl;
|
|
|
|
SimpleLine* sl1 = new SimpleLine(0);
|
|
sl1->fromLine(*l1);
|
|
|
|
SimpleLine* sl2 = new SimpleLine(0);
|
|
sl2->fromLine(*l2);
|
|
|
|
SpacePartition* sp = new SpacePartition();
|
|
vector<MyHalfSegment> seq_halfseg1; //reorder it from start to end
|
|
vector<MyHalfSegment> seq_halfseg2;
|
|
sp->ReorderLine(sl1, seq_halfseg1);
|
|
sp->ReorderLine(sl2, seq_halfseg2);
|
|
|
|
sl1->DeleteIfAllowed();
|
|
sl2->DeleteIfAllowed();
|
|
delete sp;
|
|
|
|
// cout<<seq_halfseg1.size()<<" "<<seq_halfseg2.size()<<endl;
|
|
Point p = seq_halfseg1[0].from;
|
|
Point p1 = seq_halfseg2[0].from;
|
|
Point p2 = seq_halfseg2[seq_halfseg2.size() - 1].to;
|
|
if(p.Distance(p1) > p.Distance(p2)){
|
|
|
|
//reorder seq halfseg2
|
|
vector<MyHalfSegment> temp_list;
|
|
for(int i = seq_halfseg2.size() - 1;i >= 0;i--){
|
|
MyHalfSegment mhs = seq_halfseg2[i];
|
|
MyHalfSegment new_mhs(true, mhs.to, mhs.from);
|
|
}
|
|
seq_halfseg2.clear();
|
|
for(unsigned int i = 0;i < temp_list.size();i++){
|
|
seq_halfseg2.push_back(temp_list[i]);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
// cout<<seq_halfseg1.size()<<" "<<seq_halfseg2.size()<<endl;
|
|
|
|
for(unsigned int i = 0;i < seq_halfseg1.size();i++){
|
|
Line* l = new Line(0);
|
|
Line* ul = new Line(0);
|
|
l->StartBulkLoad();
|
|
ul->StartBulkLoad();
|
|
|
|
HalfSegment hs;
|
|
hs.Set(true, seq_halfseg1[i].from, seq_halfseg1[i].to);
|
|
int edgeno1 = 0;
|
|
int edgeno_u = 0;
|
|
hs.attr.edgeno = edgeno1++;
|
|
edgeno_u++;
|
|
*l += hs;
|
|
*ul += hs;
|
|
hs.SetLeftDomPoint(!hs.IsLeftDomPoint());
|
|
*l += hs;
|
|
*ul += hs;
|
|
|
|
l->EndBulkLoad();
|
|
line_list1.push_back(*l);
|
|
l->DeleteIfAllowed();
|
|
|
|
if( i >= 1){
|
|
HalfSegment hs0;
|
|
hs0.Set(true, seq_halfseg1[i - 1].from, seq_halfseg1[i - 1].to);
|
|
hs0.attr.edgeno = edgeno_u;
|
|
edgeno_u++;
|
|
*ul += hs0;
|
|
hs0.SetLeftDomPoint(!hs0.IsLeftDomPoint());
|
|
*ul += hs0;
|
|
}
|
|
|
|
if( i + 1 < seq_halfseg1.size()){
|
|
HalfSegment hs1;
|
|
hs1.Set(true, seq_halfseg1[i + 1].from, seq_halfseg1[i + 1].to);
|
|
hs1.attr.edgeno = edgeno_u;
|
|
edgeno_u++;
|
|
*ul += hs1;
|
|
hs1.SetLeftDomPoint(!hs1.IsLeftDomPoint());
|
|
*ul += hs1;
|
|
}
|
|
|
|
if(i < seq_halfseg2.size()){
|
|
HalfSegment hs2;
|
|
hs2.Set(true, seq_halfseg2[i].from, seq_halfseg2[i].to);
|
|
hs2.attr.edgeno = edgeno_u;
|
|
edgeno_u++;
|
|
*ul += hs2;
|
|
hs2.SetLeftDomPoint(!hs2.IsLeftDomPoint());
|
|
*ul += hs2;
|
|
}
|
|
|
|
if((i + 1) < seq_halfseg2.size()){
|
|
HalfSegment hs3;
|
|
hs3.Set(true, seq_halfseg2[i + 1].from, seq_halfseg2[i + 1].to);
|
|
hs3.attr.edgeno = edgeno_u;
|
|
edgeno_u++;
|
|
*ul += hs3;
|
|
hs3.SetLeftDomPoint(!hs3.IsLeftDomPoint());
|
|
*ul += hs3;
|
|
}
|
|
|
|
if( i >= 1 && (i - 1) < seq_halfseg2.size() ){
|
|
HalfSegment hs4;
|
|
hs4.Set(true, seq_halfseg2[i - 1].from, seq_halfseg2[i - 1].to);
|
|
hs4.attr.edgeno = edgeno_u;
|
|
edgeno_u++;
|
|
*ul += hs4;
|
|
hs4.SetLeftDomPoint(!hs4.IsLeftDomPoint());
|
|
*ul += hs4;
|
|
}
|
|
|
|
ul->EndBulkLoad();
|
|
line_list2.push_back(*ul);
|
|
|
|
ul->DeleteIfAllowed();
|
|
|
|
}
|
|
|
|
for(unsigned int i = 0;i < seq_halfseg2.size();i++){
|
|
Line* l = new Line(0);
|
|
Line* ul = new Line(0);
|
|
l->StartBulkLoad();
|
|
ul->StartBulkLoad();
|
|
|
|
HalfSegment hs;
|
|
hs.Set(true, seq_halfseg2[i].from, seq_halfseg2[i].to);
|
|
int edgeno1 = 0;
|
|
int edgeno_u = 0;
|
|
hs.attr.edgeno = edgeno1++;
|
|
edgeno_u++;
|
|
*l += hs;
|
|
*ul += hs;
|
|
hs.SetLeftDomPoint(!hs.IsLeftDomPoint());
|
|
*l += hs;
|
|
*ul += hs;
|
|
|
|
l->EndBulkLoad();
|
|
line_list1.push_back(*l);
|
|
l->DeleteIfAllowed();
|
|
|
|
if( i >= 1 ){
|
|
HalfSegment hs0;
|
|
hs0.Set(true, seq_halfseg2[i - 1].from, seq_halfseg2[i - 1].to);
|
|
hs0.attr.edgeno = edgeno_u;
|
|
edgeno_u++;
|
|
*ul += hs0;
|
|
hs0.SetLeftDomPoint(!hs0.IsLeftDomPoint());
|
|
*ul += hs0;
|
|
}
|
|
|
|
if( (i + 1) < seq_halfseg2.size()){
|
|
HalfSegment hs1;
|
|
hs1.Set(true, seq_halfseg2[i + 1].from, seq_halfseg2[i + 1].to);
|
|
hs1.attr.edgeno = edgeno_u;
|
|
edgeno_u++;
|
|
*ul += hs1;
|
|
hs1.SetLeftDomPoint(!hs1.IsLeftDomPoint());
|
|
*ul += hs1;
|
|
}
|
|
|
|
if(i < seq_halfseg1.size()){
|
|
HalfSegment hs2;
|
|
hs2.Set(true, seq_halfseg1[i].from, seq_halfseg1[i].to);
|
|
hs2.attr.edgeno = edgeno_u;
|
|
edgeno_u++;
|
|
*ul += hs2;
|
|
hs2.SetLeftDomPoint(!hs2.IsLeftDomPoint());
|
|
*ul += hs2;
|
|
}
|
|
|
|
if((i + 1) < seq_halfseg1.size()){
|
|
HalfSegment hs3;
|
|
hs3.Set(true, seq_halfseg1[i + 1].from, seq_halfseg1[i + 1].to);
|
|
hs3.attr.edgeno = edgeno_u;
|
|
edgeno_u++;
|
|
*ul += hs3;
|
|
hs3.SetLeftDomPoint(!hs3.IsLeftDomPoint());
|
|
*ul += hs3;
|
|
}
|
|
|
|
if( i >= 1 && (i - 1) < seq_halfseg1.size() ){
|
|
HalfSegment hs4;
|
|
hs4.Set(true, seq_halfseg1[i - 1].from, seq_halfseg1[i - 1].to);
|
|
hs4.attr.edgeno = edgeno_u;
|
|
edgeno_u++;
|
|
*ul += hs4;
|
|
hs4.SetLeftDomPoint(!hs4.IsLeftDomPoint());
|
|
*ul += hs4;
|
|
}
|
|
|
|
ul->EndBulkLoad();
|
|
line_list2.push_back(*ul);
|
|
|
|
ul->DeleteIfAllowed();
|
|
|
|
}
|
|
|
|
// cout<<"list1 size "<<line_list1.size()
|
|
// <<" list2 size "<<line_list2.size()<<endl;
|
|
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//////////////////// Bus Network Graph //////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////////
|
|
string BusGraph::NodeTypeInfo =
|
|
"(rel (tuple ((Bus_stop busstop)(Stop_geodata point))))";
|
|
string BusGraph::NodeInternalTypeInfo =
|
|
"(rel (tuple ((Bus_stop busstop)(Stop_geodata point)(Bus_uoid int))))";
|
|
string BusGraph::NodeBTreeTypeInfo =
|
|
"(btree (tuple ((Bus_stop busstop)(Stop_geodata point)(Bus_uoid int))) int)";
|
|
|
|
string BusGraph::EdgeTypeInfo1 =
|
|
"(rel (tuple ((Bus_uoid int)(Bus_stop1 busstop)(Bus_stop2 busstop)(Path sline)\
|
|
(SubPath1 sline)(SubPath2 sline)(Path2 sline)(Bus_stop2_tid int))))";
|
|
|
|
string BusGraph::EdgeTypeInfo2 =
|
|
"(rel (tuple ((Bus_uoid int)(Bus_stop1 busstop)(Bus_stop2 busstop)\
|
|
(Bus_stop2_tid int))))";
|
|
|
|
/*
|
|
whole time: time --- bus arrival time (30 seconds waiting)
|
|
|
|
*/
|
|
string BusGraph::EdgeTypeInfo3 =
|
|
"(rel (tuple ((Bus_uoid int)(Bus_stop1 busstop)(Bus_stop2 busstop)\
|
|
(Whole_time periods)(Schedule_interval real)(Path sline)(TimeCost real)\
|
|
(Bus_stop2_tid int))))";
|
|
|
|
|
|
|
|
ListExpr BusGraph::BusGraphProp()
|
|
{
|
|
// cout<<"BaseGraphProp()"<<endl;
|
|
ListExpr examplelist = nl->TextAtom();
|
|
nl->AppendText(examplelist,
|
|
"createbusgraph(<id>,<edge-relation>,<node-relation>)");
|
|
return nl->TwoElemList(
|
|
nl->TwoElemList(nl->StringAtom("Creation"),
|
|
nl->StringAtom("Example Creation")),
|
|
nl->TwoElemList(examplelist,
|
|
nl->StringAtom("let bg=createbusgraph(id,e-rel,n-rel)")));
|
|
}
|
|
|
|
bool BusGraph::CheckBusGraph(ListExpr type, ListExpr& errorInfo)
|
|
{
|
|
// cout<<"CheckBusGraph()"<<endl;
|
|
return nl->IsEqual(type, "busgraph");
|
|
}
|
|
|
|
int BusGraph::SizeOfBusGraph()
|
|
{
|
|
// cout<<"SizeOfBusGraph()"<<endl;
|
|
return 0;
|
|
}
|
|
|
|
void* BusGraph::CastBusGraph(void* addr)
|
|
{
|
|
// cout<<"CastBusGraph()"<<endl;
|
|
return 0;
|
|
}
|
|
Word BusGraph::CloneBusGraph(const ListExpr typeInfo, const Word& w)
|
|
{
|
|
// cout<<"CloneBusGraph()"<<endl;
|
|
return SetWord(Address(0));
|
|
}
|
|
|
|
void BusGraph::CloseBusGraph(const ListExpr typeInfo, Word& w)
|
|
{
|
|
// cout<<"CloseBusGraph()"<<endl;
|
|
delete static_cast<BusGraph*> (w.addr);
|
|
w.addr = NULL;
|
|
}
|
|
|
|
Word BusGraph::CreateBusGraph(const ListExpr typeInfo)
|
|
{
|
|
// cout<<"CreateBusGraph()"<<endl;
|
|
return SetWord(new BusGraph());
|
|
}
|
|
|
|
void BusGraph::DeleteBusGraph(const ListExpr typeInfo, Word& w)
|
|
{
|
|
// cout<<"DeleteBusGraph()"<<endl;
|
|
BusGraph* bg = (BusGraph*)w.addr;
|
|
delete bg;
|
|
w.addr = NULL;
|
|
}
|
|
|
|
/*
|
|
input bus network graph
|
|
|
|
*/
|
|
Word BusGraph::InBusGraph(ListExpr in_xTypeInfo,
|
|
ListExpr in_xValue,
|
|
int in_iErrorPos, ListExpr& inout_xErrorInfo,
|
|
bool& inout_bCorrect)
|
|
{
|
|
// cout<<"InBusGraph()"<<endl;
|
|
BusGraph* bg = new BusGraph(in_xValue, in_iErrorPos, inout_xErrorInfo,
|
|
inout_bCorrect);
|
|
if(inout_bCorrect) return SetWord(bg);
|
|
else{
|
|
delete bg;
|
|
return SetWord(Address(0));
|
|
}
|
|
}
|
|
|
|
ListExpr BusGraph::OutBusGraph(ListExpr typeInfo, Word value)
|
|
{
|
|
// cout<<"OutBusGraph()"<<endl;
|
|
BusGraph* bg = (BusGraph*)value.addr;
|
|
return bg->Out(typeInfo);
|
|
}
|
|
|
|
bool BusGraph::SaveBusGraph(SmiRecord& valueRecord, size_t& offset,
|
|
const ListExpr typeInfo, Word& value)
|
|
{
|
|
// cout<<"SaveBusGraph()"<<endl;
|
|
BusGraph* bg = (BusGraph*)value.addr;
|
|
bool result = bg->Save(valueRecord, offset, typeInfo);
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
bool BusGraph::OpenBusGraph(SmiRecord& valueRecord, size_t& offset,
|
|
const ListExpr typeInfo, Word& value)
|
|
{
|
|
// cout<<"OpenBusGraph()"<<endl;
|
|
value.addr = BusGraph::Open(valueRecord, offset, typeInfo);
|
|
bool result = (value.addr != NULL);
|
|
|
|
return result;
|
|
}
|
|
|
|
BusGraph* BusGraph::Open(SmiRecord& valueRecord,size_t& offset,
|
|
const ListExpr typeInfo)
|
|
{
|
|
return new BusGraph(valueRecord,offset,typeInfo);
|
|
}
|
|
|
|
|
|
|
|
BusGraph::BusGraph():bg_id(0), min_t(0),
|
|
node_rel(NULL), btree_node(NULL),
|
|
edge_rel1(NULL), adj_list1(0), entry_adj_list1(0),
|
|
edge_rel2(NULL), adj_list2(0), entry_adj_list2(0),
|
|
edge_rel3(NULL), adj_list3(0), entry_adj_list3(0)
|
|
{
|
|
// cout<<"BusGraph::BusGraph()"<<endl;
|
|
}
|
|
|
|
BusGraph::~BusGraph()
|
|
{
|
|
if(node_rel != NULL) node_rel->Close();
|
|
if(btree_node != NULL) delete btree_node;
|
|
if(edge_rel1 != NULL) edge_rel1->Close();
|
|
if(edge_rel2 != NULL) edge_rel2->Close();
|
|
if(edge_rel3 != NULL) edge_rel3->Close();
|
|
}
|
|
|
|
|
|
BusGraph::BusGraph(ListExpr in_xValue,int in_iErrorPos,
|
|
ListExpr& inout_xErrorInfo,
|
|
bool& inout_bCorrect):
|
|
bg_id(0), min_t(0),
|
|
node_rel(NULL), btree_node(NULL),
|
|
edge_rel1(NULL), adj_list1(0), entry_adj_list1(0),
|
|
edge_rel2(NULL), adj_list2(0), entry_adj_list2(0),
|
|
edge_rel3(NULL), adj_list3(0), entry_adj_list3(0)
|
|
{
|
|
// cout<<"BusGraph::BusGraph(ListExpr)"<<endl;
|
|
}
|
|
|
|
BusGraph::BusGraph(SmiRecord& in_xValueRecord, size_t& inout_iOffset,
|
|
const ListExpr in_xTypeInfo):bg_id(0), min_t(0),
|
|
node_rel(NULL), btree_node(NULL),
|
|
edge_rel1(NULL), adj_list1(0), entry_adj_list1(0),
|
|
edge_rel2(NULL), adj_list2(0), entry_adj_list2(0),
|
|
edge_rel3(NULL), adj_list3(0), entry_adj_list3(0)
|
|
{
|
|
in_xValueRecord.Read(&bg_id,sizeof(int),inout_iOffset);
|
|
inout_iOffset += sizeof(int);
|
|
|
|
in_xValueRecord.Read(&min_t,sizeof(double),inout_iOffset);
|
|
inout_iOffset += sizeof(double);
|
|
|
|
ListExpr xType;
|
|
ListExpr xNumericType;
|
|
/***********************Open relation for node*********************/
|
|
nl->ReadFromString(NodeInternalTypeInfo,xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
node_rel = Relation::Open(in_xValueRecord, inout_iOffset, xNumericType);
|
|
if(!node_rel) {
|
|
return;
|
|
}
|
|
///////////////////open btree built on nodes//////////////////////////
|
|
nl->ReadFromString(NodeBTreeTypeInfo,xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
btree_node = BTree::Open(in_xValueRecord, inout_iOffset, xNumericType);
|
|
if(!btree_node) {
|
|
node_rel->Delete();
|
|
return;
|
|
}
|
|
|
|
/***********************Open relation for edge1*********************/
|
|
nl->ReadFromString(EdgeTypeInfo1, xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
edge_rel1 = Relation::Open(in_xValueRecord, inout_iOffset, xNumericType);
|
|
if(!edge_rel1) {
|
|
node_rel->Delete();
|
|
delete btree_node;
|
|
return;
|
|
}
|
|
|
|
/////////////////open adjacency list1////////////////////////////////
|
|
size_t bufsize = DbArray<int>::headerSize();
|
|
SmiSize offset = 0;
|
|
char* buf = (char*) malloc(bufsize);
|
|
in_xValueRecord.Read(buf, bufsize, inout_iOffset);
|
|
inout_iOffset += bufsize;
|
|
assert(buf != NULL);
|
|
adj_list1.restoreHeader(buf,offset);
|
|
free(buf);
|
|
offset = 0;
|
|
buf = (char*) malloc(bufsize);
|
|
in_xValueRecord.Read(buf, bufsize, inout_iOffset);
|
|
assert(buf != NULL);
|
|
entry_adj_list1.restoreHeader(buf,offset);
|
|
inout_iOffset += bufsize;
|
|
free(buf);
|
|
|
|
|
|
/***********************Open relation for edge2*********************/
|
|
nl->ReadFromString(EdgeTypeInfo2, xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
edge_rel2 = Relation::Open(in_xValueRecord, inout_iOffset, xNumericType);
|
|
if(!edge_rel2) {
|
|
node_rel->Delete();
|
|
delete btree_node;
|
|
edge_rel1->Delete();
|
|
adj_list1.clean();
|
|
entry_adj_list1.clean();
|
|
return;
|
|
}
|
|
|
|
/////////////////open adjacency list2////////////////////////////////
|
|
bufsize = DbArray<int>::headerSize();
|
|
offset = 0;
|
|
buf = (char*) malloc(bufsize);
|
|
in_xValueRecord.Read(buf, bufsize, inout_iOffset);
|
|
inout_iOffset += bufsize;
|
|
assert(buf != NULL);
|
|
adj_list2.restoreHeader(buf,offset);
|
|
free(buf);
|
|
offset = 0;
|
|
buf = (char*) malloc(bufsize);
|
|
in_xValueRecord.Read(buf, bufsize, inout_iOffset);
|
|
assert(buf != NULL);
|
|
entry_adj_list2.restoreHeader(buf,offset);
|
|
inout_iOffset += bufsize;
|
|
free(buf);
|
|
|
|
/***********************Open relation for edge3*********************/
|
|
nl->ReadFromString(EdgeTypeInfo3, xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
edge_rel3 = Relation::Open(in_xValueRecord, inout_iOffset, xNumericType);
|
|
if(!edge_rel3) {
|
|
node_rel->Delete();
|
|
delete btree_node;
|
|
edge_rel1->Delete();
|
|
adj_list1.clean();
|
|
entry_adj_list1.clean();
|
|
edge_rel2->Delete();
|
|
adj_list2.clean();
|
|
entry_adj_list2.clean();
|
|
return;
|
|
}
|
|
|
|
/////////////////open adjacency list3////////////////////////////////
|
|
bufsize = DbArray<ListEntry>::headerSize();
|
|
offset = 0;
|
|
buf = (char*) malloc(bufsize);
|
|
in_xValueRecord.Read(buf, bufsize, inout_iOffset);
|
|
inout_iOffset += bufsize;
|
|
assert(buf != NULL);
|
|
adj_list3.restoreHeader(buf,offset);
|
|
free(buf);
|
|
offset = 0;
|
|
buf = (char*) malloc(bufsize);
|
|
in_xValueRecord.Read(buf, bufsize, inout_iOffset);
|
|
assert(buf != NULL);
|
|
entry_adj_list3.restoreHeader(buf,offset);
|
|
inout_iOffset += bufsize;
|
|
free(buf);
|
|
|
|
}
|
|
|
|
ListExpr BusGraph::Out(ListExpr typeInfo)
|
|
{
|
|
// cout<<"Out()"<<endl;
|
|
ListExpr xNode = nl->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);
|
|
Bus_Stop* bs = (Bus_Stop*)node_tuple->GetAttribute(BG_NODE);
|
|
xNext = OutBusStop(nl->TheEmptyList(),SetWord(bs));
|
|
|
|
if(bFirst){
|
|
xNode = nl->OneElemList(xNext);
|
|
xLast = xNode;
|
|
bFirst = false;
|
|
}else
|
|
xLast = nl->Append(xLast,xNext);
|
|
node_tuple->DeleteIfAllowed();
|
|
}
|
|
|
|
// cout<< edge_rel1->GetNoTuples() + edge_rel2->GetNoTuples() +
|
|
// edge_rel3->GetNoTuples()<<endl;
|
|
|
|
return nl->TwoElemList(nl->IntAtom(bg_id),xNode);
|
|
|
|
}
|
|
|
|
/*
|
|
save bus network graph
|
|
|
|
*/
|
|
bool BusGraph::Save(SmiRecord& in_xValueRecord,size_t& inout_iOffset,
|
|
const ListExpr in_xTypeInfo)
|
|
{
|
|
// cout<<"save "<<endl;
|
|
in_xValueRecord.Write(&bg_id,sizeof(int),inout_iOffset);
|
|
inout_iOffset += sizeof(int);
|
|
|
|
in_xValueRecord.Write(&min_t,sizeof(double),inout_iOffset);
|
|
inout_iOffset += sizeof(double);
|
|
|
|
ListExpr xType;
|
|
ListExpr xNumericType;
|
|
/************************save node****************************/
|
|
nl->ReadFromString(NodeInternalTypeInfo,xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
if(!node_rel->Save(in_xValueRecord,inout_iOffset,xNumericType))
|
|
return false;
|
|
|
|
////////////////save btree on nodes///////////////////////////
|
|
nl->ReadFromString(NodeBTreeTypeInfo, xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
if(!btree_node->Save(in_xValueRecord, inout_iOffset, xNumericType))
|
|
return false;
|
|
|
|
/************************save edge1****************************/
|
|
nl->ReadFromString(EdgeTypeInfo1,xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
if(!edge_rel1->Save(in_xValueRecord,inout_iOffset,xNumericType))
|
|
return false;
|
|
|
|
/////////////////adjacency list 1//////////////////////////////
|
|
SecondoCatalog *ctlg = SecondoSystem::GetCatalog();
|
|
SmiRecordFile *rf = ctlg->GetFlobFile();
|
|
|
|
|
|
adj_list1.saveToFile(rf, adj_list1);
|
|
SmiSize offset = 0;
|
|
size_t bufsize = adj_list1.headerSize();
|
|
char* buf = (char*) malloc(bufsize);
|
|
adj_list1.serializeHeader(buf,offset);
|
|
assert(offset==bufsize);
|
|
in_xValueRecord.Write(buf, bufsize, inout_iOffset);
|
|
inout_iOffset += bufsize;
|
|
free(buf);
|
|
|
|
entry_adj_list1.saveToFile(rf, entry_adj_list1);
|
|
offset = 0;
|
|
buf = (char*) malloc(bufsize);
|
|
entry_adj_list1.serializeHeader(buf,offset);
|
|
assert(offset==bufsize);
|
|
in_xValueRecord.Write(buf,bufsize, inout_iOffset);
|
|
free(buf);
|
|
inout_iOffset += bufsize;
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
|
|
/************************save edge2****************************/
|
|
nl->ReadFromString(EdgeTypeInfo2,xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
if(!edge_rel2->Save(in_xValueRecord,inout_iOffset,xNumericType))
|
|
return false;
|
|
|
|
/////////////////adjacency list 2//////////////////////////////
|
|
|
|
adj_list2.saveToFile(rf, adj_list2);
|
|
offset = 0;
|
|
bufsize = adj_list2.headerSize();
|
|
buf = (char*) malloc(bufsize);
|
|
adj_list2.serializeHeader(buf,offset);
|
|
assert(offset==bufsize);
|
|
in_xValueRecord.Write(buf, bufsize, inout_iOffset);
|
|
inout_iOffset += bufsize;
|
|
free(buf);
|
|
|
|
entry_adj_list2.saveToFile(rf, entry_adj_list2);
|
|
offset = 0;
|
|
buf = (char*) malloc(bufsize);
|
|
entry_adj_list2.serializeHeader(buf,offset);
|
|
assert(offset==bufsize);
|
|
in_xValueRecord.Write(buf,bufsize, inout_iOffset);
|
|
free(buf);
|
|
inout_iOffset += bufsize;
|
|
|
|
/************************save edge3****************************/
|
|
nl->ReadFromString(EdgeTypeInfo3,xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
if(!edge_rel3->Save(in_xValueRecord,inout_iOffset,xNumericType))
|
|
return false;
|
|
|
|
/////////////////adjacency list 3//////////////////////////////
|
|
|
|
adj_list3.saveToFile(rf, adj_list3);
|
|
offset = 0;
|
|
bufsize = adj_list3.headerSize();
|
|
buf = (char*) malloc(bufsize);
|
|
adj_list3.serializeHeader(buf,offset);
|
|
assert(offset==bufsize);
|
|
in_xValueRecord.Write(buf, bufsize, inout_iOffset);
|
|
inout_iOffset += bufsize;
|
|
free(buf);
|
|
|
|
entry_adj_list3.saveToFile(rf, entry_adj_list3);
|
|
offset = 0;
|
|
buf = (char*) malloc(bufsize);
|
|
entry_adj_list3.serializeHeader(buf,offset);
|
|
assert(offset==bufsize);
|
|
in_xValueRecord.Write(buf,bufsize, inout_iOffset);
|
|
free(buf);
|
|
inout_iOffset += bufsize;
|
|
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
load a bus graph
|
|
edge1: the path in the pavement connecting two nearby bus stops
|
|
edge2:
|
|
|
|
*/
|
|
void BusGraph::Load(int id, Relation* r1, Relation* edge1,
|
|
Relation* edge2, Relation* edge3)
|
|
{
|
|
// cout<<"BusGraph::Load()"<<endl;
|
|
|
|
bg_id = id;
|
|
//////////////////node relation////////////////////
|
|
|
|
ListExpr xTypeInfo;
|
|
nl->ReadFromString(NodeInternalTypeInfo, xTypeInfo);
|
|
ListExpr xNumType = SecondoSystem::GetCatalog()->NumericType(xTypeInfo);
|
|
Relation* s_rel = new Relation(xNumType, true);
|
|
for(int i = 1;i <= r1->GetNoTuples();i++){
|
|
Tuple* bs_tuple = r1->GetTuple(i, false);
|
|
|
|
Bus_Stop* bs = (Bus_Stop*)bs_tuple->GetAttribute(BG_NODE);
|
|
Point* bs_loc = (Point*)bs_tuple->GetAttribute(BG_NODE_GEO);
|
|
|
|
|
|
Tuple* new_bs_tuple = new Tuple(nl->Second(xNumType));
|
|
new_bs_tuple->PutAttribute(BG_NODE, new Bus_Stop(*bs));
|
|
new_bs_tuple->PutAttribute(BG_NODE_GEO, new Point(*bs_loc));
|
|
new_bs_tuple->PutAttribute(BG_NODE_UOID, new CcInt(true, bs->GetUOid()));
|
|
|
|
s_rel->AppendTuple(new_bs_tuple);
|
|
|
|
new_bs_tuple->DeleteIfAllowed();
|
|
bs_tuple->DeleteIfAllowed();
|
|
}
|
|
|
|
|
|
ListExpr ptrList1 = listutils::getPtrList(s_rel);
|
|
|
|
string strQuery = "(consume(feed(" + NodeInternalTypeInfo +
|
|
"(ptr " + nl->ToString(ptrList1) + "))))";
|
|
|
|
|
|
Word xResult;
|
|
int QueryExecuted = QueryProcessor::ExecuteQuery(strQuery, xResult);
|
|
assert(QueryExecuted);
|
|
node_rel = (Relation*)xResult.addr;
|
|
|
|
s_rel->Delete();
|
|
|
|
////////////////////////////btree on nodes/////////////////////////
|
|
ListExpr ptrList2 = listutils::getPtrList(node_rel);
|
|
|
|
strQuery = "(createbtree (" + NodeInternalTypeInfo +
|
|
"(ptr " + nl->ToString(ptrList2) + "))" + "Bus_uoid)";
|
|
|
|
QueryExecuted = QueryProcessor::ExecuteQuery(strQuery, xResult);
|
|
assert(QueryExecuted);
|
|
btree_node = (BTree*)xResult.addr;
|
|
|
|
//////////////////////////////load edges///////////////////////////
|
|
LoadEdge1(edge1);///connected by pavements path
|
|
LoadEdge2(edge2);///same spatial location, doing transfer
|
|
LoadEdge3(edge3);//moving buses in the same route
|
|
|
|
}
|
|
|
|
/*
|
|
edges for pavement connectiong
|
|
|
|
*/
|
|
void BusGraph::LoadEdge1(Relation* r)
|
|
{
|
|
//////////////////////////////////////////////////////////////////////
|
|
////////////////////add the tid of the second bus stop/////////////////
|
|
////////////////////more efficient for query processing///////////////
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
ListExpr ptrList1 = listutils::getPtrList(r);
|
|
|
|
string strQuery = "(consume(feed(" + EdgeTypeInfo1 +
|
|
"(ptr " + nl->ToString(ptrList1) + "))))";
|
|
|
|
Word xResult;
|
|
int QueryExecuted = QueryProcessor::ExecuteQuery(strQuery, xResult);
|
|
assert(QueryExecuted);
|
|
edge_rel1 = (Relation*)xResult.addr;
|
|
|
|
GenericRelationIterator* edgeiter = edge_rel1->MakeScan();
|
|
Tuple* edge_tuple;
|
|
while((edge_tuple = edgeiter->GetNextTuple()) != 0){
|
|
|
|
//////////////////////use btree built on node rel////////////////////////
|
|
|
|
Bus_Stop* bs2 = (Bus_Stop*)edge_tuple->GetAttribute(BG_E_BS2);
|
|
int bs2_tid = -1;
|
|
CcInt* search_id = new CcInt(true, bs2->GetUOid());
|
|
BTreeIterator* btree_iter = btree_node->ExactMatch(search_id);
|
|
while(btree_iter->Next()){
|
|
bs2_tid = btree_iter->GetId();
|
|
}
|
|
delete btree_iter;
|
|
delete search_id;
|
|
assert(bs2_tid > 0 && bs2_tid <= node_rel->GetNoTuples());
|
|
/////////////////////////////////////////////////////////////////////////
|
|
/* int bs2_tid_old =
|
|
((CcInt*)edge_tuple->GetAttribute(BG_E_BS2_TID))->GetIntval();*/
|
|
vector<int> xIndices;
|
|
xIndices.push_back(BG_E_BS2_TID);
|
|
vector<Attribute*> xAttrs;
|
|
xAttrs.push_back(new CcInt(true, bs2_tid));
|
|
edge_rel1->UpdateTuple(edge_tuple,xIndices,xAttrs);
|
|
// cout<<"old "<<bs2_tid_old<<" new "<<bs2_tid<<endl;
|
|
}
|
|
|
|
// cout<<"edge1 rel no "<<edge_rel1->GetNoTuples()<<endl;
|
|
|
|
//////////////////create adjacency list///////////////////////////////////
|
|
|
|
ListExpr ptrList2 = listutils::getPtrList(edge_rel1);
|
|
|
|
strQuery = "(createbtree (" + EdgeTypeInfo1 +
|
|
"(ptr " + nl->ToString(ptrList2) + "))" + "Bus_uoid)";
|
|
|
|
QueryExecuted = QueryProcessor::ExecuteQuery(strQuery,xResult);
|
|
assert(QueryExecuted);
|
|
BTree* btree = (BTree*)xResult.addr;
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
/////////the adjacent list here is different from dual graph and
|
|
///////// visibility graph. it is the same as indoor graph ////////////
|
|
//////////in dual graph and visibility graph, we store the node id/////
|
|
/////////now we store the edge id because the weight, path is stored
|
|
////////in the edge relation ////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
for(int i = 1;i <= node_rel->GetNoTuples();i++){
|
|
Tuple* bs_tuple = node_rel->GetTuple(i, false);
|
|
Bus_Stop* bs = (Bus_Stop*)bs_tuple->GetAttribute(BG_NODE);
|
|
|
|
CcInt* nodeid = new CcInt(true, bs->GetUOid());
|
|
BTreeIterator* btree_iter = btree->ExactMatch(nodeid);
|
|
int start = adj_list1.Size();
|
|
while(btree_iter->Next()){
|
|
Tuple* edge_tuple = edge_rel1->GetTuple(btree_iter->GetId(), false);
|
|
|
|
adj_list1.Append(edge_tuple->GetTupleId());//get the edge tuple id
|
|
|
|
edge_tuple->DeleteIfAllowed();
|
|
}
|
|
delete btree_iter;
|
|
|
|
int end = adj_list1.Size();
|
|
entry_adj_list1.Append(ListEntry(start, end));
|
|
|
|
delete nodeid;
|
|
|
|
bs_tuple->DeleteIfAllowed();
|
|
|
|
}
|
|
|
|
delete btree;
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
edges for bus stops with the same spatial location but belong to different
|
|
bus routes
|
|
|
|
*/
|
|
void BusGraph::LoadEdge2(Relation* r)
|
|
{
|
|
|
|
// cout<<r->GetNoTuples()<<endl;
|
|
//////////////////////////////////////////////////////////////////////
|
|
////////////////////add the tid of the second bus stop/////////////////
|
|
////////////////////more efficient for query processing///////////////
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
ListExpr ptrList1 = listutils::getPtrList(r);
|
|
|
|
string strQuery = "(consume(feed(" + EdgeTypeInfo2 +
|
|
"(ptr " + nl->ToString(ptrList1) + "))))";
|
|
|
|
Word xResult;
|
|
int QueryExecuted = QueryProcessor::ExecuteQuery(strQuery, xResult);
|
|
assert(QueryExecuted);
|
|
edge_rel2 = (Relation*)xResult.addr;
|
|
|
|
GenericRelationIterator* edgeiter = edge_rel2->MakeScan();
|
|
Tuple* edge_tuple;
|
|
while((edge_tuple = edgeiter->GetNextTuple()) != 0){
|
|
|
|
//////////////////////use btree built on node rel////////////////////////
|
|
|
|
Bus_Stop* bs2 = (Bus_Stop*)edge_tuple->GetAttribute(BG_E2_BS2);
|
|
int bs2_tid = -1;
|
|
CcInt* search_id = new CcInt(true, bs2->GetUOid());
|
|
BTreeIterator* btree_iter = btree_node->ExactMatch(search_id);
|
|
while(btree_iter->Next()){
|
|
bs2_tid = btree_iter->GetId();
|
|
}
|
|
delete btree_iter;
|
|
delete search_id;
|
|
assert(bs2_tid > 0 && bs2_tid <= node_rel->GetNoTuples());
|
|
/////////////////////////////////////////////////////////////////////////
|
|
/* int bs2_tid_old =
|
|
((CcInt*)edge_tuple->GetAttribute(BG_E_BS2_TID))->GetIntval();*/
|
|
vector<int> xIndices;
|
|
xIndices.push_back(BG_E2_BS2_TID);
|
|
vector<Attribute*> xAttrs;
|
|
xAttrs.push_back(new CcInt(true, bs2_tid));
|
|
edge_rel2->UpdateTuple(edge_tuple,xIndices,xAttrs);
|
|
// cout<<"old "<<bs2_tid_old<<" new "<<bs2_tid<<endl;
|
|
}
|
|
|
|
// cout<<"edge2 rel no "<<edge_rel2->GetNoTuples()<<endl;
|
|
|
|
|
|
//////////////////create adjacency list////////////////////////////////////
|
|
|
|
ListExpr ptrList2 = listutils::getPtrList(edge_rel2);
|
|
|
|
strQuery = "(createbtree (" + EdgeTypeInfo2 +
|
|
"(ptr " + nl->ToString(ptrList2) + "))" + "Bus_uoid)";
|
|
|
|
QueryExecuted = QueryProcessor::ExecuteQuery(strQuery,xResult);
|
|
assert(QueryExecuted);
|
|
BTree* btree = (BTree*)xResult.addr;
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
/////////the adjacent list here is different from dual graph and
|
|
///////// visibility graph. it is the same as indoor graph ////////////
|
|
//////////in dual graph and visibility graph, we store the node id/////
|
|
/////////now we store the edge id because the weight, path is stored
|
|
////////in the edge relation ////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
for(int i = 1;i <= node_rel->GetNoTuples();i++){
|
|
Tuple* bs_tuple = node_rel->GetTuple(i, false);
|
|
Bus_Stop* bs = (Bus_Stop*)bs_tuple->GetAttribute(BG_NODE);
|
|
|
|
CcInt* nodeid = new CcInt(true, bs->GetUOid());
|
|
BTreeIterator* btree_iter = btree->ExactMatch(nodeid);
|
|
int start = adj_list2.Size();
|
|
while(btree_iter->Next()){
|
|
Tuple* edge_tuple = edge_rel2->GetTuple(btree_iter->GetId(), false);
|
|
|
|
adj_list2.Append(edge_tuple->GetTupleId());//get the edge tuple id
|
|
|
|
edge_tuple->DeleteIfAllowed();
|
|
}
|
|
delete btree_iter;
|
|
|
|
int end = adj_list2.Size();
|
|
entry_adj_list2.Append(ListEntry(start, end));
|
|
|
|
delete nodeid;
|
|
|
|
bs_tuple->DeleteIfAllowed();
|
|
|
|
}
|
|
|
|
delete btree;
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
edges for bus stops belonging to the same route, the bus stops are connected
|
|
by moving buses
|
|
|
|
*/
|
|
void BusGraph::LoadEdge3(Relation* e_rel)
|
|
{
|
|
// cout<<e_rel->GetNoTuples()<<endl;
|
|
|
|
|
|
ListExpr ptrList1 = listutils::getPtrList(e_rel);
|
|
|
|
string strQuery = "(consume(feed(" + EdgeTypeInfo3 +
|
|
"(ptr " + nl->ToString(ptrList1) + "))))";
|
|
|
|
Word xResult;
|
|
int QueryExecuted = QueryProcessor::ExecuteQuery(strQuery, xResult);
|
|
assert(QueryExecuted);
|
|
edge_rel3 = (Relation*)xResult.addr;
|
|
// Relation* edge_rel3 = (Relation*)xResult.addr;
|
|
|
|
GenericRelationIterator* edgeiter = edge_rel3->MakeScan();
|
|
Tuple* edge_tuple;
|
|
|
|
min_t = numeric_limits<double>::max();
|
|
|
|
|
|
while((edge_tuple = edgeiter->GetNextTuple()) != 0){
|
|
Periods* peri = (Periods*)edge_tuple->GetAttribute(BG_LIFETIME);
|
|
Interval<Instant> periods;
|
|
peri->Get(0, periods);
|
|
double t = periods.start.ToDouble();
|
|
if(t < min_t) min_t = t;
|
|
|
|
//////////////////////use btree built on node rel////////////////////////
|
|
|
|
Bus_Stop* bs2 = (Bus_Stop*)edge_tuple->GetAttribute(BG_E3_BS2);
|
|
int bs2_tid = -1;
|
|
CcInt* search_id = new CcInt(true, bs2->GetUOid());
|
|
BTreeIterator* btree_iter = btree_node->ExactMatch(search_id);
|
|
while(btree_iter->Next()){
|
|
bs2_tid = btree_iter->GetId();
|
|
}
|
|
delete btree_iter;
|
|
delete search_id;
|
|
assert(bs2_tid > 0 && bs2_tid <= node_rel->GetNoTuples());
|
|
// int bs2_tid_old =
|
|
// ((CcInt*)edge_tuple->GetAttribute(BG_E3_BS2_TID))->GetIntval();
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
vector<int> xIndices;
|
|
xIndices.push_back(BG_E3_BS2_TID);
|
|
vector<Attribute*> xAttrs;
|
|
xAttrs.push_back(new CcInt(true, bs2_tid));
|
|
edge_rel3->UpdateTuple(edge_tuple,xIndices,xAttrs);
|
|
// cout<<"old "<<bs2_tid_old<<" new "<<bs2_tid<<endl;
|
|
|
|
}
|
|
|
|
// Instant min(instanttype);
|
|
// min.ReadFrom(min_t);
|
|
// printf("%.10f\n",min_t);
|
|
// cout<<min<<endl;
|
|
|
|
|
|
//////////////////create adjacency list////////////////////////////////////
|
|
|
|
ListExpr ptrList2 = listutils::getPtrList(edge_rel3);
|
|
|
|
strQuery = "(createbtree (" + EdgeTypeInfo3 +
|
|
"(ptr " + nl->ToString(ptrList2) + "))" + "Bus_uoid)";
|
|
|
|
QueryExecuted = QueryProcessor::ExecuteQuery(strQuery,xResult);
|
|
assert(QueryExecuted);
|
|
BTree* btree = (BTree*)xResult.addr;
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
/////////the adjacent list here is different from dual graph and
|
|
///////// visibility graph. it is the same as indoor graph ////////////
|
|
//////////in dual graph and visibility graph, we store the node id/////
|
|
/////////now we store the edge id because the weight, path is stored
|
|
////////in the edge relation ////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
for(int i = 1;i <= node_rel->GetNoTuples();i++){
|
|
Tuple* bs_tuple = node_rel->GetTuple(i, false);
|
|
Bus_Stop* bs = (Bus_Stop*)bs_tuple->GetAttribute(BG_NODE);
|
|
|
|
CcInt* nodeid = new CcInt(true, bs->GetUOid());
|
|
BTreeIterator* btree_iter = btree->ExactMatch(nodeid);
|
|
int start = adj_list3.Size();
|
|
while(btree_iter->Next()){
|
|
// Tuple* edge_tuple = edge_rel2->GetTuple(btree_iter->GetId(), false);
|
|
Tuple* edge_tuple = edge_rel3->GetTuple(btree_iter->GetId(), false);
|
|
|
|
adj_list3.Append(edge_tuple->GetTupleId());//get the edge tuple id
|
|
|
|
edge_tuple->DeleteIfAllowed();
|
|
}
|
|
delete btree_iter;
|
|
|
|
int end = adj_list3.Size();
|
|
entry_adj_list3.Append(ListEntry(start, end));
|
|
|
|
delete nodeid;
|
|
|
|
bs_tuple->DeleteIfAllowed();
|
|
|
|
}
|
|
|
|
delete btree;
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
adjacency list for the first kind of edge (pavements)
|
|
|
|
*/
|
|
void BusGraph::FindAdj1(int node_id, vector<int>& list)
|
|
{
|
|
ListEntry list_entry;
|
|
entry_adj_list1.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_list1.Get(j, oid);
|
|
j++;
|
|
list.push_back(oid);
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
adjacency list for the second kind of edge
|
|
(bus stops with the same spatial location but belong to different bus routes)
|
|
|
|
*/
|
|
void BusGraph::FindAdj2(int node_id, vector<int>& list)
|
|
{
|
|
ListEntry list_entry;
|
|
entry_adj_list2.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_list2.Get(j, oid);
|
|
j++;
|
|
list.push_back(oid);
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
adjacency list for the third kind of edge
|
|
two adjacent bus stops are connected by moving buses
|
|
|
|
*/
|
|
void BusGraph::FindAdj3(int node_id, vector<int>& list)
|
|
{
|
|
ListEntry list_entry;
|
|
entry_adj_list3.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_list3.Get(j, oid);
|
|
j++;
|
|
list.push_back(oid);
|
|
}
|
|
}
|
|
|
|
/*
|
|
for a bus stop, find its tid in the node relation
|
|
|
|
*/
|
|
int BusGraph::GetBusStop_Tid(Bus_Stop* bs)
|
|
{
|
|
if(!bs->IsDefined()) return -1;
|
|
|
|
int bs_tid = -1;
|
|
CcInt* search_id = new CcInt(true,bs->GetUOid());
|
|
BTreeIterator* btree_iter = btree_node->ExactMatch(search_id);
|
|
while(btree_iter->Next()){
|
|
bs_tid = btree_iter->GetId();
|
|
}
|
|
delete btree_iter;
|
|
delete search_id;
|
|
assert(bs_tid > 0 && bs_tid <= node_rel->GetNoTuples());
|
|
return bs_tid;
|
|
}
|
|
////////////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////navigation in bus network//////////////////
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
/*
|
|
shortest path from one bus stop to another in length
|
|
|
|
*/
|
|
void BNNav::ShortestPath_Length(Bus_Stop* bs1, Bus_Stop* bs2, Instant* qt)
|
|
{
|
|
// cout<<"bus shortest path in length "<<endl;
|
|
|
|
BusGraph* bg = bn->GetBusGraph();
|
|
if(bg == NULL){
|
|
cout<<"bus graph is invalid"<<endl;
|
|
return;
|
|
}
|
|
|
|
if(!bs1->IsDefined() || !bs2->IsDefined()){
|
|
cout<<" bus stops are not defined"<<endl;
|
|
return;
|
|
}
|
|
|
|
Point start_p, end_p;
|
|
bn->GetBusStopGeoData(bs1, &start_p);
|
|
bn->GetBusStopGeoData(bs2, &end_p);
|
|
const double delta_dist = 0.01;
|
|
|
|
if(*bs1 == *bs2 || start_p.Distance(end_p) < delta_dist){
|
|
cout<<"two bus stops equal to each other"<<endl;
|
|
bn->CloseBusGraph(bg);
|
|
return;
|
|
}
|
|
|
|
priority_queue<BNPath_elem> path_queue;
|
|
vector<BNPath_elem> expand_queue;
|
|
|
|
vector<bool> visit_flag1;////////////bus stop visit
|
|
for(int i = 1; i <= bg->node_rel->GetNoTuples();i++)
|
|
visit_flag1.push_back(false);
|
|
|
|
/////////// initialize the queue //////////////////////////////
|
|
InitializeQueue1(bs1, bs2, path_queue, expand_queue, bn, bg, start_p, end_p);
|
|
|
|
int bs2_tid = bg->GetBusStop_Tid(bs2);
|
|
// cout<<"end bus stop tid "<<bs2_tid<<endl;
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
////////////////////search on the bus graph//////////////////////////
|
|
/////////////////////////////////////////////////////////////////////
|
|
bool find = false;
|
|
BNPath_elem dest;//////////destination
|
|
|
|
while(path_queue.empty() == false){
|
|
BNPath_elem top = path_queue.top();
|
|
path_queue.pop();
|
|
|
|
if(visit_flag1[top.tri_index - 1])continue;
|
|
|
|
// top.Print();
|
|
|
|
if(top.tri_index == bs2_tid){
|
|
// cout<<"find the shortest path"<<endl;
|
|
find = true;
|
|
dest = top;
|
|
break;
|
|
}
|
|
int pos_expand_path;
|
|
int cur_size;
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
//////////////////////connection 1 by pavement ////////////////////////
|
|
//////////////////////////////////////////////////////////////////////
|
|
vector<int> adj_list1;
|
|
bg->FindAdj1(top.tri_index, adj_list1);
|
|
pos_expand_path = top.cur_index;
|
|
for(unsigned int i = 0;i < adj_list1.size();i++){
|
|
Tuple* edge_tuple = bg->edge_rel1->GetTuple(adj_list1[i], false);
|
|
int neighbor_id1 =
|
|
((CcInt*)edge_tuple->GetAttribute(BusGraph::BG_E_BS2_TID))->GetIntval();
|
|
SimpleLine* path =
|
|
(SimpleLine*)edge_tuple->GetAttribute(BusGraph::BG_PATH2);
|
|
|
|
if(visit_flag1[neighbor_id1 - 1]){
|
|
edge_tuple->DeleteIfAllowed();
|
|
continue;
|
|
}
|
|
|
|
cur_size = expand_queue.size();
|
|
Tuple* bs_node_tuple = bg->node_rel->GetTuple(neighbor_id1, false);
|
|
Point* p = (Point*)bs_node_tuple->GetAttribute(BusGraph::BG_NODE_GEO);
|
|
|
|
double w = top.real_w + path->Length();
|
|
double hw = p->Distance(end_p);
|
|
BNPath_elem elem(pos_expand_path, cur_size,neighbor_id1, w + hw, w,
|
|
*path, TM_WALK);
|
|
path_queue.push(elem);
|
|
expand_queue.push_back(elem);
|
|
|
|
bs_node_tuple->DeleteIfAllowed();
|
|
edge_tuple->DeleteIfAllowed();
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
//////////////////////connection 2 same spatial location/////////////
|
|
////////////////////////////////////////////////////////////////////
|
|
vector<int> adj_list2;
|
|
bg->FindAdj2(top.tri_index, adj_list2);
|
|
for(unsigned int i = 0;i < adj_list2.size();i++){
|
|
Tuple* edge_tuple = bg->edge_rel2->GetTuple(adj_list2[i], false);
|
|
int neighbor_id2 =
|
|
((CcInt*)edge_tuple->GetAttribute(BusGraph::BG_E2_BS2_TID))->GetIntval();
|
|
SimpleLine* path = new SimpleLine(0);
|
|
path->StartBulkLoad();
|
|
path->EndBulkLoad();
|
|
|
|
if(visit_flag1[neighbor_id2 - 1]){
|
|
edge_tuple->DeleteIfAllowed();
|
|
path->DeleteIfAllowed();
|
|
continue;
|
|
}
|
|
|
|
cur_size = expand_queue.size();
|
|
double w = top.real_w;
|
|
|
|
Tuple* bs_node_tuple = bg->node_rel->GetTuple(neighbor_id2, false);
|
|
Point* p = (Point*)bs_node_tuple->GetAttribute(BusGraph::BG_NODE_GEO);
|
|
double hw = p->Distance(end_p);
|
|
bs_node_tuple->DeleteIfAllowed();
|
|
|
|
|
|
BNPath_elem elem(pos_expand_path, cur_size, neighbor_id2, w + hw, w,
|
|
*path, -1);
|
|
path_queue.push(elem);
|
|
expand_queue.push_back(elem);
|
|
|
|
path->DeleteIfAllowed();
|
|
|
|
edge_tuple->DeleteIfAllowed();
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
////////////////////connection 3 moving buses/////////////////////////
|
|
//////////////////////////////////////////////////////////////////////
|
|
vector<int> adj_list3;
|
|
bg->FindAdj3(top.tri_index, adj_list3);
|
|
for(unsigned int i = 0;i < adj_list3.size();i++){
|
|
Tuple* edge_tuple = bg->edge_rel3->GetTuple(adj_list3[i], false);
|
|
int neighbor_id3 =
|
|
((CcInt*)edge_tuple->GetAttribute(BusGraph::BG_E3_BS2_TID))->GetIntval();
|
|
SimpleLine* path =
|
|
(SimpleLine*)edge_tuple->GetAttribute(BusGraph::BG_PATH3);
|
|
|
|
if(visit_flag1[neighbor_id3 - 1]){
|
|
edge_tuple->DeleteIfAllowed();
|
|
continue;
|
|
}
|
|
|
|
cur_size = expand_queue.size();
|
|
double w = top.real_w + path->Length();
|
|
|
|
Tuple* bs_node_tuple = bg->node_rel->GetTuple(neighbor_id3, false);
|
|
Point* p = (Point*)bs_node_tuple->GetAttribute(BusGraph::BG_NODE_GEO);
|
|
double hw = p->Distance(end_p);
|
|
bs_node_tuple->DeleteIfAllowed();
|
|
|
|
BNPath_elem elem(pos_expand_path, cur_size,neighbor_id3, w + hw, w,
|
|
*path, TM_BUS);
|
|
path_queue.push(elem);
|
|
expand_queue.push_back(elem);
|
|
edge_tuple->DeleteIfAllowed();
|
|
|
|
}
|
|
|
|
visit_flag1[top.tri_index - 1] = true;
|
|
}
|
|
///////////////////////////////////////////////////////////////////////
|
|
if(find){ ////////constrcut the result
|
|
vector<int> id_list;
|
|
while(dest.prev_index != -1){
|
|
id_list.push_back(dest.cur_index);
|
|
dest = expand_queue[dest.prev_index];
|
|
}
|
|
|
|
id_list.push_back(dest.cur_index);
|
|
|
|
Bus_Stop bs_last = *bs1;
|
|
for(int i = id_list.size() - 1;i >= 0;i--){
|
|
BNPath_elem elem = expand_queue[id_list[i]];
|
|
path_list.push_back(elem.path);
|
|
// cout<<elem.tri_index<<endl;
|
|
if(elem.tm == TM_WALK){
|
|
tm_list.push_back(str_tm[elem.tm]);
|
|
}else if(elem.tm == TM_BUS){
|
|
tm_list.push_back(str_tm[elem.tm]);
|
|
}else{
|
|
// assert(false);
|
|
tm_list.push_back("none");
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
////////////////we also return///////////////////////////////////////
|
|
////////the start and end bus stop connected by the path ////////////
|
|
////////////////////////////////////////////////////////////////////
|
|
char buf1[256], buf2[256];
|
|
|
|
sprintf(buf1, "br: %d ", bs_last.GetId());
|
|
sprintf(buf2, "stop: %d", bs_last.GetStopId());
|
|
strcat (buf1, buf2);
|
|
if(bs_last.GetUp())strcat (buf1, " UP");
|
|
else strcat (buf1, " DOWN");
|
|
|
|
string str1(buf1);
|
|
bs1_list.push_back(str1);
|
|
|
|
if(i == (int)(id_list.size() - 1)){
|
|
string str2(str1);
|
|
bs2_list.push_back(str2);
|
|
|
|
}else{////////////////the end bus stop
|
|
|
|
Tuple* bs_tuple = bg->node_rel->GetTuple(elem.tri_index, false);
|
|
Bus_Stop* bs_cur =
|
|
(Bus_Stop*)bs_tuple->GetAttribute(BusGraph::BG_NODE);
|
|
char buf_1[256], buf_2[256];
|
|
sprintf(buf_1, "br: %d ", bs_cur->GetId());
|
|
sprintf(buf_2, "stop: %d", bs_cur->GetStopId());
|
|
strcat (buf_1, buf_2);
|
|
if(bs_cur->GetUp()) strcat (buf_1, " UP");
|
|
else strcat (buf_1, " DOWN");
|
|
|
|
string str2(buf_1);
|
|
bs2_list.push_back(str2);
|
|
bs_last = *bs_cur;
|
|
bs_tuple->DeleteIfAllowed();
|
|
}
|
|
|
|
}
|
|
}else{
|
|
// cout<<"bs1 ("<<*bs1<<") bs2 ("<<*bs2<<") not reachable "<<endl;
|
|
}
|
|
|
|
bn->CloseBusGraph(bg);
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
put the start bus stop into the queue for minimum length
|
|
|
|
*/
|
|
void BNNav::InitializeQueue1(Bus_Stop* bs1, Bus_Stop* bs2,
|
|
priority_queue<BNPath_elem>& path_queue,
|
|
vector<BNPath_elem>& expand_queue, BusNetwork* bn,
|
|
BusGraph* bg, Point& start_p, Point& end_p)
|
|
{
|
|
|
|
int cur_size = expand_queue.size();
|
|
double w = 0.0;
|
|
double hw = start_p.Distance(end_p);
|
|
SimpleLine* sl = new SimpleLine(0);
|
|
sl->StartBulkLoad();
|
|
sl->EndBulkLoad();
|
|
|
|
int bs_tid = bg->GetBusStop_Tid(bs1);
|
|
// cout<<"start bus stop tid "<<bs_tid<<endl;
|
|
BNPath_elem elem(-1, cur_size, bs_tid, w + hw, w, *sl, TM_BUS);
|
|
path_queue.push(elem);
|
|
expand_queue.push_back(elem);
|
|
sl->DeleteIfAllowed();
|
|
}
|
|
|
|
|
|
/*
|
|
shortest path from one bus stop to another in time
|
|
|
|
*/
|
|
void BNNav::ShortestPath_Time(Bus_Stop* bs1, Bus_Stop* bs2, Instant* qt)
|
|
{
|
|
BusGraph* bg = bn->GetBusGraph();
|
|
if(bg == NULL){
|
|
cout<<"bus graph is invalid"<<endl;
|
|
return;
|
|
}
|
|
|
|
if(!bs1->IsDefined() || !bs2->IsDefined()){
|
|
cout<<" bus stops are not defined"<<endl;
|
|
return;
|
|
}
|
|
|
|
Point start_p, end_p;
|
|
bn->GetBusStopGeoData(bs1, &start_p);
|
|
bn->GetBusStopGeoData(bs2, &end_p);
|
|
const double delta_dist = 0.01;
|
|
|
|
if(*bs1 == *bs2 || start_p.Distance(end_p) < delta_dist){
|
|
cout<<"two bus stops equal to each other"<<endl;
|
|
bn->CloseBusGraph(bg);
|
|
return;
|
|
}
|
|
/////////////////////////build the start time///////////////////////////
|
|
Instant new_st(instanttype);
|
|
Instant bg_min(instanttype);
|
|
bg_min.ReadFrom(bg->min_t);
|
|
|
|
assert(bg_min.GetWeekday() == 6);//start from Sunday
|
|
|
|
if(qt->GetWeekday() == 6){
|
|
new_st.Set(bg_min.GetYear(),bg_min.GetMonth(),bg_min.GetGregDay(),
|
|
qt->GetHour(), qt->GetMinute(), qt->GetSecond(),
|
|
qt->GetMillisecond());
|
|
// cout<<"Sunday"<<endl;
|
|
|
|
}else{ //Monday-Saturday
|
|
////////////////////////////to Monday///////////////////////
|
|
new_st.Set(bg_min.GetYear(),bg_min.GetMonth(),bg_min.GetGregDay() + 1,
|
|
qt->GetHour(), qt->GetMinute(), qt->GetSecond(),
|
|
qt->GetMillisecond());
|
|
// cout<<"workday --->Monday"<<endl;
|
|
}
|
|
// cout<<"mapping start time"<<new_st<<endl;
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
priority_queue<BNPath_elem> path_queue;
|
|
vector<BNPath_elem> expand_queue;
|
|
|
|
vector<bool> visit_flag1;////////////bus stop visit
|
|
for(int i = 1; i <= bg->node_rel->GetNoTuples();i++)
|
|
visit_flag1.push_back(false);
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
/////////////from bus network, get the maximum speed of the bus///
|
|
/////////////for setting heuristic value/////////////////////////
|
|
///////////////////////////////////////////////////////////////////
|
|
// cout<<"max bus speed "<<bn->GetMaxSpeed()*60.0*60.0/1000.0<<"km/h"<<endl;
|
|
|
|
/////////// initialize the queue //////////////////////////////
|
|
InitializeQueue2(bs1, bs2, path_queue, expand_queue, bn, bg, start_p, end_p);
|
|
|
|
int bs2_tid = bg->GetBusStop_Tid(bs2);
|
|
// cout<<"end bus stop tid "<<bs2_tid<<endl;
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
////////////////////search on the bus graph//////////////////////////
|
|
/////////////////////////////////////////////////////////////////////
|
|
bool find = false;
|
|
BNPath_elem dest;//////////destination
|
|
double speed_human = 1.0;
|
|
|
|
// int elem_count = 0;
|
|
|
|
while(path_queue.empty() == false){
|
|
BNPath_elem top = path_queue.top();
|
|
path_queue.pop();
|
|
|
|
// elem_count++;
|
|
|
|
if(visit_flag1[top.tri_index - 1])continue;
|
|
|
|
// top.Print();
|
|
|
|
if(top.tri_index == bs2_tid){
|
|
// cout<<"find the shortest path"<<endl;
|
|
find = true;
|
|
dest = top;
|
|
break;
|
|
}
|
|
int pos_expand_path;
|
|
int cur_size;
|
|
|
|
pos_expand_path = top.cur_index;
|
|
///////////////////////////////////////////////////////////////////////
|
|
//////////////////////connection 1 by pavements ///////////////////////
|
|
//////////////////////////////////////////////////////////////////////
|
|
vector<int> adj_list1;
|
|
bg->FindAdj1(top.tri_index, adj_list1);
|
|
|
|
bool search_flag = true;
|
|
BNPath_elem temp_elem = top;
|
|
while(dest.prev_index != -1){
|
|
if(temp_elem.tm == TM_BUS){
|
|
break;
|
|
}
|
|
if(temp_elem.tm == TM_WALK){
|
|
search_flag = false;
|
|
break;
|
|
}
|
|
temp_elem = expand_queue[temp_elem.prev_index];
|
|
}
|
|
|
|
for(unsigned int i = 0;i < adj_list1.size() && search_flag;i++){
|
|
Tuple* edge_tuple = bg->edge_rel1->GetTuple(adj_list1[i], false);
|
|
int neighbor_id1 =
|
|
((CcInt*)edge_tuple->GetAttribute(BusGraph::BG_E_BS2_TID))->GetIntval();
|
|
SimpleLine* path =
|
|
(SimpleLine*)edge_tuple->GetAttribute(BusGraph::BG_PATH2);
|
|
|
|
if(visit_flag1[neighbor_id1 - 1]){
|
|
edge_tuple->DeleteIfAllowed();
|
|
continue;
|
|
}
|
|
|
|
cur_size = expand_queue.size();
|
|
|
|
double w = top.real_w + path->Length()/(speed_human*24.0*60.0*60.0);
|
|
|
|
Tuple* bs_node_tuple = bg->node_rel->GetTuple(neighbor_id1, false);
|
|
Point* p = (Point*)bs_node_tuple->GetAttribute(BusGraph::BG_NODE_GEO);
|
|
double hw = p->Distance(end_p)/(bn->GetMaxSpeed()*24.0*60.0*60.0);
|
|
bs_node_tuple->DeleteIfAllowed();
|
|
|
|
|
|
/* BNPath_elem elem(pos_expand_path, cur_size,neighbor_id1, w + hw, w,
|
|
*path, TM_WALK, true);*/
|
|
SimpleLine temp_sl(0);
|
|
BNPath_elem elem(pos_expand_path, cur_size,neighbor_id1, w + hw, w,
|
|
temp_sl, TM_WALK, true);
|
|
elem.type = TM_WALK;
|
|
elem.edge_tid = adj_list1[i];
|
|
|
|
|
|
path_queue.push(elem);
|
|
expand_queue.push_back(elem);
|
|
edge_tuple->DeleteIfAllowed();
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
//////////////////////connection 2 same spatial location/////////////
|
|
////////////////////////////////////////////////////////////////////
|
|
vector<int> adj_list2;
|
|
bg->FindAdj2(top.tri_index, adj_list2);
|
|
|
|
for(unsigned int i = 0;i < adj_list2.size();i++){
|
|
Tuple* edge_tuple = bg->edge_rel2->GetTuple(adj_list2[i], false);
|
|
int neighbor_id2 =
|
|
((CcInt*)edge_tuple->GetAttribute(BusGraph::BG_E2_BS2_TID))->GetIntval();
|
|
SimpleLine* path = new SimpleLine(0);
|
|
path->StartBulkLoad();
|
|
path->EndBulkLoad();
|
|
|
|
if(visit_flag1[neighbor_id2 - 1]){
|
|
edge_tuple->DeleteIfAllowed();
|
|
path->DeleteIfAllowed();
|
|
continue;
|
|
}
|
|
|
|
cur_size = expand_queue.size();
|
|
double w = top.real_w;
|
|
Tuple* bs_node_tuple = bg->node_rel->GetTuple(neighbor_id2, false);
|
|
Point* p = (Point*)bs_node_tuple->GetAttribute(BusGraph::BG_NODE_GEO);
|
|
double hw = p->Distance(end_p)/(bn->GetMaxSpeed()*24.0*60.0*60.0);
|
|
bs_node_tuple->DeleteIfAllowed();
|
|
|
|
|
|
/* BNPath_elem elem(pos_expand_path, cur_size, neighbor_id2, w + hw, w,
|
|
*path, -1, false); //not useful for time cost */
|
|
|
|
BNPath_elem elem(pos_expand_path, cur_size, neighbor_id2, w + hw, w,
|
|
*path, -1, false); //not useful for time cost
|
|
elem.type = -1;
|
|
elem.edge_tid = 0;
|
|
|
|
path_queue.push(elem);
|
|
expand_queue.push_back(elem);
|
|
|
|
path->DeleteIfAllowed();
|
|
edge_tuple->DeleteIfAllowed();
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
////////////////////connection 3 moving buses/////////////////////////
|
|
//////////////////////////////////////////////////////////////////////
|
|
vector<int> adj_list3;
|
|
bg->FindAdj3(top.tri_index, adj_list3);
|
|
int64_t max_64_int = numeric_limits<int64_t>::max();
|
|
|
|
for(unsigned int i = 0;i < adj_list3.size();i++){
|
|
Tuple* edge_tuple = bg->edge_rel3->GetTuple(adj_list3[i], false);
|
|
int neighbor_id3 =
|
|
((CcInt*)edge_tuple->GetAttribute(BusGraph::BG_E3_BS2_TID))->GetIntval();
|
|
// SimpleLine* path =
|
|
// (SimpleLine*)edge_tuple->GetAttribute(BusGraph::BG_PATH3);
|
|
|
|
if(visit_flag1[neighbor_id3 - 1]){
|
|
edge_tuple->DeleteIfAllowed();
|
|
continue;
|
|
}
|
|
|
|
cur_size = expand_queue.size();
|
|
double cur_t = new_st.ToDouble() + top.real_w;
|
|
Instant cur_inst = new_st;
|
|
cur_inst.ReadFrom(cur_t); //time to arrive current bus stop
|
|
// cout<<"time at bus stop "<<cur_inst<<endl;
|
|
|
|
int64_t cur_t_int = cur_t*86400000;
|
|
assert(cur_t_int <= max_64_int);
|
|
|
|
Periods* peri =
|
|
(Periods*)edge_tuple->GetAttribute(BusGraph::BG_LIFETIME);
|
|
Interval<Instant> periods;
|
|
peri->Get(0, periods);
|
|
|
|
double sched =
|
|
((CcReal*)edge_tuple->GetAttribute(BusGraph::BG_SCHEDULE))->GetRealval();
|
|
double st = periods.start.ToDouble();
|
|
double et = periods.end.ToDouble();
|
|
int64_t st_int = st*86400000;
|
|
int64_t et_int = et*86400000;
|
|
assert(st_int <= max_64_int);
|
|
assert(et_int <= max_64_int);
|
|
|
|
// cout<<"st "<<periods.start<<" et "<<periods.end<<endl;
|
|
|
|
if(et_int < cur_t_int){//end time smaller than curtime
|
|
edge_tuple->DeleteIfAllowed();
|
|
continue;
|
|
}
|
|
double wait_time = 0.0;
|
|
if(st_int > cur_t_int){//wait for the first start time
|
|
wait_time += st - cur_t;
|
|
wait_time += 30.0/(24.0*60.0*60.0);//30 seconds at bus stop
|
|
}else if(st_int == cur_t_int){
|
|
wait_time += 30.0/(24.0*60.0*60.0);//30 seconds at bus stop
|
|
}else{ //most times, it is here, wait for the next schedule
|
|
|
|
bool valid = false;
|
|
while(st_int < cur_t_int && st_int <= et_int){
|
|
|
|
/* Instant temp(instanttype);
|
|
temp.ReadFrom(st);
|
|
cout<<"t1 "<<temp<<endl; */
|
|
|
|
if((st_int + 30000) >= cur_t_int){//30 second
|
|
wait_time += st + 30.0/(24.0*60.0*60.0) - cur_t;
|
|
valid = true;
|
|
break;
|
|
}
|
|
st += sched;
|
|
st_int = st * 86400000;
|
|
if(st_int >= cur_t_int){
|
|
wait_time += st + 30.0/(24.0*60.0*60.0) - cur_t;
|
|
valid = true;
|
|
break;
|
|
}
|
|
assert(st_int <= max_64_int);
|
|
|
|
// temp.ReadFrom(st);
|
|
// cout<<"t2 "<<temp<<endl;
|
|
|
|
}
|
|
if(valid == false){
|
|
cout<<"should not arrive at here"<<endl;
|
|
assert(false);
|
|
}
|
|
}
|
|
|
|
double weight =
|
|
((CcReal*)edge_tuple->GetAttribute(BusGraph::BG_TIMECOST))->GetRealval();
|
|
double w = top.real_w + wait_time + weight;
|
|
|
|
Tuple* bs_node_tuple = bg->node_rel->GetTuple(neighbor_id3, false);
|
|
Point* p = (Point*)bs_node_tuple->GetAttribute(BusGraph::BG_NODE_GEO);
|
|
double hw = p->Distance(end_p)/(bn->GetMaxSpeed()*24.0*60.0*60.0);
|
|
bs_node_tuple->DeleteIfAllowed();
|
|
|
|
|
|
/* BNPath_elem elem(pos_expand_path, cur_size,neighbor_id3, w + hw, w,
|
|
*path, TM_BUS, true);*/
|
|
SimpleLine temp_sl(0);
|
|
BNPath_elem elem(pos_expand_path, cur_size,neighbor_id3, w + hw, w,
|
|
temp_sl, TM_BUS, true);
|
|
elem.type = TM_BUS;
|
|
elem.edge_tid = adj_list3[i];
|
|
|
|
|
|
if(wait_time > 0.0){ //to the time waiting for bus
|
|
elem.SetW(top.real_w + wait_time);
|
|
}
|
|
|
|
path_queue.push(elem);
|
|
expand_queue.push_back(elem);
|
|
|
|
|
|
edge_tuple->DeleteIfAllowed();
|
|
|
|
}
|
|
|
|
visit_flag1[top.tri_index - 1] = true;
|
|
|
|
}
|
|
/* cout<<elem_count<<" elements poped from queue"<<endl;*/
|
|
//////////////////////////////////////////////////////////////////////
|
|
////////////////construct the result//////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////
|
|
if(find){ ////////constrcut the result
|
|
vector<int> id_list;
|
|
while(dest.prev_index != -1){
|
|
id_list.push_back(dest.cur_index);
|
|
dest = expand_queue[dest.prev_index];
|
|
}
|
|
|
|
id_list.push_back(dest.cur_index);
|
|
|
|
Bus_Stop bs_last = *bs1;
|
|
Instant t1 = *qt;
|
|
// int no_transfer = 0;
|
|
|
|
for(int i = id_list.size() - 1;i >= 0;i--){
|
|
BNPath_elem elem = expand_queue[id_list[i]];
|
|
////////////////////////////////////////////////////////////
|
|
if(elem.type == TM_WALK){
|
|
assert(1 <= elem.edge_tid &&
|
|
elem.edge_tid <= bg->edge_rel1->GetNoTuples());
|
|
Tuple* edge_tuple = bg->edge_rel1->GetTuple(elem.edge_tid, false);
|
|
SimpleLine* path =
|
|
(SimpleLine*)edge_tuple->GetAttribute(BusGraph::BG_PATH2);
|
|
elem.path = *path;
|
|
edge_tuple->DeleteIfAllowed();
|
|
|
|
}else if(elem.type == TM_BUS){
|
|
if(elem.edge_tid > 0){
|
|
Tuple* edge_tuple = bg->edge_rel3->GetTuple(elem.edge_tid, false);
|
|
SimpleLine* path =
|
|
(SimpleLine*)edge_tuple->GetAttribute(BusGraph::BG_PATH3);
|
|
elem.path = *path;
|
|
edge_tuple->DeleteIfAllowed();
|
|
}
|
|
|
|
}else if(elem.type == -1){
|
|
|
|
}else{
|
|
cout<<"should not be here"<<endl;
|
|
assert(false);
|
|
}
|
|
////////////////////////////////////////////////////////////
|
|
|
|
path_list.push_back(elem.path);
|
|
|
|
if(elem.tm == TM_WALK){
|
|
tm_list.push_back(str_tm[elem.tm]);
|
|
}else if(elem.tm == TM_BUS){
|
|
tm_list.push_back(str_tm[elem.tm]);
|
|
}else{
|
|
// assert(false);
|
|
tm_list.push_back("none");
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
////////////////we also return///////////////////////////////////////
|
|
////////the start and end bus stops connected by the path ////////////
|
|
////////////////////////////////////////////////////////////////////
|
|
char buf1[256], buf2[256];
|
|
|
|
sprintf(buf1, "br: %d ", bs_last.GetId());
|
|
sprintf(buf2, "stop: %d", bs_last.GetStopId());
|
|
strcat (buf1, buf2);
|
|
if(bs_last.GetUp())strcat (buf1, " UP");
|
|
else strcat (buf1, " DOWN");
|
|
|
|
string str1(buf1);
|
|
bs1_list.push_back(str1);
|
|
|
|
if(i == (int)(id_list.size() - 1)){
|
|
string str2(str1);
|
|
bs2_list.push_back(str2);
|
|
|
|
}else{////////////////the end bus stop
|
|
|
|
Tuple* bs_tuple = bg->node_rel->GetTuple(elem.tri_index, false);
|
|
Bus_Stop* bs_cur =
|
|
(Bus_Stop*)bs_tuple->GetAttribute(BusGraph::BG_NODE);
|
|
char buf_1[256], buf_2[256];
|
|
sprintf(buf_1, "br: %d ", bs_cur->GetId());
|
|
sprintf(buf_2, "stop: %d", bs_cur->GetStopId());
|
|
strcat (buf_1, buf_2);
|
|
if(bs_cur->GetUp()) strcat (buf_1, " UP");
|
|
else strcat (buf_1, " DOWN");
|
|
|
|
string str2(buf_1);
|
|
bs2_list.push_back(str2);
|
|
bs_last = *bs_cur;
|
|
bs_tuple->DeleteIfAllowed();
|
|
}
|
|
|
|
////////////////time duration////////////////////////////////
|
|
|
|
Instant t2(instanttype);
|
|
if(elem.b_w == false){
|
|
t2.ReadFrom(elem.real_w + qt->ToDouble());
|
|
// cout<<t1<<" "<<t2<<endl;
|
|
|
|
//time cost in seconds
|
|
if(elem.valid)
|
|
time_cost_list.push_back((t2.ToDouble() - t1.ToDouble())*86400.0);
|
|
else //doing transfer without moving
|
|
time_cost_list.push_back(0.0);
|
|
Interval<Instant> time_span;
|
|
time_span.start = t1;
|
|
time_span.lc = true;
|
|
time_span.end = t2;
|
|
time_span.rc = false;
|
|
|
|
Periods* peri = new Periods(0);
|
|
peri->StartBulkLoad();
|
|
if(elem.valid)
|
|
peri->MergeAdd(time_span);
|
|
peri->EndBulkLoad();
|
|
peri_list.push_back(*peri);
|
|
t1 = t2;
|
|
peri->DeleteIfAllowed();
|
|
}else{ //////////to dinstinguish time of waiting for the bus
|
|
t2.ReadFrom(elem.w + qt->ToDouble());
|
|
// cout<<t1<<" "<<t2<<endl;
|
|
|
|
//time cost in seconds
|
|
if(elem.valid)
|
|
time_cost_list.push_back((t2.ToDouble() - t1.ToDouble())*86400.0);
|
|
else //doing transfer without moving
|
|
time_cost_list.push_back(0.0);
|
|
Interval<Instant> time_span;
|
|
time_span.start = t1;
|
|
time_span.lc = true;
|
|
time_span.end = t2;
|
|
time_span.rc = false;
|
|
|
|
Periods* peri1 = new Periods(0);
|
|
peri1->StartBulkLoad();
|
|
if(elem.valid)
|
|
peri1->MergeAdd(time_span);
|
|
peri1->EndBulkLoad();
|
|
peri_list.push_back(*peri1);
|
|
t1 = t2;
|
|
peri1->DeleteIfAllowed();
|
|
|
|
SimpleLine* sl = new SimpleLine(0);
|
|
sl->StartBulkLoad();
|
|
sl->EndBulkLoad();
|
|
path_list[path_list.size() - 1] = *sl;
|
|
sl->DeleteIfAllowed();
|
|
|
|
tm_list[tm_list.size() - 1] = "none"; //waiting is no tm
|
|
string str = bs2_list[bs2_list.size() - 1];
|
|
////////the same as last bus stop //////////////////////
|
|
bs2_list[bs2_list.size() - 1] = bs1_list[bs1_list.size() - 1];
|
|
|
|
|
|
/////////////moving with bus////////////////////////////////
|
|
t2.ReadFrom(elem.real_w + qt->ToDouble());
|
|
// cout<<t1<<" "<<t2<<endl;
|
|
|
|
//time cost in seconds
|
|
if(elem.valid)
|
|
time_cost_list.push_back((t2.ToDouble() - t1.ToDouble())*86400.0);
|
|
else //doing transfer without moving
|
|
time_cost_list.push_back(0.0);
|
|
|
|
time_span.start = t1;
|
|
time_span.lc = true;
|
|
time_span.end = t2;
|
|
time_span.rc = false;
|
|
|
|
Periods* peri2 = new Periods(0);
|
|
peri2->StartBulkLoad();
|
|
if(elem.valid)
|
|
peri2->MergeAdd(time_span);
|
|
peri2->EndBulkLoad();
|
|
peri_list.push_back(*peri2);
|
|
t1 = t2;
|
|
peri2->DeleteIfAllowed();
|
|
path_list.push_back(elem.path);
|
|
tm_list.push_back(str_tm[elem.tm]);
|
|
bs1_list.push_back(str1);
|
|
bs2_list.push_back(str);
|
|
|
|
}
|
|
|
|
}
|
|
// cout<<" transfer "<<no_transfer<<" times "<<endl;
|
|
}else{
|
|
cout<<"bs1 ("<<*bs1<<") bs2 ("<<*bs2<<") not reachable "<<endl;
|
|
}
|
|
|
|
bn->CloseBusGraph(bg);
|
|
}
|
|
|
|
/*
|
|
shortest path from one bus stop to another in time
|
|
edge without any cost, id does not connect walk edge and no cost edge because
|
|
its previous node has expanded these edges
|
|
for the edge connected by moving buses, for a route which is accessed for the
|
|
first time, it records the searching time of the whole periods.
|
|
in this case, it does not have to start from the begin of the periods for a
|
|
bus stop
|
|
|
|
*/
|
|
void BNNav::ShortestPath_TimeNew(Bus_Stop* bs1, Bus_Stop* bs2, Instant* qt)
|
|
{
|
|
BusGraph* bg = bn->GetBusGraph();
|
|
if(bg == NULL){
|
|
cout<<"bus graph is invalid"<<endl;
|
|
return;
|
|
}
|
|
|
|
if(!bs1->IsDefined() || !bs2->IsDefined()){
|
|
cout<<" bus stops are not defined"<<endl;
|
|
return;
|
|
}
|
|
|
|
Point start_p, end_p;
|
|
bn->GetBusStopGeoData(bs1, &start_p);
|
|
bn->GetBusStopGeoData(bs2, &end_p);
|
|
const double delta_dist = 0.01;
|
|
|
|
if(*bs1 == *bs2 || start_p.Distance(end_p) < delta_dist){
|
|
cout<<"two bus stops equal to each other"<<endl;
|
|
bn->CloseBusGraph(bg);
|
|
return;
|
|
}
|
|
// cout<<*bs1<<" "<<*bs2<<" "<<*qt<<endl;
|
|
/////////////////////////////////////////////////////////////////////
|
|
////////// initialize counter for searhcing periods/////////////////
|
|
///////////////////////////////////////////////////////////////////
|
|
vector<int> counter_up;
|
|
vector<int> counter_down;
|
|
for(int i = 0;i < bn->GetBR_Rel()->GetNoTuples();i++){
|
|
counter_up.push_back(0);
|
|
counter_down.push_back(0);
|
|
}
|
|
// cout<<counter_up.size()<<endl;
|
|
|
|
/////////////////////////build the start time///////////////////////////
|
|
Instant new_st(instanttype);
|
|
Instant bg_min(instanttype);
|
|
bg_min.ReadFrom(bg->min_t);
|
|
|
|
assert(bg_min.GetWeekday() == 6);//start from Sunday
|
|
|
|
if(qt->GetWeekday() == 6){
|
|
new_st.Set(bg_min.GetYear(),bg_min.GetMonth(),bg_min.GetGregDay(),
|
|
qt->GetHour(), qt->GetMinute(), qt->GetSecond(),
|
|
qt->GetMillisecond());
|
|
// cout<<"Sunday"<<endl;
|
|
|
|
}else{ //Monday-Saturday
|
|
////////////////////////////to Monday///////////////////////
|
|
new_st.Set(bg_min.GetYear(),bg_min.GetMonth(),bg_min.GetGregDay() + 1,
|
|
qt->GetHour(), qt->GetMinute(), qt->GetSecond(),
|
|
qt->GetMillisecond());
|
|
// cout<<"workday --->Monday"<<endl;
|
|
}
|
|
// cout<<"mapping start time"<<new_st<<endl;
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
priority_queue<BNPath_elem> path_queue;
|
|
vector<BNPath_elem> expand_queue;
|
|
|
|
vector<bool> visit_flag1;////////////bus stop visit
|
|
for(int i = 1; i <= bg->node_rel->GetNoTuples();i++)
|
|
visit_flag1.push_back(false);
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
/////////////from bus network, get the maximum speed of the bus///
|
|
/////////////for setting heuristic value/////////////////////////
|
|
///////////////////////////////////////////////////////////////////
|
|
// cout<<"max bus speed "<<bn->GetMaxSpeed()*60.0*60.0/1000.0<<"km/h"<<endl;
|
|
|
|
/////////// initialize the queue //////////////////////////////
|
|
InitializeQueue2(bs1, bs2, path_queue, expand_queue, bn, bg, start_p, end_p);
|
|
|
|
int bs2_tid = bg->GetBusStop_Tid(bs2);
|
|
// cout<<"end bus stop tid "<<bs2_tid<<endl;
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
////////////////////search on the bus graph//////////////////////////
|
|
/////////////////////////////////////////////////////////////////////
|
|
bool find = false;
|
|
BNPath_elem dest;//////////destination
|
|
double speed_human = 1.0;
|
|
|
|
// int elem_count = 0;
|
|
|
|
while(path_queue.empty() == false){
|
|
BNPath_elem top = path_queue.top();
|
|
path_queue.pop();
|
|
|
|
// elem_count++;
|
|
|
|
if(visit_flag1[top.tri_index - 1])continue;
|
|
|
|
// top.Print();
|
|
|
|
if(top.tri_index == bs2_tid){
|
|
// cout<<"find the shortest path"<<endl;
|
|
find = true;
|
|
dest = top;
|
|
break;
|
|
}
|
|
int pos_expand_path;
|
|
int cur_size;
|
|
|
|
pos_expand_path = top.cur_index;
|
|
///////////////////////////////////////////////////////////////////////
|
|
//////////////////////connection 1 by pavements ///////////////////////
|
|
//////////////////////////////////////////////////////////////////////
|
|
if(top.tm == TM_BUS){
|
|
vector<int> adj_list1;
|
|
bg->FindAdj1(top.tri_index, adj_list1);
|
|
|
|
bool search_flag = true;
|
|
BNPath_elem temp_elem = top;
|
|
while(dest.prev_index != -1){
|
|
if(temp_elem.tm == TM_BUS){
|
|
break;
|
|
}
|
|
if(temp_elem.tm == TM_WALK){
|
|
search_flag = false;
|
|
break;
|
|
}
|
|
temp_elem = expand_queue[temp_elem.prev_index];
|
|
}
|
|
|
|
for(unsigned int i = 0;i < adj_list1.size() && search_flag;i++){
|
|
Tuple* edge_tuple = bg->edge_rel1->GetTuple(adj_list1[i], false);
|
|
int neighbor_id1 =
|
|
((CcInt*)edge_tuple->GetAttribute(BusGraph::BG_E_BS2_TID))->GetIntval();
|
|
SimpleLine* path =
|
|
(SimpleLine*)edge_tuple->GetAttribute(BusGraph::BG_PATH2);
|
|
|
|
if(visit_flag1[neighbor_id1 - 1]){
|
|
edge_tuple->DeleteIfAllowed();
|
|
continue;
|
|
}
|
|
|
|
cur_size = expand_queue.size();
|
|
|
|
double w = top.real_w + path->Length()/(speed_human*24.0*60.0*60.0);
|
|
|
|
Tuple* bs_node_tuple = bg->node_rel->GetTuple(neighbor_id1, false);
|
|
Point* p = (Point*)bs_node_tuple->GetAttribute(BusGraph::BG_NODE_GEO);
|
|
double hw = p->Distance(end_p)/(bn->GetMaxSpeed()*24.0*60.0*60.0);
|
|
bs_node_tuple->DeleteIfAllowed();
|
|
|
|
/* BNPath_elem elem(pos_expand_path, cur_size,neighbor_id1, w + hw, w,
|
|
*path, TM_WALK, true);*/
|
|
SimpleLine temp_sl(0);
|
|
BNPath_elem elem(pos_expand_path, cur_size,neighbor_id1, w + hw, w,
|
|
temp_sl, TM_WALK, true);
|
|
elem.type = TM_WALK;
|
|
elem.edge_tid = adj_list1[i];
|
|
////////////////////////////////////////////////////////////////
|
|
|
|
path_queue.push(elem);
|
|
expand_queue.push_back(elem);
|
|
edge_tuple->DeleteIfAllowed();
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
//////////////////////connection 2 same spatial location/////////////
|
|
////////////////////////////////////////////////////////////////////
|
|
// if(top.tm == TM_WALK || top.tm == TM_BUS){
|
|
if(top.tm == TM_BUS){
|
|
vector<int> adj_list2;
|
|
bg->FindAdj2(top.tri_index, adj_list2);
|
|
|
|
for(unsigned int i = 0;i < adj_list2.size();i++){
|
|
Tuple* edge_tuple = bg->edge_rel2->GetTuple(adj_list2[i], false);
|
|
int neighbor_id2 =
|
|
((CcInt*)edge_tuple->GetAttribute(BusGraph::BG_E2_BS2_TID))->GetIntval();
|
|
SimpleLine* path = new SimpleLine(0);
|
|
path->StartBulkLoad();
|
|
path->EndBulkLoad();
|
|
|
|
if(visit_flag1[neighbor_id2 - 1]){
|
|
edge_tuple->DeleteIfAllowed();
|
|
path->DeleteIfAllowed();
|
|
continue;
|
|
}
|
|
|
|
cur_size = expand_queue.size();
|
|
double w = top.real_w;
|
|
Tuple* bs_node_tuple = bg->node_rel->GetTuple(neighbor_id2, false);
|
|
Point* p = (Point*)bs_node_tuple->GetAttribute(BusGraph::BG_NODE_GEO);
|
|
double hw = p->Distance(end_p)/(bn->GetMaxSpeed()*24.0*60.0*60.0);
|
|
bs_node_tuple->DeleteIfAllowed();
|
|
|
|
|
|
/* BNPath_elem elem(pos_expand_path, cur_size, neighbor_id2, w + hw, w,
|
|
*path, -1, false); //not useful for time cost */
|
|
|
|
BNPath_elem elem(pos_expand_path, cur_size, neighbor_id2, w + hw, w,
|
|
*path, -1, false); //not useful for time cost
|
|
elem.type = -1;
|
|
elem.edge_tid = 0;
|
|
////////////////////////////////////////////////////////////////
|
|
|
|
path_queue.push(elem);
|
|
expand_queue.push_back(elem);
|
|
|
|
path->DeleteIfAllowed();
|
|
edge_tuple->DeleteIfAllowed();
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
////////////////////connection 3 moving buses/////////////////////////
|
|
//////////////////////////////////////////////////////////////////////
|
|
vector<int> adj_list3;
|
|
bg->FindAdj3(top.tri_index, adj_list3);
|
|
int64_t max_64_int = numeric_limits<int64_t>::max();
|
|
|
|
for(unsigned int i = 0;i < adj_list3.size();i++){
|
|
Tuple* edge_tuple = bg->edge_rel3->GetTuple(adj_list3[i], false);
|
|
int neighbor_id3 =
|
|
((CcInt*)edge_tuple->GetAttribute(BusGraph::BG_E3_BS2_TID))->GetIntval();
|
|
// SimpleLine* path =
|
|
// (SimpleLine*)edge_tuple->GetAttribute(BusGraph::BG_PATH3);
|
|
|
|
if(visit_flag1[neighbor_id3 - 1]){
|
|
edge_tuple->DeleteIfAllowed();
|
|
continue;
|
|
}
|
|
|
|
cur_size = expand_queue.size();
|
|
double cur_t = new_st.ToDouble() + top.real_w;
|
|
Instant cur_inst = new_st;
|
|
cur_inst.ReadFrom(cur_t); //time to arrive current bus stop
|
|
// cout<<"time at bus stop "<<cur_inst<<endl;
|
|
|
|
int64_t cur_t_int = cur_t*86400000;
|
|
assert(cur_t_int <= max_64_int);
|
|
|
|
Periods* peri =
|
|
(Periods*)edge_tuple->GetAttribute(BusGraph::BG_LIFETIME);
|
|
Interval<Instant> periods;
|
|
peri->Get(0, periods);
|
|
|
|
double sched =
|
|
((CcReal*)edge_tuple->GetAttribute(BusGraph::BG_SCHEDULE))->GetRealval();
|
|
double st = periods.start.ToDouble();
|
|
double et = periods.end.ToDouble();
|
|
int64_t st_int = st*86400000;
|
|
int64_t et_int = et*86400000;
|
|
assert(st_int <= max_64_int);
|
|
assert(et_int <= max_64_int);
|
|
|
|
|
|
if(et_int < cur_t_int){//end time smaller than curtime
|
|
edge_tuple->DeleteIfAllowed();
|
|
continue;
|
|
}
|
|
double wait_time = 0.0;
|
|
Tuple* bs_top_tuple = bg->node_rel->GetTuple(top.tri_index, false);
|
|
Bus_Stop* bs_top =
|
|
(Bus_Stop*)bs_top_tuple->GetAttribute(BusGraph::BG_NODE);
|
|
|
|
|
|
if(bs_top->GetUp()){
|
|
int last_record = counter_up[bs_top->GetId() - 1];
|
|
// cout<<"up "<<last_record<<endl;
|
|
|
|
st += sched * last_record;
|
|
st_int = st * 86400000;
|
|
|
|
}else{
|
|
int last_record = counter_down[bs_top->GetId() - 1];
|
|
// cout<<"down "<<last_record<<endl;
|
|
|
|
st += sched * last_record;
|
|
st_int = st * 86400000;
|
|
}
|
|
|
|
// temp.ReadFrom(st);
|
|
// cout<<"t2 "<<temp<<endl;
|
|
// cout<<st_int<<" "<<cur_t_int<<endl;
|
|
|
|
if(st_int > cur_t_int){//wait for the first start time
|
|
wait_time += st - cur_t;
|
|
wait_time += 30.0/(24.0*60.0*60.0);//30 seconds at bus stop
|
|
}else if(st_int == cur_t_int){
|
|
wait_time += 30.0/(24.0*60.0*60.0);//30 seconds at bus stop
|
|
}else{ //most times, it is here, wait for the next schedule
|
|
|
|
bool valid = false;
|
|
int record_count = 0;
|
|
while(st_int < cur_t_int && st_int <= et_int){
|
|
|
|
if((st_int + 30000) >= cur_t_int){//30 second
|
|
wait_time += st + 30.0/(24.0*60.0*60.0) - cur_t;
|
|
valid = true;
|
|
break;
|
|
}
|
|
st += sched;
|
|
st_int = st * 86400000;
|
|
|
|
if(st_int >= cur_t_int){
|
|
wait_time += st + 30.0/(24.0*60.0*60.0) - cur_t;
|
|
valid = true;
|
|
break;
|
|
}
|
|
assert(st_int <= max_64_int);
|
|
record_count++;
|
|
}
|
|
|
|
if(bs_top->GetUp()){
|
|
if(counter_up[bs_top->GetId() - 1] == 0) //for the first time
|
|
counter_up[bs_top->GetId() - 1] = record_count;
|
|
}else{
|
|
if(counter_down[bs_top->GetId() - 1] == 0) //for the first time
|
|
counter_down[bs_top->GetId() - 1] = record_count;
|
|
}
|
|
|
|
if(valid == false){
|
|
cout<<"should not arrive at here"<<endl;
|
|
assert(false);
|
|
}
|
|
}
|
|
|
|
bs_top_tuple->DeleteIfAllowed();
|
|
//////////////////////////////////////////////////////////////
|
|
|
|
double weight =
|
|
((CcReal*)edge_tuple->GetAttribute(BusGraph::BG_TIMECOST))->GetRealval();
|
|
double w = top.real_w + wait_time + weight;
|
|
|
|
Tuple* bs_node_tuple = bg->node_rel->GetTuple(neighbor_id3, false);
|
|
Point* p = (Point*)bs_node_tuple->GetAttribute(BusGraph::BG_NODE_GEO);
|
|
double hw = p->Distance(end_p)/(bn->GetMaxSpeed()*24.0*60.0*60.0);
|
|
bs_node_tuple->DeleteIfAllowed();
|
|
|
|
|
|
/* BNPath_elem elem(pos_expand_path, cur_size,neighbor_id3, w + hw, w,
|
|
*path, TM_BUS, true);*/
|
|
//////////////////////////////////////////////////////////////////
|
|
SimpleLine temp_sl(0);
|
|
BNPath_elem elem(pos_expand_path, cur_size,neighbor_id3, w + hw, w,
|
|
temp_sl, TM_BUS, true);
|
|
elem.type = TM_BUS;
|
|
elem.edge_tid = adj_list3[i];
|
|
/////////////////////////////////////////////////////////////
|
|
|
|
|
|
if(wait_time > 0.0){ //to the time waiting for bus
|
|
elem.SetW(top.real_w + wait_time);
|
|
}
|
|
|
|
path_queue.push(elem);
|
|
expand_queue.push_back(elem);
|
|
|
|
|
|
edge_tuple->DeleteIfAllowed();
|
|
|
|
}
|
|
|
|
visit_flag1[top.tri_index - 1] = true;
|
|
|
|
}
|
|
// cout<<elem_count<<" elements poped from queue"<<endl;
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
////////////////construct the result//////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////
|
|
if(find){ ////////constrcut the result
|
|
vector<int> id_list;
|
|
while(dest.prev_index != -1){
|
|
id_list.push_back(dest.cur_index);
|
|
dest = expand_queue[dest.prev_index];
|
|
}
|
|
|
|
id_list.push_back(dest.cur_index);
|
|
|
|
Bus_Stop bs_last = *bs1;
|
|
Instant t1 = *qt;
|
|
// int no_transfer = 0;
|
|
|
|
for(int i = id_list.size() - 1;i >= 0;i--){
|
|
BNPath_elem elem = expand_queue[id_list[i]];
|
|
////////////////////////////////////////////////////////////
|
|
if(elem.type == TM_WALK){
|
|
assert(1 <= elem.edge_tid &&
|
|
elem.edge_tid <= bg->edge_rel1->GetNoTuples());
|
|
Tuple* edge_tuple = bg->edge_rel1->GetTuple(elem.edge_tid, false);
|
|
SimpleLine* path =
|
|
(SimpleLine*)edge_tuple->GetAttribute(BusGraph::BG_PATH2);
|
|
elem.path = *path;
|
|
edge_tuple->DeleteIfAllowed();
|
|
|
|
}else if(elem.type == TM_BUS){
|
|
if(elem.edge_tid > 0){
|
|
Tuple* edge_tuple = bg->edge_rel3->GetTuple(elem.edge_tid, false);
|
|
SimpleLine* path =
|
|
(SimpleLine*)edge_tuple->GetAttribute(BusGraph::BG_PATH3);
|
|
elem.path = *path;
|
|
edge_tuple->DeleteIfAllowed();
|
|
}
|
|
|
|
}else if(elem.type == -1){
|
|
|
|
}else{
|
|
cout<<"should not be here"<<endl;
|
|
assert(false);
|
|
}
|
|
////////////////////////////////////////////////////////////
|
|
|
|
|
|
path_list.push_back(elem.path);
|
|
|
|
if(elem.tm == TM_WALK){
|
|
tm_list.push_back(str_tm[elem.tm]);
|
|
}else if(elem.tm == TM_BUS){
|
|
tm_list.push_back(str_tm[elem.tm]);
|
|
}else{
|
|
// assert(false);
|
|
tm_list.push_back("none");
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
////////////////we also return///////////////////////////////////////
|
|
////////the start and end bus stops connected by the path ////////////
|
|
////////////////////////////////////////////////////////////////////
|
|
char buf1[256], buf2[256];
|
|
|
|
sprintf(buf1, "br: %d ", bs_last.GetId());
|
|
sprintf(buf2, "stop: %d", bs_last.GetStopId());
|
|
strcat (buf1, buf2);
|
|
if(bs_last.GetUp())strcat (buf1, " UP");
|
|
else strcat (buf1, " DOWN");
|
|
|
|
string str1(buf1);
|
|
bs1_list.push_back(str1);
|
|
|
|
if(i == (int)(id_list.size() - 1)){
|
|
string str2(str1);
|
|
bs2_list.push_back(str2);
|
|
|
|
}else{////////////////the end bus stop
|
|
|
|
Tuple* bs_tuple = bg->node_rel->GetTuple(elem.tri_index, false);
|
|
Bus_Stop* bs_cur =
|
|
(Bus_Stop*)bs_tuple->GetAttribute(BusGraph::BG_NODE);
|
|
char buf_1[256], buf_2[256];
|
|
sprintf(buf_1, "br: %d ", bs_cur->GetId());
|
|
sprintf(buf_2, "stop: %d", bs_cur->GetStopId());
|
|
strcat (buf_1, buf_2);
|
|
if(bs_cur->GetUp()) strcat (buf_1, " UP");
|
|
else strcat (buf_1, " DOWN");
|
|
|
|
string str2(buf_1);
|
|
bs2_list.push_back(str2);
|
|
bs_last = *bs_cur;
|
|
bs_tuple->DeleteIfAllowed();
|
|
}
|
|
|
|
////////////////time duration////////////////////////////////
|
|
|
|
Instant t2(instanttype);
|
|
if(elem.b_w == false){
|
|
t2.ReadFrom(elem.real_w + qt->ToDouble());
|
|
// cout<<t1<<" "<<t2<<endl;
|
|
|
|
//time cost in seconds
|
|
if(elem.valid)
|
|
time_cost_list.push_back((t2.ToDouble() - t1.ToDouble())*86400.0);
|
|
else //doing transfer without moving
|
|
time_cost_list.push_back(0.0);
|
|
Interval<Instant> time_span;
|
|
time_span.start = t1;
|
|
time_span.lc = true;
|
|
time_span.end = t2;
|
|
time_span.rc = false;
|
|
|
|
Periods* peri = new Periods(0);
|
|
peri->StartBulkLoad();
|
|
if(elem.valid)
|
|
peri->MergeAdd(time_span);
|
|
peri->EndBulkLoad();
|
|
peri_list.push_back(*peri);
|
|
t1 = t2;
|
|
peri->DeleteIfAllowed();
|
|
}else{ //////////to dinstinguish time of waiting for the bus
|
|
t2.ReadFrom(elem.w + qt->ToDouble());
|
|
// cout<<t1<<" "<<t2<<endl;
|
|
|
|
//time cost in seconds
|
|
if(elem.valid)
|
|
time_cost_list.push_back((t2.ToDouble() - t1.ToDouble())*86400.0);
|
|
else //doing transfer without moving
|
|
time_cost_list.push_back(0.0);
|
|
Interval<Instant> time_span;
|
|
time_span.start = t1;
|
|
time_span.lc = true;
|
|
time_span.end = t2;
|
|
time_span.rc = false;
|
|
|
|
Periods* peri1 = new Periods(0);
|
|
peri1->StartBulkLoad();
|
|
if(elem.valid)
|
|
peri1->MergeAdd(time_span);
|
|
peri1->EndBulkLoad();
|
|
peri_list.push_back(*peri1);
|
|
t1 = t2;
|
|
peri1->DeleteIfAllowed();
|
|
|
|
SimpleLine* sl = new SimpleLine(0);
|
|
sl->StartBulkLoad();
|
|
sl->EndBulkLoad();
|
|
path_list[path_list.size() - 1] = *sl;
|
|
sl->DeleteIfAllowed();
|
|
|
|
tm_list[tm_list.size() - 1] = "none"; //waiting is no tm
|
|
string str = bs2_list[bs2_list.size() - 1];
|
|
////////the same as last bus stop //////////////////////
|
|
bs2_list[bs2_list.size() - 1] = bs1_list[bs1_list.size() - 1];
|
|
|
|
|
|
/////////////moving with bus////////////////////////////////
|
|
t2.ReadFrom(elem.real_w + qt->ToDouble());
|
|
// cout<<t1<<" "<<t2<<endl;
|
|
|
|
//time cost in seconds
|
|
if(elem.valid)
|
|
time_cost_list.push_back((t2.ToDouble() - t1.ToDouble())*86400.0);
|
|
else //doing transfer without moving
|
|
time_cost_list.push_back(0.0);
|
|
|
|
time_span.start = t1;
|
|
time_span.lc = true;
|
|
time_span.end = t2;
|
|
time_span.rc = false;
|
|
|
|
Periods* peri2 = new Periods(0);
|
|
peri2->StartBulkLoad();
|
|
if(elem.valid)
|
|
peri2->MergeAdd(time_span);
|
|
peri2->EndBulkLoad();
|
|
peri_list.push_back(*peri2);
|
|
t1 = t2;
|
|
peri2->DeleteIfAllowed();
|
|
path_list.push_back(elem.path);
|
|
tm_list.push_back(str_tm[elem.tm]);
|
|
bs1_list.push_back(str1);
|
|
bs2_list.push_back(str);
|
|
|
|
}
|
|
|
|
}
|
|
// cout<<" transfer "<<no_transfer<<" times "<<endl;
|
|
}else{
|
|
cout<<"bs1 ("<<*bs1<<") bs2 ("<<*bs2<<") not reachable "<<endl;
|
|
}
|
|
|
|
bn->CloseBusGraph(bg);
|
|
}
|
|
|
|
/*
|
|
initialize the queue: shortest path in time
|
|
|
|
*/
|
|
void BNNav::InitializeQueue2(Bus_Stop* bs1, Bus_Stop* bs2,
|
|
priority_queue<BNPath_elem>& path_queue,
|
|
vector<BNPath_elem>& expand_queue,
|
|
BusNetwork* bn, BusGraph* bg,
|
|
Point& start_p, Point& end_p)
|
|
{
|
|
int cur_size = expand_queue.size();
|
|
double w = 0.0;
|
|
|
|
double hw = start_p.Distance(end_p)/(bn->GetMaxSpeed()*24.0*60.0*60.0);
|
|
// double hw = 0.0;
|
|
|
|
SimpleLine* sl = new SimpleLine(0);
|
|
sl->StartBulkLoad();
|
|
sl->EndBulkLoad();
|
|
|
|
int bs_tid = bg->GetBusStop_Tid(bs1);
|
|
// cout<<"start bus stop tid "<<bs_tid<<endl;
|
|
//////////////////no time cost////////////////////////////////////
|
|
BNPath_elem elem(-1, cur_size, bs_tid, w + hw, w, *sl, TM_BUS, false);
|
|
|
|
elem.type = TM_BUS;//////start condition
|
|
elem.edge_tid = 0;////initial condition
|
|
|
|
path_queue.push(elem);
|
|
expand_queue.push_back(elem);
|
|
sl->DeleteIfAllowed();
|
|
}
|
|
|
|
/*
|
|
shortest path from one bus stop to another in time
|
|
for the start bus stop, it does not consider the walk segment connection
|
|
|
|
*/
|
|
void BNNav::ShortestPath_Time2(Bus_Stop* bs1, Bus_Stop* bs2, Instant* qt)
|
|
{
|
|
|
|
BusGraph* bg = bn->GetBusGraph();
|
|
if(bg == NULL){
|
|
cout<<"bus graph is invalid"<<endl;
|
|
return;
|
|
}
|
|
|
|
if(!bs1->IsDefined() || !bs2->IsDefined()){
|
|
cout<<" bus stops are not defined"<<endl;
|
|
return;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
////////// initialize counter for searhcing periods/////////////////
|
|
///////////////////////////////////////////////////////////////////
|
|
/* vector<int> counter_up;
|
|
vector<int> counter_down;
|
|
for(int i = 0;i < bn->GetBR_Rel()->GetNoTuples();i++){
|
|
counter_up.push_back(0);
|
|
counter_down.push_back(0);
|
|
}*/
|
|
|
|
vector<int> counter_up(bn->GetBR_Rel()->GetNoTuples(), 0);
|
|
vector<int> counter_down(bn->GetBR_Rel()->GetNoTuples(), 0);
|
|
|
|
Point start_p, end_p;
|
|
bn->GetBusStopGeoData(bs1, &start_p);
|
|
bn->GetBusStopGeoData(bs2, &end_p);
|
|
const double delta_dist = 0.01;
|
|
|
|
if(*bs1 == *bs2 || start_p.Distance(end_p) < delta_dist){
|
|
cout<<"two bus stops equal to each other"<<endl;
|
|
bn->CloseBusGraph(bg);
|
|
return;
|
|
}
|
|
/////////////////////////build the start time///////////////////////////
|
|
Instant new_st(instanttype);
|
|
Instant bg_min(instanttype);
|
|
bg_min.ReadFrom(bg->min_t);
|
|
|
|
assert(bg_min.GetWeekday() == 6);//start from Sunday
|
|
|
|
if(qt->GetWeekday() == 6){
|
|
new_st.Set(bg_min.GetYear(),bg_min.GetMonth(),bg_min.GetGregDay(),
|
|
qt->GetHour(), qt->GetMinute(), qt->GetSecond(),
|
|
qt->GetMillisecond());
|
|
// cout<<"Sunday"<<endl;
|
|
|
|
}else{ //Monday-Saturday
|
|
////////////////////////////to Monday///////////////////////
|
|
new_st.Set(bg_min.GetYear(),bg_min.GetMonth(),bg_min.GetGregDay() + 1,
|
|
qt->GetHour(), qt->GetMinute(), qt->GetSecond(),
|
|
qt->GetMillisecond());
|
|
// cout<<"workday --->Monday"<<endl;
|
|
}
|
|
// cout<<"mapping start time"<<new_st<<endl;
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
priority_queue<BNPath_elem> path_queue;
|
|
vector<BNPath_elem> expand_queue;
|
|
|
|
/* vector<bool> visit_flag1;////////////bus stop visit
|
|
vector<bool> visit_flag2;
|
|
vector<int> visit_flag3;
|
|
vector<string> tm_list1;
|
|
vector<string> tm_list2;
|
|
for(int i = 1; i <= bg->node_rel->GetNoTuples();i++){
|
|
visit_flag1.push_back(false);
|
|
visit_flag2.push_back(false);
|
|
visit_flag3.push_back(0);
|
|
tm_list1.push_back("empty");
|
|
tm_list2.push_back("empty");
|
|
}*/
|
|
|
|
vector<bool> visit_flag1(bg->node_rel->GetNoTuples(), false);
|
|
vector<bool> visit_flag2(bg->node_rel->GetNoTuples(), false);
|
|
vector<int> visit_flag3(bg->node_rel->GetNoTuples(), 0);
|
|
vector<string> tm_list1(bg->node_rel->GetNoTuples(), "empty");
|
|
vector<string> tm_list2(bg->node_rel->GetNoTuples(), "empty");
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
/////////////from bus network, get the maximum speed of the bus///
|
|
/////////////for setting heuristic value/////////////////////////
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
/////////// initialize the queue //////////////////////////////
|
|
InitializeQueue2(bs1, bs2, path_queue, expand_queue, bn, bg, start_p, end_p);
|
|
|
|
int bs2_tid = bg->GetBusStop_Tid(bs2);
|
|
// cout<<"end bus stop tid "<<bs2_tid<<endl;
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
////////////////////search on the bus graph//////////////////////////
|
|
/////////////////////////////////////////////////////////////////////
|
|
bool find = false;
|
|
BNPath_elem dest;//////////destination
|
|
double speed_human = 1.0;
|
|
const double delta_t = 0.001;
|
|
|
|
while(path_queue.empty() == false){
|
|
BNPath_elem top = path_queue.top();
|
|
path_queue.pop();
|
|
|
|
if(visit_flag1[top.tri_index - 1]) continue;
|
|
|
|
// top.Print();
|
|
|
|
if(top.tri_index == bs2_tid){
|
|
find = true;
|
|
dest = top;
|
|
break;
|
|
}
|
|
int pos_expand_path;
|
|
int cur_size;
|
|
pos_expand_path = top.cur_index;
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
//////////////////////connection 1 by pavements ///////////////////////
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
////for the first bus stop, do not consider walk segment////////////
|
|
if(top.real_w > delta_t){
|
|
|
|
if(top.tm == TM_BUS){
|
|
bool search_flag = true;
|
|
BNPath_elem temp_elem = top;
|
|
|
|
while(temp_elem.prev_index != -1){
|
|
if(temp_elem.tm == TM_BUS){
|
|
break;
|
|
}
|
|
if(temp_elem.tm == TM_WALK){
|
|
search_flag = false;
|
|
break;
|
|
}
|
|
temp_elem = expand_queue[temp_elem.prev_index];
|
|
}
|
|
|
|
vector<int> adj_list1;
|
|
bg->FindAdj1(top.tri_index, adj_list1);
|
|
|
|
for(unsigned int i = 0;i < adj_list1.size() && search_flag;i++){
|
|
Tuple* edge_tuple = bg->edge_rel1->GetTuple(adj_list1[i], false);
|
|
int neighbor_id1 =
|
|
((CcInt*)edge_tuple->GetAttribute(BusGraph::BG_E_BS2_TID))->GetIntval();
|
|
SimpleLine* path =
|
|
(SimpleLine*)edge_tuple->GetAttribute(BusGraph::BG_PATH2);
|
|
|
|
if(visit_flag1[neighbor_id1 - 1]){
|
|
edge_tuple->DeleteIfAllowed();
|
|
continue;
|
|
}
|
|
|
|
cur_size = expand_queue.size();
|
|
|
|
double w = top.real_w + path->Length()/(speed_human*24.0*60.0*60.0);
|
|
|
|
Tuple* bs_node_tuple = bg->node_rel->GetTuple(neighbor_id1, false);
|
|
Point* p = (Point*)bs_node_tuple->GetAttribute(BusGraph::BG_NODE_GEO);
|
|
double hw = p->Distance(end_p)/(bn->GetMaxSpeed()*24.0*60.0*60.0);
|
|
bs_node_tuple->DeleteIfAllowed();
|
|
|
|
|
|
// BNPath_elem elem(pos_expand_path, cur_size,neighbor_id1, w + hw, w,
|
|
// *path, TM_WALK, true);
|
|
/////////////////////////////////////////////////////
|
|
SimpleLine temp_sl(0);
|
|
BNPath_elem elem(pos_expand_path, cur_size,neighbor_id1, w + hw, w,
|
|
temp_sl, TM_WALK, true);
|
|
elem.type = TM_WALK;
|
|
elem.edge_tid = adj_list1[i];
|
|
//////////////////////////////////////////////
|
|
|
|
path_queue.push(elem);
|
|
expand_queue.push_back(elem);
|
|
edge_tuple->DeleteIfAllowed();
|
|
|
|
|
|
if(visit_flag1[neighbor_id1 - 1] == 0)
|
|
tm_list1[neighbor_id1 - 1] = "walk";
|
|
else
|
|
tm_list2[neighbor_id1 - 1] = "walk";
|
|
|
|
visit_flag3[neighbor_id1 - 1]++;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
//////////////////////connection 2 same spatial location/////////////
|
|
////////////////////////////////////////////////////////////////////
|
|
// if(top.tm == TM_WALK || top.tm == TM_BUS){
|
|
if(top.tm == TM_BUS){
|
|
vector<int> adj_list2;
|
|
bg->FindAdj2(top.tri_index, adj_list2);
|
|
|
|
for(unsigned int i = 0;i < adj_list2.size();i++){
|
|
Tuple* edge_tuple = bg->edge_rel2->GetTuple(adj_list2[i], false);
|
|
int neighbor_id2 =
|
|
((CcInt*)edge_tuple->GetAttribute(BusGraph::BG_E2_BS2_TID))->GetIntval();
|
|
|
|
if(visit_flag1[neighbor_id2 - 1]){
|
|
edge_tuple->DeleteIfAllowed();
|
|
continue;
|
|
}
|
|
|
|
if(visit_flag2[neighbor_id2 - 1]){
|
|
edge_tuple->DeleteIfAllowed();
|
|
continue;
|
|
}
|
|
|
|
SimpleLine* path = new SimpleLine(0);
|
|
path->StartBulkLoad();
|
|
path->EndBulkLoad();
|
|
|
|
cur_size = expand_queue.size();
|
|
double w = top.real_w;
|
|
Tuple* bs_node_tuple = bg->node_rel->GetTuple(neighbor_id2, false);
|
|
Point* p = (Point*)bs_node_tuple->GetAttribute(BusGraph::BG_NODE_GEO);
|
|
double hw = p->Distance(end_p)/(bn->GetMaxSpeed()*24.0*60.0*60.0);
|
|
bs_node_tuple->DeleteIfAllowed();
|
|
|
|
|
|
/* BNPath_elem elem(pos_expand_path, cur_size, neighbor_id2, w + hw, w,
|
|
*path, -1, false); //-1, not useful for time cost */
|
|
|
|
///////////////////////////////////////
|
|
BNPath_elem elem(pos_expand_path, cur_size, neighbor_id2, w + hw, w,
|
|
*path, -1, false); //-1, not useful for time cost
|
|
elem.type = -1;
|
|
elem.edge_tid = 0;
|
|
//////////////////////////////////////////////
|
|
path_queue.push(elem);
|
|
expand_queue.push_back(elem);
|
|
|
|
path->DeleteIfAllowed();
|
|
edge_tuple->DeleteIfAllowed();
|
|
|
|
|
|
if(visit_flag3[neighbor_id2 - 1] == 0)
|
|
tm_list1[neighbor_id2 - 1] = "none";
|
|
else
|
|
tm_list2[neighbor_id2 - 1] = "none";
|
|
|
|
visit_flag2[neighbor_id2 - 1] = true;
|
|
|
|
visit_flag3[neighbor_id2 - 1]++;
|
|
}
|
|
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
////////////////////connection 3 moving buses/////////////////////////
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
vector<int> adj_list3;
|
|
bg->FindAdj3(top.tri_index, adj_list3);
|
|
int64_t max_64_int = numeric_limits<int64_t>::max();
|
|
|
|
for(unsigned int i = 0;i < adj_list3.size();i++){
|
|
Tuple* edge_tuple = bg->edge_rel3->GetTuple(adj_list3[i], false);
|
|
int neighbor_id3 =
|
|
((CcInt*)edge_tuple->GetAttribute(BusGraph::BG_E3_BS2_TID))->GetIntval();
|
|
|
|
if(visit_flag1[neighbor_id3 - 1]){
|
|
edge_tuple->DeleteIfAllowed();
|
|
continue;
|
|
}
|
|
|
|
|
|
cur_size = expand_queue.size();
|
|
double cur_t = new_st.ToDouble() + top.real_w;
|
|
Instant cur_inst = new_st;
|
|
cur_inst.ReadFrom(cur_t); //time to arrive current bus stop
|
|
// cout<<"time at bus stop "<<cur_inst<<endl;
|
|
|
|
int64_t cur_t_int = cur_t*86400000;
|
|
assert(cur_t_int <= max_64_int);
|
|
|
|
Periods* peri =
|
|
(Periods*)edge_tuple->GetAttribute(BusGraph::BG_LIFETIME);
|
|
Interval<Instant> periods;
|
|
peri->Get(0, periods);
|
|
|
|
double sched =
|
|
((CcReal*)edge_tuple->GetAttribute(BusGraph::BG_SCHEDULE))->GetRealval();
|
|
double st = periods.start.ToDouble();
|
|
double et = periods.end.ToDouble();
|
|
int64_t st_int = st*86400000;
|
|
int64_t et_int = et*86400000;
|
|
assert(st_int <= max_64_int);
|
|
assert(et_int <= max_64_int);
|
|
|
|
// cout<<"st "<<periods.start<<" et "<<periods.end<<endl;
|
|
|
|
if(et_int < cur_t_int){//end time smaller than curtime
|
|
edge_tuple->DeleteIfAllowed();
|
|
continue;
|
|
}
|
|
|
|
|
|
double wait_time = 0.0;
|
|
///////////////////////////////////////////////////////////////
|
|
Tuple* bs_top_tuple = bg->node_rel->GetTuple(top.tri_index, false);
|
|
Bus_Stop* bs_top =
|
|
(Bus_Stop*)bs_top_tuple->GetAttribute(BusGraph::BG_NODE);
|
|
|
|
if(bs_top->GetUp()){
|
|
int last_record = counter_up[bs_top->GetId() - 1];
|
|
st += sched*last_record;
|
|
st_int = st*86400000;
|
|
}else{
|
|
int last_record = counter_down[bs_top->GetId() - 1];
|
|
st += sched*last_record;
|
|
st_int = st*86400000;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////
|
|
|
|
if(st_int > cur_t_int){//wait for the first start time
|
|
wait_time += st - cur_t;
|
|
wait_time += 30.0/(24.0*60.0*60.0);//30 seconds at bus stop
|
|
}else if(st_int == cur_t_int){
|
|
wait_time += 30.0/(24.0*60.0*60.0);//30 seconds at bus stop
|
|
}else{ //most times, it is here, wait for the next schedule
|
|
|
|
bool valid = false;
|
|
int record_count = 0;
|
|
while(st_int < cur_t_int && st_int <= et_int){
|
|
|
|
/* Instant temp(instanttype);
|
|
temp.ReadFrom(st);
|
|
cout<<"t1 "<<temp<<endl; */
|
|
|
|
if((st_int + 30000) >= cur_t_int){//30 second
|
|
wait_time += st + 30.0/(24.0*60.0*60.0) - cur_t;
|
|
valid = true;
|
|
break;
|
|
}
|
|
st += sched;
|
|
st_int = st * 86400000;
|
|
if(st_int >= cur_t_int){
|
|
wait_time += st + 30.0/(24.0*60.0*60.0) - cur_t;
|
|
valid = true;
|
|
break;
|
|
}
|
|
assert(st_int <= max_64_int);
|
|
record_count++;
|
|
|
|
// temp.ReadFrom(st);
|
|
// cout<<"t2 "<<temp<<endl;
|
|
}
|
|
|
|
if(bs_top->GetUp()){
|
|
if(counter_up[bs_top->GetId() - 1] == 0)
|
|
counter_up[bs_top->GetId() - 1] = record_count;
|
|
}else{
|
|
if(counter_down[bs_top->GetId() - 1] == 0)
|
|
counter_down[bs_top->GetId() - 1] = record_count;
|
|
}
|
|
|
|
if(valid == false){
|
|
cout<<"should not arrive at here"<<endl;
|
|
assert(false);
|
|
}
|
|
}////////end else
|
|
|
|
bs_top_tuple->DeleteIfAllowed();
|
|
|
|
// SimpleLine* path =
|
|
// (SimpleLine*)edge_tuple->GetAttribute(BusGraph::BG_PATH3);
|
|
|
|
double weight =
|
|
((CcReal*)edge_tuple->GetAttribute(BusGraph::BG_TIMECOST))->GetRealval();
|
|
double w = top.real_w + wait_time + weight;
|
|
|
|
Tuple* bs_node_tuple = bg->node_rel->GetTuple(neighbor_id3, false);
|
|
Point* p = (Point*)bs_node_tuple->GetAttribute(BusGraph::BG_NODE_GEO);
|
|
double hw = p->Distance(end_p)/(bn->GetMaxSpeed()*24.0*60.0*60.0);
|
|
bs_node_tuple->DeleteIfAllowed();
|
|
|
|
|
|
/* BNPath_elem elem(pos_expand_path, cur_size,neighbor_id3, w + hw, w,
|
|
*path, TM_BUS, true);*/
|
|
/////////////////////////////////////////////////////
|
|
SimpleLine temp_sl(0);
|
|
BNPath_elem elem(pos_expand_path, cur_size,neighbor_id3, w + hw, w,
|
|
temp_sl, TM_BUS, true);
|
|
elem.type = TM_BUS;
|
|
elem.edge_tid = adj_list3[i];
|
|
//////////////////////////////////////////////////////
|
|
|
|
if(wait_time > 0.0){ //to the time waiting for bus
|
|
elem.SetW(top.real_w + wait_time);
|
|
}
|
|
|
|
path_queue.push(elem);
|
|
expand_queue.push_back(elem);
|
|
edge_tuple->DeleteIfAllowed();
|
|
|
|
if(visit_flag3[neighbor_id3 - 1] == 0)
|
|
tm_list1[neighbor_id3 - 1] = "bus";
|
|
else
|
|
tm_list2[neighbor_id3 - 1] = "bus";
|
|
|
|
visit_flag3[neighbor_id3 - 1]++;
|
|
|
|
}
|
|
|
|
visit_flag1[top.tri_index - 1] = true;
|
|
}
|
|
|
|
|
|
|
|
|
|
// for(unsigned int i = 0;i < visit_flag3.size();i++){
|
|
// if(visit_flag3[i] > 1) {
|
|
// cout<<visit_flag3[i]<<" "<<tm_list1[i]<<" "<<tm_list2[i]<<endl;
|
|
// }
|
|
// }
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
////////////////construct the result//////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////
|
|
if(find){ ///constrcut the result
|
|
vector<int> id_list;
|
|
while(dest.prev_index != -1){
|
|
id_list.push_back(dest.cur_index);
|
|
dest = expand_queue[dest.prev_index];
|
|
}
|
|
|
|
id_list.push_back(dest.cur_index);
|
|
|
|
Bus_Stop bs_last = *bs1;
|
|
Instant t1 = *qt;
|
|
// int no_transfer = 0;
|
|
|
|
t_cost = 0.0;
|
|
for(int i = id_list.size() - 1;i >= 0;i--){
|
|
BNPath_elem elem = expand_queue[id_list[i]];
|
|
////////////////////////////////////////////////////////////
|
|
if(elem.type == TM_WALK){
|
|
assert(1 <= elem.edge_tid &&
|
|
elem.edge_tid <= bg->edge_rel1->GetNoTuples());
|
|
Tuple* edge_tuple = bg->edge_rel1->GetTuple(elem.edge_tid, false);
|
|
SimpleLine* path =
|
|
(SimpleLine*)edge_tuple->GetAttribute(BusGraph::BG_PATH2);
|
|
elem.path = *path;
|
|
edge_tuple->DeleteIfAllowed();
|
|
|
|
}else if(elem.type == TM_BUS){
|
|
if(elem.edge_tid > 0){
|
|
Tuple* edge_tuple = bg->edge_rel3->GetTuple(elem.edge_tid, false);
|
|
SimpleLine* path =
|
|
(SimpleLine*)edge_tuple->GetAttribute(BusGraph::BG_PATH3);
|
|
elem.path = *path;
|
|
edge_tuple->DeleteIfAllowed();
|
|
}
|
|
|
|
}else if(elem.type == -1){
|
|
|
|
}else{
|
|
cout<<"should not be here"<<endl;
|
|
assert(false);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////
|
|
path_list.push_back(elem.path);
|
|
|
|
if(elem.tm == TM_WALK){
|
|
tm_list.push_back(str_tm[elem.tm]);
|
|
}else if(elem.tm == TM_BUS){
|
|
tm_list.push_back(str_tm[elem.tm]);
|
|
}else{
|
|
// assert(false);
|
|
tm_list.push_back("none");
|
|
}
|
|
|
|
// cout<<" elem.valid "<<elem.valid<<endl;
|
|
////////////////////////////////////////////////////////////////////
|
|
////////////////we also return//////////////////////////////////////
|
|
////////the start and end bus stops connected by the path //////////
|
|
////////////////////////////////////////////////////////////////////
|
|
char buf1[256], buf2[256];
|
|
|
|
sprintf(buf1, "br: %d ", bs_last.GetId());
|
|
sprintf(buf2, "stop: %d", bs_last.GetStopId());
|
|
strcat (buf1, buf2);
|
|
if(bs_last.GetUp())strcat (buf1, " UP");
|
|
else strcat (buf1, " DOWN");
|
|
|
|
string str1(buf1);
|
|
bs1_list.push_back(str1);
|
|
|
|
if(i == (int)(id_list.size() - 1)){
|
|
string str2(str1);
|
|
bs2_list.push_back(str2);
|
|
|
|
}else{////////////////the end bus stop
|
|
|
|
Tuple* bs_tuple = bg->node_rel->GetTuple(elem.tri_index, false);
|
|
Bus_Stop* bs_cur =
|
|
(Bus_Stop*)bs_tuple->GetAttribute(BusGraph::BG_NODE);
|
|
char buf_1[256], buf_2[256];
|
|
sprintf(buf_1, "br: %d ", bs_cur->GetId());
|
|
sprintf(buf_2, "stop: %d", bs_cur->GetStopId());
|
|
strcat (buf_1, buf_2);
|
|
if(bs_cur->GetUp()) strcat (buf_1, " UP");
|
|
else strcat (buf_1, " DOWN");
|
|
|
|
string str2(buf_1);
|
|
bs2_list.push_back(str2);
|
|
bs_last = *bs_cur;
|
|
bs_tuple->DeleteIfAllowed();
|
|
}
|
|
|
|
////////////////time duration////////////////////////////////
|
|
|
|
Instant t2(instanttype);
|
|
if(elem.b_w == false){
|
|
t2.ReadFrom(elem.real_w + qt->ToDouble());
|
|
// cout<<t1<<" "<<t2<<endl;
|
|
|
|
Interval<Instant> time_span;
|
|
time_span.start = t1;
|
|
time_span.lc = true;
|
|
time_span.end = t2;
|
|
time_span.rc = false;
|
|
|
|
//time cost in seconds
|
|
// if(elem.valid){
|
|
if(elem.valid && time_span.IsValid()){
|
|
time_cost_list.push_back((t2.ToDouble() - t1.ToDouble())*86400.0);
|
|
t_cost += (t2.ToDouble() - t1.ToDouble())*86400.0;
|
|
}else{ //doing transfer without moving
|
|
time_cost_list.push_back(0.0);
|
|
t_cost += 0.0;
|
|
}
|
|
|
|
Periods* peri = new Periods(0);
|
|
peri->StartBulkLoad();
|
|
// cout<<time_span<<endl;
|
|
// if(elem.valid)
|
|
if(elem.valid && time_span.IsValid())
|
|
peri->MergeAdd(time_span);
|
|
peri->EndBulkLoad();
|
|
peri_list.push_back(*peri);
|
|
t1 = t2;
|
|
peri->DeleteIfAllowed();
|
|
}else{ //////////to dinstinguish time of waiting for the bus
|
|
t2.ReadFrom(elem.w + qt->ToDouble());
|
|
// cout<<t1<<" "<<t2<<endl;
|
|
|
|
Interval<Instant> time_span;
|
|
time_span.start = t1;
|
|
time_span.lc = true;
|
|
time_span.end = t2;
|
|
time_span.rc = false;
|
|
|
|
//time cost in seconds
|
|
// if(elem.valid){
|
|
if(elem.valid && time_span.IsValid()){
|
|
time_cost_list.push_back((t2.ToDouble() - t1.ToDouble())*86400.0);
|
|
t_cost += (t2.ToDouble() - t1.ToDouble())*86400.0;
|
|
}else{ //doing transfer without moving
|
|
time_cost_list.push_back(0.0);
|
|
t_cost += 0.0;
|
|
}
|
|
|
|
Periods* peri1 = new Periods(0);
|
|
peri1->StartBulkLoad();
|
|
// if(elem.valid)
|
|
if(elem.valid && time_span.IsValid())
|
|
peri1->MergeAdd(time_span);
|
|
peri1->EndBulkLoad();
|
|
peri_list.push_back(*peri1);
|
|
t1 = t2;
|
|
peri1->DeleteIfAllowed();
|
|
|
|
SimpleLine* sl = new SimpleLine(0);
|
|
sl->StartBulkLoad();
|
|
sl->EndBulkLoad();
|
|
path_list[path_list.size() - 1] = *sl;
|
|
sl->DeleteIfAllowed();
|
|
|
|
tm_list[tm_list.size() - 1] = "none"; //waiting is no tm
|
|
string str = bs2_list[bs2_list.size() - 1];
|
|
////////the same as last bus stop //////////////////////
|
|
bs2_list[bs2_list.size() - 1] = bs1_list[bs1_list.size() - 1];
|
|
|
|
|
|
/////////////moving with bus////////////////////////////////
|
|
t2.ReadFrom(elem.real_w + qt->ToDouble());
|
|
// cout<<t1<<" "<<t2<<endl;
|
|
|
|
time_span.start = t1;
|
|
time_span.lc = true;
|
|
time_span.end = t2;
|
|
time_span.rc = false;
|
|
|
|
//time cost in seconds
|
|
// if(elem.valid){
|
|
if(elem.valid && time_span.IsValid()){
|
|
time_cost_list.push_back((t2.ToDouble() - t1.ToDouble())*86400.0);
|
|
t_cost += (t2.ToDouble() - t1.ToDouble())*86400.0;
|
|
}else{ //doing transfer without moving
|
|
time_cost_list.push_back(0.0);
|
|
t_cost += 0.0;
|
|
}
|
|
|
|
|
|
Periods* peri2 = new Periods(0);
|
|
peri2->StartBulkLoad();
|
|
// if(elem.valid)
|
|
if(elem.valid && time_span.IsValid())
|
|
peri2->MergeAdd(time_span);
|
|
peri2->EndBulkLoad();
|
|
peri_list.push_back(*peri2);
|
|
t1 = t2;
|
|
peri2->DeleteIfAllowed();
|
|
path_list.push_back(elem.path);
|
|
tm_list.push_back(str_tm[elem.tm]);
|
|
bs1_list.push_back(str1);
|
|
bs2_list.push_back(str);
|
|
|
|
}
|
|
|
|
}
|
|
// cout<<" transfer "<<no_transfer<<" times "<<endl;
|
|
}else{
|
|
// cout<<"bs1 ("<<*bs1<<") bs2 ("<<*bs2<<") not reachable "<<endl;
|
|
}
|
|
|
|
bn->CloseBusGraph(bg);
|
|
}
|
|
|
|
|
|
/*
|
|
shortest path from one bus stop to another in bus transfer
|
|
|
|
*/
|
|
void BNNav::ShortestPath_Transfer(Bus_Stop* bs1, Bus_Stop* bs2, Instant* qt)
|
|
{
|
|
BusGraph* bg = bn->GetBusGraph();
|
|
if(bg == NULL){
|
|
cout<<"bus graph is invalid"<<endl;
|
|
return;
|
|
}
|
|
|
|
if(!bs1->IsDefined() || !bs2->IsDefined()){
|
|
cout<<" bus stops are not defined"<<endl;
|
|
return;
|
|
}
|
|
|
|
Point start_p, end_p;
|
|
bn->GetBusStopGeoData(bs1, &start_p);
|
|
bn->GetBusStopGeoData(bs2, &end_p);
|
|
const double delta_dist = 0.01;
|
|
|
|
if(*bs1 == *bs2 || start_p.Distance(end_p) < delta_dist){
|
|
cout<<"two bus stops equal to each other"<<endl;
|
|
bn->CloseBusGraph(bg);
|
|
return;
|
|
}
|
|
/////////////////////////build the start time///////////////////////////
|
|
Instant new_st(instanttype);
|
|
Instant bg_min(instanttype);
|
|
bg_min.ReadFrom(bg->min_t);
|
|
|
|
assert(bg_min.GetWeekday() == 6);//start from Sunday
|
|
|
|
if(qt->GetWeekday() == 6){
|
|
new_st.Set(bg_min.GetYear(),bg_min.GetMonth(),bg_min.GetGregDay(),
|
|
qt->GetHour(), qt->GetMinute(), qt->GetSecond(),
|
|
qt->GetMillisecond());
|
|
// cout<<"Sunday"<<endl;
|
|
|
|
}else{ //Monday-Saturday
|
|
////////////////////////////to Monday///////////////////////
|
|
new_st.Set(bg_min.GetYear(),bg_min.GetMonth(),bg_min.GetGregDay() + 1,
|
|
qt->GetHour(), qt->GetMinute(), qt->GetSecond(),
|
|
qt->GetMillisecond());
|
|
// cout<<"workday --->Monday"<<endl;
|
|
}
|
|
// cout<<"mapping start time"<<new_st<<endl;
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
priority_queue<BNPath_elem2> path_queue;
|
|
vector<BNPath_elem2> expand_queue;
|
|
|
|
vector<bool> visit_flag1;////////////bus stop visit
|
|
for(int i = 1; i <= bg->node_rel->GetNoTuples();i++){
|
|
visit_flag1.push_back(false);
|
|
}
|
|
//////////////////////////////////////////////////////////////////
|
|
/////////////from bus network, get the maximum speed of the bus///
|
|
/////////////for setting heuristic value/////////////////////////
|
|
///////////////////////////////////////////////////////////////////
|
|
// cout<<"max bus speed "<<bn->GetMaxSpeed()*60.0*60.0/1000.0<<"km/h"<<endl;
|
|
|
|
/////////// initialize the queue //////////////////////////////
|
|
InitializeQueue3(bs1, bs2, path_queue, expand_queue, bn, bg, start_p, end_p);
|
|
|
|
int bs2_tid = bg->GetBusStop_Tid(bs2);
|
|
// cout<<"end bus stop tid "<<bs2_tid<<endl;
|
|
|
|
// ofstream output("debug.txt");
|
|
////////////////////////////////////////////////////////////////////
|
|
////////////////////search on the bus graph//////////////////////////
|
|
/////////////////////////////////////////////////////////////////////
|
|
bool find = false;
|
|
BNPath_elem2 dest;//////////destination
|
|
double speed_human = 1.0;
|
|
|
|
while(path_queue.empty() == false){
|
|
BNPath_elem2 top = path_queue.top();
|
|
path_queue.pop();
|
|
|
|
if(visit_flag1[top.tri_index - 1])continue;
|
|
|
|
|
|
// top.Print();
|
|
|
|
|
|
if(top.tri_index == bs2_tid){
|
|
// cout<<"find the shortest path"<<endl;
|
|
find = true;
|
|
dest = top;
|
|
break;
|
|
}
|
|
int pos_expand_path;
|
|
int cur_size;
|
|
pos_expand_path = top.cur_index;
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
//////////////////////connection 1 by pavements ///////////////////////
|
|
//////////////////////////////////////////////////////////////////////
|
|
vector<int> adj_list1;
|
|
bg->FindAdj1(top.tri_index, adj_list1);
|
|
|
|
bool search_flag = true;
|
|
BNPath_elem2 temp_elem = top;
|
|
while(dest.prev_index != -1){
|
|
if(temp_elem.tm == TM_BUS){
|
|
break;
|
|
}
|
|
if(temp_elem.tm == TM_WALK){
|
|
search_flag = false;
|
|
break;
|
|
}
|
|
temp_elem = expand_queue[temp_elem.prev_index];
|
|
}
|
|
|
|
for(unsigned int i = 0;i < adj_list1.size() && search_flag;i++){
|
|
Tuple* edge_tuple = bg->edge_rel1->GetTuple(adj_list1[i], false);
|
|
int neighbor_id1 =
|
|
((CcInt*)edge_tuple->GetAttribute(BusGraph::BG_E_BS2_TID))->GetIntval();
|
|
SimpleLine* path =
|
|
(SimpleLine*)edge_tuple->GetAttribute(BusGraph::BG_PATH2);
|
|
|
|
if(visit_flag1[neighbor_id1 - 1]){
|
|
edge_tuple->DeleteIfAllowed();
|
|
continue;
|
|
}
|
|
|
|
cur_size = expand_queue.size();
|
|
|
|
double w2 = top.real_w + path->Length()/(speed_human*24.0*60.0*60.0);
|
|
|
|
int w1 = top.weight;///walk is not bus transfer
|
|
|
|
// BNPath_elem2 elem(pos_expand_path, cur_size, neighbor_id1, w1, w2,
|
|
// *path, TM_WALK, true);
|
|
SimpleLine temp_sl(0);
|
|
BNPath_elem2 elem(pos_expand_path, cur_size, neighbor_id1, w1, w2,
|
|
temp_sl, TM_WALK, true);
|
|
elem.type = TM_WALK;
|
|
elem.edge_tid = adj_list1[i];
|
|
|
|
path_queue.push(elem);
|
|
expand_queue.push_back(elem);
|
|
edge_tuple->DeleteIfAllowed();
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
//////////////////////connection 2 same spatial location/////////////
|
|
////////////////////////////////////////////////////////////////////
|
|
vector<int> adj_list2;
|
|
bg->FindAdj2(top.tri_index, adj_list2);
|
|
|
|
for(unsigned int i = 0;i < adj_list2.size();i++){
|
|
Tuple* edge_tuple = bg->edge_rel2->GetTuple(adj_list2[i], false);
|
|
int neighbor_id2 =
|
|
((CcInt*)edge_tuple->GetAttribute(BusGraph::BG_E2_BS2_TID))->GetIntval();
|
|
SimpleLine* path = new SimpleLine(0);
|
|
path->StartBulkLoad();
|
|
path->EndBulkLoad();
|
|
|
|
if(visit_flag1[neighbor_id2 - 1]){
|
|
edge_tuple->DeleteIfAllowed();
|
|
path->DeleteIfAllowed();
|
|
continue;
|
|
}
|
|
|
|
cur_size = expand_queue.size();
|
|
double w2 = top.real_w;
|
|
|
|
int w1 = top.weight;
|
|
// BNPath_elem2 elem(pos_expand_path, cur_size, neighbor_id2, w1, w2,
|
|
// *path, -1, false); //not useful for time cost
|
|
|
|
BNPath_elem2 elem(pos_expand_path, cur_size, neighbor_id2, w1, w2,
|
|
*path, -1, false); //not useful for time cost
|
|
elem.type = -1;
|
|
elem.edge_tid = 0;
|
|
|
|
|
|
path_queue.push(elem);
|
|
expand_queue.push_back(elem);
|
|
|
|
path->DeleteIfAllowed();
|
|
edge_tuple->DeleteIfAllowed();
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
////////////////////connection 3 moving buses/////////////////////////
|
|
//////////////////////////////////////////////////////////////////////
|
|
vector<int> adj_list3;
|
|
bg->FindAdj3(top.tri_index, adj_list3);
|
|
int64_t max_64_int = numeric_limits<int64_t>::max();
|
|
|
|
for(unsigned int i = 0;i < adj_list3.size();i++){
|
|
Tuple* edge_tuple = bg->edge_rel3->GetTuple(adj_list3[i], false);
|
|
int neighbor_id3 =
|
|
((CcInt*)edge_tuple->GetAttribute(BusGraph::BG_E3_BS2_TID))->GetIntval();
|
|
// SimpleLine* path =
|
|
// (SimpleLine*)edge_tuple->GetAttribute(BusGraph::BG_PATH3);
|
|
|
|
if(visit_flag1[neighbor_id3 - 1]){
|
|
edge_tuple->DeleteIfAllowed();
|
|
continue;
|
|
}
|
|
|
|
cur_size = expand_queue.size();
|
|
double cur_t = new_st.ToDouble() + top.real_w;
|
|
Instant cur_inst = new_st;
|
|
cur_inst.ReadFrom(cur_t); //time to arrive current bus stop
|
|
// cout<<"time at bus stop "<<cur_inst<<endl;
|
|
|
|
|
|
int64_t cur_t_int = cur_t*86400000;
|
|
assert(cur_t_int <= max_64_int);
|
|
|
|
Periods* peri =
|
|
(Periods*)edge_tuple->GetAttribute(BusGraph::BG_LIFETIME);
|
|
Interval<Instant> periods;
|
|
peri->Get(0, periods);
|
|
|
|
// output<<"periods "<<periods<<"query time "<<cur_inst<<endl;
|
|
|
|
double sched =
|
|
((CcReal*)edge_tuple->GetAttribute(BusGraph::BG_SCHEDULE))->GetRealval();
|
|
double st = periods.start.ToDouble();
|
|
double et = periods.end.ToDouble();
|
|
int64_t st_int = st*86400000;
|
|
int64_t et_int = et*86400000;
|
|
assert(st_int <= max_64_int);
|
|
assert(et_int <= max_64_int);
|
|
|
|
// cout<<"st "<<periods.start<<" et "<<periods.end<<endl;
|
|
|
|
if(et_int < cur_t_int){//end time smaller than curtime
|
|
edge_tuple->DeleteIfAllowed();
|
|
continue;
|
|
}
|
|
double wait_time = 0.0;
|
|
|
|
if(st_int > cur_t_int){//wait for the first start time
|
|
wait_time += st - cur_t;
|
|
wait_time += 30.0/(24.0*60.0*60.0);//30 seconds at bus stop
|
|
}else if(st_int == cur_t_int){
|
|
wait_time += 30.0/(24.0*60.0*60.0);//30 seconds at bus stop
|
|
}else{ //most times, it is here, wait for the next schedule
|
|
|
|
bool valid = false;
|
|
while(st_int < cur_t_int && st_int <= et_int){
|
|
|
|
/* Instant temp(instanttype);
|
|
temp.ReadFrom(st);
|
|
cout<<"t1 "<<temp<<endl; */
|
|
|
|
if((st_int + 30000) >= cur_t_int){//30 second
|
|
wait_time += st + 30.0/(24.0*60.0*60.0) - cur_t;
|
|
valid = true;
|
|
break;
|
|
}
|
|
st += sched;
|
|
st_int = st * 86400000;
|
|
if(st_int >= cur_t_int){
|
|
wait_time += st + 30.0/(24.0*60.0*60.0) - cur_t;
|
|
valid = true;
|
|
break;
|
|
}
|
|
assert(st_int <= max_64_int);
|
|
|
|
// temp.ReadFrom(st);
|
|
// cout<<"t2 "<<temp<<endl;
|
|
|
|
}
|
|
if(valid == false){
|
|
cout<<"should not arrive at here"<<endl;
|
|
assert(false);
|
|
}
|
|
}
|
|
|
|
double weight =
|
|
((CcReal*)edge_tuple->GetAttribute(BusGraph::BG_TIMECOST))->GetRealval();
|
|
double w2 = top.real_w + wait_time + weight;
|
|
|
|
int w1;
|
|
|
|
if(fabs(int64_t(wait_time*86400) - 30) <= 2 ||
|
|
(int)(top.real_w*86400.0) == 0)
|
|
w1 = top.weight;
|
|
else w1 = top.weight + 1;
|
|
|
|
|
|
// BNPath_elem2 elem(pos_expand_path, cur_size,neighbor_id3, w1, w2,
|
|
// *path, TM_BUS, true);
|
|
SimpleLine temp_sl(0);
|
|
BNPath_elem2 elem(pos_expand_path, cur_size,neighbor_id3, w1, w2,
|
|
temp_sl, TM_BUS, true);
|
|
elem.type = TM_BUS;
|
|
elem.edge_tid = adj_list3[i];
|
|
|
|
|
|
if(wait_time > 0.0){ //to the time waiting for bus
|
|
elem.SetW(top.real_w + wait_time);
|
|
}
|
|
|
|
path_queue.push(elem);
|
|
expand_queue.push_back(elem);
|
|
|
|
|
|
edge_tuple->DeleteIfAllowed();
|
|
|
|
|
|
}
|
|
|
|
visit_flag1[top.tri_index - 1] = true;
|
|
}
|
|
//////////////////////////////////////////////////////////////////////
|
|
////////////////construct the result//////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////
|
|
if(find){ ////////constrcut the result
|
|
// cout<<dest.weight<<" bus transfers"<<endl;
|
|
vector<int> id_list;
|
|
while(dest.prev_index != -1){
|
|
id_list.push_back(dest.cur_index);
|
|
dest = expand_queue[dest.prev_index];
|
|
}
|
|
|
|
id_list.push_back(dest.cur_index);
|
|
|
|
Bus_Stop bs_last = *bs1;
|
|
Instant t1 = *qt;
|
|
|
|
|
|
for(int i = id_list.size() - 1;i >= 0;i--){
|
|
BNPath_elem2 elem = expand_queue[id_list[i]];
|
|
path_list.push_back(elem.path);
|
|
|
|
if(elem.tm == TM_WALK){
|
|
tm_list.push_back(str_tm[elem.tm]);
|
|
}else if(elem.tm == TM_BUS){
|
|
tm_list.push_back(str_tm[elem.tm]);
|
|
}else{
|
|
// assert(false);
|
|
tm_list.push_back("none");
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
////////////////we also return///////////////////////////////////////
|
|
////////the start and end bus stops connected by the path ////////////
|
|
////////////////////////////////////////////////////////////////////
|
|
char buf1[256], buf2[256];
|
|
|
|
sprintf(buf1, "br: %d ", bs_last.GetId());
|
|
sprintf(buf2, "stop: %d", bs_last.GetStopId());
|
|
strcat (buf1, buf2);
|
|
if(bs_last.GetUp())strcat (buf1, " UP");
|
|
else strcat (buf1, " DOWN");
|
|
|
|
string str1(buf1);
|
|
bs1_list.push_back(str1);
|
|
|
|
if(i == (int)(id_list.size() - 1)){
|
|
string str2(str1);
|
|
bs2_list.push_back(str2);
|
|
|
|
}else{////////////////the end bus stop
|
|
|
|
Tuple* bs_tuple = bg->node_rel->GetTuple(elem.tri_index, false);
|
|
Bus_Stop* bs_cur =
|
|
(Bus_Stop*)bs_tuple->GetAttribute(BusGraph::BG_NODE);
|
|
char buf_1[256], buf_2[256];
|
|
sprintf(buf_1, "br: %d ", bs_cur->GetId());
|
|
sprintf(buf_2, "stop: %d", bs_cur->GetStopId());
|
|
strcat (buf_1, buf_2);
|
|
if(bs_cur->GetUp()) strcat (buf_1, " UP");
|
|
else strcat (buf_1, " DOWN");
|
|
|
|
string str2(buf_1);
|
|
bs2_list.push_back(str2);
|
|
bs_last = *bs_cur;
|
|
bs_tuple->DeleteIfAllowed();
|
|
}
|
|
|
|
////////////////time duration////////////////////////////////
|
|
|
|
Instant t2(instanttype);
|
|
if(elem.b_w == false){
|
|
t2.ReadFrom(elem.real_w + qt->ToDouble());
|
|
// cout<<t1<<" "<<t2<<endl;
|
|
|
|
//time cost in seconds
|
|
if(elem.valid)
|
|
time_cost_list.push_back((t2.ToDouble() - t1.ToDouble())*86400.0);
|
|
else //doing transfer without moving
|
|
time_cost_list.push_back(0.0);
|
|
|
|
Interval<Instant> time_span;
|
|
time_span.start = t1;
|
|
time_span.lc = true;
|
|
time_span.end = t2;
|
|
time_span.rc = false;
|
|
|
|
Periods* peri = new Periods(0);
|
|
peri->StartBulkLoad();
|
|
if(elem.valid)
|
|
peri->MergeAdd(time_span);
|
|
peri->EndBulkLoad();
|
|
peri_list.push_back(*peri);
|
|
t1 = t2;
|
|
peri->DeleteIfAllowed();
|
|
}else{ //////////to dinstinguish time of waiting for the bus
|
|
t2.ReadFrom(elem.w + qt->ToDouble());
|
|
// cout<<t1<<" "<<t2<<endl;
|
|
|
|
//time cost in seconds
|
|
if(elem.valid)
|
|
time_cost_list.push_back((t2.ToDouble() - t1.ToDouble())*86400.0);
|
|
else //doing transfer without moving
|
|
time_cost_list.push_back(0.0);
|
|
Interval<Instant> time_span;
|
|
time_span.start = t1;
|
|
time_span.lc = true;
|
|
time_span.end = t2;
|
|
time_span.rc = false;
|
|
|
|
Periods* peri1 = new Periods(0);
|
|
peri1->StartBulkLoad();
|
|
if(elem.valid)
|
|
peri1->MergeAdd(time_span);
|
|
peri1->EndBulkLoad();
|
|
peri_list.push_back(*peri1);
|
|
t1 = t2;
|
|
peri1->DeleteIfAllowed();
|
|
|
|
SimpleLine* sl = new SimpleLine(0);
|
|
sl->StartBulkLoad();
|
|
sl->EndBulkLoad();
|
|
path_list[path_list.size() - 1] = *sl;
|
|
sl->DeleteIfAllowed();
|
|
|
|
tm_list[tm_list.size() - 1] = "none"; //waiting is no tm
|
|
string str = bs2_list[bs2_list.size() - 1];
|
|
////////the same as last bus stop //////////////////////
|
|
bs2_list[bs2_list.size() - 1] = bs1_list[bs1_list.size() - 1];
|
|
|
|
|
|
/////////////moving with bus////////////////////////////////
|
|
t2.ReadFrom(elem.real_w + qt->ToDouble());
|
|
// cout<<t1<<" "<<t2<<endl;
|
|
|
|
//time cost in seconds
|
|
if(elem.valid)
|
|
time_cost_list.push_back((t2.ToDouble() - t1.ToDouble())*86400.0);
|
|
else //doing transfer without moving
|
|
time_cost_list.push_back(0.0);
|
|
|
|
time_span.start = t1;
|
|
time_span.lc = true;
|
|
time_span.end = t2;
|
|
time_span.rc = false;
|
|
|
|
Periods* peri2 = new Periods(0);
|
|
peri2->StartBulkLoad();
|
|
if(elem.valid)
|
|
peri2->MergeAdd(time_span);
|
|
peri2->EndBulkLoad();
|
|
peri_list.push_back(*peri2);
|
|
t1 = t2;
|
|
peri2->DeleteIfAllowed();
|
|
path_list.push_back(elem.path);
|
|
tm_list.push_back(str_tm[elem.tm]);
|
|
bs1_list.push_back(str1);
|
|
bs2_list.push_back(str);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}else{
|
|
cout<<"bs1 ("<<*bs1<<") bs2 ("<<*bs2<<") not reachable "<<endl;
|
|
}
|
|
|
|
bn->CloseBusGraph(bg);
|
|
}
|
|
|
|
|
|
/*
|
|
shortest path from one bus stop to another in bus transfer
|
|
walk edge is not expanded twice;
|
|
only bus edge is expanded by walk edge;
|
|
only walk edge and bus edge are expanded by no cost edge
|
|
|
|
*/
|
|
void BNNav::ShortestPath_TransferNew(Bus_Stop* bs1, Bus_Stop* bs2, Instant* qt)
|
|
{
|
|
BusGraph* bg = bn->GetBusGraph();
|
|
if(bg == NULL){
|
|
cout<<"bus graph is invalid"<<endl;
|
|
return;
|
|
}
|
|
|
|
if(!bs1->IsDefined() || !bs2->IsDefined()){
|
|
cout<<" bus stops are not defined"<<endl;
|
|
return;
|
|
}
|
|
|
|
Point start_p, end_p;
|
|
bn->GetBusStopGeoData(bs1, &start_p);
|
|
bn->GetBusStopGeoData(bs2, &end_p);
|
|
const double delta_dist = 0.01;
|
|
|
|
if(*bs1 == *bs2 || start_p.Distance(end_p) < delta_dist){
|
|
cout<<"two bus stops equal to each other"<<endl;
|
|
bn->CloseBusGraph(bg);
|
|
return;
|
|
}
|
|
/////////////////////////build the start time///////////////////////////
|
|
Instant new_st(instanttype);
|
|
Instant bg_min(instanttype);
|
|
bg_min.ReadFrom(bg->min_t);
|
|
|
|
assert(bg_min.GetWeekday() == 6);//start from Sunday
|
|
|
|
if(qt->GetWeekday() == 6){
|
|
new_st.Set(bg_min.GetYear(),bg_min.GetMonth(),bg_min.GetGregDay(),
|
|
qt->GetHour(), qt->GetMinute(), qt->GetSecond(),
|
|
qt->GetMillisecond());
|
|
// cout<<"Sunday"<<endl;
|
|
|
|
}else{ //Monday-Saturday
|
|
////////////////////////////to Monday///////////////////////
|
|
new_st.Set(bg_min.GetYear(),bg_min.GetMonth(),bg_min.GetGregDay() + 1,
|
|
qt->GetHour(), qt->GetMinute(), qt->GetSecond(),
|
|
qt->GetMillisecond());
|
|
// cout<<"workday --->Monday"<<endl;
|
|
}
|
|
// cout<<"mapping start time"<<new_st<<endl;
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
priority_queue<BNPath_elem2> path_queue;
|
|
vector<BNPath_elem2> expand_queue;
|
|
|
|
vector<bool> visit_flag1;////////////bus stop visit
|
|
for(int i = 1; i <= bg->node_rel->GetNoTuples();i++){
|
|
visit_flag1.push_back(false);
|
|
}
|
|
//////////////////////////////////////////////////////////////////
|
|
/////////////from bus network, get the maximum speed of the bus///
|
|
/////////////for setting heuristic value/////////////////////////
|
|
///////////////////////////////////////////////////////////////////
|
|
// cout<<"max bus speed "<<bn->GetMaxSpeed()*60.0*60.0/1000.0<<"km/h"<<endl;
|
|
|
|
/////////// initialize the queue //////////////////////////////
|
|
InitializeQueue3(bs1, bs2, path_queue, expand_queue, bn, bg, start_p, end_p);
|
|
|
|
int bs2_tid = bg->GetBusStop_Tid(bs2);
|
|
// cout<<"end bus stop tid "<<bs2_tid<<endl;
|
|
|
|
// ofstream output("debug.txt");
|
|
////////////////////////////////////////////////////////////////////
|
|
////////////////////search on the bus graph//////////////////////////
|
|
/////////////////////////////////////////////////////////////////////
|
|
bool find = false;
|
|
BNPath_elem2 dest;//////////destination
|
|
double speed_human = 1.0;
|
|
|
|
while(path_queue.empty() == false){
|
|
BNPath_elem2 top = path_queue.top();
|
|
path_queue.pop();
|
|
|
|
if(visit_flag1[top.tri_index - 1])continue;
|
|
|
|
|
|
// top.Print();
|
|
|
|
if(top.tri_index == bs2_tid){
|
|
// cout<<"find the shortest path"<<endl;
|
|
find = true;
|
|
dest = top;
|
|
break;
|
|
}
|
|
int pos_expand_path;
|
|
int cur_size;
|
|
pos_expand_path = top.cur_index;
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
//////////////////////connection 1 by pavements ///////////////////////
|
|
//////////////////////////////////////////////////////////////////////
|
|
if(top.tm == TM_BUS){
|
|
vector<int> adj_list1;
|
|
bg->FindAdj1(top.tri_index, adj_list1);
|
|
|
|
bool search_flag = true;
|
|
BNPath_elem2 temp_elem = top;
|
|
while(dest.prev_index != -1){
|
|
if(temp_elem.tm == TM_BUS){
|
|
break;
|
|
}
|
|
if(temp_elem.tm == TM_WALK){
|
|
search_flag = false;
|
|
break;
|
|
}
|
|
temp_elem = expand_queue[temp_elem.prev_index];
|
|
}
|
|
|
|
for(unsigned int i = 0;i < adj_list1.size() && search_flag;i++){
|
|
Tuple* edge_tuple = bg->edge_rel1->GetTuple(adj_list1[i], false);
|
|
int neighbor_id1 =
|
|
((CcInt*)edge_tuple->GetAttribute(BusGraph::BG_E_BS2_TID))->GetIntval();
|
|
SimpleLine* path =
|
|
(SimpleLine*)edge_tuple->GetAttribute(BusGraph::BG_PATH2);
|
|
|
|
if(visit_flag1[neighbor_id1 - 1]){
|
|
edge_tuple->DeleteIfAllowed();
|
|
continue;
|
|
}
|
|
|
|
cur_size = expand_queue.size();
|
|
|
|
double w2 = top.real_w + path->Length()/(speed_human*24.0*60.0*60.0);
|
|
|
|
int w1 = top.weight;///walk is not bus transfer
|
|
|
|
// BNPath_elem2 elem(pos_expand_path, cur_size, neighbor_id1, w1, w2,
|
|
// *path, TM_WALK, true);
|
|
SimpleLine temp_sl(0);
|
|
BNPath_elem2 elem(pos_expand_path, cur_size, neighbor_id1, w1, w2,
|
|
temp_sl, TM_WALK, true);
|
|
elem.type = TM_WALK;
|
|
elem.edge_tid = adj_list1[i];
|
|
/////////////////////////////////////////////////////////////
|
|
|
|
path_queue.push(elem);
|
|
expand_queue.push_back(elem);
|
|
edge_tuple->DeleteIfAllowed();
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
//////////////////////connection 2 same spatial location/////////////
|
|
////////////////////////////////////////////////////////////////////
|
|
if(top.tm == TM_WALK || top.tm == TM_BUS){
|
|
vector<int> adj_list2;
|
|
bg->FindAdj2(top.tri_index, adj_list2);
|
|
|
|
for(unsigned int i = 0;i < adj_list2.size();i++){
|
|
Tuple* edge_tuple = bg->edge_rel2->GetTuple(adj_list2[i], false);
|
|
int neighbor_id2 =
|
|
((CcInt*)edge_tuple->GetAttribute(BusGraph::BG_E2_BS2_TID))->GetIntval();
|
|
SimpleLine* path = new SimpleLine(0);
|
|
path->StartBulkLoad();
|
|
path->EndBulkLoad();
|
|
|
|
if(visit_flag1[neighbor_id2 - 1]){
|
|
edge_tuple->DeleteIfAllowed();
|
|
path->DeleteIfAllowed();
|
|
continue;
|
|
}
|
|
|
|
cur_size = expand_queue.size();
|
|
double w2 = top.real_w;
|
|
|
|
int w1 = top.weight;
|
|
/* BNPath_elem2 elem(pos_expand_path, cur_size, neighbor_id2, w1, w2,
|
|
*path, -1, false); //not useful for time cost */
|
|
|
|
///////////////////////////////////////////////////////////////
|
|
BNPath_elem2 elem(pos_expand_path, cur_size, neighbor_id2, w1, w2,
|
|
*path, -1, false); //not useful for time cost
|
|
elem.type = -1;
|
|
elem.edge_tid = 0;
|
|
//////////////////////////////////////////////////////////
|
|
|
|
path_queue.push(elem);
|
|
expand_queue.push_back(elem);
|
|
|
|
path->DeleteIfAllowed();
|
|
edge_tuple->DeleteIfAllowed();
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
////////////////////connection 3 moving buses/////////////////////////
|
|
//////////////////////////////////////////////////////////////////////
|
|
vector<int> adj_list3;
|
|
bg->FindAdj3(top.tri_index, adj_list3);
|
|
int64_t max_64_int = numeric_limits<int64_t>::max();
|
|
|
|
for(unsigned int i = 0;i < adj_list3.size();i++){
|
|
Tuple* edge_tuple = bg->edge_rel3->GetTuple(adj_list3[i], false);
|
|
int neighbor_id3 =
|
|
((CcInt*)edge_tuple->GetAttribute(BusGraph::BG_E3_BS2_TID))->GetIntval();
|
|
// SimpleLine* path =
|
|
// (SimpleLine*)edge_tuple->GetAttribute(BusGraph::BG_PATH3);
|
|
|
|
if(visit_flag1[neighbor_id3 - 1]){
|
|
edge_tuple->DeleteIfAllowed();
|
|
continue;
|
|
}
|
|
|
|
cur_size = expand_queue.size();
|
|
double cur_t = new_st.ToDouble() + top.real_w;
|
|
Instant cur_inst = new_st;
|
|
cur_inst.ReadFrom(cur_t); //time to arrive current bus stop
|
|
// cout<<"time at bus stop "<<cur_inst<<endl;
|
|
|
|
|
|
int64_t cur_t_int = cur_t*86400000;
|
|
assert(cur_t_int <= max_64_int);
|
|
|
|
Periods* peri =
|
|
(Periods*)edge_tuple->GetAttribute(BusGraph::BG_LIFETIME);
|
|
Interval<Instant> periods;
|
|
peri->Get(0, periods);
|
|
|
|
// output<<"periods "<<periods<<"query time "<<cur_inst<<endl;
|
|
|
|
double sched =
|
|
((CcReal*)edge_tuple->GetAttribute(BusGraph::BG_SCHEDULE))->GetRealval();
|
|
double st = periods.start.ToDouble();
|
|
double et = periods.end.ToDouble();
|
|
int64_t st_int = st*86400000;
|
|
int64_t et_int = et*86400000;
|
|
assert(st_int <= max_64_int);
|
|
assert(et_int <= max_64_int);
|
|
|
|
// cout<<"st "<<periods.start<<" et "<<periods.end<<endl;
|
|
|
|
if(et_int < cur_t_int){//end time smaller than curtime
|
|
edge_tuple->DeleteIfAllowed();
|
|
continue;
|
|
}
|
|
double wait_time = 0.0;
|
|
|
|
if(st_int > cur_t_int){//wait for the first start time
|
|
wait_time += st - cur_t;
|
|
wait_time += 30.0/(24.0*60.0*60.0);//30 seconds at bus stop
|
|
}else if(st_int == cur_t_int){
|
|
wait_time += 30.0/(24.0*60.0*60.0);//30 seconds at bus stop
|
|
}else{ //most times, it is here, wait for the next schedule
|
|
|
|
bool valid = false;
|
|
while(st_int < cur_t_int && st_int <= et_int){
|
|
|
|
/* Instant temp(instanttype);
|
|
temp.ReadFrom(st);
|
|
cout<<"t1 "<<temp<<endl; */
|
|
|
|
if((st_int + 30000) >= cur_t_int){//30 second
|
|
wait_time += st + 30.0/(24.0*60.0*60.0) - cur_t;
|
|
valid = true;
|
|
break;
|
|
}
|
|
st += sched;
|
|
st_int = st * 86400000;
|
|
if(st_int >= cur_t_int){
|
|
wait_time += st + 30.0/(24.0*60.0*60.0) - cur_t;
|
|
valid = true;
|
|
break;
|
|
}
|
|
assert(st_int <= max_64_int);
|
|
|
|
}
|
|
if(valid == false){
|
|
cout<<"should not arrive at here"<<endl;
|
|
assert(false);
|
|
}
|
|
}
|
|
|
|
double weight =
|
|
((CcReal*)edge_tuple->GetAttribute(BusGraph::BG_TIMECOST))->GetRealval();
|
|
double w2 = top.real_w + wait_time + weight;
|
|
|
|
int w1;
|
|
|
|
if(fabs(int64_t(wait_time*86400) - 30) <= 2 ||
|
|
(int)(top.real_w*86400.0) == 0)
|
|
w1 = top.weight;
|
|
else w1 = top.weight + 1;
|
|
|
|
|
|
// BNPath_elem2 elem(pos_expand_path, cur_size,neighbor_id3, w1, w2,
|
|
// *path, TM_BUS, true);
|
|
|
|
SimpleLine temp_sl(0);
|
|
BNPath_elem2 elem(pos_expand_path, cur_size,neighbor_id3, w1, w2,
|
|
temp_sl, TM_BUS, true);
|
|
elem.type = TM_BUS;
|
|
elem.edge_tid = adj_list3[i];
|
|
|
|
|
|
if(wait_time > 0.0){ //to the time waiting for bus
|
|
elem.SetW(top.real_w + wait_time);
|
|
}
|
|
|
|
path_queue.push(elem);
|
|
expand_queue.push_back(elem);
|
|
|
|
|
|
edge_tuple->DeleteIfAllowed();
|
|
|
|
}
|
|
|
|
visit_flag1[top.tri_index - 1] = true;
|
|
}
|
|
//////////////////////////////////////////////////////////////////////
|
|
////////////////construct the result//////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////
|
|
if(find){ ////////constrcut the result
|
|
// cout<<dest.weight<<" bus transfers"<<endl;
|
|
vector<int> id_list;
|
|
while(dest.prev_index != -1){
|
|
id_list.push_back(dest.cur_index);
|
|
dest = expand_queue[dest.prev_index];
|
|
}
|
|
|
|
id_list.push_back(dest.cur_index);
|
|
|
|
Bus_Stop bs_last = *bs1;
|
|
Instant t1 = *qt;
|
|
|
|
|
|
for(int i = id_list.size() - 1;i >= 0;i--){
|
|
BNPath_elem2 elem = expand_queue[id_list[i]];
|
|
|
|
////////////////////////////////////////////////////////////
|
|
if(elem.type == TM_WALK){
|
|
assert(1 <= elem.edge_tid &&
|
|
elem.edge_tid <= bg->edge_rel1->GetNoTuples());
|
|
Tuple* edge_tuple = bg->edge_rel1->GetTuple(elem.edge_tid, false);
|
|
SimpleLine* path =
|
|
(SimpleLine*)edge_tuple->GetAttribute(BusGraph::BG_PATH2);
|
|
elem.path = *path;
|
|
edge_tuple->DeleteIfAllowed();
|
|
|
|
}else if(elem.type == TM_BUS){
|
|
if(elem.edge_tid > 0){
|
|
Tuple* edge_tuple = bg->edge_rel3->GetTuple(elem.edge_tid, false);
|
|
SimpleLine* path =
|
|
(SimpleLine*)edge_tuple->GetAttribute(BusGraph::BG_PATH3);
|
|
elem.path = *path;
|
|
edge_tuple->DeleteIfAllowed();
|
|
}
|
|
|
|
}else if(elem.type == -1){
|
|
|
|
}else{
|
|
cout<<"should not be here"<<endl;
|
|
assert(false);
|
|
}
|
|
////////////////////////////////////////////////////////////
|
|
|
|
|
|
path_list.push_back(elem.path);
|
|
|
|
if(elem.tm == TM_WALK){
|
|
tm_list.push_back(str_tm[elem.tm]);
|
|
}else if(elem.tm == TM_BUS){
|
|
tm_list.push_back(str_tm[elem.tm]);
|
|
}else{
|
|
// assert(false);
|
|
tm_list.push_back("none");
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
////////////////we also return///////////////////////////////////////
|
|
////////the start and end bus stops connected by the path ////////////
|
|
////////////////////////////////////////////////////////////////////
|
|
char buf1[256], buf2[256];
|
|
|
|
sprintf(buf1, "br: %d ", bs_last.GetId());
|
|
sprintf(buf2, "stop: %d", bs_last.GetStopId());
|
|
strcat (buf1, buf2);
|
|
if(bs_last.GetUp())strcat (buf1, " UP");
|
|
else strcat (buf1, " DOWN");
|
|
|
|
string str1(buf1);
|
|
bs1_list.push_back(str1);
|
|
|
|
if(i == (int)(id_list.size() - 1)){
|
|
string str2(str1);
|
|
bs2_list.push_back(str2);
|
|
|
|
}else{////////////////the end bus stop
|
|
|
|
Tuple* bs_tuple = bg->node_rel->GetTuple(elem.tri_index, false);
|
|
Bus_Stop* bs_cur =
|
|
(Bus_Stop*)bs_tuple->GetAttribute(BusGraph::BG_NODE);
|
|
char buf_1[256], buf_2[256];
|
|
sprintf(buf_1, "br: %d ", bs_cur->GetId());
|
|
sprintf(buf_2, "stop: %d", bs_cur->GetStopId());
|
|
strcat (buf_1, buf_2);
|
|
if(bs_cur->GetUp()) strcat (buf_1, " UP");
|
|
else strcat (buf_1, " DOWN");
|
|
|
|
string str2(buf_1);
|
|
bs2_list.push_back(str2);
|
|
bs_last = *bs_cur;
|
|
bs_tuple->DeleteIfAllowed();
|
|
}
|
|
|
|
////////////////time duration////////////////////////////////
|
|
|
|
Instant t2(instanttype);
|
|
if(elem.b_w == false){
|
|
t2.ReadFrom(elem.real_w + qt->ToDouble());
|
|
// cout<<t1<<" "<<t2<<endl;
|
|
|
|
//time cost in seconds
|
|
if(elem.valid)
|
|
time_cost_list.push_back((t2.ToDouble() - t1.ToDouble())*86400.0);
|
|
else //doing transfer without moving
|
|
time_cost_list.push_back(0.0);
|
|
|
|
Interval<Instant> time_span;
|
|
time_span.start = t1;
|
|
time_span.lc = true;
|
|
time_span.end = t2;
|
|
time_span.rc = false;
|
|
|
|
Periods* peri = new Periods(0);
|
|
peri->StartBulkLoad();
|
|
if(elem.valid)
|
|
peri->MergeAdd(time_span);
|
|
peri->EndBulkLoad();
|
|
peri_list.push_back(*peri);
|
|
t1 = t2;
|
|
peri->DeleteIfAllowed();
|
|
}else{ //////////to dinstinguish time of waiting for the bus
|
|
t2.ReadFrom(elem.w + qt->ToDouble());
|
|
// cout<<t1<<" "<<t2<<endl;
|
|
|
|
//time cost in seconds
|
|
if(elem.valid)
|
|
time_cost_list.push_back((t2.ToDouble() - t1.ToDouble())*86400.0);
|
|
else //doing transfer without moving
|
|
time_cost_list.push_back(0.0);
|
|
Interval<Instant> time_span;
|
|
time_span.start = t1;
|
|
time_span.lc = true;
|
|
time_span.end = t2;
|
|
time_span.rc = false;
|
|
|
|
Periods* peri1 = new Periods(0);
|
|
peri1->StartBulkLoad();
|
|
if(elem.valid)
|
|
peri1->MergeAdd(time_span);
|
|
peri1->EndBulkLoad();
|
|
peri_list.push_back(*peri1);
|
|
t1 = t2;
|
|
peri1->DeleteIfAllowed();
|
|
|
|
SimpleLine* sl = new SimpleLine(0);
|
|
sl->StartBulkLoad();
|
|
sl->EndBulkLoad();
|
|
path_list[path_list.size() - 1] = *sl;
|
|
sl->DeleteIfAllowed();
|
|
|
|
tm_list[tm_list.size() - 1] = "none"; //waiting is no tm
|
|
string str = bs2_list[bs2_list.size() - 1];
|
|
////////the same as last bus stop //////////////////////
|
|
bs2_list[bs2_list.size() - 1] = bs1_list[bs1_list.size() - 1];
|
|
|
|
|
|
/////////////moving with bus////////////////////////////////
|
|
t2.ReadFrom(elem.real_w + qt->ToDouble());
|
|
// cout<<t1<<" "<<t2<<endl;
|
|
|
|
//time cost in seconds
|
|
if(elem.valid)
|
|
time_cost_list.push_back((t2.ToDouble() - t1.ToDouble())*86400.0);
|
|
else //doing transfer without moving
|
|
time_cost_list.push_back(0.0);
|
|
|
|
time_span.start = t1;
|
|
time_span.lc = true;
|
|
time_span.end = t2;
|
|
time_span.rc = false;
|
|
|
|
Periods* peri2 = new Periods(0);
|
|
peri2->StartBulkLoad();
|
|
if(elem.valid)
|
|
peri2->MergeAdd(time_span);
|
|
peri2->EndBulkLoad();
|
|
peri_list.push_back(*peri2);
|
|
t1 = t2;
|
|
peri2->DeleteIfAllowed();
|
|
path_list.push_back(elem.path);
|
|
tm_list.push_back(str_tm[elem.tm]);
|
|
bs1_list.push_back(str1);
|
|
bs2_list.push_back(str);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}else{
|
|
cout<<"bs1 ("<<*bs1<<") bs2 ("<<*bs2<<") not reachable "<<endl;
|
|
}
|
|
|
|
bn->CloseBusGraph(bg);
|
|
}
|
|
|
|
/*
|
|
shortest path from one bus stop to another in bus transfer
|
|
for the first bus stop, do not consider walk segment connection
|
|
|
|
*/
|
|
void BNNav::ShortestPath_Transfer2(Bus_Stop* bs1, Bus_Stop* bs2, Instant* qt)
|
|
{
|
|
// cout<<"ShortestPath_Transfer2"<<endl;
|
|
|
|
BusGraph* bg = bn->GetBusGraph();
|
|
if(bg == NULL){
|
|
cout<<"bus graph is invalid"<<endl;
|
|
return;
|
|
}
|
|
|
|
if(!bs1->IsDefined() || !bs2->IsDefined()){
|
|
cout<<" bus stops are not defined"<<endl;
|
|
return;
|
|
}
|
|
|
|
Point start_p, end_p;
|
|
bn->GetBusStopGeoData(bs1, &start_p);
|
|
bn->GetBusStopGeoData(bs2, &end_p);
|
|
const double delta_dist = 0.01;
|
|
|
|
if(*bs1 == *bs2 || start_p.Distance(end_p) < delta_dist){
|
|
cout<<"two bus stops equal to each other"<<endl;
|
|
bn->CloseBusGraph(bg);
|
|
return;
|
|
}
|
|
/////////////////////////build the start time///////////////////////////
|
|
Instant new_st(instanttype);
|
|
Instant bg_min(instanttype);
|
|
bg_min.ReadFrom(bg->min_t);
|
|
|
|
assert(bg_min.GetWeekday() == 6);//start from Sunday
|
|
|
|
if(qt->GetWeekday() == 6){
|
|
new_st.Set(bg_min.GetYear(), bg_min.GetMonth(), bg_min.GetGregDay(),
|
|
qt->GetHour(), qt->GetMinute(), qt->GetSecond(),
|
|
qt->GetMillisecond());
|
|
// cout<<"Sunday"<<endl;
|
|
|
|
}else{ //Monday-Saturday
|
|
////////////////////////////to Monday///////////////////////
|
|
new_st.Set(bg_min.GetYear(),bg_min.GetMonth(),bg_min.GetGregDay() + 1,
|
|
qt->GetHour(), qt->GetMinute(), qt->GetSecond(),
|
|
qt->GetMillisecond());
|
|
// cout<<"workday --->Monday"<<endl;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
priority_queue<BNPath_elem2> path_queue;
|
|
vector<BNPath_elem2> expand_queue;
|
|
|
|
vector<bool> visit_flag1;////////////bus stop visit
|
|
for(int i = 1; i <= bg->node_rel->GetNoTuples();i++){
|
|
visit_flag1.push_back(false);
|
|
}
|
|
//////////////////////////////////////////////////////////////////
|
|
/////////////from bus network, get the maximum speed of the bus///
|
|
/////////////for setting heuristic value/////////////////////////
|
|
///////////////////////////////////////////////////////////////////
|
|
// cout<<"max bus speed "<<bn->GetMaxSpeed()*60.0*60.0/1000.0<<"km/h"<<endl;
|
|
|
|
/////////// initialize the queue //////////////////////////////
|
|
InitializeQueue3(bs1, bs2, path_queue, expand_queue, bn, bg, start_p, end_p);
|
|
|
|
int bs2_tid = bg->GetBusStop_Tid(bs2);
|
|
// cout<<"end bus stop tid "<<bs2_tid<<endl;
|
|
|
|
// ofstream output("debug.txt");
|
|
////////////////////////////////////////////////////////////////////
|
|
////////////////////search on the bus graph//////////////////////////
|
|
/////////////////////////////////////////////////////////////////////
|
|
bool find = false;
|
|
BNPath_elem2 dest;//////////destination
|
|
double speed_human = 1.0;
|
|
const double delta_t = 0.001;
|
|
|
|
while(path_queue.empty() == false){
|
|
BNPath_elem2 top = path_queue.top();
|
|
path_queue.pop();
|
|
|
|
if(visit_flag1[top.tri_index - 1])continue;
|
|
|
|
// top.Print();
|
|
|
|
if(top.tri_index == bs2_tid){
|
|
// cout<<"find the shortest path"<<endl;
|
|
find = true;
|
|
dest = top;
|
|
break;
|
|
}
|
|
int pos_expand_path;
|
|
int cur_size;
|
|
pos_expand_path = top.cur_index;
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
//////////////////////connection 1 by pavements ///////////////////////
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
if(top.real_w > delta_t){
|
|
if(top.tm == TM_BUS){
|
|
////////////////////////////////////////////////////
|
|
bool search_flag = true;
|
|
BNPath_elem2 temp_elem = top;
|
|
// while(dest.prev_index != -1){
|
|
while(temp_elem.prev_index != -1){
|
|
if(temp_elem.tm == TM_BUS){
|
|
break;
|
|
}
|
|
if(temp_elem.tm == TM_WALK){
|
|
search_flag = false;
|
|
break;
|
|
}
|
|
temp_elem = expand_queue[temp_elem.prev_index];
|
|
}
|
|
|
|
////////////////////////////////////////////////////
|
|
vector<int> adj_list1;
|
|
bg->FindAdj1(top.tri_index, adj_list1);
|
|
for(unsigned int i = 0;i < adj_list1.size() && search_flag;i++){
|
|
Tuple* edge_tuple = bg->edge_rel1->GetTuple(adj_list1[i], false);
|
|
int neighbor_id1 =
|
|
((CcInt*)edge_tuple->GetAttribute(BusGraph::BG_E_BS2_TID))->GetIntval();
|
|
SimpleLine* path =
|
|
(SimpleLine*)edge_tuple->GetAttribute(BusGraph::BG_PATH2);
|
|
|
|
if(visit_flag1[neighbor_id1 - 1]){
|
|
edge_tuple->DeleteIfAllowed();
|
|
continue;
|
|
}
|
|
|
|
cur_size = expand_queue.size();
|
|
|
|
double w2 = top.real_w + path->Length()/(speed_human*24.0*60.0*60.0);
|
|
|
|
int w1 = top.weight;///walk is not bus transfer
|
|
|
|
// BNPath_elem2 elem(pos_expand_path, cur_size, neighbor_id1, w1, w2,
|
|
// *path, TM_WALK, true);
|
|
/////////////////////////////////////////////////////////////
|
|
SimpleLine temp_sl(0);
|
|
BNPath_elem2 elem(pos_expand_path, cur_size, neighbor_id1, w1, w2,
|
|
temp_sl, TM_WALK, true);
|
|
elem.type = TM_WALK;
|
|
elem.edge_tid = adj_list1[i];
|
|
////////////////////////////////////////////////////////////
|
|
|
|
path_queue.push(elem);
|
|
expand_queue.push_back(elem);
|
|
edge_tuple->DeleteIfAllowed();
|
|
}
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
//////////////////////connection 2 same spatial location/////////////
|
|
////////////////////////////////////////////////////////////////////
|
|
if(top.tm == TM_WALK || top.tm == TM_BUS){
|
|
vector<int> adj_list2;
|
|
bg->FindAdj2(top.tri_index, adj_list2);
|
|
|
|
for(unsigned int i = 0;i < adj_list2.size();i++){
|
|
Tuple* edge_tuple = bg->edge_rel2->GetTuple(adj_list2[i], false);
|
|
int neighbor_id2 =
|
|
((CcInt*)edge_tuple->GetAttribute(BusGraph::BG_E2_BS2_TID))->GetIntval();
|
|
SimpleLine* path = new SimpleLine(0);
|
|
path->StartBulkLoad();
|
|
path->EndBulkLoad();
|
|
|
|
if(visit_flag1[neighbor_id2 - 1]){
|
|
edge_tuple->DeleteIfAllowed();
|
|
path->DeleteIfAllowed();
|
|
continue;
|
|
}
|
|
|
|
cur_size = expand_queue.size();
|
|
double w2 = top.real_w;
|
|
|
|
int w1 = top.weight;
|
|
/* BNPath_elem2 elem(pos_expand_path, cur_size, neighbor_id2, w1, w2,
|
|
*path, -1, false); //not useful for time cost */
|
|
/////////////////////////////////////////////////////////////
|
|
BNPath_elem2 elem(pos_expand_path, cur_size, neighbor_id2, w1, w2,
|
|
*path, -1, false); //not useful for time cost
|
|
elem.type = -1;
|
|
elem.edge_tid = 0;
|
|
///////////////////////////////////////////////////////////////
|
|
|
|
path_queue.push(elem);
|
|
expand_queue.push_back(elem);
|
|
|
|
path->DeleteIfAllowed();
|
|
edge_tuple->DeleteIfAllowed();
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
////////////////////connection 3 moving buses/////////////////////////
|
|
//////////////////////////////////////////////////////////////////////
|
|
vector<int> adj_list3;
|
|
bg->FindAdj3(top.tri_index, adj_list3);
|
|
int64_t max_64_int = numeric_limits<int64_t>::max();
|
|
|
|
for(unsigned int i = 0;i < adj_list3.size();i++){
|
|
Tuple* edge_tuple = bg->edge_rel3->GetTuple(adj_list3[i], false);
|
|
int neighbor_id3 =
|
|
((CcInt*)edge_tuple->GetAttribute(BusGraph::BG_E3_BS2_TID))->GetIntval();
|
|
|
|
if(visit_flag1[neighbor_id3 - 1]){
|
|
edge_tuple->DeleteIfAllowed();
|
|
continue;
|
|
}
|
|
|
|
cur_size = expand_queue.size();
|
|
double cur_t = new_st.ToDouble() + top.real_w;
|
|
Instant cur_inst = new_st;
|
|
cur_inst.ReadFrom(cur_t); //time to arrive current bus stop
|
|
// cout<<"time at bus stop "<<cur_inst<<endl;
|
|
|
|
|
|
int64_t cur_t_int = cur_t*86400000;
|
|
assert(cur_t_int <= max_64_int);
|
|
|
|
Periods* peri =
|
|
(Periods*)edge_tuple->GetAttribute(BusGraph::BG_LIFETIME);
|
|
Interval<Instant> periods;
|
|
peri->Get(0, periods);
|
|
|
|
// output<<"periods "<<periods<<"query time "<<cur_inst<<endl;
|
|
|
|
double sched =
|
|
((CcReal*)edge_tuple->GetAttribute(BusGraph::BG_SCHEDULE))->GetRealval();
|
|
double st = periods.start.ToDouble();
|
|
double et = periods.end.ToDouble();
|
|
int64_t st_int = st*86400000;
|
|
int64_t et_int = et*86400000;
|
|
assert(st_int <= max_64_int);
|
|
assert(et_int <= max_64_int);
|
|
|
|
// cout<<"st "<<periods.start<<" et "<<periods.end<<endl;
|
|
|
|
if(et_int < cur_t_int){//end time smaller than curtime
|
|
edge_tuple->DeleteIfAllowed();
|
|
continue;
|
|
}
|
|
double wait_time = 0.0;
|
|
|
|
if(st_int > cur_t_int){//wait for the first start time
|
|
wait_time += st - cur_t;
|
|
wait_time += 30.0/(24.0*60.0*60.0);//30 seconds at bus stop
|
|
}else if(st_int == cur_t_int){
|
|
wait_time += 30.0/(24.0*60.0*60.0);//30 seconds at bus stop
|
|
}else{ //most times, it is here, wait for the next schedule
|
|
|
|
bool valid = false;
|
|
while(st_int < cur_t_int && st_int <= et_int){
|
|
|
|
/* Instant temp(instanttype);
|
|
temp.ReadFrom(st);
|
|
cout<<"t1 "<<temp<<endl; */
|
|
|
|
if((st_int + 30000) >= cur_t_int){//30 second
|
|
wait_time += st + 30.0/(24.0*60.0*60.0) - cur_t;
|
|
valid = true;
|
|
break;
|
|
}
|
|
st += sched;
|
|
st_int = st * 86400000;
|
|
if(st_int >= cur_t_int){
|
|
wait_time += st + 30.0/(24.0*60.0*60.0) - cur_t;
|
|
valid = true;
|
|
break;
|
|
}
|
|
assert(st_int <= max_64_int);
|
|
|
|
// temp.ReadFrom(st);
|
|
// cout<<"t2 "<<temp<<endl;
|
|
|
|
}
|
|
if(valid == false){
|
|
cout<<"should not arrive at here"<<endl;
|
|
assert(false);
|
|
}
|
|
}
|
|
|
|
double weight =
|
|
((CcReal*)edge_tuple->GetAttribute(BusGraph::BG_TIMECOST))->GetRealval();
|
|
double w2 = top.real_w + wait_time + weight;
|
|
|
|
int w1;
|
|
|
|
if(fabs(int64_t(wait_time*86400) - 30) <= 2 ||
|
|
(int)(top.real_w*86400.0) == 0)
|
|
w1 = top.weight;
|
|
else w1 = top.weight + 1;
|
|
|
|
|
|
/* BNPath_elem2 elem(pos_expand_path, cur_size,neighbor_id3, w1, w2,
|
|
*path, TM_BUS, true);*/
|
|
///////////////////////////////////////////////////////
|
|
SimpleLine temp_sl(0);
|
|
BNPath_elem2 elem(pos_expand_path, cur_size,neighbor_id3, w1, w2,
|
|
temp_sl, TM_BUS, true);
|
|
elem.type = TM_BUS;
|
|
elem.edge_tid = adj_list3[i];
|
|
///////////////////////////////////////////////////////
|
|
if(wait_time > 0.0){ //to the time waiting for bus
|
|
elem.SetW(top.real_w + wait_time);
|
|
}
|
|
|
|
path_queue.push(elem);
|
|
expand_queue.push_back(elem);
|
|
|
|
|
|
edge_tuple->DeleteIfAllowed();
|
|
|
|
// output<<"wait time "<<wait_time*86400.0
|
|
// <<" move time "<<weight*86400.0<<endl;
|
|
// Tuple* bs_tuple = bg->node_rel->GetTuple(neighbor_id3, false);
|
|
// Bus_Stop* bs_cur = (Bus_Stop*)bs_tuple->GetAttribute(BusGraph::BG_NODE);
|
|
// output<<"extend elem; transfer: "<<elem.weight<<" "<<elem.real_w*86400.0
|
|
// <<" "<<*bs_cur<<endl<<endl;
|
|
// bs_tuple->DeleteIfAllowed();
|
|
|
|
}
|
|
|
|
visit_flag1[top.tri_index - 1] = true;
|
|
}
|
|
//////////////////////////////////////////////////////////////////////
|
|
////////////////construct the result//////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////
|
|
if(find){ ////////constrcut the result
|
|
// cout<<dest.weight<<" bus transfers"<<endl;
|
|
vector<int> id_list;
|
|
while(dest.prev_index != -1){
|
|
id_list.push_back(dest.cur_index);
|
|
dest = expand_queue[dest.prev_index];
|
|
}
|
|
id_list.push_back(dest.cur_index);
|
|
|
|
Bus_Stop bs_last = *bs1;
|
|
Instant t1 = *qt;
|
|
|
|
t_cost = 0.0;
|
|
for(int i = id_list.size() - 1;i >= 0;i--){
|
|
BNPath_elem2 elem = expand_queue[id_list[i]];
|
|
|
|
////////////////////////////////////////////////////////////
|
|
if(elem.type == TM_WALK){
|
|
assert(1 <= elem.edge_tid &&
|
|
elem.edge_tid <= bg->edge_rel1->GetNoTuples());
|
|
Tuple* edge_tuple = bg->edge_rel1->GetTuple(elem.edge_tid, false);
|
|
SimpleLine* path =
|
|
(SimpleLine*)edge_tuple->GetAttribute(BusGraph::BG_PATH2);
|
|
elem.path = *path;
|
|
edge_tuple->DeleteIfAllowed();
|
|
|
|
}else if(elem.type == TM_BUS){
|
|
if(elem.edge_tid > 0){
|
|
Tuple* edge_tuple = bg->edge_rel3->GetTuple(elem.edge_tid, false);
|
|
SimpleLine* path =
|
|
(SimpleLine*)edge_tuple->GetAttribute(BusGraph::BG_PATH3);
|
|
elem.path = *path;
|
|
edge_tuple->DeleteIfAllowed();
|
|
}
|
|
|
|
}else if(elem.type == -1){
|
|
|
|
}else{
|
|
cout<<"should not be here"<<endl;
|
|
assert(false);
|
|
}
|
|
////////////////////////////////////////////////////////////
|
|
|
|
path_list.push_back(elem.path);
|
|
|
|
if(elem.tm == TM_WALK){
|
|
tm_list.push_back(str_tm[elem.tm]);
|
|
}else if(elem.tm == TM_BUS){
|
|
tm_list.push_back(str_tm[elem.tm]);
|
|
}else{
|
|
// assert(false);
|
|
tm_list.push_back("none");
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
////////////////we also return///////////////////////////////////////
|
|
////////the start and end bus stops connected by the path ////////////
|
|
////////////////////////////////////////////////////////////////////
|
|
char buf1[256], buf2[256];
|
|
|
|
sprintf(buf1, "br: %d ", bs_last.GetId());
|
|
sprintf(buf2, "stop: %d", bs_last.GetStopId());
|
|
strcat (buf1, buf2);
|
|
if(bs_last.GetUp())strcat (buf1, " UP");
|
|
else strcat (buf1, " DOWN");
|
|
|
|
string str1(buf1);
|
|
bs1_list.push_back(str1);
|
|
|
|
if(i == (int)(id_list.size() - 1)){
|
|
string str2(str1);
|
|
bs2_list.push_back(str2);
|
|
|
|
}else{////////////////the end bus stop
|
|
|
|
Tuple* bs_tuple = bg->node_rel->GetTuple(elem.tri_index, false);
|
|
Bus_Stop* bs_cur =
|
|
(Bus_Stop*)bs_tuple->GetAttribute(BusGraph::BG_NODE);
|
|
char buf_1[256], buf_2[256];
|
|
sprintf(buf_1, "br: %d ", bs_cur->GetId());
|
|
sprintf(buf_2, "stop: %d", bs_cur->GetStopId());
|
|
strcat (buf_1, buf_2);
|
|
if(bs_cur->GetUp()) strcat (buf_1, " UP");
|
|
else strcat (buf_1, " DOWN");
|
|
|
|
string str2(buf_1);
|
|
bs2_list.push_back(str2);
|
|
bs_last = *bs_cur;
|
|
bs_tuple->DeleteIfAllowed();
|
|
}
|
|
|
|
////////////////time duration////////////////////////////////
|
|
|
|
Instant t2(instanttype);
|
|
if(elem.b_w == false){
|
|
t2.ReadFrom(elem.real_w + qt->ToDouble());
|
|
// cout<<t1<<" "<<t2<<endl;
|
|
|
|
//time cost in seconds
|
|
if(elem.valid){
|
|
time_cost_list.push_back((t2.ToDouble() - t1.ToDouble())*86400.0);
|
|
t_cost += (t2.ToDouble() - t1.ToDouble())*86400.0;
|
|
}else{ //doing transfer without moving
|
|
time_cost_list.push_back(0.0);
|
|
t_cost += 0.0;
|
|
}
|
|
|
|
Interval<Instant> time_span;
|
|
time_span.start = t1;
|
|
time_span.lc = true;
|
|
time_span.end = t2;
|
|
time_span.rc = false;
|
|
|
|
Periods* peri = new Periods(0);
|
|
peri->StartBulkLoad();
|
|
// if(elem.valid)
|
|
if(elem.valid && time_span.IsValid())
|
|
peri->MergeAdd(time_span);
|
|
peri->EndBulkLoad();
|
|
peri_list.push_back(*peri);
|
|
t1 = t2;
|
|
peri->DeleteIfAllowed();
|
|
}else{ //////////to dinstinguish time of waiting for the bus
|
|
t2.ReadFrom(elem.w + qt->ToDouble());
|
|
// cout<<t1<<" "<<t2<<endl;
|
|
|
|
//time cost in seconds
|
|
if(elem.valid){
|
|
time_cost_list.push_back((t2.ToDouble() - t1.ToDouble())*86400.0);
|
|
t_cost += (t2.ToDouble() - t1.ToDouble())*86400.0;
|
|
}else{ //doing transfer without moving
|
|
time_cost_list.push_back(0.0);
|
|
t_cost += 0.0;
|
|
}
|
|
|
|
Interval<Instant> time_span;
|
|
time_span.start = t1;
|
|
time_span.lc = true;
|
|
time_span.end = t2;
|
|
time_span.rc = false;
|
|
|
|
Periods* peri1 = new Periods(0);
|
|
peri1->StartBulkLoad();
|
|
// if(elem.valid)
|
|
if(elem.valid && time_span.IsValid())
|
|
peri1->MergeAdd(time_span);
|
|
peri1->EndBulkLoad();
|
|
peri_list.push_back(*peri1);
|
|
t1 = t2;
|
|
peri1->DeleteIfAllowed();
|
|
|
|
SimpleLine* sl = new SimpleLine(0);
|
|
sl->StartBulkLoad();
|
|
sl->EndBulkLoad();
|
|
path_list[path_list.size() - 1] = *sl;
|
|
sl->DeleteIfAllowed();
|
|
|
|
tm_list[tm_list.size() - 1] = "none"; //waiting is no tm
|
|
string str = bs2_list[bs2_list.size() - 1];
|
|
////////the same as last bus stop //////////////////////
|
|
bs2_list[bs2_list.size() - 1] = bs1_list[bs1_list.size() - 1];
|
|
|
|
|
|
/////////////moving with bus////////////////////////////////
|
|
t2.ReadFrom(elem.real_w + qt->ToDouble());
|
|
// cout<<t1<<" "<<t2<<endl;
|
|
|
|
//time cost in seconds
|
|
if(elem.valid){
|
|
time_cost_list.push_back((t2.ToDouble() - t1.ToDouble())*86400.0);
|
|
t_cost += (t2.ToDouble() - t1.ToDouble())*86400.0;
|
|
}else{ //doing transfer without moving
|
|
time_cost_list.push_back(0.0);
|
|
t_cost += 0.0;
|
|
}
|
|
|
|
time_span.start = t1;
|
|
time_span.lc = true;
|
|
time_span.end = t2;
|
|
time_span.rc = false;
|
|
|
|
Periods* peri2 = new Periods(0);
|
|
peri2->StartBulkLoad();
|
|
// if(elem.valid)
|
|
if(elem.valid && time_span.IsValid())
|
|
peri2->MergeAdd(time_span);
|
|
peri2->EndBulkLoad();
|
|
peri_list.push_back(*peri2);
|
|
t1 = t2;
|
|
peri2->DeleteIfAllowed();
|
|
path_list.push_back(elem.path);
|
|
tm_list.push_back(str_tm[elem.tm]);
|
|
bs1_list.push_back(str1);
|
|
bs2_list.push_back(str);
|
|
|
|
}
|
|
}
|
|
|
|
}else{
|
|
// cout<<"bs1 ("<<*bs1<<") bs2 ("<<*bs2<<") not reachable "<<endl;
|
|
}
|
|
|
|
bn->CloseBusGraph(bg);
|
|
}
|
|
|
|
/*
|
|
initialize the queue: shortest path in bus transfer
|
|
|
|
*/
|
|
void BNNav::InitializeQueue3(Bus_Stop* bs1, Bus_Stop* bs2,
|
|
priority_queue<BNPath_elem2>& path_queue,
|
|
vector<BNPath_elem2>& expand_queue,
|
|
BusNetwork* bn, BusGraph* bg,
|
|
Point& start_p, Point& end_p)
|
|
{
|
|
int cur_size = expand_queue.size();
|
|
int w1 = 0;
|
|
double w2 = 0.0;
|
|
|
|
SimpleLine* sl = new SimpleLine(0);
|
|
sl->StartBulkLoad();
|
|
sl->EndBulkLoad();
|
|
|
|
int bs_tid = bg->GetBusStop_Tid(bs1);
|
|
// cout<<"start bus stop tid "<<bs_tid<<endl;
|
|
//////////////////no transfer cost////////////////////////////////////
|
|
BNPath_elem2 elem(-1, cur_size, bs_tid, w1, w2, *sl, TM_BUS, false);
|
|
|
|
elem.type = TM_BUS;
|
|
elem.edge_tid = 0;
|
|
|
|
path_queue.push(elem);
|
|
expand_queue.push_back(elem);
|
|
sl->DeleteIfAllowed();
|
|
}
|
|
|
|
|
|
/*
|
|
converting from moving buses (mpoint) to genmo
|
|
|
|
*/
|
|
void BNNav::BusToGenMO(Relation* mo_rel, Relation* br_rel, BTree* btree)
|
|
{
|
|
|
|
for(int i = 1;i <= mo_rel->GetNoTuples();i++){
|
|
Tuple* bus_tuple = mo_rel->GetTuple(i, false);
|
|
unsigned int br_id =
|
|
((CcInt*)bus_tuple->GetAttribute(RoadDenstiy::BR_ID5))->GetIntval();
|
|
bool dir = ((CcBool*)bus_tuple->GetAttribute(
|
|
RoadDenstiy::MO_BUS_DIRECTION))->GetBoolval();
|
|
MPoint* mp = (MPoint*)bus_tuple->GetAttribute(RoadDenstiy::BUS_TRIP);
|
|
MPToGenMO(mp,br_id, dir, br_rel, btree);
|
|
bus_tuple->DeleteIfAllowed();
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
from mpoint, bool (direction), line id to genmo
|
|
|
|
*/
|
|
|
|
void BNNav::MPToGenMO(MPoint* mp,unsigned int br_id, bool dir, Relation* br_rel,
|
|
BTree* btree)
|
|
{
|
|
// cout<<"br id "<<br_id<<"dir "<<dir<<endl;
|
|
GenMO* genmo = new GenMO(0);
|
|
genmo->StartBulkLoad();
|
|
CcInt* search_id = new CcInt(true, br_id);
|
|
BTreeIterator* btree_iter = btree->ExactMatch(search_id);
|
|
SimpleLine* sl = new SimpleLine(0);
|
|
unsigned int bus_line_id = 0;
|
|
int bus_line_uoid = -1;
|
|
while(btree_iter->Next()){
|
|
Tuple* tuple = br_rel->GetTuple(btree_iter->GetId(), false);
|
|
Bus_Route* br = (Bus_Route*)tuple->GetAttribute(BusNetwork::BN_BR);
|
|
if(br->GetUp() == dir){
|
|
br->GetGeoData(*sl);
|
|
assert(br->GetId() == br_id);
|
|
bus_line_id =
|
|
((CcInt*)tuple->GetAttribute(BusNetwork::BN_ID2))->GetIntval();
|
|
assert(bus_line_id == br_id);
|
|
bus_line_uoid =
|
|
((CcInt*)tuple->GetAttribute(BusNetwork::BN_BR_OID))->GetIntval();
|
|
}
|
|
tuple->DeleteIfAllowed();
|
|
}
|
|
delete btree_iter;
|
|
delete search_id;
|
|
|
|
assert(bus_line_uoid > 0);
|
|
|
|
double pos1 = -1.0;
|
|
double pos2 = -1.0;
|
|
bool up;
|
|
/////////////find it is increasing or decreasing///////////////////////
|
|
UPoint u1, u2;
|
|
mp->Get(0, u1);
|
|
mp->Get(mp->GetNoComponents() - 1, u2);
|
|
|
|
assert(sl->AtPoint(u1.p0, true, pos1));
|
|
assert(sl->AtPoint(u2.p0, true, pos2));
|
|
if(pos1 < pos2) up = true;
|
|
else up = false;
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
///////// for numeric problem, we may not map all points to the sline////
|
|
////////so we find the first point and just simply add the length value//
|
|
//////first we have to know the relative positon on the route//////////
|
|
//////////////////////is increasing or decreasing///////////////////////
|
|
////////////////////////////////////////////////////////////////////////
|
|
for(int i = 0;i < mp->GetNoComponents();i++){
|
|
UPoint unit1;
|
|
mp->Get(i, unit1);
|
|
|
|
////////////////////the same when we convert it back////////////////
|
|
// cout<<"i "<<i<<"p0 "<<unit1.p0<<" p1 "<<unit1.p1<<endl;
|
|
if(i == 0){
|
|
assert(sl->AtPoint(unit1.p0, true, pos1));
|
|
assert(sl->AtPoint(unit1.p1, true, pos2));
|
|
|
|
}else{
|
|
double d = unit1.p0.Distance(unit1.p1);
|
|
pos1 = pos2;
|
|
if(up){
|
|
pos2 += d;
|
|
}else{
|
|
pos2 -= d;
|
|
}
|
|
}
|
|
// cout<<"pos1 "<<pos1<<" pos2 "<<pos2<<endl;
|
|
|
|
Loc loc1(pos1,-1);
|
|
Loc loc2(pos2,-1);
|
|
GenLoc gloc1(bus_line_uoid, loc1);
|
|
GenLoc gloc2(bus_line_uoid, loc2);
|
|
int tm = GetTM("Bus");
|
|
//////////////////////////////////////////////////////////////////
|
|
/////////////correct way to create UGenLoc///////////////////////
|
|
//////////////////////////////////////////////////////////////////
|
|
UGenLoc* unit2 = new UGenLoc(unit1.timeInterval, gloc1, gloc2, tm);
|
|
|
|
genmo->Add(*unit2);
|
|
delete unit2;
|
|
|
|
}
|
|
sl->DeleteIfAllowed();
|
|
|
|
genmo->EndBulkLoad();
|
|
|
|
genmo_list.push_back(*genmo);
|
|
br_id_list.push_back(bus_line_uoid);
|
|
mp_list.push_back(*mp);
|
|
genmo->DeleteIfAllowed();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
////////////////// Create UBahn Trains ///////////////////////////
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
/*
|
|
compact storage of time tables.
|
|
Instead of storing each time instant for every bus trip,
|
|
it stores the time periods and time interval of schedule for each route
|
|
|
|
*/
|
|
|
|
void UBTrain::CreateTimeTable_Compact()
|
|
{
|
|
vector<BusStop_Ext> station_list;
|
|
for(int i = 1;i <= rel1->GetNoTuples();i++){
|
|
Tuple* tuple_stop = rel1->GetTuple(i, false);
|
|
int lineid = ((CcInt*)tuple_stop->GetAttribute(T_LINEID))->GetIntval();
|
|
Point* loc = (Point*)tuple_stop->GetAttribute(T_STOP_LOC);
|
|
int stopid = ((CcInt*)tuple_stop->GetAttribute(T_STOP_ID))->GetIntval();
|
|
BusStop_Ext* bs_e = new BusStop_Ext(lineid,stopid,0.0,*loc,true);
|
|
station_list.push_back(*bs_e);
|
|
delete bs_e;
|
|
tuple_stop->DeleteIfAllowed();
|
|
}
|
|
sort(station_list.begin(), station_list.end());
|
|
|
|
const double dist_delta = 0.01;
|
|
unsigned int temp_count = 1;
|
|
for(unsigned int i = 0;i < station_list.size();i++){
|
|
vector<BusStop_Ext> station_list_new;
|
|
|
|
station_list_new.push_back(station_list[i]);
|
|
|
|
////////collect all metro stops mapping to the same 2D point in space/////
|
|
unsigned int j = i + 1;
|
|
BusStop_Ext bse = station_list_new[0];
|
|
|
|
while(j < station_list.size() &&
|
|
station_list[j].loc.Distance(bse.loc) < dist_delta ){
|
|
|
|
station_list_new.push_back(station_list[j]);
|
|
|
|
j++;
|
|
}
|
|
i = j - 1;
|
|
///////////////////process train station list new ///////////////////////
|
|
CreateLocTable_Compact(station_list_new,temp_count);
|
|
temp_count++;
|
|
|
|
// break;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
find the time table for one spatial location
|
|
Time tables for trains are the same on Sunday and Monday
|
|
Compact Storage -- [start time of first trip, start time of last trip]
|
|
schedule time interval
|
|
|
|
*/
|
|
|
|
void UBTrain::CreateLocTable_Compact(vector<BusStop_Ext> station_list_new,
|
|
int count_id)
|
|
{
|
|
// cout<<"size "<<station_list_new.size()<<endl;
|
|
|
|
Point loc = station_list_new[0].loc;
|
|
|
|
// cout<<"bus stop location "<<loc<<endl;
|
|
|
|
for(unsigned int i = 0;i < station_list_new.size();i++){
|
|
int br_id = station_list_new[i].br_id;
|
|
int stop_id = station_list_new[i].br_stop_id;
|
|
/////use btree to find all bus trips of this route ///////
|
|
CcInt* search_trip_id = new CcInt(true, br_id);
|
|
BTreeIterator* btree_iter = btree1->ExactMatch(search_trip_id);
|
|
|
|
vector<MPoint> trip_up;
|
|
vector<MPoint> trip_down;
|
|
|
|
bool one_day = false;
|
|
int bus_day = -1;
|
|
while(btree_iter->Next()){
|
|
Tuple* tuple_trip = rel2->GetTuple(btree_iter->GetId(), false);
|
|
int br_trip_id =
|
|
((CcInt*)tuple_trip->GetAttribute(T_LINE))->GetIntval();
|
|
bool trip_direction =
|
|
((CcBool*)tuple_trip->GetAttribute(T_UP))->GetBoolval();
|
|
assert(br_id == br_trip_id);
|
|
|
|
MPoint* mo = (MPoint*)tuple_trip->GetAttribute(T_TRIP);
|
|
UPoint up;
|
|
mo->Get(0, up);
|
|
if(one_day == false){
|
|
bus_day = up.timeInterval.start.GetDay();
|
|
one_day = true;
|
|
if(trip_direction)
|
|
trip_up.push_back(*mo);
|
|
else
|
|
trip_down.push_back(*mo);
|
|
}else if(up.timeInterval.start.GetDay() == bus_day){//the same day
|
|
assert(bus_day != -1);
|
|
// cout<<"bus day "<<bus_day<<endl;
|
|
if(trip_direction)
|
|
trip_up.push_back(*mo);
|
|
else
|
|
trip_down.push_back(*mo);
|
|
}
|
|
tuple_trip->DeleteIfAllowed();
|
|
}
|
|
delete btree_iter;
|
|
delete search_trip_id;
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
// cout<<"up size "<<trip_up.size()<<endl;
|
|
// cout<<"down size "<<trip_up.size()<<endl;
|
|
|
|
TimeTableCompact(trip_up,loc,br_id,stop_id,true,count_id);
|
|
TimeTableCompact(trip_down,loc,br_id,stop_id,false,count_id);
|
|
|
|
// cout<<"br_id "<<br_id<<" stop_id "<<stop_id<<" "<<endl;
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
extract the time for one route in one direction
|
|
|
|
*/
|
|
void UBTrain::TimeTableCompact(vector<MPoint>& trip_list, Point loc,int br_id,
|
|
int stop_id, bool dir, int count_id)
|
|
{
|
|
assert(trip_list.size() >= 2);
|
|
|
|
MPoint start_mo_0 = trip_list[0];
|
|
UPoint up1;
|
|
start_mo_0.Get(0, up1);//the start time of first trip
|
|
Instant start_time_0 = up1.timeInterval.start;
|
|
Instant st = start_time_0;
|
|
GetTimeInstantStop(start_mo_0, loc,st);
|
|
|
|
/////////////cut second and millsecond ///////////////////////////////
|
|
int second_val_s = st.GetSecond();
|
|
// int msecond_val_s = st.GetMillisecond();
|
|
// double double_s = st.ToDouble() -
|
|
// second_val_s/(24.0*60.0*60.0) -
|
|
// msecond_val_s/(24.0*60.0*60.0*1000.0);
|
|
|
|
double double_s = st.ToDouble();
|
|
|
|
|
|
st.ReadFrom(double_s);
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
MPoint start_mo_1 = trip_list[1];
|
|
UPoint up2;
|
|
start_mo_1.Get(0, up1);//the start time of second trip
|
|
Instant start_time_1 = up1.timeInterval.start;
|
|
|
|
|
|
/////////// get time interval for schedule ///////////////////
|
|
double sch_interval = start_time_1.ToDouble() - start_time_0.ToDouble();
|
|
assert(sch_interval > 0.0);
|
|
// cout<<"schedule "<<sch_interval*24.0*60.0*60.0<<" seconds"<<endl;
|
|
|
|
////////////////last bus trip ////////////////////////////////////
|
|
MPoint end_mo = trip_list[trip_list.size() - 1];
|
|
UPoint up3;
|
|
end_mo.Get(0, up3);//the start time of last trip
|
|
Instant end_time = up3.timeInterval.start;
|
|
/////////////////cut second and millsecond ////////////////////////////////
|
|
Instant et = end_time;
|
|
|
|
GetTimeInstantStop(end_mo, loc, et);
|
|
|
|
int second_val_e = et.GetSecond();
|
|
// int msecond_val_e = et.GetMillisecond();
|
|
// double double_e = et.ToDouble() -
|
|
// second_val_e/(24.0*60.0*60.0) -
|
|
// msecond_val_e/(24.0*60.0*60.0*1000.0);
|
|
|
|
double double_e = et.ToDouble();
|
|
|
|
et.ReadFrom(double_e);
|
|
////////////////////////////////////////////////////////////////////////////
|
|
assert(second_val_s == second_val_e);
|
|
Interval<Instant> time_span;
|
|
time_span.start = st;
|
|
time_span.lc = true;
|
|
time_span.end = et;
|
|
time_span.rc = true;
|
|
|
|
Periods* peri = new Periods(0);
|
|
peri->StartBulkLoad();
|
|
peri->MergeAdd(time_span);
|
|
peri->EndBulkLoad();
|
|
// duration.push_back(*peri);
|
|
// cout<<"periods "<<*peri<<endl;
|
|
|
|
|
|
// const double dist_delta = 0.01;
|
|
// const double stop_time = 10.0/(24.0*60.0*60.0); //10 seconds for trains
|
|
|
|
stop_loc_list.push_back(loc);
|
|
line_id_list.push_back(br_id);
|
|
stop_id_list.push_back(stop_id);
|
|
direction_list.push_back(dir);
|
|
duration.push_back(*peri);
|
|
loc_id_list.push_back(count_id);
|
|
schedule_interval.push_back(sch_interval);
|
|
peri->DeleteIfAllowed();
|
|
|
|
//////////////////////// check time //////////////////////////////
|
|
for(unsigned int i = 0;i < trip_list.size();i++){
|
|
MPoint mo = trip_list[i];
|
|
Instant temp_instant;
|
|
GetTimeInstantStop(mo, loc, temp_instant);
|
|
int second_val = temp_instant.GetSecond();
|
|
assert(second_val == second_val_s);
|
|
}
|
|
////////////////////////////////////////////////////////////////////////
|
|
}
|
|
|
|
/*
|
|
get the time that the train arrives at this point(stop)
|
|
|
|
*/
|
|
void UBTrain::GetTimeInstantStop(MPoint& mo, Point loc, Instant& arrove_t)
|
|
{
|
|
const double dist_delta = 0.01;
|
|
const double stop_time = 10.0/(24.0*60.0*60.0); //10 seconds for trains
|
|
for(int j = 0;j < mo.GetNoComponents();j++){
|
|
UPoint up;
|
|
mo.Get(j, up);
|
|
Point loc1 = up.p0;
|
|
Point loc2 = up.p1;
|
|
|
|
if(loc1.Distance(loc2) < dist_delta &&
|
|
loc1.Distance(loc) < dist_delta){ //find the place
|
|
Instant st = up.timeInterval.start;
|
|
Instant et = up.timeInterval.end;
|
|
double d_st = st.ToDouble();
|
|
double d_et = et.ToDouble();
|
|
assert(AlmostEqual(fabs(d_st-d_et), stop_time) ||
|
|
fabs(d_st-d_et) > stop_time);//check 10 seconds
|
|
arrove_t = st;
|
|
return;
|
|
}
|
|
}
|
|
assert(false);
|
|
}
|
|
|
|
string UBTrain::TrainsTypeInfo =
|
|
"(rel (tuple ((lineid int) (Up bool) (Trip mpoint))))";
|
|
|
|
string UBTrain::UBahnLineInfo =
|
|
"(rel (tuple ((lineid int) (oid int) (geoData sline))))";
|
|
|
|
string UBTrain:: UBahnTrainsTypeInfo =
|
|
"(rel (tuple ((Id int) (Line int) (Up bool) (Trip mpoint) (Schedule_id int))))";
|
|
|
|
string UBTrain::TrainsStopTypeInfo =
|
|
"(rel (tuple ((LineId int) (Loc point) (Stop_id int))))";
|
|
|
|
string UBTrain::TrainsStopExtTypeInfo =
|
|
"(rel (tuple ((LineId int) (loc point) (stop_id int) (Up bool))))";
|
|
|
|
string UBTrain::UBahnTrainsTimeTable =
|
|
"(rel (tuple ((Station_loc point) (Line_id int) (Stop_id int)\
|
|
(Train_direction bool) (Whole_time periods) (Schedule_interval real)\
|
|
(Loc_id int))))";
|
|
|
|
|
|
/*
|
|
convert berlintest trains to generic moving objects
|
|
|
|
*/
|
|
void UBTrain::TrainsToGenMO()
|
|
{
|
|
for(int i = 1;i <= rel1->GetNoTuples();i++){
|
|
Tuple* train_tuple = rel1->GetTuple(i, false);
|
|
int line_id =
|
|
((CcInt*)train_tuple->GetAttribute(TRAIN_LINE_ID))->GetIntval();
|
|
bool dir =
|
|
((CcBool*)train_tuple->GetAttribute(TRAIN_LINE_DIR))->GetBoolval();
|
|
MPoint* mp = ((MPoint*)train_tuple->GetAttribute(TRAIN_TRIP));
|
|
|
|
GenMO* genmo = new GenMO(0);
|
|
|
|
MPToGenMO(mp, genmo, line_id);
|
|
|
|
genmo_list.push_back(*genmo);
|
|
mp_list.push_back(*mp);
|
|
br_id_list.push_back(line_id);
|
|
direction_list.push_back(dir);
|
|
|
|
genmo->DeleteIfAllowed();
|
|
train_tuple->DeleteIfAllowed();
|
|
|
|
// break;
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
convert a moving point to a generic moving object
|
|
|
|
*/
|
|
void UBTrain::MPToGenMO(MPoint* mp, GenMO* mo, int l_id)
|
|
{
|
|
// cout<<"line id "<<l_id<<endl;
|
|
|
|
mo->StartBulkLoad();
|
|
CcInt* search_id = new CcInt(true, l_id);
|
|
BTreeIterator* btree_iter = btree1->ExactMatch(search_id);
|
|
SimpleLine* sl = new SimpleLine(0);
|
|
int ub_line_id = -1;
|
|
while(btree_iter->Next()){
|
|
Tuple* tuple = rel2->GetTuple(btree_iter->GetId(), false);
|
|
ub_line_id = ((CcInt*)tuple->GetAttribute(UB_LINE_ID))->GetIntval();
|
|
SimpleLine* l = (SimpleLine*)tuple->GetAttribute(UB_LINE_GEODATA);
|
|
*sl = *l;
|
|
tuple->DeleteIfAllowed();
|
|
}
|
|
delete btree_iter;
|
|
delete search_id;
|
|
assert(ub_line_id == l_id);
|
|
|
|
// cout<<"line length "<<sl->Length()<<endl;
|
|
|
|
for(int i = 0;i < mp->GetNoComponents();i++){
|
|
UPoint unit1;
|
|
mp->Get(i, unit1);
|
|
double pos1;
|
|
double pos2;
|
|
////////////////////////////////////////////////////////////////////
|
|
//////////////the same when we convert it back (TRUE) /////////////
|
|
////////////////////////////////////////////////////////////////////
|
|
assert(sl->AtPoint(unit1.p0, true, pos1));
|
|
assert(sl->AtPoint(unit1.p1, true, pos2));
|
|
// cout<<"pos1 "<<pos1<<" pos2 "<<pos2<<endl;
|
|
|
|
Loc loc1(pos1,-1);
|
|
Loc loc2(pos2,-1);
|
|
GenLoc gloc1(ub_line_id, loc1);
|
|
GenLoc gloc2(ub_line_id, loc2);
|
|
int tm = GetTM("Metro");
|
|
//////////////////////////////////////////////////////////////////
|
|
/////////////correct way to create UGenLoc///////////////////////
|
|
//////////////////////////////////////////////////////////////////
|
|
UGenLoc* unit2 = new UGenLoc(unit1.timeInterval, gloc1, gloc2, tm);
|
|
// if(i %2 == 0) //for debuging time intervals are not consequent
|
|
mo->Add(*unit2);
|
|
delete unit2;
|
|
|
|
}
|
|
|
|
sl->DeleteIfAllowed();
|
|
|
|
mo->EndBulkLoad();
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
////////////////////create metro from road network///////////////////////
|
|
/////////////////////////////////////////////////////////////////////////
|
|
|
|
string MetroStruct::MetroTripTypeInfo_Com = "(rel (tuple ((mtrip1 genmo)\
|
|
(mtrip2 mpoint) (mr_id int) (Up bool) (mr_oid int) (oid int))))";
|
|
|
|
string MetroStruct::MetroParaInfo = "(rel (tuple ((Para real))))";
|
|
|
|
/*
|
|
create metro routes
|
|
|
|
*/
|
|
void MetroStruct::CreateMRoute(DualGraph* dg, Relation* metro_para)
|
|
{
|
|
// int no_mroute = 10;
|
|
|
|
// int no_mroute;
|
|
// if(type == "Berlin")no_mroute = 10;
|
|
// else if(type == "Houston") no_mroute = 16;
|
|
|
|
Tuple* m_tuple1 = metro_para->GetTuple(1, false);
|
|
unsigned int no_mroute =
|
|
(unsigned int)((CcReal*)m_tuple1->GetAttribute(0))->GetRealval();
|
|
m_tuple1->DeleteIfAllowed();
|
|
|
|
// cout<<"no mroute "<<no_mroute<<endl;
|
|
|
|
vector<bool> cell_flag;
|
|
for(int i = 1;i <= dg->node_rel->GetNoTuples();i++){
|
|
cell_flag.push_back(false);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
///////////////get the center///////////////////////////////////
|
|
////////////////////////////////////////////////////////////////
|
|
Rectangle<2> area_box = dg->rtree_node->BoundingBox();
|
|
double center_x = (area_box.MinD(0) + area_box.MaxD(0))/2;
|
|
double center_y = (area_box.MinD(1) + area_box.MaxD(1))/2;
|
|
Point center(true, center_x, center_y);
|
|
int center_index = -1;
|
|
|
|
for(int i = 1;i <= dg->node_rel->GetNoTuples();i++){
|
|
Tuple* cell_tuple = dg->node_rel->GetTuple(i, false);
|
|
Region* reg = (Region*)cell_tuple->GetAttribute(DualGraph::PAVEMENT);
|
|
if(center.Inside(reg->BoundingBox())){
|
|
center_index = i;
|
|
break;
|
|
}
|
|
cell_tuple->DeleteIfAllowed();
|
|
}
|
|
assert(center_index >= 1);
|
|
|
|
|
|
vector<int> find_cell_list;
|
|
unsigned int count = 1;
|
|
|
|
// double min_dist = 22000.0;//minimum distance for a ubahn
|
|
// double min_dist;
|
|
// double min_dist2;
|
|
// if(type == "Berlin"){
|
|
// min_dist = 25000.0;
|
|
// min_dist2 = 1500.0;
|
|
// }else if(type == "Houston"){
|
|
// min_dist = 60000.0;
|
|
// min_dist2 = 6000.0;
|
|
// }else{
|
|
// cout<<"not processed"<<endl;
|
|
// assert(false);
|
|
// }
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
Tuple* m_tuple2 = metro_para->GetTuple(2, false);
|
|
double min_dist = ((CcReal*)m_tuple2->GetAttribute(0))->GetRealval();
|
|
m_tuple2->DeleteIfAllowed();
|
|
|
|
Tuple* m_tuple3 = metro_para->GetTuple(3, false);
|
|
double min_dist2 = ((CcReal*)m_tuple3->GetAttribute(0))->GetRealval();
|
|
m_tuple3->DeleteIfAllowed();
|
|
|
|
// cout<<"dist1 "<<min_dist<<" dist2 "<<min_dist2<<endl;
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
|
|
while(count <= no_mroute){
|
|
int cell1 = GetRandom() % dg->node_rel->GetNoTuples() + 1;
|
|
if(cell_flag[cell1 - 1]) continue;
|
|
int cell2 = GetRandom() % dg->node_rel->GetNoTuples() + 1;
|
|
if(cell_flag[cell2 - 1]) continue;
|
|
|
|
|
|
Tuple* cell_tuple1 = dg->node_rel->GetTuple(cell1, false);
|
|
Tuple* cell_tuple2 = dg->node_rel->GetTuple(cell2, false);
|
|
Region* reg1 = (Region*)cell_tuple1->GetAttribute(DualGraph::PAVEMENT);
|
|
Region* reg2 = (Region*)cell_tuple2->GetAttribute(DualGraph::PAVEMENT);
|
|
|
|
if(reg1->BoundingBox().Distance(reg2->BoundingBox()) < min_dist){
|
|
|
|
cell_tuple2->DeleteIfAllowed();
|
|
cell_tuple1->DeleteIfAllowed();
|
|
continue;
|
|
}
|
|
|
|
bool valid = true;
|
|
for(unsigned int i = 0;i < find_cell_list.size();i++){
|
|
Tuple* cell_tuple = dg->node_rel->GetTuple(find_cell_list[i], false);
|
|
Region* reg = (Region*)cell_tuple->GetAttribute(DualGraph::PAVEMENT);
|
|
if(reg->BoundingBox().Distance(reg1->BoundingBox()) < min_dist2){
|
|
valid = false;
|
|
break;
|
|
}
|
|
if(reg->BoundingBox().Distance(reg2->BoundingBox()) < min_dist2){
|
|
valid = false;
|
|
break;
|
|
}
|
|
cell_tuple->DeleteIfAllowed();
|
|
|
|
}
|
|
if(valid == false){
|
|
cell_tuple2->DeleteIfAllowed();
|
|
cell_tuple1->DeleteIfAllowed();
|
|
continue;
|
|
}
|
|
|
|
// cell_reg_list1.push_back(*reg1);
|
|
// cell_reg_list2.push_back(*reg2);
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
//////////////calculate the metro route connecting two cells////
|
|
//////////////////////////////////////////////////////////////////
|
|
// cout<<"start "<<cell1<<" end "<<cell2<<endl;
|
|
|
|
vector<int> path_list;
|
|
if(count <= 4){
|
|
vector<int> path_list1;
|
|
dg->Path_Weight(cell1, center_index, path_list1);
|
|
vector<int> path_list2;
|
|
dg->Path_Weight(center_index, cell2, path_list2);
|
|
|
|
for(unsigned int i = 0;i < path_list1.size();i++)
|
|
path_list.push_back(path_list1[i]);
|
|
|
|
for(unsigned int i = 1;i < path_list2.size();i++)
|
|
path_list.push_back(path_list2[i]);
|
|
}else{
|
|
dg->Path_Weight(cell1, cell2, path_list);
|
|
}
|
|
/////////////////////////////////////////////////////////////////
|
|
// cout<<path_list.size()<<endl;
|
|
|
|
if(BuildMetroRoute(path_list, dg, count)){
|
|
///////////////////////////////////////////////////////////////////
|
|
cell_flag[cell1 - 1] = true;
|
|
cell_flag[cell2 - 1] = true;
|
|
|
|
find_cell_list.push_back(cell1);
|
|
find_cell_list.push_back(cell2);
|
|
count++;
|
|
}
|
|
|
|
cell_tuple2->DeleteIfAllowed();
|
|
cell_tuple1->DeleteIfAllowed();
|
|
|
|
// break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
create the connection line for two cells
|
|
|
|
*/
|
|
bool MetroStruct::BuildMetroRoute(vector<int> path_list, DualGraph* dg,
|
|
int count)
|
|
{
|
|
vector<Point> ps_list;
|
|
for(unsigned int i = 0;i < path_list.size();i++){
|
|
Tuple* cell_tuple = dg->node_rel->GetTuple(path_list[i], false);
|
|
Region* reg = (Region*)cell_tuple->GetAttribute(DualGraph::PAVEMENT);
|
|
Rectangle<2> bbox_reg = reg->BoundingBox();
|
|
double x = (bbox_reg.MinD(0) + bbox_reg.MaxD(0))/2;
|
|
double y = (bbox_reg.MinD(1) + bbox_reg.MaxD(1))/2;
|
|
Point p(true, x ,y);
|
|
ps_list.push_back(p);
|
|
cell_tuple->DeleteIfAllowed();
|
|
}
|
|
|
|
SimpleLine* mroute = new SimpleLine(0);
|
|
mroute->StartBulkLoad();
|
|
int edgeno = 0;
|
|
for(unsigned int i = 0;i < ps_list.size() - 1;i++){
|
|
Point lp = ps_list[i];
|
|
Point rp = ps_list[i + 1];
|
|
HalfSegment hs(true, lp, rp);
|
|
hs.attr.edgeno = edgeno++;
|
|
*mroute += hs;
|
|
hs.SetLeftDomPoint(!hs.IsLeftDomPoint());
|
|
*mroute += hs;
|
|
}
|
|
|
|
mroute->EndBulkLoad();
|
|
const double min_len = 10000.0;
|
|
if(mroute->Length() < min_len){
|
|
mroute->DeleteIfAllowed();
|
|
return false;
|
|
}
|
|
|
|
// mroute_list.push_back(*mroute);
|
|
//////////////////////////////////////////////////////////////
|
|
////////////////use data type bus route represent the data///
|
|
/////////////////////////////////////////////////////////////
|
|
SpacePartition* sp = new SpacePartition();
|
|
vector<MyHalfSegment> seq_halfseg;
|
|
sp->ReorderLine(mroute, seq_halfseg);
|
|
|
|
mroute->DeleteIfAllowed();
|
|
|
|
// cout<<seq_halfseg.size()<<endl;
|
|
////////////////////////////////////////////////////////////
|
|
///////////////create two:up and down//////////////////////
|
|
//////////////////////////////////////////////////////////
|
|
Bus_Route* br1 = new Bus_Route(count, true);
|
|
br1->StartBulkLoad();
|
|
int no_1 = 0;
|
|
for(unsigned int i = 0; i < seq_halfseg.size();i++){
|
|
MyHalfSegment mhs = seq_halfseg[i];
|
|
HalfSegment hs(true, mhs.from, mhs.to);
|
|
br1->Add2(hs, no_1);
|
|
no_1++;
|
|
}
|
|
|
|
br1->EndBulkLoad();
|
|
mroute_list.push_back(*br1);
|
|
br1->DeleteIfAllowed();
|
|
///////////////////////////////////////////////////////////////
|
|
Bus_Route* br2 = new Bus_Route(count, false);
|
|
br2->StartBulkLoad();
|
|
int no_2 = 0;
|
|
for(int i = seq_halfseg.size() - 1;i >= 0;i--){
|
|
MyHalfSegment mhs = seq_halfseg[i];
|
|
HalfSegment hs(true, mhs.to, mhs.from);
|
|
br2->Add2(hs, no_2);
|
|
no_2++;
|
|
}
|
|
|
|
br2->EndBulkLoad();
|
|
mroute_list.push_back(*br2);
|
|
br2->DeleteIfAllowed();
|
|
|
|
|
|
id_list.push_back(count);
|
|
id_list.push_back(count);
|
|
|
|
delete sp;
|
|
/////////////////////////////////////////////////////////////
|
|
return true;
|
|
|
|
}
|
|
|
|
/*
|
|
create metro stops: very important format !!!
|
|
Up: stop id increases from small to large
|
|
Down: stop id decreases from large to small
|
|
1 2 3 4 5 6 true
|
|
1 2 3 4 5 6 false
|
|
|
|
*/
|
|
void MetroStruct::CreateMStop(Relation* mr)
|
|
{
|
|
for(int i = 1;i <= mr->GetNoTuples();i++){
|
|
Tuple* mr_tuple = mr->GetTuple(i, false);
|
|
int mr_id = ((CcInt*)mr_tuple->GetAttribute(MR_ID))->GetIntval();
|
|
Bus_Route* mr = (Bus_Route*)mr_tuple->GetAttribute(MR_ROUTE);
|
|
bool dir = mr->GetUp();
|
|
assert(mr_id == (int) mr->GetId());
|
|
|
|
SimpleLine sl(0);
|
|
mr->GetGeoData(sl);
|
|
|
|
SpacePartition* sp = new SpacePartition();
|
|
vector<MyHalfSegment> seq_halfseg;
|
|
sp->ReorderLine(&sl, seq_halfseg);
|
|
|
|
int s_id = 1;
|
|
for(unsigned int j = 0;j < seq_halfseg.size();j++){
|
|
Bus_Stop ms_stop(true, mr_id, s_id, dir);
|
|
Point geo_loc = seq_halfseg[j].from;
|
|
s_id++;
|
|
|
|
mstop_list.push_back(ms_stop);
|
|
stop_geo_list.push_back(geo_loc);
|
|
id_list.push_back(mr_id);
|
|
|
|
if(j == seq_halfseg.size() - 1){
|
|
Bus_Stop ms_stop2(true, mr_id, s_id, dir);
|
|
Point geo_loc2 = seq_halfseg[j].to;
|
|
s_id++;
|
|
|
|
mstop_list.push_back(ms_stop2);
|
|
stop_geo_list.push_back(geo_loc2);
|
|
id_list.push_back(mr_id);
|
|
}
|
|
|
|
}
|
|
|
|
delete sp;
|
|
|
|
mr_tuple->DeleteIfAllowed();
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
create moving metros
|
|
|
|
*/
|
|
void MetroStruct::CreateMTrips(Relation* mr, Periods* peri)
|
|
{
|
|
|
|
for(int i = 1;i <= mr->GetNoTuples();i++){
|
|
Tuple* mr_tuple = mr->GetTuple(i, false);
|
|
int mr_id = ((CcInt*)mr_tuple->GetAttribute(MR_ID))->GetIntval();
|
|
Bus_Route* mr = (Bus_Route*)mr_tuple->GetAttribute(MR_ROUTE);
|
|
bool dir = mr->GetUp();
|
|
int mr_oid = ((CcInt*)mr_tuple->GetAttribute(MR_OID))->GetIntval();
|
|
|
|
assert(mr_id == (int) mr->GetId());
|
|
|
|
SimpleLine sl(0);
|
|
mr->GetGeoData(sl);
|
|
|
|
SpacePartition* sp = new SpacePartition();
|
|
vector<MyHalfSegment> seq_halfseg;
|
|
sp->ReorderLine(&sl, seq_halfseg);
|
|
|
|
if(dir){
|
|
CreateMetroUp(seq_halfseg, peri, mr_id, mr_oid, dir);
|
|
}else{
|
|
CreateMetroDown(seq_halfseg, peri, mr_id, mr_oid, dir);
|
|
|
|
}
|
|
delete sp;
|
|
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
/////////////copy all trips one day before//////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////
|
|
CopyTripOneDayBefore();
|
|
|
|
}
|
|
|
|
/*
|
|
create metros up direction
|
|
|
|
*/
|
|
void MetroStruct::CreateMetroUp(vector<MyHalfSegment>& seg_list,
|
|
Periods* peri, int mr_id, int mr_oid, bool dir)
|
|
{
|
|
double metro_speed = 70.0*1000.0/3600.0;// -- 70km h, convert to meter second
|
|
double time_interval = 30.0/(24.0*60.0*60.0); //time of waiting
|
|
|
|
Interval<Instant> metro_periods;
|
|
peri->Get(0, metro_periods);
|
|
|
|
Instant start_time = metro_periods.start;
|
|
start_time.ReadFrom(start_time.ToDouble() + (GetRandom() % 30)/(24.0*60.0));
|
|
|
|
|
|
// cout<<start_time<<endl;
|
|
|
|
MPoint* mo = new MPoint(0);
|
|
GenMO* genmo = new GenMO(0);
|
|
mo->StartBulkLoad();
|
|
genmo->StartBulkLoad();
|
|
////////////genmo/////////////
|
|
///////////mpoint/////////////
|
|
Instant st = start_time;
|
|
Instant et = start_time;
|
|
Interval<Instant> up_interval;
|
|
|
|
for(unsigned int i = 0;i < seg_list.size();i++){
|
|
Point from_loc = seg_list[i].from;
|
|
Point to_loc = seg_list[i].to;
|
|
|
|
double dist = from_loc.Distance(to_loc);
|
|
double time = dist/metro_speed;
|
|
|
|
//////////////////////static unit /////////////////////////////
|
|
// et.ReadFrom(st.ToDouble() + 30.0/(24.0*60.0*60.0));//30 seconds
|
|
et.ReadFrom(st.ToDouble() + time_interval);//30 seconds
|
|
|
|
////////////////////create a upoint////////////////////////
|
|
up_interval.start = st;
|
|
up_interval.lc = true;
|
|
up_interval.end = et;
|
|
up_interval.rc = false;
|
|
UPoint* up1 = new UPoint(up_interval,from_loc,from_loc);
|
|
// cout<<*up<<endl;
|
|
mo->Add(*up1);
|
|
|
|
delete up1;
|
|
st = et;
|
|
/////////////////////////////////////////////////////////////
|
|
/////////////generic location unit /////////////////////////
|
|
////////////////////////////////////////////////////////////
|
|
Loc loc1(i + 1, 0.0);
|
|
Loc loc2(i + 1, 0.0);
|
|
GenLoc gloc1(mr_oid, loc1);
|
|
GenLoc gloc2(mr_oid, loc2);
|
|
int tm = GetTM("Metro");
|
|
UGenLoc* unit1 = new UGenLoc(up_interval, gloc1, gloc2, tm);
|
|
genmo->Add(*unit1);
|
|
delete unit1;
|
|
|
|
|
|
////////////////moving unit /////////////////////////////////
|
|
et.ReadFrom(st.ToDouble() + time/(24.0*60.0*60.0));
|
|
|
|
////////////////////create a upoint////////////////////////
|
|
up_interval.start = st;
|
|
up_interval.lc = true;
|
|
up_interval.end = et;
|
|
up_interval.rc = false;
|
|
UPoint* up2 = new UPoint(up_interval,from_loc,to_loc);
|
|
// cout<<*up<<endl;
|
|
mo->Add(*up2);
|
|
delete up2;
|
|
st = et;
|
|
//////////////////////////////////////////////////////////////
|
|
/////////////generic location unit //////////////////////////
|
|
////////////////////////////////////////////////////////////
|
|
Loc loc3(i + 1, 0.0);
|
|
Loc loc4(i + 1 + 1, 0.0);
|
|
GenLoc gloc3(mr_oid, loc3);
|
|
GenLoc gloc4(mr_oid, loc4);
|
|
tm = GetTM("Metro");
|
|
UGenLoc* unit2 = new UGenLoc(up_interval, gloc3, gloc4, tm);
|
|
genmo->Add(*unit2);
|
|
delete unit2;
|
|
|
|
|
|
/////////////////////////////////////////////////////////////
|
|
|
|
if(i == seg_list.size() - 1){//////the last stop
|
|
|
|
et.ReadFrom(st.ToDouble() + 30.0/(24.0*60.0*60.0));//30 seconds
|
|
|
|
////////////////////create a upoint////////////////////////
|
|
up_interval.start = st;
|
|
up_interval.lc = true;
|
|
up_interval.end = et;
|
|
up_interval.rc = false;
|
|
UPoint* up = new UPoint(up_interval,to_loc,to_loc);
|
|
// cout<<*up<<endl;
|
|
mo->Add(*up);
|
|
delete up;
|
|
st = et;
|
|
//////////////////////////////////////////////////////////////
|
|
/////////////generic location unit //////////////////////////
|
|
////////////////////////////////////////////////////////////
|
|
|
|
Loc loc5(i + 1 + 1, 0.0);
|
|
Loc loc6(i + 1 + 1, 0.0);
|
|
GenLoc gloc5(mr_oid, loc5);
|
|
GenLoc gloc6(mr_oid, loc6);
|
|
tm = GetTM("Metro");
|
|
UGenLoc* unit3 = new UGenLoc(up_interval, gloc5, gloc6, tm);
|
|
genmo->Add(*unit3);
|
|
delete unit3;
|
|
|
|
}
|
|
}
|
|
|
|
mo->EndBulkLoad();
|
|
genmo->EndBulkLoad();
|
|
|
|
|
|
mtrip_list1.push_back(*genmo);
|
|
mtrip_list2.push_back(*mo);
|
|
id_list.push_back(mr_id);
|
|
mr_oid_list.push_back(mr_oid);//unique object id for a metro route
|
|
|
|
dir_list.push_back(dir);
|
|
|
|
CopyMetroTrip(genmo, mo, peri, start_time, mr_id, mr_oid, dir);
|
|
|
|
mo->DeleteIfAllowed();
|
|
genmo->DeleteIfAllowed();
|
|
}
|
|
|
|
/*
|
|
create metros down direction
|
|
|
|
*/
|
|
void MetroStruct::CreateMetroDown(vector<MyHalfSegment>& seg_list,
|
|
Periods* peri, int mr_id,
|
|
int mr_oid, bool dir)
|
|
{
|
|
double metro_speed = 70.0*1000.0/3600;// -- 70km h, convert to meter minute
|
|
double time_interval = 30.0/(24.0*60.0*60.0); //time of waiting
|
|
|
|
|
|
Interval<Instant> metro_periods;
|
|
peri->Get(0, metro_periods);
|
|
|
|
Instant start_time = metro_periods.start;
|
|
start_time.ReadFrom(start_time.ToDouble() + (GetRandom() % 30)/(24.0*60.0));
|
|
|
|
MPoint* mo = new MPoint(0);
|
|
GenMO* genmo = new GenMO(0);
|
|
mo->StartBulkLoad();
|
|
genmo->StartBulkLoad();
|
|
|
|
|
|
////////////genmo/////////////
|
|
///////////mpoint/////////////
|
|
Instant st = start_time;
|
|
Instant et = start_time;
|
|
Interval<Instant> up_interval;
|
|
|
|
|
|
for(int i = seg_list.size() - 1; i >= 0; i--){
|
|
|
|
Point from_loc = seg_list[i].to;
|
|
Point to_loc = seg_list[i].from;
|
|
|
|
double dist = from_loc.Distance(to_loc);
|
|
double time = dist/metro_speed;
|
|
|
|
//////////////////////static unit /////////////////////////////
|
|
// et.ReadFrom(st.ToDouble() + 30.0/(24.0*60.0*60.0));//30 seconds
|
|
et.ReadFrom(st.ToDouble() + time_interval);//30 seconds
|
|
|
|
////////////////////create a upoint////////////////////////
|
|
up_interval.start = st;
|
|
up_interval.lc = true;
|
|
up_interval.end = et;
|
|
up_interval.rc = false;
|
|
UPoint* up1 = new UPoint(up_interval,from_loc,from_loc);
|
|
// cout<<*up<<endl;
|
|
mo->Add(*up1);
|
|
|
|
delete up1;
|
|
st = et;
|
|
|
|
/////////////////////////////////////////////////////////////
|
|
/////////////generic location unit /////////////////////////
|
|
////////////////////////////////////////////////////////////
|
|
|
|
Loc loc1(i + 1 + 1, 0.0);
|
|
Loc loc2(i + 1 + 1, 0.0);
|
|
GenLoc gloc1(mr_oid, loc1);
|
|
GenLoc gloc2(mr_oid, loc2);
|
|
int tm = GetTM("Metro");
|
|
UGenLoc* unit1 = new UGenLoc(up_interval, gloc1, gloc2, tm);
|
|
genmo->Add(*unit1);
|
|
delete unit1;
|
|
|
|
|
|
////////////////moving unit /////////////////////////////////
|
|
et.ReadFrom(st.ToDouble() + time/(24.0*60.0*60.0));
|
|
|
|
////////////////////create a upoint////////////////////////
|
|
up_interval.start = st;
|
|
up_interval.lc = true;
|
|
up_interval.end = et;
|
|
up_interval.rc = false;
|
|
UPoint* up2 = new UPoint(up_interval,from_loc,to_loc);
|
|
// cout<<*up<<endl;
|
|
mo->Add(*up2);
|
|
delete up2;
|
|
st = et;
|
|
////////////////////////////////////////////////////////////
|
|
|
|
//////////////////////////////////////////////////////////////
|
|
/////////////generic location unit //////////////////////////
|
|
////////////////////////////////////////////////////////////
|
|
|
|
Loc loc3(i + 1 + 1, 0.0);
|
|
Loc loc4(i + 1, 0.0);
|
|
GenLoc gloc3(mr_oid, loc3);
|
|
GenLoc gloc4(mr_oid, loc4);
|
|
tm = GetTM("Metro");
|
|
UGenLoc* unit2 = new UGenLoc(up_interval, gloc3, gloc4, tm);
|
|
genmo->Add(*unit2);
|
|
delete unit2;
|
|
|
|
|
|
if(i == 0){//////the last stop
|
|
|
|
et.ReadFrom(st.ToDouble() + 30.0/(24.0*60.0*60.0));//30 seconds
|
|
|
|
////////////////////create a upoint////////////////////////
|
|
up_interval.start = st;
|
|
up_interval.lc = true;
|
|
up_interval.end = et;
|
|
up_interval.rc = false;
|
|
UPoint* up = new UPoint(up_interval, to_loc, to_loc);
|
|
// cout<<*up<<endl;
|
|
mo->Add(*up);
|
|
delete up;
|
|
st = et;
|
|
//////////////////////////////////////////////////////////////
|
|
/////////////generic location unit //////////////////////////
|
|
////////////////////////////////////////////////////////////
|
|
|
|
Loc loc5(i + 1, 0.0);
|
|
Loc loc6(i + 1, 0.0);
|
|
GenLoc gloc5(mr_oid, loc5);
|
|
GenLoc gloc6(mr_oid, loc6);
|
|
tm = GetTM("Metro");
|
|
UGenLoc* unit3 = new UGenLoc(up_interval, gloc5, gloc6, tm);
|
|
genmo->Add(*unit3);
|
|
delete unit3;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
mo->EndBulkLoad();
|
|
genmo->EndBulkLoad();
|
|
|
|
mtrip_list1.push_back(*genmo);
|
|
mtrip_list2.push_back(*mo);
|
|
id_list.push_back(mr_id);
|
|
mr_oid_list.push_back(mr_oid);//unique object id for a metro route
|
|
|
|
dir_list.push_back(dir);
|
|
|
|
CopyMetroTrip(genmo, mo, peri, start_time, mr_id, mr_oid, dir);
|
|
|
|
mo->DeleteIfAllowed();
|
|
genmo->DeleteIfAllowed();
|
|
|
|
}
|
|
|
|
/*
|
|
copy the metro to have more schedules
|
|
|
|
*/
|
|
void MetroStruct::CopyMetroTrip(GenMO* genmo, MPoint* mo,
|
|
Periods* peri, Instant s_time,
|
|
int mr_id, int mr_oid, bool dir)
|
|
{
|
|
|
|
Interval<Instant> metro_periods;
|
|
peri->Get(0, metro_periods);
|
|
|
|
double schedule = 10.0/(24.0*60.0);
|
|
Instant new_start = s_time;
|
|
/////////////////10 minutes for each metro ////////////////
|
|
new_start.ReadFrom(new_start.ToDouble() + schedule);
|
|
|
|
int sched_id = 1;
|
|
while(new_start < metro_periods.end){
|
|
|
|
// cout<<"start time "<<new_start<<endl;
|
|
|
|
MPoint* new_mo = new MPoint(0);
|
|
GenMO* new_genmo = new GenMO(0);
|
|
new_mo->StartBulkLoad();
|
|
new_genmo->StartBulkLoad();
|
|
|
|
|
|
assert(mo->GetNoComponents() == genmo->GetNoComponents());
|
|
|
|
for(int i = 0;i < mo->GetNoComponents();i++){
|
|
UPoint up;
|
|
mo->Get(i, up);
|
|
Instant st = up.timeInterval.start;
|
|
st.ReadFrom(st.ToDouble() + schedule*sched_id );
|
|
Instant et = up.timeInterval.end;
|
|
et.ReadFrom(et.ToDouble() + schedule*sched_id);
|
|
up.timeInterval.start = st;
|
|
up.timeInterval.end = et;
|
|
new_mo->Add(up);
|
|
|
|
/////////////////////////////////////////////////
|
|
//////////genmo units //////////////////////////
|
|
/////////////////////////////////////////////////
|
|
UGenLoc ugloc;
|
|
genmo->Get(i, ugloc);
|
|
// cout<<ugloc<<endl;
|
|
|
|
UGenLoc* unit_new = new UGenLoc(up.timeInterval, ugloc.gloc1,
|
|
ugloc.gloc2, ugloc.tm);
|
|
new_genmo->Add(*unit_new);
|
|
delete unit_new;
|
|
|
|
}
|
|
|
|
new_mo->EndBulkLoad();
|
|
new_genmo->EndBulkLoad();
|
|
|
|
|
|
mtrip_list1.push_back(*new_genmo);
|
|
mtrip_list2.push_back(*new_mo);
|
|
id_list.push_back(mr_id);
|
|
mr_oid_list.push_back(mr_oid);//unique object id for a metro route
|
|
|
|
dir_list.push_back(dir);
|
|
|
|
new_mo->DeleteIfAllowed();
|
|
new_genmo->DeleteIfAllowed();
|
|
|
|
new_start.ReadFrom(new_start.ToDouble() + schedule);
|
|
sched_id++;
|
|
|
|
}
|
|
}
|
|
|
|
/*
|
|
copy the metro trips on Sunday
|
|
|
|
*/
|
|
void MetroStruct::CopyTripOneDayBefore()
|
|
{
|
|
int start = 0;
|
|
int end = mtrip_list1.size();
|
|
|
|
for(;start < end; start++){
|
|
|
|
GenMO* genmo = &mtrip_list1[start];
|
|
MPoint* mo = &mtrip_list2[start];
|
|
|
|
int mr_id = id_list[start];
|
|
bool dir = dir_list[start];
|
|
int mr_oid = mr_oid_list[start];
|
|
|
|
|
|
MPoint* new_mo = new MPoint(0);
|
|
GenMO* new_genmo = new GenMO(0);
|
|
new_mo->StartBulkLoad();
|
|
new_genmo->StartBulkLoad();
|
|
double schedule = 1.0;///////// one day before
|
|
|
|
for(int i = 0;i < mo->GetNoComponents();i++){
|
|
UPoint up;
|
|
mo->Get(i, up);
|
|
Instant st = up.timeInterval.start;
|
|
st.ReadFrom(st.ToDouble() - schedule);
|
|
Instant et = up.timeInterval.end;
|
|
et.ReadFrom(et.ToDouble() - schedule);
|
|
up.timeInterval.start = st;
|
|
up.timeInterval.end = et;
|
|
new_mo->Add(up);
|
|
|
|
/////////////////////////////////////////////////
|
|
//////////genmo units //////////////////////////
|
|
/////////////////////////////////////////////////
|
|
UGenLoc ugloc;
|
|
genmo->Get(i, ugloc);
|
|
// cout<<ugloc<<endl;
|
|
|
|
UGenLoc* unit_new = new UGenLoc(up.timeInterval, ugloc.gloc1,
|
|
ugloc.gloc2, ugloc.tm);
|
|
new_genmo->Add(*unit_new);
|
|
delete unit_new;
|
|
|
|
}
|
|
|
|
new_mo->EndBulkLoad();
|
|
new_genmo->EndBulkLoad();
|
|
|
|
id_list.push_back(mr_id);
|
|
dir_list.push_back(dir);
|
|
mr_oid_list.push_back(mr_oid);
|
|
|
|
mtrip_list1.push_back(*new_genmo);
|
|
mtrip_list2.push_back(*new_mo);
|
|
|
|
new_mo->DeleteIfAllowed();
|
|
new_genmo->DeleteIfAllowed();
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
create one kind of edges for metro graph where two metro stops have the same
|
|
spatial location
|
|
|
|
*/
|
|
void MetroStruct::MsNeighbors1(Relation* r)
|
|
{
|
|
// cout<<"MsNeighbors1"<<endl;
|
|
vector<UBahn_Stop> ub_stop_list;
|
|
for(int i = 1;i <= r->GetNoTuples();i++){
|
|
Tuple* ub_tuple = r->GetTuple(i, false);
|
|
|
|
int line_id =
|
|
((CcInt*)ub_tuple->GetAttribute(MetroNetwork::M_R_ID))->GetIntval();
|
|
|
|
Bus_Stop* mr_stop =
|
|
(Bus_Stop*)ub_tuple->GetAttribute(MetroNetwork::M_STOP);
|
|
Point* loc =
|
|
(Point*)ub_tuple->GetAttribute(MetroNetwork::M_STOP_GEO);
|
|
int stop_id = mr_stop->GetStopId();
|
|
bool dir = mr_stop->GetUp();
|
|
|
|
UBahn_Stop ub_stop(line_id, *loc, stop_id, dir, ub_tuple->GetTupleId());
|
|
ub_stop_list.push_back(ub_stop);
|
|
ub_tuple->DeleteIfAllowed();
|
|
}
|
|
|
|
// cout<<ub_stop_list.size()<<endl;
|
|
// sort(ub_stop_list.begin(), ub_stop_list.end());
|
|
|
|
const double delta_dist = 0.01;
|
|
for(unsigned int i = 0; i < ub_stop_list.size();i++){
|
|
|
|
for(unsigned int j = 0; j < ub_stop_list.size();j++){
|
|
if(i != j){
|
|
if(ub_stop_list[i].loc.Distance(ub_stop_list[j].loc) < delta_dist){
|
|
ms_tid_list1.push_back(ub_stop_list[i].tid);
|
|
ms_tid_list2.push_back(ub_stop_list[j].tid);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
create edges for metro graph where two metro stops are connected by moving
|
|
metros
|
|
|
|
*/
|
|
void MetroStruct::MsNeighbors2(MetroNetwork* mn, Relation* timetable,
|
|
BTree* btree1,
|
|
Relation* metrotrip, BTree* btree2)
|
|
{
|
|
// cout<<"MsNeighbors2 "<<endl;
|
|
Relation* ms_rel = mn->GetMS_Rel();
|
|
for(int i = 1;i <= ms_rel->GetNoTuples();i++){
|
|
Tuple* ms_tuple = ms_rel->GetTuple(i, false);
|
|
|
|
/* int line_id = ((CcInt*)ms_tuple->GetAttribute(T_LINEID_EXT))->GetIntval();
|
|
Point *loc = (Point*)ms_tuple->GetAttribute(T_STOP_LOC_EXT);
|
|
int stop_id = ((CcInt*)ms_tuple->GetAttribute(T_STOP_ID_EXT))->GetIntval();
|
|
bool dir = ((CcBool*)ms_tuple->GetAttribute(T_DIRECTION))->GetBoolval();*/
|
|
|
|
int line_id =
|
|
((CcInt*)ms_tuple->GetAttribute(MetroNetwork::M_R_ID))->GetIntval();
|
|
Bus_Stop* ms = (Bus_Stop*)ms_tuple->GetAttribute(MetroNetwork::M_STOP);
|
|
Point *loc = (Point*)ms_tuple->GetAttribute(MetroNetwork::M_STOP_GEO);
|
|
int stop_id = ms->GetStopId();
|
|
bool dir = ms->GetUp();
|
|
|
|
|
|
UBahn_Stop ms_stop(line_id, *loc, stop_id, dir, ms_tuple->GetTupleId());
|
|
|
|
int neighbor_tid = mn->GetMS_Stop_Neighbor(&ms_stop);
|
|
|
|
if(neighbor_tid > 0){
|
|
// ms_stop.Print();
|
|
Tuple* ms_tuple2 = ms_rel->GetTuple(neighbor_tid, false);
|
|
// Point *loc2 = (Point*)ms_tuple2->GetAttribute(T_STOP_LOC_EXT);
|
|
Point *loc2 = (Point*)ms_tuple2->GetAttribute(MetroNetwork::M_STOP_GEO);
|
|
|
|
ConnectionOneRoute(&ms_stop, timetable, btree1,
|
|
metrotrip, btree2, neighbor_tid, loc2);
|
|
|
|
ms_tuple2->DeleteIfAllowed();
|
|
|
|
ms_tid_list1.push_back(ms_tuple->GetTupleId());
|
|
ms_tid_list2.push_back(neighbor_tid);
|
|
}
|
|
|
|
ms_tuple->DeleteIfAllowed();
|
|
|
|
/*if(neighbor_tid > 0){
|
|
Tuple* ms_tuple2 = ms_rel->GetTuple(neighbor_tid, false);
|
|
int line_id2 = ((CcInt*)ms_tuple2->GetAttribute(T_LINEID_EXT))->GetIntval();
|
|
Point *loc2 = (Point*)ms_tuple2->GetAttribute(T_STOP_LOC_EXT);
|
|
int stop_id2 = ((CcInt*)ms_tuple2->GetAttribute(T_STOP_ID_EXT))->GetIntval();
|
|
bool dir2 = ((CcBool*)ms_tuple2->GetAttribute(T_DIRECTION))->GetBoolval();
|
|
UBahn_Stop ms_stop2(line_id2, *loc2, stop_id2, dir2, ms_tuple2->GetTupleId());
|
|
|
|
ms_tuple2->DeleteIfAllowed();
|
|
ms_stop2.Print();
|
|
cout<<endl;
|
|
}else
|
|
cout<<"no neighbor "<<endl; */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
build the connection for a metro stop in one route, to its next stop
|
|
|
|
*/
|
|
void MetroStruct::ConnectionOneRoute(UBahn_Stop* ms_stop, Relation* timetable,
|
|
BTree* btree1, Relation* metrotrip,
|
|
BTree* btree2,
|
|
int Neighbor_tid, Point* Neighbor_loc)
|
|
{
|
|
///////////////////////////////////////////////////////////////
|
|
//////////////////find the periods and schedule ///////////////
|
|
///////////////////////////////////////////////////////////////
|
|
CcInt* search_cell_id1 = new CcInt(true, ms_stop->line_id);
|
|
BTreeIterator* btree_iter1 = btree1->ExactMatch(search_cell_id1);
|
|
while(btree_iter1->Next()){
|
|
Tuple* tuple = timetable->GetTuple(btree_iter1->GetId(), false);
|
|
int l_id =
|
|
((CcInt*)tuple->GetAttribute(UBTrain::UB_LINE_ID_T))->GetIntval();
|
|
assert(l_id == ms_stop->line_id);
|
|
int s_id =
|
|
((CcInt*)tuple->GetAttribute(UBTrain::UB_STOP_ID_T))->GetIntval();
|
|
bool dir =
|
|
((CcBool*)tuple->GetAttribute(UBTrain::UB_DIR_T))->GetBoolval();
|
|
if(s_id == ms_stop->stop_id && dir == ms_stop->d){
|
|
Periods* peri = (Periods*)tuple->GetAttribute(UBTrain::UB_PERIODS_T);
|
|
double sche_int =
|
|
((CcReal*)tuple->GetAttribute(UBTrain::UB_INTERVAL_T))->GetRealval();
|
|
// cout<<"periods "<<*peri<<" interval "<<sche_int*86400.0<<endl;
|
|
|
|
period_list.push_back(*peri);
|
|
schedule_interval.push_back(sche_int);
|
|
break;
|
|
}
|
|
|
|
tuple->DeleteIfAllowed();
|
|
}
|
|
delete btree_iter1;
|
|
delete search_cell_id1;
|
|
|
|
////////////////////////////////////////////////////////////////
|
|
//////////////////find the trip connecting two metro stops /////
|
|
////////////////////////////////////////////////////////////////
|
|
CcInt* search_cell_id2 = new CcInt(true, ms_stop->line_id);
|
|
BTreeIterator* btree_iter2 = btree2->ExactMatch(search_cell_id2);
|
|
bool found = false;
|
|
while(btree_iter2->Next()){
|
|
Tuple* tuple = metrotrip->GetTuple(btree_iter2->GetId(), false);
|
|
/* int l_id =
|
|
((CcInt*)tuple->GetAttribute(MetroNetwork::UB_M_LINE_ID))->GetIntval();
|
|
assert(l_id == ms_stop->line_id);
|
|
bool dir =
|
|
((CcBool*)tuple->GetAttribute(MetroNetwork::UB_M_LINE_DIR))->GetBoolval();*/
|
|
|
|
int l_id = ((CcInt*)tuple->GetAttribute(M_R_ID_COM))->GetIntval();
|
|
assert(l_id == ms_stop->line_id);
|
|
bool dir = ((CcBool*)tuple->GetAttribute(M_DIR_COM))->GetBoolval();
|
|
|
|
|
|
// cout<<"l_id "<<l_id<<" dir "<<dir<<endl;
|
|
if(dir == ms_stop->d){
|
|
const double delta_dist = 0.01;
|
|
// MPoint* mo = (MPoint*)tuple->GetAttribute(MetroNetwork::UB_TRIP2_MO);
|
|
MPoint* mo = (MPoint*)tuple->GetAttribute(M_MP_COM);
|
|
///////////////////////////////////////////////////////////
|
|
///////////////find the stop units////////////////////////
|
|
/////////////////////////////////////////////////////////
|
|
int j = 0;
|
|
for(;j < mo->GetNoComponents();j++){
|
|
UPoint up;
|
|
mo->Get(j, up);
|
|
Point lp = up.p0;
|
|
Point rp = up.p1;
|
|
if(ms_stop->loc.Distance(lp) < delta_dist &&
|
|
ms_stop->loc.Distance(rp) < delta_dist){
|
|
// cout<<"find the stop "<<endl;
|
|
break;
|
|
}
|
|
}
|
|
assert(j < mo->GetNoComponents());
|
|
if(j == mo->GetNoComponents() - 1){//last stop, need not process
|
|
|
|
}else{
|
|
MPoint sub_move(0);
|
|
sub_move.StartBulkLoad();
|
|
double time_move = 0.0;
|
|
for(j++;j < mo->GetNoComponents();j++){//start from next unit
|
|
UPoint up;
|
|
mo->Get(j, up);
|
|
Point lp = up.p0;
|
|
Point rp = up.p1;
|
|
if(lp.Distance(rp) < delta_dist &&
|
|
Neighbor_loc->Distance(lp) < delta_dist){ //next bus stop
|
|
break;
|
|
}else{
|
|
sub_move.Add(up);
|
|
time_move += up.timeInterval.end.ToDouble() -
|
|
up.timeInterval.start.ToDouble();
|
|
}
|
|
}
|
|
sub_move.EndBulkLoad();
|
|
// cout<<" time cost "<<time_move*86400.0<<endl;
|
|
Line traj(0);
|
|
sub_move.Trajectory(traj);
|
|
SimpleLine sl_traj(0);
|
|
sl_traj.fromLine(traj);
|
|
|
|
geodata.push_back(sl_traj);
|
|
time_cost_list.push_back(time_move);
|
|
|
|
}
|
|
|
|
found = true;
|
|
}
|
|
tuple->DeleteIfAllowed();
|
|
|
|
if(found)break;
|
|
}
|
|
delete btree_iter2;
|
|
delete search_cell_id2;
|
|
|
|
assert(found);
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
map a metro stop to a pavement area
|
|
|
|
*/
|
|
void MetroStruct::MapMSToPave(Relation* rel1, Relation* rel2,
|
|
R_Tree<2,TupleId>* rtree)
|
|
{
|
|
Rectangle<2> bbox = rtree->BoundingBox();
|
|
|
|
for(int i = 1;i <= rel1->GetNoTuples();i++){
|
|
Tuple* ms_tuple = rel1->GetTuple(i, false);
|
|
Point* ms_loc = (Point*)ms_tuple->GetAttribute(MetroNetwork::M_STOP_GEO);
|
|
vector<int> tri_tid_list;
|
|
double dist = bbox.MaxD(0) - bbox.MinD(0);
|
|
DFTraverse(rtree, rel2, rtree->RootRecordId(), ms_loc, tri_tid_list, dist);
|
|
// cout<<"min dist "<<dist<<" size "<<tri_tid_list.size()<<endl;
|
|
|
|
Tuple* pave_tuple =
|
|
rel2->GetTuple(tri_tid_list[tri_tid_list.size() - 1], false);
|
|
int tri_oid =
|
|
((CcInt*)pave_tuple->GetAttribute(DualGraph::OID))->GetIntval();
|
|
Region* reg = (Region*)pave_tuple->GetAttribute(DualGraph::PAVEMENT);
|
|
///////////////////////////////////////////////////////////////////
|
|
/////////////get the closet point on the region to the ms loc/////
|
|
///////////////////////////////////////////////////////////////////
|
|
SpacePartition* sp = new SpacePartition();
|
|
|
|
Point ms_loc1 = *ms_loc;
|
|
Point ms_loc2;
|
|
for(int j = 0;j < reg->Size();j++){
|
|
HalfSegment hs;
|
|
reg->Get(j, hs);
|
|
if(!hs.IsLeftDomPoint()) continue;
|
|
Point cp;
|
|
sp->GetClosestPoint(hs, ms_loc1, cp);
|
|
if(j == 0){
|
|
ms_loc2 = cp;
|
|
}else{
|
|
if(ms_loc1.Distance(cp) < ms_loc1.Distance(ms_loc2)){
|
|
ms_loc2 = cp;
|
|
}
|
|
}
|
|
}
|
|
|
|
delete sp;
|
|
|
|
Rectangle<2> reg_box = reg->BoundingBox();
|
|
Loc loc(ms_loc2.GetX() - reg_box.MinD(0),
|
|
ms_loc2.GetY() - reg_box.MinD(1));
|
|
GenLoc gloc(tri_oid, loc);
|
|
loc_list1.push_back(gloc);/////////generic location in the pavement
|
|
|
|
// id_list.push_back(tri_oid);
|
|
// neighbor_list.push_back(*reg);
|
|
// loc_list2.push_back(*ms_loc);
|
|
|
|
Bus_Stop* ms_stop = (Bus_Stop*)ms_tuple->GetAttribute(MetroNetwork::M_STOP);
|
|
Point* ms_stop_loc =
|
|
(Point*)ms_tuple->GetAttribute(MetroNetwork::M_STOP_GEO);
|
|
|
|
stop_geo_list.push_back(*ms_stop_loc);
|
|
mstop_list.push_back(*ms_stop);
|
|
loc_list2.push_back(ms_loc2);
|
|
|
|
pave_tuple->DeleteIfAllowed();
|
|
ms_tuple->DeleteIfAllowed();
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
traverse the rtree built on pavement areas and find the clost point to the
|
|
metro stop
|
|
|
|
*/
|
|
void MetroStruct::DFTraverse(R_Tree<2,TupleId>* rtree, Relation* rel,
|
|
SmiRecordId adr, Point* loc,
|
|
vector<int>& tri_tid_list, double& min_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 = rel->GetTuple(e.info, false);
|
|
Region* reg =
|
|
(Region*)dg_tuple->GetAttribute(DualGraph::PAVEMENT);
|
|
|
|
double d = reg->Distance(*loc);
|
|
if(d < min_dist){
|
|
tri_tid_list.push_back(e.info);
|
|
min_dist = d;
|
|
}
|
|
dg_tuple->DeleteIfAllowed();
|
|
}else{
|
|
R_TreeInternalEntry<2> e =
|
|
(R_TreeInternalEntry<2>&)(*node)[j];
|
|
if(loc->Distance(e.box) < min_dist){
|
|
DFTraverse(rtree, rel, e.pointer, loc, tri_tid_list, min_dist);
|
|
}
|
|
}
|
|
}
|
|
delete node;
|
|
}
|
|
///////////////////////////////////////////////////////////////
|
|
//////////////////// metro network/////////////////////////////
|
|
///////////////////////////////////////////////////////////////
|
|
|
|
/////////////// used for the real data (ubahn, converting)///////////////////
|
|
|
|
string MetroNetwork::UBAHNStopsTypeInfo =
|
|
"(rel (tuple ((LineId int) (loc point) (stop_id int) (Up bool))))";
|
|
|
|
string MetroNetwork::UBAHNStopsBTreeTypeInfo =
|
|
"(btree (tuple ((LineId int) (loc point) (stop_id int) (Up bool))) int)";
|
|
|
|
string MetroNetwork::UBAHNStopsRTreeTypeInfo = "(rtree (tuple ((LineId int)\
|
|
(loc point) (stop_id int) (Up bool))) point FALSE)";
|
|
|
|
string MetroNetwork::UBAHNRoutesTypeInfo = "(rel (tuple ((lineid int)\
|
|
(oid int) (geoData sline))))";
|
|
|
|
string MetroNetwork::UBAHNRotuesBTreeTypeInfo = "(rel (tuple ((lineid int)\
|
|
(oid int) (geoData sline))) int)";
|
|
|
|
|
|
string MetroNetwork::MetroStopsTypeInfo =
|
|
"(rel (tuple ((Ms_stop busstop) (Stop_geodata point) (Mr_id int))))";
|
|
|
|
string MetroNetwork::MetroStopsBTreeTypeInfo =
|
|
"(btree (tuple ((Ms_stop busstop) (Stop_geodata point) (Mr_id int))) int)";
|
|
|
|
string MetroNetwork::MetroStopsRTreeTypeInfo =
|
|
"(rtree (tuple ((Ms_stop busstop)(Stop_geodata point)\
|
|
(Mr_id int))) point FALSE)";
|
|
|
|
string MetroNetwork::MetroRoutesTypeInfo = "(rel (tuple ((Mr_id int) \
|
|
(Mroute busroute) (Oid int))))";
|
|
|
|
string MetroNetwork::MetroRoutesBTreTypeInfo = "(rel (tuple ((Mr_id int)\
|
|
(Mroute busroute) (Oid int))) int)";
|
|
|
|
string MetroNetwork::MetroTripTypeInfo = "(rel (tuple ((Mtrip1 genmo)\
|
|
(Mtrip2 mpoint) (Mr_oid int) (Oid int))))";
|
|
|
|
string MetroNetwork::MetroTypeBTreeTypeInfo = "(btree (tuple ((Mtrip1 genmo)\
|
|
(Mtrip2 mpoint) (Mr_id int) (Oid int))) int)";
|
|
|
|
string MetroNetwork::MetroPaveTypeInfo =
|
|
"(rel (tuple ((Loc1 genloc) (Loc2 point) (Ms_stop busstop)\
|
|
(Ms_stop_loc point))))";
|
|
|
|
string MetroNetwork::RTreeMetroPaveTypeInfo =
|
|
"(rtree (tuple ((Loc1 genloc) (Loc2 point) (Ms_stop busstop)\
|
|
(Ms_stop_loc point))) point FALSE)";
|
|
|
|
|
|
ListExpr MetroNetworkProperty()
|
|
{
|
|
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("metronetwork"),
|
|
nl->StringAtom("((def, id))"),
|
|
nl->StringAtom("((TRUE 1))"))));
|
|
}
|
|
|
|
/*
|
|
In function. there is no nested list expression here.
|
|
|
|
*/
|
|
Word InMetroNetwork( const ListExpr typeInfo, const ListExpr instance,
|
|
const int errorPos, ListExpr& errorInfo, bool& correct )
|
|
{
|
|
|
|
// cout<<"length "<<nl->ListLength(instance)<<endl;
|
|
|
|
if( !nl->IsAtom( instance ) ){
|
|
|
|
if(nl->ListLength(instance) != 2){
|
|
cout<<"length should be 2"<<endl;
|
|
correct = false;
|
|
return SetWord(Address(0));
|
|
}
|
|
ListExpr first = nl->First(instance);
|
|
ListExpr second = nl->Second(instance);
|
|
|
|
if(!nl->IsAtom(first) || nl->AtomType(first) != BoolType){
|
|
cout<< "busnetwork(): definition must be bool type"<<endl;
|
|
correct = false;
|
|
return SetWord(Address(0));
|
|
}
|
|
bool d = nl->BoolValue(first);
|
|
|
|
|
|
if(!nl->IsAtom(second) || nl->AtomType(second) != IntType){
|
|
cout<< "metronetwork(): metro network id must be int type"<<endl;
|
|
correct = false;
|
|
return SetWord(Address(0));
|
|
}
|
|
unsigned int id = nl->IntValue(second);
|
|
|
|
MetroNetwork* mn = new MetroNetwork(d, id);
|
|
|
|
////////////////very important /////////////////////////////
|
|
correct = true;
|
|
///////////////////////////////////////////////////////////
|
|
return SetWord(mn);
|
|
}
|
|
|
|
correct = false;
|
|
return SetWord(Address(0));
|
|
}
|
|
|
|
/*
|
|
output the metro network
|
|
|
|
*/
|
|
ListExpr OutMetroNetwork( ListExpr typeInfo, Word value )
|
|
{
|
|
// cout<<"OutMetroNetwork"<<endl;
|
|
MetroNetwork* mn = (MetroNetwork*)(value.addr);
|
|
if(!mn->IsDefined()){
|
|
return nl->SymbolAtom("undef");
|
|
}
|
|
|
|
ListExpr list1 = nl->TwoElemList(
|
|
nl->StringAtom("Metro Network Id:"),
|
|
nl->IntAtom(mn->GetId()));
|
|
|
|
// return nl->OneElemList(list1);
|
|
|
|
////////////////out put bus stops relation////////////////////////////////
|
|
ListExpr bs_list = nl->TheEmptyList();
|
|
Relation* bs_rel = mn->GetMS_Rel();
|
|
|
|
if(bs_rel != NULL){
|
|
bool bFirst = true;
|
|
ListExpr xNext = nl->TheEmptyList();
|
|
ListExpr xLast = nl->TheEmptyList();
|
|
for(int i = 1;i <= bs_rel->GetNoTuples();i++){
|
|
Tuple* node_tuple = bs_rel->GetTuple(i, false);
|
|
int line_id =
|
|
((CcInt*)node_tuple->GetAttribute(MetroNetwork::M_R_ID))->GetIntval();
|
|
Bus_Stop* ms =
|
|
(Bus_Stop*)node_tuple->GetAttribute(MetroNetwork::M_STOP);
|
|
int stop_id = ms->GetStopId();
|
|
bool direction = ms->GetUp();
|
|
|
|
Point* loc = (Point*)node_tuple->GetAttribute(MetroNetwork::M_STOP_GEO);
|
|
|
|
ListExpr stop_list = nl->FourElemList(
|
|
nl->IntAtom(line_id), nl->IntAtom(stop_id),
|
|
nl-> BoolAtom(direction),
|
|
OutPoint( nl->TheEmptyList(), SetWord(loc) ));
|
|
|
|
xNext = stop_list;
|
|
if(bFirst){
|
|
bs_list = nl->OneElemList(xNext);
|
|
xLast = bs_list;
|
|
bFirst = false;
|
|
}else
|
|
xLast = nl->Append(xLast,xNext);
|
|
node_tuple->DeleteIfAllowed();
|
|
}
|
|
}
|
|
|
|
// return nl->TwoElemList(list1, bs_list);
|
|
|
|
|
|
//////////////////////output metro routes relation///////////////////////////
|
|
ListExpr br_list = nl->TheEmptyList();
|
|
Relation* br_rel = mn->GetMR_Rel();
|
|
|
|
if(br_rel != NULL){
|
|
bool bFirst = true;
|
|
ListExpr xNext = nl->TheEmptyList();
|
|
ListExpr xLast = nl->TheEmptyList();
|
|
for(int i = 1;i <= br_rel->GetNoTuples();i++){
|
|
Tuple* node_tuple = br_rel->GetTuple(i, false);
|
|
|
|
int lineid =
|
|
((CcInt*)node_tuple->GetAttribute(MetroNetwork::M_ROUTE_ID))->GetIntval();
|
|
Bus_Route* mr =
|
|
(Bus_Route*)node_tuple->GetAttribute(MetroNetwork::M_ROUTE);
|
|
SimpleLine mr_sl(0);
|
|
mr->GetGeoData(mr_sl);
|
|
|
|
ListExpr route_list = nl->TwoElemList(
|
|
nl->IntAtom(lineid),
|
|
OutSimpleLine( nl->TheEmptyList(), SetWord(&mr_sl)));
|
|
|
|
xNext = route_list;
|
|
if(bFirst){
|
|
br_list = nl->OneElemList(xNext);
|
|
xLast = br_list;
|
|
bFirst = false;
|
|
}else
|
|
xLast = nl->Append(xLast,xNext);
|
|
node_tuple->DeleteIfAllowed();
|
|
}
|
|
}
|
|
////////////////////////////////////////////////////////////////////////
|
|
////////////////no output bus trips relation: too much data///////////////
|
|
//////////////////////////////////////////////////////////////////////////
|
|
return nl->ThreeElemList(list1, bs_list, br_list);
|
|
|
|
}
|
|
|
|
bool SaveMetroNetwork(SmiRecord& valueRecord, size_t& offset,
|
|
const ListExpr typeInfo, Word& value)
|
|
{
|
|
MetroNetwork* mn = (MetroNetwork*)value.addr;
|
|
return mn->Save(valueRecord, offset, typeInfo);
|
|
}
|
|
|
|
bool OpenMetroNetwork(SmiRecord& valueRecord, size_t& offset,
|
|
const ListExpr typeInfo, Word& value)
|
|
{
|
|
value.addr = MetroNetwork::Open(valueRecord, offset, typeInfo);
|
|
return value.addr != NULL;
|
|
}
|
|
|
|
MetroNetwork* MetroNetwork::Open(SmiRecord& valueRecord, size_t& offset,
|
|
const ListExpr typeInfo)
|
|
{
|
|
return new MetroNetwork(valueRecord, offset, typeInfo);
|
|
|
|
}
|
|
|
|
|
|
Word CreateMetroNetwork(const ListExpr typeInfo)
|
|
{
|
|
// cout<<"CreateMetroNetwork()"<<endl;
|
|
return SetWord (new MetroNetwork());
|
|
}
|
|
|
|
|
|
void DeleteMetroNetwork(const ListExpr typeInfo, Word& w)
|
|
{
|
|
// cout<<"DeleteMetroNetwork()"<<endl;
|
|
MetroNetwork* mn = (MetroNetwork*)w.addr;
|
|
delete mn;
|
|
w.addr = NULL;
|
|
}
|
|
|
|
|
|
void CloseMetroNetwork( const ListExpr typeInfo, Word& w )
|
|
{
|
|
// cout<<"CloseMetroNetwork"<<endl;
|
|
delete static_cast<MetroNetwork*>(w.addr);
|
|
w.addr = 0;
|
|
}
|
|
|
|
Word CloneMetroNetwork( const ListExpr typeInfo, const Word& w )
|
|
{
|
|
// cout<<"CloneMetroNetwork"<<endl;
|
|
return SetWord( new Address(0));
|
|
}
|
|
|
|
void* MetroNetwork::Cast(void* addr)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
int SizeOfMetroNetwork()
|
|
{
|
|
// cout<<"SizeOfMetroNetwork"<<endl;
|
|
return sizeof(MetroNetwork);
|
|
}
|
|
|
|
bool CheckMetroNetwork( ListExpr type, ListExpr& errorInfo )
|
|
{
|
|
// cout<<"CheckMetroNetwork"<<endl;
|
|
return (nl->IsEqual( type, "metronetwork" ));
|
|
}
|
|
|
|
|
|
MetroNetwork::MetroNetwork():
|
|
def(false), mn_id(0), graph_init(false), graph_id(0), max_metro_speed(0),
|
|
min_mr_oid(0), min_mt_oid(0), start_time(0), end_time(0),
|
|
stops_rel(NULL), btree_ms(NULL), rtree_ms(NULL),
|
|
routes_rel(NULL), btree_mr(NULL), btree_mr_uoid(NULL),
|
|
metrotrips_rel(NULL), btree_trip_br_id(NULL), btree_trip_oid(NULL)
|
|
{
|
|
|
|
|
|
}
|
|
|
|
MetroNetwork::MetroNetwork(bool d, unsigned int i): def(d), mn_id(i),
|
|
graph_init(false), graph_id(0), max_metro_speed(0),
|
|
min_mr_oid(0), min_mt_oid(0), start_time(0), end_time(0),
|
|
stops_rel(NULL), btree_ms(NULL), rtree_ms(NULL),
|
|
routes_rel(NULL), btree_mr(NULL), btree_mr_uoid(NULL),
|
|
metrotrips_rel(NULL), btree_trip_br_id(NULL), btree_trip_oid(NULL)
|
|
{
|
|
|
|
|
|
}
|
|
|
|
/*
|
|
read the data from record
|
|
|
|
*/
|
|
MetroNetwork::MetroNetwork(SmiRecord& valueRecord, size_t& offset,
|
|
const ListExpr typeInfo):
|
|
def(false), mn_id(0), graph_init(false), graph_id(0), max_metro_speed(0),
|
|
min_mr_oid(0), min_mt_oid(0), start_time(0), end_time(0),
|
|
stops_rel(NULL), btree_ms(NULL), rtree_ms(NULL),
|
|
routes_rel(NULL), btree_mr(NULL), btree_mr_uoid(NULL),
|
|
metrotrips_rel(NULL), btree_trip_br_id(NULL), btree_trip_oid(NULL)
|
|
{
|
|
valueRecord.Read(&def, sizeof(bool), offset);
|
|
offset += sizeof(bool);
|
|
|
|
valueRecord.Read(&mn_id, sizeof(unsigned int), offset);
|
|
offset += sizeof(unsigned int);
|
|
|
|
valueRecord.Read(&graph_init, sizeof(bool), offset);
|
|
offset += sizeof(bool);
|
|
|
|
valueRecord.Read(&graph_id, sizeof(unsigned int), offset);
|
|
offset += sizeof(unsigned int);
|
|
|
|
valueRecord.Read(&max_metro_speed, sizeof(double), offset);
|
|
offset += sizeof(double);
|
|
|
|
valueRecord.Read(&min_mr_oid, sizeof(unsigned int), offset);
|
|
offset += sizeof(unsigned int);
|
|
|
|
valueRecord.Read(&min_mt_oid, sizeof(unsigned int), offset);
|
|
offset += sizeof(unsigned int);
|
|
|
|
valueRecord.Read(&start_time, sizeof(double), offset);
|
|
offset += sizeof(double);
|
|
|
|
valueRecord.Read(&end_time, sizeof(double), offset);
|
|
offset += sizeof(double);
|
|
|
|
ListExpr xType;
|
|
ListExpr xNumericType;
|
|
////////////////Open relation for metro stops///////////////////////
|
|
nl->ReadFromString(MetroStopsTypeInfo, xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
stops_rel = Relation::Open(valueRecord, offset, xNumericType);
|
|
if(!stops_rel) {
|
|
return;
|
|
}
|
|
|
|
///////////////////btree on metro stops on brid///////////////////////////////
|
|
nl->ReadFromString(MetroStopsBTreeTypeInfo,xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
btree_ms = BTree::Open(valueRecord, offset, xNumericType);
|
|
if(!btree_ms) {
|
|
stops_rel->Delete();
|
|
return;
|
|
}
|
|
|
|
///////////////////rtree on metro stops //////////////////////////////
|
|
Word xValue;
|
|
if(!(rtree_ms->Open(valueRecord,offset, MetroStopsRTreeTypeInfo,xValue))){
|
|
stops_rel->Delete();
|
|
delete btree_ms;
|
|
return;
|
|
}
|
|
|
|
rtree_ms = ( R_Tree<2,TupleId>* ) xValue.addr;
|
|
|
|
///////////////////////////////Open relation for metroroutes///////////////
|
|
nl->ReadFromString(MetroRoutesTypeInfo, xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
routes_rel = Relation::Open(valueRecord, offset, xNumericType);
|
|
if(!routes_rel) {
|
|
stops_rel->Delete();
|
|
delete btree_ms;
|
|
delete rtree_ms;
|
|
return;
|
|
}
|
|
|
|
///////////////////btree on metro routes//////////////////////////////////
|
|
nl->ReadFromString(MetroRoutesBTreTypeInfo, xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
btree_mr = BTree::Open(valueRecord, offset, xNumericType);
|
|
if(!btree_mr) {
|
|
stops_rel->Delete();
|
|
delete btree_ms;
|
|
delete rtree_ms;
|
|
routes_rel->Delete();
|
|
return;
|
|
}
|
|
|
|
///////////////////btree on metro routes unique oid///////////////////////
|
|
nl->ReadFromString(MetroRoutesBTreTypeInfo, xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
btree_mr_uoid = BTree::Open(valueRecord, offset, xNumericType);
|
|
if(!btree_mr_uoid) {
|
|
stops_rel->Delete();
|
|
delete btree_ms;
|
|
routes_rel->Delete();
|
|
delete btree_mr;
|
|
delete rtree_ms;
|
|
return;
|
|
}
|
|
|
|
///////////////open relation storing metro trips//////////////////////
|
|
nl->ReadFromString(MetroTripTypeInfo, xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
metrotrips_rel = Relation::Open(valueRecord, offset, xNumericType);
|
|
if(!metrotrips_rel) {
|
|
stops_rel->Delete();
|
|
delete btree_ms;
|
|
routes_rel->Delete();
|
|
delete btree_mr;
|
|
delete rtree_ms;
|
|
delete btree_mr_uoid;
|
|
return;
|
|
}
|
|
|
|
///////////////////btree on metro trips metro route id///////////////////////
|
|
nl->ReadFromString(MetroTypeBTreeTypeInfo, xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
btree_trip_br_id = BTree::Open(valueRecord, offset, xNumericType);
|
|
if(!btree_trip_br_id) {
|
|
stops_rel->Delete();
|
|
delete btree_ms;
|
|
routes_rel->Delete();
|
|
delete btree_mr;
|
|
delete rtree_ms;
|
|
delete btree_mr_uoid;
|
|
metrotrips_rel->Delete();
|
|
return;
|
|
}
|
|
|
|
///////////////////btree on metro trips unique id////////////////////////////
|
|
nl->ReadFromString(MetroTypeBTreeTypeInfo, xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
btree_trip_oid = BTree::Open(valueRecord, offset, xNumericType);
|
|
if(!btree_trip_oid) {
|
|
stops_rel->Delete();
|
|
delete btree_ms;
|
|
routes_rel->Delete();
|
|
delete btree_mr;
|
|
delete rtree_ms;
|
|
delete btree_mr_uoid;
|
|
metrotrips_rel->Delete();
|
|
delete btree_trip_br_id;
|
|
return;
|
|
}
|
|
|
|
}
|
|
|
|
MetroNetwork::~MetroNetwork()
|
|
{
|
|
if(stops_rel != NULL) stops_rel->Close();
|
|
if(btree_ms != NULL) delete btree_ms;
|
|
if(rtree_ms != NULL) delete rtree_ms;
|
|
if(routes_rel != NULL) routes_rel->Close();
|
|
if(btree_mr != NULL) delete btree_mr;
|
|
if(btree_mr_uoid != NULL) delete btree_mr_uoid;
|
|
if(metrotrips_rel != NULL) metrotrips_rel->Close();
|
|
if(btree_trip_br_id != NULL) delete btree_trip_br_id;
|
|
if(btree_trip_oid != NULL) delete btree_trip_oid;
|
|
}
|
|
|
|
bool MetroNetwork::Save(SmiRecord& valueRecord, size_t& offset,
|
|
const ListExpr typeInfo)
|
|
{
|
|
|
|
// cout<<"MetroNetwork::Save"<<endl;
|
|
|
|
valueRecord.Write(&def, sizeof(bool), offset);
|
|
offset += sizeof(bool);
|
|
|
|
valueRecord.Write(&mn_id, sizeof(unsigned int), offset);
|
|
offset += sizeof(unsigned int);
|
|
|
|
valueRecord.Write(&graph_init, sizeof(bool), offset);
|
|
offset += sizeof(bool);
|
|
|
|
valueRecord.Write(&graph_id, sizeof(unsigned int), offset);
|
|
offset += sizeof(unsigned int);
|
|
|
|
valueRecord.Write(&max_metro_speed, sizeof(double), offset);
|
|
offset += sizeof(double);
|
|
|
|
valueRecord.Write(&min_mr_oid, sizeof(unsigned int), offset);
|
|
offset += sizeof(unsigned int);
|
|
|
|
valueRecord.Write(&min_mt_oid, sizeof(unsigned int), offset);
|
|
offset += sizeof(unsigned int);
|
|
|
|
valueRecord.Write(&start_time, sizeof(double), offset);
|
|
offset += sizeof(double);
|
|
|
|
valueRecord.Write(&end_time, sizeof(double), offset);
|
|
offset += sizeof(double);
|
|
|
|
ListExpr xType;
|
|
ListExpr xNumericType;
|
|
|
|
////////////////////metro stops relation/////////////////////////////
|
|
nl->ReadFromString(MetroStopsTypeInfo,xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
if(!stops_rel->Save(valueRecord,offset,xNumericType))
|
|
return false;
|
|
|
|
|
|
/////////////////////btree on metro stops on lineid/////////////////////////
|
|
nl->ReadFromString(MetroStopsBTreeTypeInfo,xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
if(!btree_ms->Save(valueRecord,offset,xNumericType))
|
|
return false;
|
|
|
|
///////////////////////rtree on metro stops ///////////////////////
|
|
if(!rtree_ms->Save(valueRecord, offset)){
|
|
return false;
|
|
}
|
|
|
|
///////////////////metro routes relation///////////////////////////
|
|
nl->ReadFromString(MetroRoutesTypeInfo,xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
if(!routes_rel->Save(valueRecord,offset,xNumericType))
|
|
return false;
|
|
|
|
///////////////////////btree on metro routes////////////////////////////
|
|
nl->ReadFromString(MetroRoutesBTreTypeInfo, xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
if(!btree_mr->Save(valueRecord,offset,xNumericType))
|
|
return false;
|
|
|
|
///////////////////////btree on bus routes on unique id///////////////////
|
|
nl->ReadFromString(MetroRoutesBTreTypeInfo, xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
if(!btree_mr_uoid->Save(valueRecord,offset,xNumericType))
|
|
return false;
|
|
|
|
///////////////////metro trips relation/////////////////////////////
|
|
nl->ReadFromString(MetroTripTypeInfo, xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
if(!metrotrips_rel->Save(valueRecord,offset,xNumericType))
|
|
return false;
|
|
|
|
//////////////////btree on metro trips on metro route id/////////////////
|
|
nl->ReadFromString(MetroTypeBTreeTypeInfo, xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
if(!btree_trip_br_id->Save(valueRecord,offset,xNumericType))
|
|
return false;
|
|
|
|
///////////////////////btree on metro trips on unique id///////////////////
|
|
nl->ReadFromString(MetroTypeBTreeTypeInfo, xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
if(!btree_trip_oid->Save(valueRecord,offset,xNumericType))
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
load stops, routes, and moving metros relation
|
|
|
|
*/
|
|
void MetroNetwork::Load(unsigned int i, Relation* r1, Relation* r2,
|
|
Relation* r3)
|
|
{
|
|
|
|
if(i < 1){
|
|
def = false;
|
|
return;
|
|
}
|
|
mn_id = i;
|
|
|
|
LoadStops(r1); /////to get 2D points in space
|
|
LoadRoutes(r2); //first load bus routes because bus stops access bus routes
|
|
LoadMetros(r3); //load moving metros
|
|
|
|
def = true;
|
|
}
|
|
|
|
/*
|
|
load metro stops relation
|
|
|
|
*/
|
|
void MetroNetwork::LoadStops(Relation* r)
|
|
{
|
|
// cout<<"LoadStops"<<endl;
|
|
|
|
ListExpr ptrList1 = listutils::getPtrList(r);
|
|
|
|
string strQuery = "(consume(feed(" + MetroStopsTypeInfo +
|
|
"(ptr " + nl->ToString(ptrList1) + "))))";
|
|
|
|
// cout<<strQuery<<endl;
|
|
|
|
Word xResult;
|
|
int QueryExecuted = QueryProcessor::ExecuteQuery(strQuery, xResult);
|
|
assert(QueryExecuted);
|
|
stops_rel = (Relation*)xResult.addr;
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
//////////////////////btree on metro stops line id/////////////////////
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
ListExpr ptrList2 = listutils::getPtrList(stops_rel);
|
|
|
|
strQuery = "(createbtree (" + MetroStopsTypeInfo +
|
|
"(ptr " + nl->ToString(ptrList2) + "))" + "Mr_id)";
|
|
|
|
QueryExecuted = QueryProcessor::ExecuteQuery(strQuery,xResult);
|
|
assert(QueryExecuted);
|
|
btree_ms = (BTree*)xResult.addr;
|
|
|
|
|
|
//////////////////////rtree on metro stops//////////////////////////
|
|
|
|
ListExpr ptrList3 = listutils::getPtrList(stops_rel);
|
|
|
|
strQuery = "(bulkloadrtree(sortby(addid(feed (" + MetroStopsTypeInfo +
|
|
" (ptr " + nl->ToString(ptrList3) +
|
|
"))))((Stop_geodata asc))) Stop_geodata)";
|
|
|
|
QueryExecuted = QueryProcessor::ExecuteQuery ( strQuery, xResult );
|
|
assert ( QueryExecuted );
|
|
rtree_ms = ( R_Tree<2,TupleId>* ) xResult.addr;
|
|
|
|
}
|
|
|
|
/*
|
|
load metro routes relation
|
|
|
|
*/
|
|
void MetroNetwork::LoadRoutes(Relation* r2)
|
|
{
|
|
// cout<<"LoadRotes"<<endl;
|
|
|
|
ListExpr ptrList1 = listutils::getPtrList(r2);
|
|
|
|
string strQuery = "(consume(feed(" + MetroRoutesTypeInfo +
|
|
"(ptr " + nl->ToString(ptrList1) + "))))";
|
|
|
|
// cout<<strQuery<<endl;
|
|
|
|
Word xResult;
|
|
int QueryExecuted = QueryProcessor::ExecuteQuery(strQuery, xResult);
|
|
assert(QueryExecuted);
|
|
routes_rel = (Relation*)xResult.addr;
|
|
|
|
///////////////////get the minimum metro route oid////////////////////////
|
|
int temp_id = numeric_limits<int>::max();
|
|
for(int i = 1;i <= routes_rel->GetNoTuples();i++){
|
|
Tuple* mr_tuple = routes_rel->GetTuple(i, false);
|
|
int id = ((CcInt*)mr_tuple->GetAttribute(M_R_OID))->GetIntval();
|
|
if(id < temp_id) temp_id = id;
|
|
mr_tuple->DeleteIfAllowed();
|
|
}
|
|
min_mr_oid = temp_id;
|
|
|
|
// cout<<"min mr oid "<<min_mr_oid<<endl;
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
//////////////////////btree on metro routes lineid/////////////////
|
|
//////////////////////////////////////////////////////////////////
|
|
|
|
ListExpr ptrList2 = listutils::getPtrList(routes_rel);
|
|
|
|
strQuery = "(createbtree (" + MetroRoutesTypeInfo +
|
|
"(ptr " + nl->ToString(ptrList2) + "))" + "Mr_id)";
|
|
// cout<<strQuery<<endl;
|
|
QueryExecuted = QueryProcessor::ExecuteQuery(strQuery,xResult);
|
|
assert(QueryExecuted);
|
|
btree_mr = (BTree*)xResult.addr;
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
//////////////////////btree on metro routes unique oid////////////
|
|
//////////////////////////////////////////////////////////////////
|
|
|
|
ListExpr ptrList3 = listutils::getPtrList(routes_rel);
|
|
|
|
strQuery = "(createbtree (" + MetroRoutesTypeInfo +
|
|
"(ptr " + nl->ToString(ptrList3) + "))" + "Oid)";
|
|
|
|
QueryExecuted = QueryProcessor::ExecuteQuery(strQuery,xResult);
|
|
assert(QueryExecuted);
|
|
btree_mr_uoid = (BTree*)xResult.addr;
|
|
|
|
}
|
|
|
|
/*
|
|
load moving metros
|
|
|
|
*/
|
|
void MetroNetwork::LoadMetros(Relation* r3)
|
|
{
|
|
// cout<<"LoadMetros"<<endl;
|
|
|
|
ListExpr ptrList1 = listutils::getPtrList(r3);
|
|
|
|
string strQuery = "(consume(feed(" + MetroTripTypeInfo +
|
|
"(ptr " + nl->ToString(ptrList1) + "))))";
|
|
|
|
// cout<<strQuery<<endl;
|
|
|
|
Word xResult;
|
|
int QueryExecuted = QueryProcessor::ExecuteQuery(strQuery, xResult);
|
|
assert(QueryExecuted);
|
|
metrotrips_rel = (Relation*)xResult.addr;
|
|
|
|
// cout<<"metro trips size "<<metrotrips_rel->GetNoTuples()<<endl;
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
//////////////////////set maximum metro speed///////////////////////////
|
|
/////////////////////////////////////////////////////////////////////
|
|
int temp_id = numeric_limits<int>::max();
|
|
for(int i = 1;i <= metrotrips_rel->GetNoTuples();i++){
|
|
Tuple* metro_tuple = metrotrips_rel->GetTuple(i, false);
|
|
MPoint* mo = (MPoint*)metro_tuple->GetAttribute(M_TRIP_MP);
|
|
|
|
/////////////get the start and end time of all bus trips//////////////
|
|
Periods* peri = new Periods(0);
|
|
mo->DefTime(*peri);
|
|
Interval<Instant> time_span;
|
|
peri->Get(0, time_span);
|
|
// cout<<time_span.start<<" "<<time_span.end<<endl;
|
|
if(i == 1){
|
|
start_time = time_span.start.ToDouble();
|
|
end_time = time_span.end.ToDouble();
|
|
}else{
|
|
if(time_span.start.ToDouble() < start_time)
|
|
start_time = time_span.start.ToDouble();
|
|
if(time_span.end.ToDouble() > end_time)
|
|
end_time = time_span.end.ToDouble();
|
|
}
|
|
peri->DeleteIfAllowed();
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
for( int j = 0; j < mo->GetNoComponents(); j++ ){
|
|
UPoint unit;
|
|
mo->Get( j, unit );
|
|
Point pos1 = unit.p0;
|
|
Point pos2 = unit.p1;
|
|
if(pos1.Distance(pos2) > 1.0){
|
|
double t =
|
|
unit.timeInterval.end.ToDouble()*86400.0 -
|
|
unit.timeInterval.start.ToDouble()*86400.0;
|
|
double speed = pos1.Distance(pos2)/t;
|
|
/* cout<<"dist "<<fabs(pos1 - pos2)<<" t "<<t
|
|
<<" speed "<<speed<<endl;*/
|
|
if(speed > max_metro_speed){
|
|
max_metro_speed = speed;
|
|
}
|
|
}
|
|
}
|
|
int id = ((CcInt*)metro_tuple->GetAttribute(M_TRIP_OID))->GetIntval();
|
|
if(id < temp_id) temp_id = id;
|
|
|
|
metro_tuple->DeleteIfAllowed();
|
|
}
|
|
|
|
|
|
|
|
min_mt_oid = temp_id;
|
|
// cout<<"max metro speed "<<max_metro_speed*60*60/1000.0<<"km/h "<<endl;
|
|
// cout<<"min metro trip oid "<<min_mt_oid<<endl;
|
|
|
|
|
|
////////////////btree on metro trips metro route id ///////////////////////
|
|
|
|
ListExpr ptrList2 = listutils::getPtrList(metrotrips_rel);
|
|
|
|
strQuery = "(createbtree (" + MetroTripTypeInfo +
|
|
"(ptr " + nl->ToString(ptrList2) + "))" + "Mr_oid)";
|
|
|
|
QueryExecuted = QueryProcessor::ExecuteQuery(strQuery,xResult);
|
|
assert(QueryExecuted);
|
|
btree_trip_br_id = (BTree*)xResult.addr;
|
|
|
|
////////////////btree on metro trips oid///////////////////////////
|
|
|
|
ListExpr ptrList3 = listutils::getPtrList(metrotrips_rel);
|
|
|
|
strQuery = "(createbtree (" + MetroTripTypeInfo +
|
|
"(ptr " + nl->ToString(ptrList3) + "))" + "Oid)";
|
|
|
|
QueryExecuted = QueryProcessor::ExecuteQuery(strQuery,xResult);
|
|
assert(QueryExecuted);
|
|
btree_trip_oid = (BTree*)xResult.addr;
|
|
|
|
|
|
/* Instant t1(start_time);
|
|
Instant t2(end_time);
|
|
cout<<t1<<" "<<t2<<endl; */
|
|
|
|
}
|
|
|
|
/*
|
|
given a metro stop, find its neighbor stop, i.e., the one after it
|
|
|
|
*/
|
|
|
|
int MetroNetwork::GetMS_Stop_Neighbor(UBahn_Stop* ms_stop )
|
|
{
|
|
int line_id = ms_stop->line_id;
|
|
int stop_id = ms_stop->stop_id;
|
|
bool dir = ms_stop->d;
|
|
|
|
CcInt* search_cell_id = new CcInt(true, line_id);
|
|
BTreeIterator* btree_iter = btree_ms->ExactMatch(search_cell_id);
|
|
|
|
int neighbor_tid = 0;
|
|
bool found = false;
|
|
while(btree_iter->Next()){
|
|
Tuple* tuple = stops_rel->GetTuple(btree_iter->GetId(), false);
|
|
|
|
int l_id = ((CcInt*)tuple->GetAttribute(M_R_ID))->GetIntval();
|
|
assert(l_id == line_id);
|
|
// bool d = ((CcBool*)tuple->GetAttribute(UB_DIRECTION))->GetBoolval();
|
|
Bus_Stop* ms = (Bus_Stop*)tuple->GetAttribute(M_STOP);
|
|
bool d = ms->GetUp();
|
|
if(dir == d){
|
|
// int s_id = ((CcInt*)tuple->GetAttribute(UB_STOP_ID))->GetIntval();
|
|
int s_id = ms->GetStopId();
|
|
if(dir){
|
|
if(s_id == stop_id + 1){
|
|
neighbor_tid = tuple->GetTupleId();
|
|
found = true;
|
|
}
|
|
}else{
|
|
if(s_id == stop_id - 1){
|
|
neighbor_tid = tuple->GetTupleId();
|
|
found = true;
|
|
}
|
|
}
|
|
}
|
|
tuple->DeleteIfAllowed();
|
|
if(found)break;
|
|
}
|
|
delete btree_iter;
|
|
delete search_cell_id;
|
|
|
|
return neighbor_tid;
|
|
}
|
|
|
|
|
|
/*
|
|
set the metro graph id
|
|
|
|
*/
|
|
void MetroNetwork::SetGraphId(int g_id)
|
|
{
|
|
graph_id = g_id;
|
|
graph_init = true;
|
|
}
|
|
|
|
|
|
/*
|
|
get the metro graph in metro network
|
|
|
|
*/
|
|
MetroGraph* MetroNetwork::GetMetroGraph()
|
|
{
|
|
if(graph_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) == "metrograph"){
|
|
// Get name of the metro graph
|
|
ListExpr xObjectName = nl->Second(xCurrent);
|
|
string strObjectName = nl->SymbolValue(xObjectName);
|
|
|
|
// Load object to find out the id of the network.
|
|
Word xValue;
|
|
bool bDefined;
|
|
bool bOk = SecondoSystem::GetCatalog()->GetObject(strObjectName,
|
|
xValue,
|
|
bDefined);
|
|
if(!bDefined || !bOk)
|
|
{
|
|
// Undefined
|
|
continue;
|
|
}
|
|
MetroGraph* mg = (MetroGraph*)xValue.addr;
|
|
if(mg->GetMG_ID() == graph_id){
|
|
// This is the metro graph we have been looking for
|
|
return mg;
|
|
}
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
close the metro graph
|
|
|
|
*/
|
|
void MetroNetwork::CloseMetroGraph(MetroGraph* mg)
|
|
{
|
|
if(mg == NULL) return;
|
|
Word xValue;
|
|
xValue.addr = mg;
|
|
SecondoSystem::GetCatalog()->CloseObject(nl->SymbolAtom("metrograph"),
|
|
xValue);
|
|
}
|
|
|
|
/*
|
|
get the 2d point of a metro stop
|
|
|
|
*/
|
|
void MetroNetwork::GetMetroStopGeoData(Bus_Stop* ms, Point* p)
|
|
{
|
|
|
|
int id = ms->GetId();
|
|
if(id < 1){
|
|
cout<<"invalid metro stop"<<endl;
|
|
return;
|
|
}
|
|
|
|
CcInt* search_id = new CcInt(true, id);
|
|
BTreeIterator* btree_iter = btree_mr->ExactMatch(search_id);
|
|
while(btree_iter->Next()){
|
|
Tuple* tuple = routes_rel->GetTuple(btree_iter->GetId(), false);
|
|
Bus_Route* mr = (Bus_Route*)tuple->GetAttribute(M_ROUTE);
|
|
if(mr->GetUp() == ms->GetUp()){
|
|
mr->GetMetroStopGeoData(ms, p);
|
|
tuple->DeleteIfAllowed();
|
|
break;
|
|
}
|
|
tuple->DeleteIfAllowed();
|
|
}
|
|
delete btree_iter;
|
|
delete search_id;
|
|
|
|
}
|
|
|
|
/*
|
|
get the moving metro pass the metro stop at the input time
|
|
|
|
*/
|
|
int MetroNetwork::GetMOMetro_Oid(Bus_Stop* ms, Point* ms_loc, Instant& t)
|
|
{
|
|
// cout<<"metro stop "<<*ms<<" loc "<<*ms_loc<<" time "<<t<<endl;
|
|
|
|
int mr_id = ms->GetId();
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
////////////get the unique id for the metro route/////////////////
|
|
//////////////////////////////////////////////////////////////////
|
|
CcInt* search_id1 = new CcInt(true, mr_id);
|
|
BTreeIterator* btree_iter1 = btree_mr->ExactMatch(search_id1);
|
|
int mr_uoid = 0;
|
|
while(btree_iter1->Next()){
|
|
Tuple* tuple = routes_rel->GetTuple(btree_iter1->GetId(), false);
|
|
Bus_Route* mr = (Bus_Route*)tuple->GetAttribute(M_ROUTE);
|
|
if(mr->GetUp() == ms->GetUp()){
|
|
mr_uoid = ((CcInt*)tuple->GetAttribute(M_R_OID))->GetIntval();
|
|
tuple->DeleteIfAllowed();
|
|
break;
|
|
}
|
|
tuple->DeleteIfAllowed();
|
|
}
|
|
delete btree_iter1;
|
|
delete search_id1;
|
|
assert(mr_uoid > 0);
|
|
|
|
// cout<<"mr_uoid "<<mr_uoid<<endl;
|
|
|
|
///////////////////////////////////////////////////////////////
|
|
///////////////get moving metros moving on the route///////////
|
|
///////////////////////////////////////////////////////////////
|
|
int metro_oid = 0;
|
|
CcInt* search_id2 = new CcInt(true, mr_uoid);
|
|
BTreeIterator* btree_iter2 = btree_trip_br_id->ExactMatch(search_id2);
|
|
const double delta_dist = 0.01;
|
|
vector<Id_Time> res_list;
|
|
|
|
while(btree_iter2->Next()){
|
|
Tuple* tuple = metrotrips_rel->GetTuple(btree_iter2->GetId(), false);
|
|
int mrid =
|
|
((CcInt*)tuple->GetAttribute(M_REFMR_OID))->GetIntval();
|
|
assert(mrid == mr_uoid);
|
|
MPoint* mo_metro = (MPoint*)tuple->GetAttribute(M_TRIP_MP);
|
|
Periods* peri = new Periods(0);
|
|
mo_metro->DefTime(*peri);
|
|
// cout<<"periods "<<*peri<<endl;
|
|
if(peri->Contains(t)){
|
|
// cout<<"periods containt instant "<<endl;
|
|
|
|
for(int i = 0;i < mo_metro->GetNoComponents();i++){
|
|
UPoint unit;
|
|
mo_metro->Get(i, unit);
|
|
Point p0 = unit.p0;
|
|
Point p1 = unit.p1;
|
|
|
|
// cout<<unit.timeInterval<<" dist "<<bs_loc->Distance(p0)<<endl;
|
|
// cout<<"dist1 "<<bs_loc->Distance(p0)
|
|
// <<" dist2 "<<bs_loc->Distance(p1)<<endl;
|
|
|
|
if(ms_loc->Distance(p0) < delta_dist &&
|
|
ms_loc->Distance(p1) < delta_dist){
|
|
metro_oid = ((CcInt*)tuple->GetAttribute(M_TRIP_OID))->GetIntval();
|
|
double delta_t =
|
|
fabs(unit.timeInterval.start.ToDouble() - t.ToDouble());
|
|
Id_Time* id_time = new Id_Time(metro_oid, delta_t);
|
|
res_list.push_back(*id_time);
|
|
delete id_time;
|
|
}
|
|
}
|
|
}
|
|
peri->DeleteIfAllowed();
|
|
tuple->DeleteIfAllowed();
|
|
}
|
|
|
|
delete btree_iter2;
|
|
delete search_id2;
|
|
|
|
|
|
sort(res_list.begin(), res_list.end());
|
|
|
|
assert(res_list.size() > 0);
|
|
metro_oid = res_list[0].oid;
|
|
|
|
assert(metro_oid > 0);
|
|
|
|
return metro_oid;
|
|
|
|
}
|
|
|
|
/*
|
|
given a metro stop and time, it returns mpoint of the moving metro belonging to
|
|
that metro route and direction as well as covering the time
|
|
|
|
*/
|
|
|
|
int MetroNetwork::GetMOMetro_MP(Bus_Stop* ms, Point* ms_loc,
|
|
Instant t, MPoint& mp)
|
|
{
|
|
|
|
// cout<<"metro stop "<<*ms<<" loc "<<*ms_loc<<" time "<<t<<endl;
|
|
|
|
int mr_id = ms->GetId();
|
|
//////////////////////////////////////////////////////////////////
|
|
////////////get the unique id for the metro route/////////////////
|
|
//////////////////////////////////////////////////////////////////
|
|
CcInt* search_id1 = new CcInt(true, mr_id);
|
|
BTreeIterator* btree_iter1 = btree_mr->ExactMatch(search_id1);
|
|
int mr_uoid = 0;
|
|
while(btree_iter1->Next()){
|
|
Tuple* tuple = routes_rel->GetTuple(btree_iter1->GetId(), false);
|
|
Bus_Route* mr = (Bus_Route*)tuple->GetAttribute(M_ROUTE);
|
|
if(mr->GetUp() == ms->GetUp()){
|
|
mr_uoid = ((CcInt*)tuple->GetAttribute(M_R_OID))->GetIntval();
|
|
tuple->DeleteIfAllowed();
|
|
break;
|
|
}
|
|
tuple->DeleteIfAllowed();
|
|
}
|
|
delete btree_iter1;
|
|
delete search_id1;
|
|
assert(mr_uoid > 0);
|
|
|
|
// cout<<"mr_uoid "<<mr_uoid<<endl;
|
|
|
|
///////////////////////////////////////////////////////////////
|
|
///////////////get moving metro moving on the route///////////
|
|
///////////////////////////////////////////////////////////////
|
|
int metro_oid = 0;
|
|
CcInt* search_id2 = new CcInt(true, mr_uoid);
|
|
BTreeIterator* btree_iter2 = btree_trip_br_id->ExactMatch(search_id2);
|
|
bool found = false;
|
|
const double delta_dist = 0.01;
|
|
vector<Id_Time> res_list;
|
|
|
|
while(btree_iter2->Next() && found == false){
|
|
Tuple* tuple = metrotrips_rel->GetTuple(btree_iter2->GetId(), false);
|
|
int mrid = ((CcInt*)tuple->GetAttribute(M_REFMR_OID))->GetIntval();
|
|
assert(mrid == mr_uoid);
|
|
MPoint* mo_metro = (MPoint*)tuple->GetAttribute(M_TRIP_MP);
|
|
Periods* peri = new Periods(0);
|
|
mo_metro->DefTime(*peri);
|
|
if(peri->Contains(t)){
|
|
// cout<<"periods "<<*peri<<endl;
|
|
for(int i = 0;i < mo_metro->GetNoComponents();i++){
|
|
UPoint unit;
|
|
mo_metro->Get(i, unit);
|
|
Point p0 = unit.p0;
|
|
Point p1 = unit.p1;
|
|
|
|
if(ms_loc->Distance(p0) < delta_dist &&
|
|
unit.timeInterval.Contains(t)){
|
|
mp = *mo_metro;
|
|
metro_oid = ((CcInt*)tuple->GetAttribute(M_TRIP_OID))->GetIntval();
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
peri->DeleteIfAllowed();
|
|
tuple->DeleteIfAllowed();
|
|
}
|
|
delete btree_iter2;
|
|
delete search_id2;
|
|
assert(metro_oid > 0);
|
|
return metro_oid;
|
|
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
////////////////////metro graph/////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////////
|
|
string MetroGraph::MGNodeTypeInfo =
|
|
"(rel (tuple ((Ms_stop busstop) (Stop_geodata point) (Mr_id int))))";
|
|
|
|
string MetroGraph::MGEdge1TypeInfo =
|
|
"(rel (tuple ((Ms_stop1_tid int) (Ms_stop2_tid int))))";
|
|
|
|
string MetroGraph::MGEdge2TypeInfo = "(rel (tuple ((Ms_stop1_tid int)\
|
|
(Ms_stop2_tid int) (Whole_time periods)(Schedule_interval real)\
|
|
(Path sline) (TimeCost real))))";
|
|
|
|
string MetroGraph::MGNodeBTreeTypeInfo =
|
|
"(btree (tuple ((Ms_stop busstop) (Stop_geodata point) (Mr_id int))) int)";
|
|
|
|
|
|
ListExpr MetroGraph::MetroGraphProp()
|
|
{
|
|
ListExpr examplelist = nl->TextAtom();
|
|
nl->AppendText(examplelist,
|
|
"createmetrograph(<id>,<edge-relation>,<node-relation>)");
|
|
return nl->TwoElemList(
|
|
nl->TwoElemList(nl->StringAtom("Creation"),
|
|
nl->StringAtom("Example Creation")),
|
|
nl->TwoElemList(examplelist,
|
|
nl->StringAtom("let mg=createmetrograph(id,e-rel,n-rel)")));
|
|
}
|
|
|
|
|
|
bool MetroGraph::CheckMetroGraph(ListExpr type, ListExpr& errorInfo)
|
|
{
|
|
// cout<<"CheckMetroGraph()"<<endl;
|
|
return nl->IsEqual(type, "metrograph");
|
|
}
|
|
|
|
int MetroGraph::SizeOfMetroGraph()
|
|
{
|
|
// cout<<"SizeOfMetroGraph()"<<endl;
|
|
return 0;
|
|
}
|
|
|
|
void* MetroGraph::CastMetroGraph(void* addr)
|
|
{
|
|
// cout<<"CastMetroGraph()"<<endl;
|
|
return 0;
|
|
}
|
|
Word MetroGraph::CloneMetroGraph(const ListExpr typeInfo, const Word& w)
|
|
{
|
|
// cout<<"CloneMetroGraph()"<<endl;
|
|
return SetWord(Address(0));
|
|
}
|
|
|
|
void MetroGraph::CloseMetroGraph(const ListExpr typeInfo, Word& w)
|
|
{
|
|
// cout<<"CloseMetroGraph()"<<endl;
|
|
delete static_cast<MetroGraph*> (w.addr);
|
|
w.addr = NULL;
|
|
}
|
|
|
|
Word MetroGraph::CreateMetroGraph(const ListExpr typeInfo)
|
|
{
|
|
// cout<<"MetroMetroGraph()"<<endl;
|
|
return SetWord(new MetroGraph());
|
|
}
|
|
|
|
void MetroGraph::DeleteMetroGraph(const ListExpr typeInfo, Word& w)
|
|
{
|
|
// cout<<"DeleteMetroGraph()"<<endl;
|
|
MetroGraph* mg = (MetroGraph*)w.addr;
|
|
delete mg;
|
|
w.addr = NULL;
|
|
}
|
|
|
|
/*
|
|
input metro network graph
|
|
|
|
*/
|
|
Word MetroGraph::InMetroGraph(ListExpr in_xTypeInfo,
|
|
ListExpr in_xValue,
|
|
int in_iErrorPos, ListExpr& inout_xErrorInfo,
|
|
bool& inout_bCorrect)
|
|
{
|
|
// cout<<"InMetroGraph()"<<endl;
|
|
MetroGraph* mg = new MetroGraph(in_xValue, in_iErrorPos, inout_xErrorInfo,
|
|
inout_bCorrect);
|
|
if(inout_bCorrect) return SetWord(mg);
|
|
else{
|
|
delete mg;
|
|
return SetWord(Address(0));
|
|
}
|
|
}
|
|
|
|
ListExpr MetroGraph::OutMetroGraph(ListExpr typeInfo, Word value)
|
|
{
|
|
// cout<<"OutMetroGraph()"<<endl;
|
|
MetroGraph* mg = (MetroGraph*)value.addr;
|
|
return mg->Out(typeInfo);
|
|
}
|
|
|
|
ListExpr MetroGraph::Out(ListExpr typeInfo)
|
|
{
|
|
// cout<<"Out()"<<endl;
|
|
ListExpr xNode = nl->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);
|
|
/* int l_id =
|
|
((CcInt*)node_tuple->GetAttribute(MG_NODE_LINE_ID))->GetIntval();
|
|
Point* loc = (Point*)node_tuple->GetAttribute(MG_NODE_LOC);
|
|
int stop_id =
|
|
((CcInt*)node_tuple->GetAttribute(MG_NODE_STOP_ID))->GetIntval();
|
|
bool dir =
|
|
((CcBool*)node_tuple->GetAttribute(MG_NODE_UP))->GetBoolval();*/
|
|
|
|
int l_id =
|
|
((CcInt*)node_tuple->GetAttribute(MG_NODE_MR_ID))->GetIntval();
|
|
Point* loc = (Point*)node_tuple->GetAttribute(MG_NODE_STOP_GEO);
|
|
Bus_Stop* ms_stop = (Bus_Stop*)node_tuple->GetAttribute(MG_NODE_STOP);
|
|
int stop_id = ms_stop->GetStopId();
|
|
bool dir = ms_stop->GetUp();
|
|
|
|
xNext = nl->FourElemList(
|
|
nl->IntAtom(l_id), nl->IntAtom(stop_id),
|
|
nl-> BoolAtom(dir),
|
|
OutPoint( nl->TheEmptyList(), SetWord(loc) ));
|
|
|
|
if(bFirst){
|
|
xNode = nl->OneElemList(xNext);
|
|
xLast = xNode;
|
|
bFirst = false;
|
|
}else
|
|
xLast = nl->Append(xLast,xNext);
|
|
node_tuple->DeleteIfAllowed();
|
|
}
|
|
return nl->TwoElemList(nl->IntAtom(mg_id),xNode);
|
|
|
|
// return nl->OneElemList(nl->IntAtom(mg_id));
|
|
|
|
}
|
|
|
|
bool MetroGraph::SaveMetroGraph(SmiRecord& valueRecord, size_t& offset,
|
|
const ListExpr typeInfo, Word& value)
|
|
{
|
|
// cout<<"SaveMetroGraph()"<<endl;
|
|
MetroGraph* mg = (MetroGraph*)value.addr;
|
|
bool result = mg->Save(valueRecord, offset, typeInfo);
|
|
|
|
return result;
|
|
}
|
|
|
|
bool MetroGraph::OpenMetroGraph(SmiRecord& valueRecord, size_t& offset,
|
|
const ListExpr typeInfo, Word& value)
|
|
{
|
|
// cout<<"OpenMetroGraph()"<<endl;
|
|
value.addr = MetroGraph::Open(valueRecord, offset, typeInfo);
|
|
bool result = (value.addr != NULL);
|
|
|
|
return result;
|
|
}
|
|
|
|
MetroGraph* MetroGraph::Open(SmiRecord& valueRecord,size_t& offset,
|
|
const ListExpr typeInfo)
|
|
{
|
|
return new MetroGraph(valueRecord,offset,typeInfo);
|
|
}
|
|
|
|
|
|
MetroGraph::MetroGraph():mg_id(0), min_t(0),
|
|
node_rel(NULL), btree_node(NULL),
|
|
edge_rel1(NULL), adj_list1(0), entry_adj_list1(0),
|
|
edge_rel2(NULL), adj_list2(0), entry_adj_list2(0)
|
|
{
|
|
// cout<<"BusGraph::BusGraph()"<<endl;
|
|
}
|
|
|
|
MetroGraph::~MetroGraph()
|
|
{
|
|
if(node_rel != NULL) node_rel->Close();
|
|
if(btree_node != NULL) delete btree_node;
|
|
if(edge_rel1 != NULL) edge_rel1->Close();
|
|
if(edge_rel2 != NULL) edge_rel2->Close();
|
|
|
|
}
|
|
|
|
MetroGraph::MetroGraph(ListExpr in_xValue,int in_iErrorPos,
|
|
ListExpr& inout_xErrorInfo,
|
|
bool& inout_bCorrect):
|
|
mg_id(0), min_t(0),
|
|
node_rel(NULL), btree_node(NULL),
|
|
edge_rel1(NULL), adj_list1(0), entry_adj_list1(0),
|
|
edge_rel2(NULL), adj_list2(0), entry_adj_list2(0)
|
|
{
|
|
// cout<<"MetroGraph::MetroGraph(ListExpr)"<<endl;
|
|
}
|
|
|
|
MetroGraph::MetroGraph(SmiRecord& in_xValueRecord, size_t& inout_iOffset,
|
|
const ListExpr in_xTypeInfo):mg_id(0), min_t(0),
|
|
node_rel(NULL), btree_node(NULL),
|
|
edge_rel1(NULL), adj_list1(0), entry_adj_list1(0),
|
|
edge_rel2(NULL), adj_list2(0), entry_adj_list2(0)
|
|
{
|
|
in_xValueRecord.Read(&mg_id,sizeof(int),inout_iOffset);
|
|
inout_iOffset += sizeof(int);
|
|
|
|
in_xValueRecord.Read(&min_t,sizeof(double),inout_iOffset);
|
|
inout_iOffset += sizeof(double);
|
|
|
|
ListExpr xType;
|
|
ListExpr xNumericType;
|
|
///////////////////Open relation for node////////////////////////////
|
|
nl->ReadFromString(MGNodeTypeInfo,xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
node_rel = Relation::Open(in_xValueRecord, inout_iOffset, xNumericType);
|
|
if(!node_rel) {
|
|
return;
|
|
}
|
|
|
|
///////////////////open btree built on nodes//////////////////////////
|
|
nl->ReadFromString(MGNodeBTreeTypeInfo,xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
btree_node = BTree::Open(in_xValueRecord, inout_iOffset, xNumericType);
|
|
if(!btree_node) {
|
|
node_rel->Delete();
|
|
return;
|
|
}
|
|
|
|
///////////////////////Open relation for edge1///////////////////////////
|
|
nl->ReadFromString(MGEdge1TypeInfo, xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
edge_rel1 = Relation::Open(in_xValueRecord, inout_iOffset, xNumericType);
|
|
if(!edge_rel1) {
|
|
node_rel->Delete();
|
|
delete btree_node;
|
|
return;
|
|
}
|
|
|
|
/////////////////open adjacency list1////////////////////////////////
|
|
size_t bufsize = DbArray<ListEntry>::headerSize();
|
|
SmiSize offset = 0;
|
|
char* buf = (char*) malloc(bufsize);
|
|
in_xValueRecord.Read(buf, bufsize, inout_iOffset);
|
|
inout_iOffset += bufsize;
|
|
assert(buf != NULL);
|
|
adj_list1.restoreHeader(buf,offset);
|
|
free(buf);
|
|
offset = 0;
|
|
buf = (char*) malloc(bufsize);
|
|
in_xValueRecord.Read(buf, bufsize, inout_iOffset);
|
|
assert(buf != NULL);
|
|
entry_adj_list1.restoreHeader(buf,offset);
|
|
inout_iOffset += bufsize;
|
|
free(buf);
|
|
|
|
///////////////////////Open relation for edge2//////////////////////////
|
|
nl->ReadFromString(MGEdge2TypeInfo, xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
edge_rel2 = Relation::Open(in_xValueRecord, inout_iOffset, xNumericType);
|
|
if(!edge_rel2) {
|
|
node_rel->Delete();
|
|
delete btree_node;
|
|
edge_rel1->Delete();
|
|
adj_list1.clean();
|
|
entry_adj_list1.clean();
|
|
return;
|
|
}
|
|
|
|
/////////////////open adjacency list2////////////////////////////////
|
|
bufsize = DbArray<ListEntry>::headerSize();
|
|
offset = 0;
|
|
buf = (char*) malloc(bufsize);
|
|
in_xValueRecord.Read(buf, bufsize, inout_iOffset);
|
|
inout_iOffset += bufsize;
|
|
assert(buf != NULL);
|
|
adj_list2.restoreHeader(buf,offset);
|
|
free(buf);
|
|
offset = 0;
|
|
buf = (char*) malloc(bufsize);
|
|
in_xValueRecord.Read(buf, bufsize, inout_iOffset);
|
|
assert(buf != NULL);
|
|
entry_adj_list2.restoreHeader(buf,offset);
|
|
inout_iOffset += bufsize;
|
|
free(buf);
|
|
|
|
}
|
|
|
|
|
|
bool MetroGraph::Save(SmiRecord& in_xValueRecord,size_t& inout_iOffset,
|
|
const ListExpr in_xTypeInfo)
|
|
{
|
|
|
|
// cout<<"save "<<endl;
|
|
in_xValueRecord.Write(&mg_id,sizeof(int),inout_iOffset);
|
|
inout_iOffset += sizeof(int);
|
|
|
|
in_xValueRecord.Write(&min_t,sizeof(double),inout_iOffset);
|
|
inout_iOffset += sizeof(double);
|
|
|
|
ListExpr xType;
|
|
ListExpr xNumericType;
|
|
///////////////////////////save node/////////////////////////////
|
|
nl->ReadFromString(MGNodeTypeInfo,xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
if(!node_rel->Save(in_xValueRecord,inout_iOffset,xNumericType))
|
|
return false;
|
|
|
|
////////////////save btree on nodes///////////////////////////
|
|
nl->ReadFromString(MGNodeBTreeTypeInfo, xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
if(!btree_node->Save(in_xValueRecord, inout_iOffset, xNumericType))
|
|
return false;
|
|
|
|
/////////////////////save edge1/////////////////////////////
|
|
nl->ReadFromString(MGEdge1TypeInfo,xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
if(!edge_rel1->Save(in_xValueRecord,inout_iOffset,xNumericType))
|
|
return false;
|
|
|
|
/////////////////adjacency list 1//////////////////////////////
|
|
SecondoCatalog *ctlg = SecondoSystem::GetCatalog();
|
|
SmiRecordFile *rf = ctlg->GetFlobFile();
|
|
|
|
|
|
adj_list1.saveToFile(rf, adj_list1);
|
|
SmiSize offset = 0;
|
|
size_t bufsize = adj_list1.headerSize();
|
|
char* buf = (char*) malloc(bufsize);
|
|
adj_list1.serializeHeader(buf,offset);
|
|
assert(offset==bufsize);
|
|
in_xValueRecord.Write(buf, bufsize, inout_iOffset);
|
|
inout_iOffset += bufsize;
|
|
free(buf);
|
|
|
|
entry_adj_list1.saveToFile(rf, entry_adj_list1);
|
|
offset = 0;
|
|
buf = (char*) malloc(bufsize);
|
|
entry_adj_list1.serializeHeader(buf,offset);
|
|
assert(offset==bufsize);
|
|
in_xValueRecord.Write(buf,bufsize, inout_iOffset);
|
|
free(buf);
|
|
inout_iOffset += bufsize;
|
|
|
|
|
|
///////////////////////save edge2/////////////////////////////////////
|
|
nl->ReadFromString(MGEdge2TypeInfo,xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
if(!edge_rel2->Save(in_xValueRecord,inout_iOffset,xNumericType))
|
|
return false;
|
|
|
|
/////////////////adjacency list 2//////////////////////////////////
|
|
|
|
adj_list2.saveToFile(rf, adj_list2);
|
|
offset = 0;
|
|
bufsize = adj_list2.headerSize();
|
|
buf = (char*) malloc(bufsize);
|
|
adj_list2.serializeHeader(buf,offset);
|
|
assert(offset==bufsize);
|
|
in_xValueRecord.Write(buf, bufsize, inout_iOffset);
|
|
inout_iOffset += bufsize;
|
|
free(buf);
|
|
|
|
entry_adj_list2.saveToFile(rf, entry_adj_list2);
|
|
offset = 0;
|
|
buf = (char*) malloc(bufsize);
|
|
entry_adj_list2.serializeHeader(buf,offset);
|
|
assert(offset==bufsize);
|
|
in_xValueRecord.Write(buf,bufsize, inout_iOffset);
|
|
free(buf);
|
|
inout_iOffset += bufsize;
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
/*
|
|
load metro graph from input relations
|
|
|
|
*/
|
|
|
|
void MetroGraph::Load(int g_id, Relation* r1, Relation* edge1, Relation* edge2)
|
|
{
|
|
if(g_id <= 0){
|
|
cout<<"invalid graph id "<<g_id<<endl;
|
|
return;
|
|
}
|
|
mg_id = g_id;
|
|
|
|
//////////////////node relation////////////////////
|
|
ListExpr ptrList1 = listutils::getPtrList(r1);
|
|
|
|
string strQuery = "(consume(feed(" + MGNodeTypeInfo +
|
|
"(ptr " + nl->ToString(ptrList1) + "))))";
|
|
|
|
Word xResult;
|
|
int QueryExecuted = QueryProcessor::ExecuteQuery(strQuery, xResult);
|
|
assert(QueryExecuted);
|
|
node_rel = (Relation*)xResult.addr;
|
|
|
|
// cout<<"nodes size "<<node_rel->GetNoTuples()<<endl;
|
|
|
|
///////////////////////////btree on nodes///////////////////////////
|
|
|
|
ListExpr ptrList2 = listutils::getPtrList(node_rel);
|
|
|
|
strQuery = "(createbtree (" + MGNodeTypeInfo +
|
|
"(ptr " + nl->ToString(ptrList2) + "))" + "Mr_id)";
|
|
QueryExecuted = QueryProcessor::ExecuteQuery(strQuery, xResult);
|
|
assert(QueryExecuted);
|
|
btree_node = (BTree*)xResult.addr;
|
|
|
|
|
|
// cout<<edge1->GetNoTuples()<<" "<<edge2->GetNoTuples()<<endl;
|
|
|
|
LoadEdge1(edge1);
|
|
LoadEdge2(edge2);
|
|
|
|
}
|
|
|
|
/*
|
|
metro graph edges: two metro stops have the same spatial location in space
|
|
|
|
*/
|
|
void MetroGraph::LoadEdge1(Relation* edge1)
|
|
{
|
|
ListExpr ptrList1 = listutils::getPtrList(edge1);
|
|
|
|
string strQuery = "(consume(feed(" + MGEdge1TypeInfo +
|
|
"(ptr " + nl->ToString(ptrList1) + "))))";
|
|
|
|
Word xResult;
|
|
int QueryExecuted = QueryProcessor::ExecuteQuery(strQuery, xResult);
|
|
assert(QueryExecuted);
|
|
edge_rel1 = (Relation*)xResult.addr;
|
|
|
|
//////////////////create adjacency list////////////////////////////////////
|
|
|
|
ListExpr ptrList2 = listutils::getPtrList(edge_rel1);
|
|
|
|
strQuery = "(createbtree (" + MGEdge1TypeInfo +
|
|
"(ptr " + nl->ToString(ptrList2) + "))" + "Ms_stop1_tid)";
|
|
|
|
QueryExecuted = QueryProcessor::ExecuteQuery(strQuery,xResult);
|
|
assert(QueryExecuted);
|
|
BTree* btree = (BTree*)xResult.addr;
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
/////////the adjacent list here is different from dual graph and
|
|
////// visibility graph. it is the same as indoor and bus graph //////////
|
|
//////////in dual graph and visibility graph, we store the node id/////
|
|
/////////now we store the edge id because the weight, path is stored
|
|
////////in the edge relation ////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
for(int i = 1;i <= node_rel->GetNoTuples();i++){
|
|
Tuple* ms_tuple = node_rel->GetTuple(i, false);
|
|
|
|
CcInt* nodeid = new CcInt(true, ms_tuple->GetTupleId());
|
|
BTreeIterator* btree_iter = btree->ExactMatch(nodeid);
|
|
int start = adj_list1.Size();
|
|
while(btree_iter->Next()){
|
|
Tuple* edge_tuple = edge_rel1->GetTuple(btree_iter->GetId(), false);
|
|
|
|
adj_list1.Append(edge_tuple->GetTupleId());//get the edge tuple id
|
|
|
|
edge_tuple->DeleteIfAllowed();
|
|
}
|
|
delete btree_iter;
|
|
|
|
int end = adj_list1.Size();
|
|
entry_adj_list1.Append(ListEntry(start, end));
|
|
|
|
//cout<<"start "<<start<<" end "<<end<<endl;
|
|
|
|
delete nodeid;
|
|
|
|
ms_tuple->DeleteIfAllowed();
|
|
|
|
}
|
|
|
|
delete btree;
|
|
}
|
|
|
|
/*
|
|
metro graph edges: two metro stops are connected by moving metros
|
|
|
|
*/
|
|
void MetroGraph::LoadEdge2(Relation* edge2)
|
|
{
|
|
|
|
ListExpr ptrList1 = listutils::getPtrList(edge2);
|
|
|
|
string strQuery = "(consume(feed(" + MGEdge2TypeInfo +
|
|
"(ptr " + nl->ToString(ptrList1) + "))))";
|
|
|
|
Word xResult;
|
|
int QueryExecuted = QueryProcessor::ExecuteQuery(strQuery, xResult);
|
|
assert(QueryExecuted);
|
|
edge_rel2 = (Relation*)xResult.addr;
|
|
|
|
|
|
min_t = numeric_limits<double>::max();
|
|
|
|
for(int i = 1;i <= edge_rel2->GetNoTuples();i++){
|
|
Tuple* edge_tuple = edge_rel2->GetTuple(i, false);
|
|
|
|
Periods* peri = (Periods*)edge_tuple->GetAttribute(MG_EDGE2_PERI);
|
|
Interval<Instant> periods;
|
|
peri->Get(0, periods);
|
|
double t = periods.start.ToDouble();
|
|
if(t < min_t) min_t = t;
|
|
|
|
edge_tuple->DeleteIfAllowed();
|
|
|
|
}
|
|
|
|
// Instant min_time(instanttype);
|
|
// min_time.ReadFrom(min_t);
|
|
// printf("%.10f\n",min_t);
|
|
// cout<<min_time<<endl;
|
|
|
|
|
|
//////////////////create adjacency list////////////////////////////////////
|
|
|
|
ListExpr ptrList2 = listutils::getPtrList(edge_rel2);
|
|
|
|
strQuery = "(createbtree (" + MGEdge2TypeInfo +
|
|
"(ptr " + nl->ToString(ptrList2) + "))" + "Ms_stop1_tid)";
|
|
|
|
|
|
QueryExecuted = QueryProcessor::ExecuteQuery(strQuery,xResult);
|
|
assert(QueryExecuted);
|
|
BTree* btree = (BTree*)xResult.addr;
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
/////////the adjacent list here is different from dual graph and
|
|
///// visibility graph. it is the same as indoor and bus graph /////////
|
|
//////////in dual graph and visibility graph, we store the node id/////
|
|
/////////now we store the edge id because the weight, path is stored
|
|
////////in the edge relation ////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
for(int i = 1;i <= node_rel->GetNoTuples();i++){
|
|
Tuple* ms_tuple = node_rel->GetTuple(i, false);
|
|
|
|
CcInt* nodeid = new CcInt(true, ms_tuple->GetTupleId());
|
|
BTreeIterator* btree_iter = btree->ExactMatch(nodeid);
|
|
int start = adj_list2.Size();
|
|
while(btree_iter->Next()){
|
|
Tuple* edge_tuple = edge_rel2->GetTuple(btree_iter->GetId(), false);
|
|
adj_list2.Append(edge_tuple->GetTupleId());//get the edge tuple id
|
|
edge_tuple->DeleteIfAllowed();
|
|
}
|
|
delete btree_iter;
|
|
|
|
int end = adj_list2.Size();
|
|
entry_adj_list2.Append(ListEntry(start, end));
|
|
|
|
delete nodeid;
|
|
|
|
ms_tuple->DeleteIfAllowed();
|
|
|
|
}
|
|
|
|
delete btree;
|
|
|
|
}
|
|
|
|
/*
|
|
find the metro stop tid in the relation
|
|
|
|
*/
|
|
int MetroGraph::GetMetroStop_Tid(Bus_Stop* ms)
|
|
{
|
|
|
|
if(!ms->IsDefined()) return -1;
|
|
|
|
int ms_tid = -1;
|
|
CcInt* search_id = new CcInt(true,ms->GetId());
|
|
BTreeIterator* btree_iter = btree_node->ExactMatch(search_id);
|
|
while(btree_iter->Next()){
|
|
Tuple* ms_tuple = node_rel->GetTuple(btree_iter->GetId(), false);
|
|
Bus_Stop* ms_stop = (Bus_Stop*)ms_tuple->GetAttribute(MG_NODE_STOP);
|
|
int mr_id = ms->GetId();
|
|
|
|
assert(mr_id == (int) ms->GetId());
|
|
if(ms->GetStopId() == ms_stop->GetStopId() &&
|
|
ms->GetUp() == ms_stop->GetUp()){
|
|
ms_tid = ms_tuple->GetTupleId();
|
|
ms_tuple->DeleteIfAllowed();
|
|
break;
|
|
}
|
|
|
|
ms_tuple->DeleteIfAllowed();
|
|
|
|
}
|
|
delete btree_iter;
|
|
delete search_id;
|
|
assert(ms_tid > 0 && ms_tid <= node_rel->GetNoTuples());
|
|
return ms_tid;
|
|
|
|
|
|
}
|
|
|
|
/*
|
|
metro stops have the same spatial location in space
|
|
|
|
*/
|
|
void MetroGraph::FindAdj1(int node_id, vector<int>& list)
|
|
{
|
|
ListEntry list_entry;
|
|
entry_adj_list1.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_list1.Get(j, oid);
|
|
j++;
|
|
list.push_back(oid);
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
metro stops are connected by moving metros
|
|
|
|
*/
|
|
void MetroGraph::FindAdj2(int node_id, vector<int>& list)
|
|
{
|
|
|
|
ListEntry list_entry;
|
|
entry_adj_list2.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_list2.Get(j, oid);
|
|
j++;
|
|
list.push_back(oid);
|
|
}
|
|
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
////////////////// query processing on the metro graph and network//////////
|
|
////////////////////////////////////////////////////////////////////////////
|
|
/*
|
|
shortest path on metro network and graph
|
|
|
|
*/
|
|
void MNNav::ShortestPath_Time(Bus_Stop* ms1, Bus_Stop* ms2, Instant* qt)
|
|
{
|
|
// cout<<"shortest path on metro network"<<endl;
|
|
MetroGraph* mg = mn->GetMetroGraph();
|
|
|
|
if(mg == NULL){
|
|
cout<<"metro graph is invalid"<<endl;
|
|
return;
|
|
}
|
|
|
|
// cout<<mg->GetNode_Rel()->GetNoTuples()<<endl;
|
|
|
|
if(!ms1->IsDefined() || !ms2->IsDefined()){
|
|
cout<<" metro stops are not defined"<<endl;
|
|
return;
|
|
}
|
|
|
|
// cout<<*ms1<<" "<<*ms2<<endl;
|
|
|
|
Point start_p, end_p;
|
|
mn->GetMetroStopGeoData(ms1, &start_p);
|
|
mn->GetMetroStopGeoData(ms2, &end_p);
|
|
// cout<<"start "<<start_p<<" end "<<end_p<<endl;
|
|
|
|
|
|
const double delta_dist = 0.01;
|
|
|
|
if(*ms1 == *ms2 || start_p.Distance(end_p) < delta_dist){
|
|
cout<<"two bus stops equal to each other"<<endl;
|
|
mn->CloseMetroGraph(mg);
|
|
return;
|
|
}
|
|
|
|
/////////////////////////build the start time///////////////////////////
|
|
Instant new_st(instanttype);
|
|
Instant mg_min(instanttype);
|
|
mg_min.ReadFrom(mg->GetMIN_T());
|
|
|
|
// cout<<"mg_min "<<mg_min<<endl;
|
|
|
|
new_st.Set(mg_min.GetYear(), mg_min.GetMonth(), mg_min.GetGregDay(),
|
|
qt->GetHour(), qt->GetMinute(), qt->GetSecond(),
|
|
qt->GetMillisecond());
|
|
|
|
// cout<<"mapping start time"<<new_st<<endl;
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
priority_queue<BNPath_elem> path_queue;
|
|
vector<BNPath_elem> expand_queue;
|
|
|
|
vector<bool> visit_flag1;////////////metro stop visit
|
|
for(int i = 1; i <= mg->GetNode_Rel()->GetNoTuples();i++)
|
|
visit_flag1.push_back(false);
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
/////////from metro network, get the maximum speed of the metro///
|
|
/////////////for setting heuristic value/////////////////////////
|
|
///////////////////////////////////////////////////////////////////
|
|
// cout<<"max metro speed "<<mn->GetMaxSpeed()*60.0*60.0/1000.0<<"km/h"<<endl;
|
|
|
|
|
|
/////////// initialize the queue //////////////////////////////
|
|
InitializeQueue(ms1, ms2, path_queue, expand_queue, mn, mg, start_p, end_p);
|
|
|
|
int ms2_tid = mg->GetMetroStop_Tid(ms2);
|
|
// cout<<"end bus stop tid "<<ms2_tid<<endl;
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
////////////////////search on the metro graph///////////////////////
|
|
////////////////////////////////////////////////////////////////////
|
|
bool find = false;
|
|
BNPath_elem dest;//////////destination
|
|
|
|
while(path_queue.empty() == false){
|
|
BNPath_elem top = path_queue.top();
|
|
path_queue.pop();
|
|
|
|
if(visit_flag1[top.tri_index - 1]) continue;
|
|
|
|
// cout<<"top elem "<<endl;
|
|
// top.Print();
|
|
|
|
|
|
if(top.tri_index == ms2_tid){
|
|
// cout<<"find the shortest path"<<endl;
|
|
find = true;
|
|
dest = top;
|
|
break;
|
|
}
|
|
int pos_expand_path;
|
|
int cur_size;
|
|
|
|
pos_expand_path = top.cur_index;
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
//////////////////////connection 1 same spatial location/////////////
|
|
////////////////////////////////////////////////////////////////////
|
|
if(top.tm == TM_METRO){
|
|
vector<int> adj_list1;
|
|
mg->FindAdj1(top.tri_index, adj_list1);
|
|
// cout<<"adj1 size "<<adj_list1.size()<<endl;
|
|
|
|
for(unsigned int i = 0;i < adj_list1.size();i++){
|
|
Tuple* edge_tuple = mg->GetEdge_Rel1()->GetTuple(adj_list1[i], false);
|
|
int neighbor_id1 =
|
|
((CcInt*)edge_tuple->GetAttribute(MetroGraph::MG_EDGE1_TID2))->GetIntval();
|
|
SimpleLine* path = new SimpleLine(0);
|
|
path->StartBulkLoad();
|
|
path->EndBulkLoad();
|
|
// cout<<"neighbor_tid1 "<<neighbor_id1<<endl;
|
|
|
|
if(visit_flag1[neighbor_id1 - 1]){
|
|
edge_tuple->DeleteIfAllowed();
|
|
path->DeleteIfAllowed();
|
|
continue;
|
|
}
|
|
|
|
cur_size = expand_queue.size();
|
|
double w = top.real_w;
|
|
Tuple* ms_node_tuple = mg->GetNode_Rel()->GetTuple(neighbor_id1, false);
|
|
Point* p =
|
|
(Point*)ms_node_tuple->GetAttribute(MetroGraph::MG_NODE_STOP_GEO);
|
|
double hw = p->Distance(end_p)/(mn->GetMaxSpeed()*24.0*60.0*60.0);
|
|
ms_node_tuple->DeleteIfAllowed();
|
|
|
|
|
|
// BNPath_elem elem(pos_expand_path, cur_size, neighbor_id1, w + hw, w,
|
|
// *path, -1, false); //no useful for time cost
|
|
|
|
|
|
BNPath_elem elem(pos_expand_path, cur_size, neighbor_id1, w + hw, w,
|
|
*path, -1, false); //no useful for time cost
|
|
elem.type = -1;
|
|
elem.edge_tid = 0;
|
|
|
|
path_queue.push(elem);
|
|
expand_queue.push_back(elem);
|
|
|
|
// cout<<"neighbor1 ";
|
|
// elem.Print();
|
|
// cout<<endl;
|
|
|
|
path->DeleteIfAllowed();
|
|
edge_tuple->DeleteIfAllowed();
|
|
}
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
////////////////////connection 2 moving metros/////////////////////////
|
|
//////////////////////////////////////////////////////////////////////
|
|
vector<int> adj_list2;
|
|
mg->FindAdj2(top.tri_index, adj_list2);
|
|
int64_t max_64_int = numeric_limits<int64_t>::max();
|
|
|
|
// cout<<"ajd2 size "<<adj_list2.size()<<endl;
|
|
|
|
for(unsigned int i = 0;i < adj_list2.size();i++){
|
|
Tuple* edge_tuple = mg->GetEdge_Rel2()->GetTuple(adj_list2[i], false);
|
|
int neighbor_id2 =
|
|
((CcInt*)edge_tuple->GetAttribute(MetroGraph::MG_EDGE2_TID2))->GetIntval();
|
|
// SimpleLine* path =
|
|
// (SimpleLine*)edge_tuple->GetAttribute(MetroGraph::MG_EDGE2_PATH);
|
|
|
|
// cout<<"neighbor_id2 "<<neighbor_id2<<endl;
|
|
|
|
if(visit_flag1[neighbor_id2 - 1]){
|
|
edge_tuple->DeleteIfAllowed();
|
|
continue;
|
|
}
|
|
|
|
cur_size = expand_queue.size();
|
|
double cur_t = new_st.ToDouble() + top.real_w;
|
|
Instant cur_inst = new_st;
|
|
cur_inst.ReadFrom(cur_t); //time to arrive current metro stop
|
|
// cout<<"time at metro stop "<<cur_inst<<endl;
|
|
|
|
int64_t cur_t_int = cur_t*86400000;
|
|
assert(cur_t_int <= max_64_int);
|
|
|
|
Periods* peri =
|
|
(Periods*)edge_tuple->GetAttribute(MetroGraph::MG_EDGE2_PERI);
|
|
Interval<Instant> periods;
|
|
peri->Get(0, periods);
|
|
|
|
double sched =
|
|
((CcReal*)edge_tuple->GetAttribute(MetroGraph::
|
|
MG_EDGE2_SCHED))->GetRealval();
|
|
|
|
double st = periods.start.ToDouble();
|
|
double et = periods.end.ToDouble();
|
|
int64_t st_int = st*86400000;
|
|
int64_t et_int = et*86400000;
|
|
assert(st_int <= max_64_int);
|
|
assert(et_int <= max_64_int);
|
|
|
|
// cout<<"st "<<periods.start<<" et "<<periods.end<<endl;
|
|
|
|
if(et_int < cur_t_int){//end time smaller than curtime
|
|
edge_tuple->DeleteIfAllowed();
|
|
continue;
|
|
}
|
|
// cout<<"st_int "<<st_int<<" cur_t_int "<<cur_t_int<<endl;
|
|
|
|
double wait_time = 0.0;
|
|
if(st_int > cur_t_int){//wait for the first start time
|
|
wait_time += st - cur_t;
|
|
wait_time += 30.0/(24.0*60.0*60.0);//30 seconds at metro stop
|
|
}else if(st_int == cur_t_int){
|
|
wait_time += 30.0/(24.0*60.0*60.0);//30 seconds at metro stop
|
|
}else{ //most times, it is here, wait for the next schedule
|
|
|
|
bool valid = false;
|
|
while(st_int < cur_t_int && st_int <= et_int){
|
|
|
|
Instant temp(instanttype);
|
|
temp.ReadFrom(st);
|
|
// cout<<"t1 "<<temp<<endl;
|
|
// cout<<"st_int "<<st_int<<" cur_t_int "<<cur_t_int<<endl;
|
|
|
|
if((st_int + 30000) >= cur_t_int){//30 second
|
|
wait_time += st + 30.0/(24.0*60.0*60.0) - cur_t;
|
|
valid = true;
|
|
break;
|
|
}
|
|
st += sched;
|
|
st_int = st * 86400000;
|
|
if(st_int >= cur_t_int){
|
|
wait_time += st + 30.0/(24.0*60.0*60.0) - cur_t;
|
|
valid = true;
|
|
break;
|
|
}
|
|
assert(st_int <= max_64_int);
|
|
|
|
// temp.ReadFrom(st);
|
|
// cout<<"t2 "<<temp<<endl;
|
|
|
|
}
|
|
if(valid == false){
|
|
cout<<"should not arrive at here"<<endl;
|
|
assert(false);
|
|
}
|
|
}
|
|
|
|
double weight =
|
|
((CcReal*)edge_tuple->GetAttribute(MetroGraph::
|
|
MG_EDGE2_TIME_COST))->GetRealval();
|
|
double w = top.real_w + wait_time + weight;
|
|
|
|
Tuple* ms_node_tuple = mg->GetNode_Rel()->GetTuple(neighbor_id2, false);
|
|
Point* p =
|
|
(Point*)ms_node_tuple->GetAttribute(MetroGraph::MG_NODE_STOP_GEO);
|
|
double hw = p->Distance(end_p)/(mn->GetMaxSpeed()*24.0*60.0*60.0);
|
|
ms_node_tuple->DeleteIfAllowed();
|
|
|
|
|
|
// BNPath_elem elem(pos_expand_path, cur_size, neighbor_id2, w + hw, w,
|
|
// *path, TM_METRO, true);
|
|
|
|
SimpleLine temp_sl(0);
|
|
BNPath_elem elem(pos_expand_path, cur_size, neighbor_id2, w + hw, w,
|
|
temp_sl, TM_METRO, true);
|
|
elem.type = TM_METRO;
|
|
elem.edge_tid = adj_list2[i];
|
|
|
|
|
|
if(wait_time > 0.0){ //to the time waiting for metro
|
|
elem.SetW(top.real_w + wait_time);
|
|
}
|
|
|
|
path_queue.push(elem);
|
|
expand_queue.push_back(elem);
|
|
|
|
// cout<<"neighbor2 "<<wait_time<<" "<<weight<<endl;
|
|
// elem.Print();
|
|
// cout<<endl;
|
|
|
|
edge_tuple->DeleteIfAllowed();
|
|
|
|
}
|
|
|
|
visit_flag1[top.tri_index - 1] = true;
|
|
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
////////////////construct the result//////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////
|
|
if(find){ ////////constrcut the result
|
|
vector<int> id_list;
|
|
while(dest.prev_index != -1){
|
|
id_list.push_back(dest.cur_index);
|
|
dest = expand_queue[dest.prev_index];
|
|
}
|
|
|
|
id_list.push_back(dest.cur_index);
|
|
|
|
Bus_Stop ms_last = *ms1;
|
|
Instant t1 = *qt;
|
|
// int no_transfer = 0;
|
|
t_cost = 0.0;
|
|
|
|
for(int i = id_list.size() - 1;i >= 0;i--){
|
|
BNPath_elem elem = expand_queue[id_list[i]];
|
|
|
|
if(elem.type == TM_METRO){
|
|
if(elem.edge_tid > 0){
|
|
Tuple* edge_tuple = mg->GetEdge_Rel2()->GetTuple(elem.edge_tid, false);
|
|
SimpleLine* path =
|
|
(SimpleLine*)edge_tuple->GetAttribute(MetroGraph::MG_EDGE2_PATH);
|
|
elem.path = *path;
|
|
edge_tuple->DeleteIfAllowed();
|
|
}
|
|
|
|
}else if(elem.type == -1){
|
|
|
|
}else{
|
|
cout<<"should not be here"<<endl;
|
|
assert(false);
|
|
}
|
|
|
|
|
|
path_list.push_back(elem.path);
|
|
|
|
if(elem.tm == TM_METRO){
|
|
tm_list.push_back(str_tm[elem.tm]);
|
|
}else{
|
|
// assert(false);
|
|
tm_list.push_back("none");
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
////////////////we also return///////////////////////////////////////
|
|
////////the start and end metro stops connected by the path /////////
|
|
////////////////////////////////////////////////////////////////////
|
|
char buf1[256], buf2[256];
|
|
|
|
sprintf(buf1, "mr: %d ", ms_last.GetId());
|
|
sprintf(buf2, "stop: %d", ms_last.GetStopId());
|
|
strcat (buf1, buf2);
|
|
if(ms_last.GetUp()) strcat (buf1, " UP");
|
|
else strcat (buf1, " DOWN");
|
|
|
|
string str1(buf1);
|
|
ms1_list.push_back(str1);
|
|
|
|
if(i == (int)(id_list.size() - 1)){
|
|
string str2(str1);
|
|
ms2_list.push_back(str2);
|
|
|
|
}else{////////////////the end metro stop
|
|
|
|
Tuple* ms_tuple = mg->GetNode_Rel()->GetTuple(elem.tri_index, false);
|
|
Bus_Stop* ms_cur =
|
|
(Bus_Stop*)ms_tuple->GetAttribute(MetroGraph::MG_NODE_STOP);
|
|
char buf_1[256], buf_2[256];
|
|
sprintf(buf_1, "mr: %d ", ms_cur->GetId());
|
|
sprintf(buf_2, "stop: %d", ms_cur->GetStopId());
|
|
strcat (buf_1, buf_2);
|
|
if(ms_cur->GetUp()) strcat (buf_1, " UP");
|
|
else strcat (buf_1, " DOWN");
|
|
|
|
string str2(buf_1);
|
|
ms2_list.push_back(str2);
|
|
ms_last = *ms_cur;
|
|
ms_tuple->DeleteIfAllowed();
|
|
}
|
|
|
|
////////////////time duration////////////////////////////////
|
|
|
|
Instant t2(instanttype);
|
|
if(elem.b_w == false){
|
|
t2.ReadFrom(elem.real_w + qt->ToDouble());
|
|
// cout<<t1<<" "<<t2<<endl;
|
|
|
|
//time cost in seconds
|
|
if(elem.valid){
|
|
time_cost_list.push_back((t2.ToDouble() - t1.ToDouble())*86400.0);
|
|
t_cost += (t2.ToDouble() - t1.ToDouble())*86400.0;
|
|
}
|
|
else{ //doing transfer without moving
|
|
time_cost_list.push_back(0.0);
|
|
t_cost += 0.0;
|
|
}
|
|
Interval<Instant> time_span;
|
|
time_span.start = t1;
|
|
time_span.lc = true;
|
|
time_span.end = t2;
|
|
time_span.rc = false;
|
|
|
|
Periods* peri = new Periods(0);
|
|
peri->StartBulkLoad();
|
|
if(elem.valid)
|
|
peri->MergeAdd(time_span);
|
|
peri->EndBulkLoad();
|
|
peri_list.push_back(*peri);
|
|
t1 = t2;
|
|
peri->DeleteIfAllowed();
|
|
}else{ //////////to dinstinguish time of waiting for the metro
|
|
t2.ReadFrom(elem.w + qt->ToDouble());
|
|
// cout<<t1<<" "<<t2<<endl;
|
|
|
|
//time cost in seconds
|
|
if(elem.valid){
|
|
time_cost_list.push_back((t2.ToDouble() - t1.ToDouble())*86400.0);
|
|
t_cost += (t2.ToDouble() - t1.ToDouble())*86400.0;
|
|
}
|
|
else{ //doing transfer without moving
|
|
time_cost_list.push_back(0.0);
|
|
t_cost += 0.0;
|
|
}
|
|
Interval<Instant> time_span;
|
|
time_span.start = t1;
|
|
time_span.lc = true;
|
|
time_span.end = t2;
|
|
time_span.rc = false;
|
|
|
|
Periods* peri1 = new Periods(0);
|
|
peri1->StartBulkLoad();
|
|
if(elem.valid)
|
|
peri1->MergeAdd(time_span);
|
|
peri1->EndBulkLoad();
|
|
peri_list.push_back(*peri1);
|
|
t1 = t2;
|
|
peri1->DeleteIfAllowed();
|
|
|
|
SimpleLine* sl = new SimpleLine(0);
|
|
sl->StartBulkLoad();
|
|
sl->EndBulkLoad();
|
|
path_list[path_list.size() - 1] = *sl;
|
|
sl->DeleteIfAllowed();
|
|
|
|
tm_list[tm_list.size() - 1] = "none"; //waiting is no tm
|
|
string str = ms2_list[ms2_list.size() - 1];
|
|
////////the same as last metro stop //////////////////////
|
|
ms2_list[ms2_list.size() - 1] = ms1_list[ms1_list.size() - 1];
|
|
|
|
/////////////moving with metro////////////////////////////////
|
|
t2.ReadFrom(elem.real_w + qt->ToDouble());
|
|
// cout<<t1<<" "<<t2<<endl;
|
|
|
|
//time cost in seconds
|
|
if(elem.valid){
|
|
time_cost_list.push_back((t2.ToDouble() - t1.ToDouble())*86400.0);
|
|
t_cost += (t2.ToDouble() - t1.ToDouble())*86400.0;
|
|
}
|
|
else{ //doing transfer without moving
|
|
time_cost_list.push_back(0.0);
|
|
t_cost += 0.0;
|
|
}
|
|
|
|
time_span.start = t1;
|
|
time_span.lc = true;
|
|
time_span.end = t2;
|
|
time_span.rc = false;
|
|
|
|
Periods* peri2 = new Periods(0);
|
|
peri2->StartBulkLoad();
|
|
if(elem.valid)
|
|
peri2->MergeAdd(time_span);
|
|
peri2->EndBulkLoad();
|
|
peri_list.push_back(*peri2);
|
|
t1 = t2;
|
|
peri2->DeleteIfAllowed();
|
|
path_list.push_back(elem.path);
|
|
tm_list.push_back(str_tm[elem.tm]);
|
|
ms1_list.push_back(str1);
|
|
ms2_list.push_back(str);
|
|
|
|
}
|
|
|
|
}
|
|
// cout<<" transfer "<<no_transfer<<" times "<<endl;
|
|
}else{
|
|
// cout<<"ms1 ("<<*ms1<<") ms2 ("<<*ms2<<") not reachable "<<endl;
|
|
}
|
|
|
|
|
|
mn->CloseMetroGraph(mg);
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
initialize the queue: shortest path in time
|
|
|
|
*/
|
|
void MNNav::InitializeQueue(Bus_Stop* ms1, Bus_Stop* ms2,
|
|
priority_queue<BNPath_elem>& path_queue,
|
|
vector<BNPath_elem>& expand_queue,
|
|
MetroNetwork* mn, MetroGraph* mg,
|
|
Point& start_p, Point& end_p)
|
|
{
|
|
int cur_size = expand_queue.size();
|
|
double w = 0.0;
|
|
|
|
double hw = start_p.Distance(end_p)/(mn->GetMaxSpeed()*24.0*60.0*60.0);
|
|
// double hw = 0.0;
|
|
|
|
SimpleLine* sl = new SimpleLine(0);
|
|
sl->StartBulkLoad();
|
|
sl->EndBulkLoad();
|
|
|
|
int ms_tid = mg->GetMetroStop_Tid(ms1);
|
|
// cout<<"start metro stop tid "<<ms_tid<<endl;
|
|
//////////////////no time cost////////////////////////////////////
|
|
BNPath_elem elem(-1, cur_size, ms_tid, w + hw, w, *sl, TM_METRO, false);
|
|
|
|
elem.type = TM_METRO;
|
|
elem.edge_tid = 0;
|
|
|
|
path_queue.push(elem);
|
|
expand_queue.push_back(elem);
|
|
sl->DeleteIfAllowed();
|
|
}
|
|
|
|
/*
|
|
get adjacent list for a metro graph node
|
|
|
|
*/
|
|
void MNNav::GetAdjNodeMG(MetroGraph* mg, int nodeid)
|
|
{
|
|
|
|
if(mg->GetNode_Rel() == NULL){
|
|
cout<<"no metro graph node rel"<<endl;
|
|
return;
|
|
}
|
|
if(nodeid < 1 || nodeid > mg->GetNode_Rel()->GetNoTuples()){
|
|
cout<<"invalid node id "<<endl;
|
|
return;
|
|
}
|
|
|
|
cout<<"total "<<mg->GetNode_Rel()->GetNoTuples()<<" nodes "<<endl;
|
|
cout<<"total "<<mg->GetEdge_Rel1()->GetNoTuples() +
|
|
mg->GetEdge_Rel2()->GetNoTuples()<<" edges "<<endl;
|
|
|
|
|
|
Relation* node_rel = mg->GetNode_Rel();
|
|
|
|
Tuple* ms_tuple = node_rel->GetTuple(nodeid, false);
|
|
Bus_Stop* ms1 = (Bus_Stop*)ms_tuple->GetAttribute(MetroGraph::MG_NODE_STOP);
|
|
// cout<<*ms1<<endl;
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//////the first kind of connection (no path; the same spatial location)////
|
|
////////////////////////////////////////////////////////////////////////////
|
|
vector<int> tid_list1;
|
|
mg->FindAdj1(nodeid, tid_list1);
|
|
|
|
for(unsigned int i = 0;i < tid_list1.size();i++){
|
|
Tuple* edge_tuple = mg->GetEdge_Rel1()->GetTuple(tid_list1[i], false);
|
|
int neighbor_id =
|
|
((CcInt*)edge_tuple->GetAttribute(MetroGraph::MG_EDGE1_TID2))->GetIntval();
|
|
edge_tuple->DeleteIfAllowed();
|
|
|
|
Tuple* ms_neighbor1 = node_rel->GetTuple(neighbor_id, false);
|
|
Bus_Stop* ms2 =
|
|
(Bus_Stop*)ms_neighbor1->GetAttribute(MetroGraph::MG_NODE_STOP);
|
|
|
|
SimpleLine* path = new SimpleLine(0);
|
|
path->StartBulkLoad();
|
|
path->EndBulkLoad();
|
|
ms_list1.push_back(*ms1);
|
|
ms_list2.push_back(*ms2);
|
|
path_list.push_back(*path);
|
|
path->DeleteIfAllowed();
|
|
|
|
ms_neighbor1->DeleteIfAllowed();
|
|
type_list.push_back(1);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//////the second kind of connection (connected by moving metros)////
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
vector<int> tid_list2;
|
|
mg->FindAdj2(nodeid, tid_list2);
|
|
|
|
for(unsigned int i = 0;i < tid_list2.size();i++){
|
|
|
|
Tuple* edge_tuple = mg->GetEdge_Rel2()->GetTuple(tid_list2[i], false);
|
|
int neighbor_id =
|
|
((CcInt*)edge_tuple->GetAttribute(MetroGraph::MG_EDGE2_TID2))->GetIntval();
|
|
Tuple* ms_neighbor2 = node_rel->GetTuple(neighbor_id, false);
|
|
|
|
Bus_Stop* ms3 =
|
|
(Bus_Stop*)ms_neighbor2->GetAttribute(MetroGraph::MG_NODE_STOP);
|
|
|
|
|
|
SimpleLine* path =
|
|
(SimpleLine*)edge_tuple->GetAttribute(MetroGraph::MG_EDGE2_PATH);
|
|
ms_list1.push_back(*ms1);
|
|
ms_list2.push_back(*ms3);
|
|
path_list.push_back(*path);
|
|
|
|
edge_tuple->DeleteIfAllowed();
|
|
ms_neighbor2->DeleteIfAllowed();
|
|
|
|
type_list.push_back(2);
|
|
}
|
|
|
|
ms_tuple->DeleteIfAllowed();
|
|
|
|
|
|
}
|
|
|
|
void MyToPoint(Network* rn, GPoint* gp, Point& res)
|
|
{
|
|
Relation* routes = rn->GetRoutes();
|
|
if(routes == NULL){
|
|
cout<<"routes loading error"<<endl;
|
|
assert(false);
|
|
return;
|
|
}
|
|
Tuple* road_tuple = routes->GetTuple(gp->GetRouteId(), false);
|
|
|
|
SimpleLine* sl = (SimpleLine*)road_tuple->GetAttribute(ROUTE_CURVE);
|
|
assert(sl->GetStartSmaller());
|
|
|
|
assert(sl->AtPosition(gp->GetPosition(), sl->GetStartSmaller(), res));
|
|
|
|
road_tuple->DeleteIfAllowed();
|
|
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
////////// improve join algorithm, not use symmjoin////////////////////
|
|
///////////////////////////////////////////////////////////////////////
|
|
string TM_Join::CellBoxTypeInfo = "(rel (tuple ((Cellid int)\
|
|
(Cover_area region) (X_id int) (Y_id int))))";
|
|
|
|
string TM_Join::RoadSectionTypeInfo = "(rel (tuple ((Rid int) (Meas1 real)\
|
|
(Meas2 real) (Dual bool) (Curve sline)(CurveStartsSmaller bool)\
|
|
(Rrc tid) (Sid int))))";
|
|
|
|
/*
|
|
for each cell, it collects the number of route section intersecting it
|
|
|
|
*/
|
|
void TM_Join::Road_Cell_Join(Relation* rel1, Relation* rel2,
|
|
R_Tree<2,TupleId>* rtree)
|
|
{
|
|
// cout<<rel1->GetNoTuples()<<" "<<rel2->GetNoTuples()<<endl;
|
|
|
|
|
|
vector<Region> cell_area_list(rel2->GetNoTuples(), Region(0));
|
|
for(int i = 1;i <= rel2->GetNoTuples();i++){
|
|
Tuple* cell_tuple = rel2->GetTuple(i, false);
|
|
int cellid = ((CcInt*)cell_tuple->GetAttribute(TM_JOIN_ID))->GetIntval();
|
|
Region* reg = (Region*)cell_tuple->GetAttribute(TM_JOIN_AREA);
|
|
cell_area_list[cellid - 1] = *reg;
|
|
cell_tuple->DeleteIfAllowed();
|
|
}
|
|
|
|
vector<int> cell_list;
|
|
vector<int> sec_id_list(rel2->GetNoTuples(), 0);
|
|
|
|
for(int i = 1;i <= rel1->GetNoTuples();i++){
|
|
Tuple* road_tuple = rel1->GetTuple(i, false);
|
|
int sec_id = ((CcInt*)road_tuple->GetAttribute(SECTION_SID))->GetIntval();
|
|
SimpleLine* sl = (SimpleLine*)road_tuple->GetAttribute(SECTION_CURVE);
|
|
Line* l = new Line(0);
|
|
sl->toLine(*l);
|
|
|
|
vector<int> tid_list;
|
|
DFTraverse(rel2, rtree, rtree->RootRecordId(), l, tid_list);
|
|
|
|
// cout<<"rid "<<r_id<<" "<<tid_list.size()<<endl;
|
|
if(tid_list.size() > 0){
|
|
for(unsigned int j = 0;j < tid_list.size();j++){
|
|
|
|
Tuple* cell_tuple = rel2->GetTuple(tid_list[j], false);
|
|
int cell_id =
|
|
((CcInt*)cell_tuple->GetAttribute(TM_JOIN_ID))->GetIntval();
|
|
|
|
cell_list.push_back(cell_id);
|
|
cell_tuple->DeleteIfAllowed();
|
|
|
|
if(sec_id_list[cell_id - 1] == 0){
|
|
sec_id_list[cell_id - 1] = sec_id;
|
|
}
|
|
}
|
|
}
|
|
l->DeleteIfAllowed();
|
|
road_tuple->DeleteIfAllowed();
|
|
}
|
|
|
|
sort(cell_list.begin(), cell_list.end());
|
|
for(unsigned int i = 0;i < cell_list.size();i++){
|
|
int cell_id = cell_list[i];
|
|
unsigned int j = i + 1;
|
|
int count = 1;
|
|
while(j < cell_list.size() && cell_list[j] == cell_id){
|
|
count++;
|
|
j++;
|
|
}
|
|
|
|
i = j - 1;
|
|
|
|
sec_list.push_back(sec_id_list[cell_id - 1]);
|
|
id_list.push_back(cell_id);
|
|
count_list.push_back(count);
|
|
area_list.push_back(cell_area_list[cell_id - 1]);
|
|
}
|
|
|
|
// for(unsigned int i = 0;i < id_list.size();i++)
|
|
// cout<<id_list[i]<<" no: "<<count_list[i]<<endl;
|
|
|
|
}
|
|
|
|
/*
|
|
find all cell box that intersect the road line
|
|
|
|
*/
|
|
void TM_Join::DFTraverse(Relation* rel, R_Tree<2,TupleId>* rtree,
|
|
SmiRecordId adr, Line* l, vector<int>& 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* tuple = rel->GetTuple(e.info,false);
|
|
Region* reg =(Region*)tuple->GetAttribute(TM_JOIN_AREA);
|
|
if(l->Intersects(*reg)){
|
|
id_list.push_back(e.info);
|
|
}
|
|
tuple->DeleteIfAllowed();
|
|
}else{
|
|
R_TreeInternalEntry<2> e =
|
|
(R_TreeInternalEntry<2>&)(*node)[j];
|
|
// if(l->Intersects(e.box)){
|
|
if(l->Intersects(Region(e.box))){
|
|
DFTraverse(rel, rtree, e.pointer, l, id_list);
|
|
}
|
|
}
|
|
}
|
|
delete node;
|
|
}
|
|
|
|
|
|
/*
|
|
for each bus or metro stop, find the pavement areas nearby
|
|
|
|
*/
|
|
void TM_Join::NearStopPave(Space* sp, string type)
|
|
{
|
|
|
|
Pavement* pm = sp->LoadPavement(IF_REGION);
|
|
DualGraph* dg = pm->GetDualGraph();
|
|
|
|
if(type == "Bus"){
|
|
BusNetwork* bn = sp->LoadBusNetwork(IF_BUSNETWORK);
|
|
NearBusStopPave(bn, dg);
|
|
sp->CloseBusNetwork(bn);
|
|
}else if(type == "Metro"){
|
|
MetroNetwork* mn = sp->LoadMetroNetwork(IF_METRONETWORK);
|
|
NearMetroStopPave(mn, dg);
|
|
sp->CloseMetroNetwork(mn);
|
|
}else{
|
|
|
|
cout<<"invalid type "<<type<<endl;
|
|
}
|
|
|
|
pm->CloseDualGraph(dg);
|
|
sp->ClosePavement(pm);
|
|
}
|
|
|
|
/*
|
|
for each bus stop, find its nearby pavement areas.
|
|
For the roads data Houston, if all pavement areas are randomly selected,
|
|
some may not find bus stops nearby
|
|
|
|
*/
|
|
void TM_Join::NearBusStopPave(BusNetwork* bn, DualGraph* dg)
|
|
{
|
|
Relation* bs_rel = bn->GetBS_Rel();
|
|
Relation* tri_rel = dg->node_rel_sort;
|
|
R_Tree<2,TupleId>* rtree = dg->rtree_node;
|
|
|
|
|
|
vector<int> unique_id_list;
|
|
for(int i = 1;i <= bs_rel->GetNoTuples();i++){
|
|
Tuple* bs_tuple = bs_rel->GetTuple(i, false);
|
|
Point* bs_loc = (Point*)bs_tuple->GetAttribute(BusNetwork::BS_GEO);
|
|
// cout<<*bs_loc<<endl;
|
|
|
|
vector<int> tid_list;
|
|
DFTraverseBMS(rtree, rtree->RootRecordId(), tri_rel, *bs_loc,
|
|
tid_list, NEARBUSSTOP);
|
|
|
|
for(unsigned int j = 0;j < tid_list.size();j++){
|
|
unique_id_list.push_back(tid_list[j]);
|
|
}
|
|
bs_tuple->DeleteIfAllowed();
|
|
}
|
|
|
|
// cout<<unique_id_list.size()<<endl;
|
|
|
|
sort(unique_id_list.begin(), unique_id_list.end());
|
|
vector<int>::iterator it =
|
|
unique(unique_id_list.begin(), unique_id_list.end());
|
|
unique_id_list.resize( it - unique_id_list.begin() );
|
|
|
|
// cout<<unique_id_list.size()<<endl;
|
|
|
|
for(it = unique_id_list.begin(); it != unique_id_list.end();it++){
|
|
Tuple* tri_tuple = tri_rel->GetTuple(*it, false);
|
|
int oid = ((CcInt*)tri_tuple->GetAttribute(DualGraph::OID))->GetIntval();
|
|
int rid = ((CcInt*)tri_tuple->GetAttribute(DualGraph::RID))->GetIntval();
|
|
Region* reg = (Region*)tri_tuple->GetAttribute(DualGraph::PAVEMENT);
|
|
|
|
// cout<<oid<<endl;
|
|
id_list.push_back(oid);
|
|
rid_list.push_back(rid);
|
|
area_list.push_back(*reg);
|
|
|
|
tri_tuple->DeleteIfAllowed();
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
for each metro stop, find its nearby pavement areas
|
|
|
|
*/
|
|
void TM_Join::NearMetroStopPave(MetroNetwork* mn, DualGraph* dg)
|
|
{
|
|
// cout<<"metro stop"<<endl;
|
|
|
|
Relation* ms_rel = mn->GetMS_Rel();
|
|
Relation* tri_rel = dg->node_rel_sort;
|
|
R_Tree<2,TupleId>* rtree = dg->rtree_node;
|
|
|
|
|
|
vector<int> unique_id_list;
|
|
for(int i = 1;i <= ms_rel->GetNoTuples();i++){
|
|
Tuple* ms_tuple = ms_rel->GetTuple(i, false);
|
|
Point* ms_loc = (Point*)ms_tuple->GetAttribute(MetroNetwork::M_STOP_GEO);
|
|
// cout<<*ms_loc<<endl;
|
|
|
|
vector<int> tid_list;
|
|
DFTraverseBMS(rtree, rtree->RootRecordId(), tri_rel,
|
|
*ms_loc, tid_list, NEARMETROSTOP);
|
|
|
|
// cout<<tid_list.size()<<endl;
|
|
|
|
for(unsigned int j = 0;j < tid_list.size();j++){
|
|
unique_id_list.push_back(tid_list[j]);
|
|
}
|
|
ms_tuple->DeleteIfAllowed();
|
|
}
|
|
|
|
// cout<<unique_id_list.size()<<endl;
|
|
|
|
sort(unique_id_list.begin(), unique_id_list.end());
|
|
vector<int>::iterator it =
|
|
unique(unique_id_list.begin(), unique_id_list.end());
|
|
unique_id_list.resize( it - unique_id_list.begin() );
|
|
|
|
// cout<<unique_id_list.size()<<endl;
|
|
|
|
for(it = unique_id_list.begin(); it != unique_id_list.end();it++){
|
|
Tuple* tri_tuple = tri_rel->GetTuple(*it, false);
|
|
int oid = ((CcInt*)tri_tuple->GetAttribute(DualGraph::OID))->GetIntval();
|
|
int rid = ((CcInt*)tri_tuple->GetAttribute(DualGraph::RID))->GetIntval();
|
|
Region* reg = (Region*)tri_tuple->GetAttribute(DualGraph::PAVEMENT);
|
|
|
|
// cout<<oid<<endl;
|
|
id_list.push_back(oid);
|
|
rid_list.push_back(rid);
|
|
area_list.push_back(*reg);
|
|
|
|
tri_tuple->DeleteIfAllowed();
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
traverse the rtree to find nearby pavement areas for bus and metro stops
|
|
|
|
*/
|
|
void TM_Join::DFTraverseBMS(R_Tree<2,TupleId>* rtree, SmiRecordId adr,
|
|
Relation* rel,
|
|
Point query_loc, vector<int>& tid_list,
|
|
double max_dist)
|
|
{
|
|
////should be consist with the one used in GeneralType.cpp/////
|
|
// const double max_dist = NEARBUSSTOP;
|
|
|
|
R_TreeNode<2,TupleId>* node = rtree->GetMyNode(adr,false,
|
|
rtree->MinEntries(0), rtree->MaxEntries(0));
|
|
for(int j = 0;j < node->EntryCount();j++){
|
|
if(node->IsLeaf()){
|
|
R_TreeLeafEntry<2,TupleId> e =
|
|
(R_TreeLeafEntry<2,TupleId>&)(*node)[j];
|
|
Tuple* dg_tuple = rel->GetTuple(e.info, false);
|
|
Region* reg =
|
|
(Region*)dg_tuple->GetAttribute(DualGraph::PAVEMENT);
|
|
|
|
if(reg->Distance(query_loc, NULL) < max_dist){
|
|
tid_list.push_back(e.info);
|
|
}
|
|
dg_tuple->DeleteIfAllowed();
|
|
}else{
|
|
R_TreeInternalEntry<2> e =
|
|
(R_TreeInternalEntry<2>&)(*node)[j];
|
|
if(query_loc.Distance(e.box) < max_dist){
|
|
DFTraverseBMS(rtree, e.pointer, rel, query_loc,
|
|
tid_list, max_dist);
|
|
}
|
|
}
|
|
}
|
|
delete node;
|
|
}
|
|
|
|
|
|
/*
|
|
for each bus or metro stop, find the buildings nearby
|
|
|
|
*/
|
|
void TM_Join::NearStopBuilding(Space* sp, string type)
|
|
{
|
|
IndoorInfra* i_infra = sp->LoadIndoorInfra(IF_GROOM);
|
|
if(i_infra == NULL){
|
|
cout<<"indoor infrastructure does not exist "<<endl;
|
|
return;
|
|
}
|
|
|
|
Relation* build_rel = i_infra->BuildingType_Rel();
|
|
R_Tree<2,TupleId>* rtree = i_infra->BuildingRTree();
|
|
|
|
if(type == "Bus"){
|
|
BusNetwork* bn = sp->LoadBusNetwork(IF_BUSNETWORK);
|
|
if(bn == NULL){
|
|
cout<<"bus network does not exist "<<endl;
|
|
return;
|
|
}
|
|
NearBusStopBuilding(bn, build_rel, rtree);
|
|
sp->CloseBusNetwork(bn);
|
|
}else if(type == "Metro"){
|
|
MetroNetwork* mn = sp->LoadMetroNetwork(IF_METRONETWORK);
|
|
if(mn == NULL){
|
|
cout<<"metro network does not exist"<<endl;
|
|
return;
|
|
}
|
|
NearMetroStopBuilding(mn, build_rel, rtree);
|
|
sp->CloseMetroNetwork(mn);
|
|
}else{
|
|
|
|
cout<<"invalid type "<<type<<endl;
|
|
}
|
|
|
|
sp->CloseIndoorInfra(i_infra);
|
|
|
|
}
|
|
|
|
/*
|
|
for each bus stop, find all buildings nearby
|
|
|
|
*/
|
|
void TM_Join::NearBusStopBuilding(BusNetwork* bn, Relation* build_rel,
|
|
R_Tree<2,TupleId>* rtree)
|
|
{
|
|
Relation* bs_rel = bn->GetBS_Rel();
|
|
|
|
vector<int> unique_id_list;
|
|
for(int i = 1;i <= bs_rel->GetNoTuples();i++){
|
|
Tuple* bs_tuple = bs_rel->GetTuple(i, false);
|
|
Point* bs_loc = (Point*)bs_tuple->GetAttribute(BusNetwork::BS_GEO);
|
|
// cout<<*bs_loc<<endl;
|
|
|
|
vector<int> tid_list;
|
|
DFTraverseBMS2(rtree, rtree->RootRecordId(), build_rel, *bs_loc,
|
|
tid_list, NEARBUSSTOP);
|
|
|
|
for(unsigned int j = 0;j < tid_list.size();j++){
|
|
unique_id_list.push_back(tid_list[j]);
|
|
}
|
|
|
|
bs_tuple->DeleteIfAllowed();
|
|
}
|
|
|
|
// cout<<unique_id_list.size()<<endl;
|
|
|
|
sort(unique_id_list.begin(), unique_id_list.end());
|
|
vector<int>::iterator it =
|
|
unique(unique_id_list.begin(), unique_id_list.end());
|
|
unique_id_list.resize( it - unique_id_list.begin() );
|
|
|
|
// cout<<unique_id_list.size()<<endl;
|
|
|
|
for(it = unique_id_list.begin(); it != unique_id_list.end();it++){
|
|
Tuple* tuple = build_rel->GetTuple(*it, false);
|
|
int Tid = *it;
|
|
int type =
|
|
((CcInt*)tuple->GetAttribute(IndoorInfra::INDOORIF_BUILD_TYPE))->GetIntval();
|
|
Rectangle<2>* reg =
|
|
(Rectangle<2>*)tuple->GetAttribute(IndoorInfra::INDOORIF_GEODATA);
|
|
|
|
// cout<<oid<<endl;
|
|
id_list.push_back(Tid);
|
|
type_list.push_back(type);
|
|
rect_list.push_back(*reg);
|
|
|
|
tuple->DeleteIfAllowed();
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
for each metro stop, find all buildings nearby
|
|
|
|
*/
|
|
void TM_Join::NearMetroStopBuilding(MetroNetwork* mn, Relation* build_rel,
|
|
R_Tree<2,TupleId>* rtree)
|
|
{
|
|
Relation* ms_rel = mn->GetMS_Rel();
|
|
|
|
vector<int> unique_id_list;
|
|
for(int i = 1;i <= ms_rel->GetNoTuples();i++){
|
|
Tuple* ms_tuple = ms_rel->GetTuple(i, false);
|
|
Point* ms_loc = (Point*)ms_tuple->GetAttribute(MetroNetwork::M_STOP_GEO);
|
|
// cout<<*ms_loc<<endl;
|
|
|
|
vector<int> tid_list;
|
|
DFTraverseBMS2(rtree, rtree->RootRecordId(), build_rel,
|
|
*ms_loc, tid_list, NEARMETROSTOP);
|
|
|
|
// cout<<tid_list.size()<<endl;
|
|
|
|
for(unsigned int j = 0;j < tid_list.size();j++){
|
|
unique_id_list.push_back(tid_list[j]);
|
|
}
|
|
ms_tuple->DeleteIfAllowed();
|
|
}
|
|
|
|
|
|
// cout<<unique_id_list.size()<<endl;
|
|
|
|
sort(unique_id_list.begin(), unique_id_list.end());
|
|
vector<int>::iterator it =
|
|
unique(unique_id_list.begin(), unique_id_list.end());
|
|
unique_id_list.resize( it - unique_id_list.begin() );
|
|
|
|
// cout<<unique_id_list.size()<<endl;
|
|
|
|
for(it = unique_id_list.begin(); it != unique_id_list.end();it++){
|
|
Tuple* tuple = build_rel->GetTuple(*it, false);
|
|
int Tid = *it;
|
|
int type =
|
|
((CcInt*)tuple->GetAttribute(IndoorInfra::INDOORIF_BUILD_TYPE))->GetIntval();
|
|
Rectangle<2>* reg =
|
|
(Rectangle<2>*)tuple->GetAttribute(IndoorInfra::INDOORIF_GEODATA);
|
|
|
|
// cout<<oid<<endl;
|
|
id_list.push_back(Tid);
|
|
type_list.push_back(type);
|
|
rect_list.push_back(*reg);
|
|
|
|
tuple->DeleteIfAllowed();
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
traverse the rtree to find nearby pavement areas for bus and metro stops
|
|
|
|
*/
|
|
void TM_Join::DFTraverseBMS2(R_Tree<2,TupleId>* rtree, SmiRecordId adr,
|
|
Relation* rel,
|
|
Point query_loc, vector<int>& tid_list,
|
|
double max_dist)
|
|
{
|
|
////should be consist with the one used in GeneralType.cpp/////
|
|
// const double max_dist = NEARBUSSTOP;
|
|
|
|
R_TreeNode<2,TupleId>* node = rtree->GetMyNode(adr,false,
|
|
rtree->MinEntries(0), rtree->MaxEntries(0));
|
|
for(int j = 0;j < node->EntryCount();j++){
|
|
if(node->IsLeaf()){
|
|
R_TreeLeafEntry<2,TupleId> e =
|
|
(R_TreeLeafEntry<2,TupleId>&)(*node)[j];
|
|
Tuple* dg_tuple = rel->GetTuple(e.info, false);
|
|
Rectangle<2>* reg =
|
|
(Rectangle<2>*)dg_tuple->GetAttribute(IndoorInfra::INDOORIF_GEODATA);
|
|
|
|
if(query_loc.Distance(*reg) < max_dist){
|
|
tid_list.push_back(e.info);
|
|
}
|
|
dg_tuple->DeleteIfAllowed();
|
|
}else{
|
|
R_TreeInternalEntry<2> e =
|
|
(R_TreeInternalEntry<2>&)(*node)[j];
|
|
if(query_loc.Distance(e.box) < max_dist){
|
|
DFTraverseBMS2(rtree, e.pointer, rel, query_loc,
|
|
tid_list, max_dist);
|
|
}
|
|
}
|
|
}
|
|
delete node;
|
|
}
|
|
|