11879 lines
358 KiB
C++
11879 lines
358 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
|
||
|
||
April, 2010 Jianqiu Xu
|
||
|
||
[TOC]
|
||
|
||
1 Overview
|
||
|
||
This source file essentially contains the necessary implementations for
|
||
creating the graph model for walk planning.
|
||
|
||
|
||
*/
|
||
#include "Partition.h"
|
||
#include "Triangulate.h"
|
||
#include "PaveGraph.h"
|
||
#include "GeneralType.h"
|
||
#include "Indoor.h"
|
||
#include "Algebras/Spatial/Point.h"
|
||
#include "Algebras/Spatial/SpatialAlgebra.h"
|
||
|
||
using namespace network;
|
||
using namespace std;
|
||
|
||
/*
|
||
Decompose the pavement on one side of the road into a set of subregions
|
||
|
||
*/
|
||
|
||
void SpacePartition::DecomposePave(Region* reg1, Region* reg2,
|
||
vector<Region>& result)
|
||
{
|
||
|
||
vector<Region> temp_result;
|
||
|
||
vector<Region> result1;
|
||
// int no_faces = reg1->NoComponents();
|
||
// int no_faces = reg1->Size();//faceno in halfsegment is not recomputed
|
||
int no_faces = 0;
|
||
for(int i = 0;i < reg1->Size();i++){
|
||
HalfSegment hs;
|
||
reg1->Get(i, hs);
|
||
if(hs.attr.faceno >= no_faces) no_faces = hs.attr.faceno + 1;
|
||
}
|
||
|
||
for(int i = 0;i < no_faces;i++){
|
||
Region* temp = new Region(0);
|
||
|
||
result1.push_back(*temp);
|
||
temp->DeleteIfAllowed();
|
||
result1[i].StartBulkLoad();
|
||
}
|
||
|
||
for(int index = 0;index < reg1->Size();index++){
|
||
HalfSegment temp_hs;
|
||
reg1->Get(index, temp_hs);
|
||
int face = temp_hs.attr.faceno;
|
||
if(temp_hs.attr.cycleno == 0){/////do not need the hole
|
||
result1[face] += temp_hs;
|
||
}
|
||
}
|
||
|
||
|
||
for(int i = 0;i < no_faces;i++){
|
||
result1[i].SetNoComponents(1);
|
||
result1[i].EndBulkLoad(false,false,false,false);
|
||
if(result1[i].Size() >= 6){
|
||
temp_result.push_back(result1[i]);
|
||
}
|
||
}
|
||
|
||
|
||
vector<Region> result2;
|
||
// no_faces = reg2->NoComponents();
|
||
// no_faces = reg2->Size();
|
||
|
||
no_faces = 0; /// original faceno in halfsegment is not recomputed
|
||
for(int i = 0;i < reg2->Size();i++){
|
||
HalfSegment hs;
|
||
reg2->Get(i, hs);
|
||
if(hs.attr.faceno >= no_faces) no_faces = hs.attr.faceno + 1;
|
||
}
|
||
|
||
for(int i = 0;i < no_faces;i++){
|
||
Region* temp = new Region(0);
|
||
result2.push_back(*temp);
|
||
temp->DeleteIfAllowed();
|
||
result2[i].StartBulkLoad();
|
||
}
|
||
|
||
|
||
for(int i = 0;i < reg2->Size();i++){
|
||
HalfSegment hs;
|
||
reg2->Get(i,hs);
|
||
int face = hs.attr.faceno;
|
||
if(hs.attr.cycleno == 0){/////do not need the hole
|
||
result2[face] += hs;
|
||
}
|
||
}
|
||
|
||
|
||
for(int i = 0;i < no_faces;i++){
|
||
result2[i].SetNoComponents(1);
|
||
result2[i].EndBulkLoad(false,false,false,false);
|
||
if(result2[i].Size() >= 6) {
|
||
temp_result.push_back(result2[i]);
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
//////////////////////////////////////////////////////////
|
||
|
||
|
||
for(unsigned int i = 0;i < temp_result.size();i++){
|
||
|
||
Line* line = new Line(0);
|
||
temp_result[i].Boundary(line);
|
||
SimpleLine* sline = new SimpleLine(0);
|
||
sline->fromLine(*line);
|
||
|
||
vector<MyHalfSegment> mhs;
|
||
ReorderLine(sline, mhs);
|
||
|
||
sline->DeleteIfAllowed();
|
||
line->DeleteIfAllowed();
|
||
vector<Point> ps;
|
||
|
||
for(unsigned int j = 0;j < mhs.size();j++){
|
||
Point p = mhs[j].from;
|
||
// cout<<"before "<<setprecision(10)<<p;
|
||
// Modify_Point(p);
|
||
ps.push_back(p);
|
||
// cout<<"after "<<setprecision(10)<<p<<endl;
|
||
}
|
||
|
||
|
||
//////////////////////////////////
|
||
vector<Point> newps;
|
||
const double delta_dist = 0.1;
|
||
for(unsigned int i = 0;i < ps.size();i++){
|
||
if(i == 0){
|
||
newps.push_back(ps[i]);
|
||
continue;
|
||
}
|
||
if(i < ps.size() - 1){
|
||
Point last_p = ps[i - 1];
|
||
if(last_p.Distance(ps[i]) > delta_dist){
|
||
newps.push_back(ps[i]);
|
||
continue;
|
||
}
|
||
}
|
||
if(i == ps.size() - 1){
|
||
Point first_p = ps[0];
|
||
if(first_p.Distance(ps[i]) > delta_dist){
|
||
newps.push_back(ps[i]);
|
||
continue;
|
||
}
|
||
}
|
||
}
|
||
|
||
///////////////////////////////////
|
||
vector<Region> regs;
|
||
// ComputeRegion(ps, regs);
|
||
ComputeRegion(newps, regs);
|
||
if(!regs.empty()){
|
||
result.push_back(regs[0]);
|
||
}
|
||
//////////////////////////////////////////////////////
|
||
|
||
}
|
||
///////////////////////////////////////////////////////////
|
||
}
|
||
|
||
/*
|
||
get the closest point in hs to p, and return it in cp
|
||
it also returns the distance between hs and p
|
||
|
||
*/
|
||
double SpacePartition::GetClosestPoint(HalfSegment& hs, Point& p, Point& cp)
|
||
{
|
||
|
||
assert( p.IsDefined() );
|
||
Coord xl = hs.GetLeftPoint().GetX(),
|
||
yl = hs.GetLeftPoint().GetY(),
|
||
xr = hs.GetRightPoint().GetX(),
|
||
yr = hs.GetRightPoint().GetY(),
|
||
X = p.GetX(),
|
||
Y = p.GetY();
|
||
|
||
double result, auxresult;
|
||
|
||
if( xl == xr || yl == yr ){
|
||
if( xl == xr){ //hs is vertical
|
||
if( (yl <= Y && Y <= yr) || (yr <= Y && Y <= yl) ){
|
||
result = fabs( X - xl );
|
||
cp.Set(xl, Y); //store the closest point
|
||
}
|
||
else{
|
||
result = p.Distance(hs.GetLeftPoint());
|
||
auxresult = p.Distance(hs.GetRightPoint());
|
||
if( result > auxresult ){
|
||
result = auxresult;
|
||
cp = hs.GetRightPoint(); //store the closest point
|
||
}else{
|
||
cp = hs.GetLeftPoint(); //store the closest point
|
||
}
|
||
}
|
||
}else{ //hs is horizontal line: (yl==yr)
|
||
if( xl <= X && X <= xr ){
|
||
result = fabs( Y - yl );
|
||
cp.Set(X,yl);//store the closest point
|
||
}else{
|
||
result = p.Distance(hs.GetLeftPoint());
|
||
auxresult = p.Distance(hs.GetRightPoint());
|
||
if( result > auxresult ){
|
||
result = auxresult;
|
||
cp = hs.GetRightPoint();//store the closest point
|
||
}else{
|
||
cp = hs.GetLeftPoint();//store the closest point
|
||
}
|
||
}
|
||
}
|
||
}else
|
||
{
|
||
double k = (yr - yl) / (xr - xl),
|
||
a = yl - k * xl,
|
||
xx = (k * (Y - a) + X) / (k * k + 1),
|
||
yy = k * xx + a;
|
||
Coord XX = xx,
|
||
YY = yy;
|
||
Point PP( true, XX, YY );
|
||
if( xl <= XX && XX <= xr ){
|
||
result = p.Distance( PP );
|
||
cp = PP; //store the closest point
|
||
}
|
||
else
|
||
{
|
||
result = p.Distance( hs.GetLeftPoint() );
|
||
auxresult = p.Distance( hs.GetRightPoint());
|
||
if( result > auxresult ){
|
||
result = auxresult;
|
||
cp = hs.GetRightPoint();
|
||
}else{
|
||
cp = hs.GetLeftPoint();
|
||
}
|
||
}
|
||
}
|
||
return result;
|
||
|
||
}
|
||
|
||
|
||
double SpacePartition::GetClosestPoint_New(HalfSegment& hs, Point& p, Point& cp)
|
||
{
|
||
|
||
assert( p.IsDefined() );
|
||
Coord xl = hs.GetLeftPoint().GetX(),
|
||
yl = hs.GetLeftPoint().GetY(),
|
||
xr = hs.GetRightPoint().GetX(),
|
||
yr = hs.GetRightPoint().GetY(),
|
||
X = p.GetX(),
|
||
Y = p.GetY();
|
||
|
||
double result, auxresult;
|
||
|
||
if( AlmostEqual(xl,xr) || AlmostEqual(yl ,yr) ){
|
||
if( AlmostEqual(xl, xr)){ //hs is vertical
|
||
if(((yl < Y || AlmostEqual(yl,Y)) && (Y < yr || AlmostEqual(Y, yr))) ||
|
||
((yr < Y || AlmostEqual(yr,Y)) && (Y < yl || AlmostEqual(Y, yl) ))){
|
||
result = fabs( X - xl );
|
||
cp.Set(xl, Y); //store the closest point
|
||
}
|
||
else{
|
||
result = p.Distance(hs.GetLeftPoint());
|
||
auxresult = p.Distance(hs.GetRightPoint());
|
||
if( result > auxresult ){
|
||
result = auxresult;
|
||
cp = hs.GetRightPoint(); //store the closest point
|
||
}else{
|
||
cp = hs.GetLeftPoint(); //store the closest point
|
||
}
|
||
}
|
||
}else{ //hs is horizontal line: (yl==yr)
|
||
// if( xl <= X && X <= xr ){
|
||
if( (xl < X || AlmostEqual(xl,X)) &&
|
||
(X < xr || AlmostEqual(X, xr) ) ){
|
||
result = fabs( Y - yl );
|
||
cp.Set(X,yl);//store the closest point
|
||
}else{
|
||
result = p.Distance(hs.GetLeftPoint());
|
||
auxresult = p.Distance(hs.GetRightPoint());
|
||
if( result > auxresult ){
|
||
result = auxresult;
|
||
cp = hs.GetRightPoint();//store the closest point
|
||
}else{
|
||
cp = hs.GetLeftPoint();//store the closest point
|
||
}
|
||
}
|
||
}
|
||
}else{
|
||
double k = (yr - yl) / (xr - xl),
|
||
a = yl - k * xl,
|
||
xx = (k * (Y - a) + X) / (k * k + 1),
|
||
yy = k * xx + a;
|
||
Coord XX = xx,
|
||
YY = yy;
|
||
Point PP( true, XX, YY );
|
||
// if( xl <= XX && XX <= xr ){
|
||
if( (xl < XX || AlmostEqual(xl, XX)) &&
|
||
(XX < xr || AlmostEqual(XX, xr) ) ){
|
||
// cout<<setprecision(16)<<XX<<" "<<YY<<endl;
|
||
result = p.Distance( PP );
|
||
cp = PP; //store the closest point
|
||
}
|
||
else
|
||
{
|
||
result = p.Distance( hs.GetLeftPoint() );
|
||
auxresult = p.Distance( hs.GetRightPoint());
|
||
if( result > auxresult ){
|
||
result = auxresult;
|
||
cp = hs.GetRightPoint();
|
||
}else{
|
||
cp = hs.GetLeftPoint();
|
||
}
|
||
}
|
||
}
|
||
return result;
|
||
|
||
}
|
||
|
||
|
||
/*
|
||
Decompose the pavement of one road into a set of subregions
|
||
|
||
*/
|
||
|
||
void SpacePartition::DecomposePavement1(Network* n, Relation* rel,
|
||
int attr_pos1, int attr_pos2, int attr_pos3)
|
||
{
|
||
vector<Region> paves1;
|
||
vector<Region> paves2;
|
||
vector<bool> route_flag;
|
||
for(int i = 1;i <= rel->GetNoTuples();i++){
|
||
|
||
Tuple* pave_tuple = rel->GetTuple(i, false);
|
||
Region* reg1 = (Region*)pave_tuple->GetAttribute(attr_pos2);
|
||
Region* reg2 = (Region*)pave_tuple->GetAttribute(attr_pos3);
|
||
paves1.push_back(*reg1);
|
||
paves2.push_back(*reg2);
|
||
pave_tuple->DeleteIfAllowed();
|
||
route_flag.push_back(false);
|
||
}
|
||
|
||
|
||
vector<Region> pavements1;
|
||
vector<Region> pavements2;
|
||
|
||
int oid = 1;//object identifier
|
||
|
||
assert(paves1.size() == paves2.size());
|
||
for(int i = 1;i <= rel->GetNoTuples();i++){
|
||
|
||
Tuple* pave_tuple = rel->GetTuple(i, false);
|
||
int rid = ((CcInt*)pave_tuple->GetAttribute(attr_pos1))->GetIntval();
|
||
// cout<<"rid "<<rid<<endl;
|
||
|
||
/* if(!(rid == 3116)){
|
||
pave_tuple->DeleteIfAllowed();
|
||
continue;
|
||
}*/
|
||
// cout<<"pave1 "<<paves1[rid - 1].NoComponents()<<endl;
|
||
// cout<<"pave2 "<<paves2[rid - 1].NoComponents()<<endl;
|
||
|
||
DecomposePave(&paves1[rid - 1], &paves2[rid - 1], pavements1);
|
||
for(unsigned int j = 0;j < pavements1.size();j++){
|
||
junid1.push_back(oid);
|
||
junid2.push_back(rid);
|
||
outer_regions1.push_back(Region(pavements1[j],false));
|
||
oid++;
|
||
}
|
||
pave_tuple->DeleteIfAllowed();
|
||
pavements1.clear();
|
||
}
|
||
////////////check inside above//////////////////////////////
|
||
}
|
||
|
||
|
||
/*
|
||
Decompose the zebra crossings into a set of subregions
|
||
|
||
*/
|
||
|
||
void SpacePartition::DecomposePavement2(int start_oid, Relation* rel,
|
||
int attr_pos1, int attr_pos2)
|
||
{
|
||
// cout<<"start_oid "<<start_oid<<endl;
|
||
int oid = start_oid + 1;//object identifier
|
||
vector<Region> zc_regs;
|
||
for(int i = 1;i <= rel->GetNoTuples();i++){
|
||
|
||
Tuple* zc_tuple = rel->GetTuple(i, false);
|
||
int rid = ((CcInt*)zc_tuple->GetAttribute(attr_pos1))->GetIntval();
|
||
Region* zc_reg = (Region*)zc_tuple->GetAttribute(attr_pos2);
|
||
Region* temp = new Region(0);
|
||
// cout<<"rid "<<rid<<endl;
|
||
DecomposePave(zc_reg, temp, zc_regs);
|
||
// assert(zc_regs.size() > 0);
|
||
// cout<<zc_regs.size()<<endl;
|
||
/* for(unsigned int j = 0;j < zc_regs.size();j++){
|
||
junid1.push_back(oid);
|
||
junid2.push_back(rid);
|
||
outer_regions1.push_back(zc_regs[j]);
|
||
oid++;
|
||
}*/
|
||
|
||
//filter two zebra crossings are too close to each other
|
||
const double delta_dist = 4.0;
|
||
vector<Region> zc_regs_filter;
|
||
for(unsigned int j1 = 0;j1 < zc_regs.size();j1++){
|
||
unsigned int j2 = 0;
|
||
for(;j2 < zc_regs_filter.size();j2++){
|
||
if(zc_regs_filter[j2].Distance(zc_regs[j1]) < delta_dist)
|
||
break;
|
||
}
|
||
if(j2 == zc_regs_filter.size())
|
||
zc_regs_filter.push_back(zc_regs[j2]);
|
||
// zc_regs_filter.push_back(zc_regs[j1]);
|
||
}
|
||
|
||
for(unsigned int j = 0;j < zc_regs_filter.size();j++){
|
||
junid1.push_back(oid);
|
||
junid2.push_back(rid);
|
||
outer_regions1.push_back(Region(zc_regs_filter[j],false));
|
||
oid++;
|
||
}
|
||
|
||
temp->DeleteIfAllowed();
|
||
zc_regs.clear();
|
||
zc_tuple->DeleteIfAllowed();
|
||
}
|
||
}
|
||
|
||
/*
|
||
get the commone line between two pavements (node in the graph model)
|
||
|
||
*/
|
||
void SpacePartition::GetPavementEdge1(Network* n, Relation* rel,
|
||
BTree* btree_pave,
|
||
int attr1, int attr2, int attr3)
|
||
{
|
||
|
||
Relation* juns = n->GetJunctions();
|
||
|
||
vector<Region_Oid> regs1;
|
||
vector<Region_Oid> regs2;
|
||
|
||
for(int i = 1;i <= n->GetNoJunctions();i++){
|
||
|
||
Tuple* jun_tuple = juns->GetTuple(i, false);
|
||
CcInt* rid1 = (CcInt*)jun_tuple->GetAttribute(JUNCTION_ROUTE1_ID);
|
||
CcInt* rid2 = (CcInt*)jun_tuple->GetAttribute(JUNCTION_ROUTE2_ID);
|
||
int id1 = rid1->GetIntval();
|
||
int id2 = rid2->GetIntval();
|
||
|
||
/* if(!(id1 == 3 && id2 == 6)){
|
||
jun_tuple->DeleteIfAllowed();
|
||
continue;
|
||
}*/
|
||
|
||
// cout<<"rid1 "<<id1<<" rid2 "<<id2<<endl;
|
||
|
||
BTreeIterator* btreeiter1 = btree_pave->ExactMatch(rid1);
|
||
while(btreeiter1->Next()){
|
||
|
||
Tuple* pave_tup = rel->GetTuple(btreeiter1->GetId(), false);
|
||
int oid = ((CcInt*)pave_tup->GetAttribute(attr1))->GetIntval();
|
||
Region* pave = (Region*)pave_tup->GetAttribute(attr3);
|
||
Region_Oid* ro = new Region_Oid(oid, *pave);
|
||
regs1.push_back(*ro);
|
||
delete ro;
|
||
pave_tup->DeleteIfAllowed();
|
||
}
|
||
delete btreeiter1;
|
||
|
||
BTreeIterator* btreeiter2 = btree_pave->ExactMatch(rid2);
|
||
while(btreeiter2->Next()){
|
||
|
||
Tuple* pave_tup = rel->GetTuple(btreeiter2->GetId(), false);
|
||
int oid = ((CcInt*)pave_tup->GetAttribute(attr1))->GetIntval();
|
||
Region* pave = (Region*)pave_tup->GetAttribute(attr3);
|
||
Region_Oid* ro = new Region_Oid(oid, *pave);
|
||
regs2.push_back(*ro);
|
||
delete ro;
|
||
pave_tup->DeleteIfAllowed();
|
||
}
|
||
delete btreeiter2;
|
||
// cout<<regs1.size()<<" "<<regs2.size()<<endl;
|
||
|
||
GetCommPave1(regs1, regs2, id1, id2);
|
||
|
||
regs1.clear();
|
||
regs2.clear();
|
||
jun_tuple->DeleteIfAllowed();
|
||
|
||
}
|
||
|
||
juns->Delete();
|
||
|
||
}
|
||
|
||
|
||
/*
|
||
get the commone line between zc and pavement (node in the graph model)
|
||
|
||
*/
|
||
void SpacePartition::GetPavementEdge2(Relation* rel1,
|
||
Relation* rel2, BTree* btree_pave,
|
||
int attr1, int attr2, int attr3)
|
||
{
|
||
vector<Region_Oid> reg_pave;
|
||
|
||
for(int i = 1;i <= rel1->GetNoTuples();i++){
|
||
|
||
Tuple* zc_tuple = rel1->GetTuple(i, false);
|
||
CcInt* zc_oid = (CcInt*)zc_tuple->GetAttribute(attr1);
|
||
CcInt* rid = (CcInt*)zc_tuple->GetAttribute(attr2);
|
||
Region* reg = (Region*)zc_tuple->GetAttribute(attr3);
|
||
|
||
|
||
/* if(!(rid->GetIntval() == 476)){
|
||
zc_tuple->DeleteIfAllowed();
|
||
continue;
|
||
}*/
|
||
|
||
// cout<<"oid "<<zc_oid->GetIntval()<<"rid "<<rid->GetIntval()<<endl;
|
||
|
||
BTreeIterator* btreeiter = btree_pave->ExactMatch(rid);
|
||
while(btreeiter->Next()){
|
||
Tuple* pave_tuple = rel2->GetTuple(btreeiter->GetId(), false);
|
||
int oid = ((CcInt*)pave_tuple->GetAttribute(attr1))->GetIntval();
|
||
Region* pave = (Region*)pave_tuple->GetAttribute(attr3);
|
||
Region_Oid* ro = new Region_Oid(oid, *pave);
|
||
reg_pave.push_back(*ro);
|
||
delete ro;
|
||
pave_tuple->DeleteIfAllowed();
|
||
}
|
||
delete btreeiter;
|
||
|
||
|
||
GetCommPave2(reg, zc_oid->GetIntval(),reg_pave);
|
||
|
||
|
||
reg_pave.clear();
|
||
zc_tuple->DeleteIfAllowed();
|
||
}
|
||
|
||
}
|
||
|
||
/*
|
||
detect whether two pavements intersect, (pave1, pave2)
|
||
|
||
*/
|
||
void SpacePartition::GetCommPave1(vector<Region_Oid>& pave1,
|
||
vector<Region_Oid>& pave2, int rid1,
|
||
int rid2)
|
||
{
|
||
// const double delta_dist = 0.01;
|
||
const double delta_dist = 0.00001;
|
||
for(unsigned int i = 0;i < pave1.size();i++){
|
||
for(unsigned int j = 0;j < pave2.size();j++){
|
||
|
||
if(pave1[i].reg.Inside(pave2[j].reg)){
|
||
continue;
|
||
}
|
||
if(pave2[j].reg.Inside(pave1[i].reg)){
|
||
continue;
|
||
}
|
||
//////////////////////////////////////////////////////////////
|
||
if(MyRegIntersects(&pave1[i].reg, &pave2[j].reg)){
|
||
|
||
vector<Point> common_ps;
|
||
for(int index1 = 0; index1 < pave1[i].reg.Size();index1++){
|
||
HalfSegment hs1;
|
||
pave1[i].reg.Get(index1, hs1);
|
||
if(!hs1.IsLeftDomPoint())continue;
|
||
for(int index2 = 0;index2 < pave2[j].reg.Size();index2++){
|
||
HalfSegment hs2;
|
||
pave2[j].reg.Get(index2, hs2);
|
||
if(!hs2.IsLeftDomPoint())continue;
|
||
Point cp;
|
||
if(hs1.Intersection(hs2,cp)){
|
||
unsigned int index = 0;
|
||
for(;index < common_ps.size();index++){
|
||
if(cp.Distance(common_ps[index]) < delta_dist)
|
||
break;
|
||
}
|
||
if(index == common_ps.size())
|
||
common_ps.push_back(cp);
|
||
}
|
||
}
|
||
}
|
||
// cout<<"oid1 "<<pave1[i].oid<<" oid2 "<<pave2[j].oid<<endl;
|
||
assert(common_ps.size() > 1);
|
||
if(common_ps.size() > 1){
|
||
junid1.push_back(pave1[i].oid);
|
||
junid2.push_back(pave2[j].oid);
|
||
Line* l = new Line(0);
|
||
pave_line1.push_back(*l);
|
||
l->DeleteIfAllowed();
|
||
}
|
||
}
|
||
/////////////////////////////////////////////////////////////
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
/*
|
||
detect whether the zebra crossing intersects the pavement
|
||
|
||
*/
|
||
void SpacePartition::GetCommPave2(Region* reg, int oid,
|
||
vector<Region_Oid>& pave2)
|
||
{
|
||
for(unsigned int i = 0;i < pave2.size();i++){
|
||
if(MyRegIntersects(reg, &pave2[i].reg)){
|
||
Line* boundary = new Line(0);
|
||
pave2[i].reg.Boundary(boundary);
|
||
Line* result = new Line(0);
|
||
boundary->Intersection(*reg, *result);
|
||
if(result->Size() == 0){
|
||
cout<<"zc oid1 "<<oid<<endl;
|
||
cout<<"pave oid2 "<<pave2[i].oid<<endl;
|
||
}
|
||
assert(result->Size() > 0);
|
||
if(result->Size() > 0){
|
||
junid1.push_back(oid);
|
||
junid2.push_back(pave2[i].oid);
|
||
Line* l = new Line(0);
|
||
pave_line1.push_back(*l);
|
||
l->DeleteIfAllowed();
|
||
}
|
||
result->DeleteIfAllowed();
|
||
boundary->DeleteIfAllowed();
|
||
}
|
||
}
|
||
}
|
||
|
||
/*
|
||
doing triangulation for a polygon with and without hole
|
||
|
||
*/
|
||
|
||
CompTriangle::CompTriangle()
|
||
{
|
||
count = 0;
|
||
path = NULL;
|
||
resulttype = NULL;
|
||
}
|
||
CompTriangle::CompTriangle(Region* r):reg(r),count(0),
|
||
path(NULL),resulttype(NULL)
|
||
{
|
||
|
||
}
|
||
|
||
CompTriangle:: ~CompTriangle()
|
||
{
|
||
if(path != NULL) path->DeleteIfAllowed();
|
||
if(resulttype != NULL) delete resulttype;
|
||
}
|
||
|
||
/*
|
||
get the clockwise value
|
||
|
||
*/
|
||
bool CompTriangle::GetClockwise(const vector<Point>& contour)
|
||
{
|
||
float obj_area = Area(contour);
|
||
if(0.0f < obj_area) return false;
|
||
else return true;
|
||
}
|
||
|
||
/*
|
||
Compute the area of a polygon. It is also used to compute the clockwise
|
||
value of a list of points.
|
||
if area > 0.0f, counter-clockwise order
|
||
else clockwise order
|
||
|
||
*/
|
||
|
||
float CompTriangle::Area(const vector<Point>& contour)
|
||
{
|
||
int n = contour.size();
|
||
|
||
float A=0.0f;
|
||
|
||
for(int p=n-1,q=0; q<n; p=q++)
|
||
{
|
||
A+=
|
||
contour[p].GetX()*contour[q].GetY() - contour[q].GetX()*contour[p].GetY();
|
||
}
|
||
return A*0.5f;
|
||
|
||
}
|
||
|
||
/*
|
||
InsideTriangle decides if a point P is Inside of the triangle
|
||
defined by A, B, C.
|
||
If P equals to A, B or C, it returns true
|
||
|
||
*/
|
||
inline bool CompTriangle::InsideTriangle(float Ax, float Ay,
|
||
float Bx, float By,
|
||
float Cx, float Cy,
|
||
float Px, float Py)
|
||
|
||
{
|
||
float ax, ay, bx, by, cx, cy, apx, apy, bpx, bpy, cpx, cpy;
|
||
float cCROSSap, bCROSScp, aCROSSbp;
|
||
|
||
ax = Cx - Bx; ay = Cy - By;
|
||
bx = Ax - Cx; by = Ay - Cy;
|
||
cx = Bx - Ax; cy = By - Ay;
|
||
apx= Px - Ax; apy= Py - Ay;
|
||
bpx= Px - Bx; bpy= Py - By;
|
||
cpx= Px - Cx; cpy= Py - Cy;
|
||
|
||
aCROSSbp = ax*bpy - ay*bpx;
|
||
cCROSSap = cx*apy - cy*apx;
|
||
bCROSScp = bx*cpy - by*cpx;
|
||
|
||
return ((aCROSSbp >= 0.0f) && (bCROSScp >= 0.0f) && (cCROSSap >= 0.0f));
|
||
};
|
||
|
||
|
||
bool CompTriangle::Snip(const vector<Point>& contour,int u,int v,int w,
|
||
int n,int *V)
|
||
{
|
||
int p;
|
||
float Ax, Ay, Bx, By, Cx, Cy, Px, Py;
|
||
|
||
Ax = contour[V[u]].GetX();
|
||
Ay = contour[V[u]].GetY();
|
||
|
||
Bx = contour[V[v]].GetX();
|
||
By = contour[V[v]].GetY();
|
||
|
||
Cx = contour[V[w]].GetX();
|
||
Cy = contour[V[w]].GetY();
|
||
|
||
if ( EPSILON > (((Bx-Ax)*(Cy-Ay)) - ((By-Ay)*(Cx-Ax))) ) return false;
|
||
|
||
for (p=0;p<n;p++)
|
||
{
|
||
if( (p == u) || (p == v) || (p == w) ) continue;
|
||
Px = contour[V[p]].GetX();
|
||
Py = contour[V[p]].GetY();
|
||
if (InsideTriangle(Ax,Ay,Bx,By,Cx,Cy,Px,Py)) return false;
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
/*
|
||
decompose a polygon into a set of triangles
|
||
Using the implementation by John W.Ratcliff
|
||
|
||
*/
|
||
|
||
bool CompTriangle::GetTriangles(const vector<Point>& contour,
|
||
vector<Point>& result)
|
||
{
|
||
/* allocate and initialize list of Vertices in polygon */
|
||
|
||
int n = contour.size();
|
||
if ( n < 3 ) return false;
|
||
|
||
int *V = new int[n];
|
||
|
||
/* we want a counter-clockwise polygon in V */
|
||
// cout<<"Area "<<Area(contour)<<endl;
|
||
|
||
if ( 0.0f < Area(contour) )
|
||
for (int v=0; v<n; v++) V[v] = v;
|
||
else
|
||
for(int v=0; v<n; v++) V[v] = (n-1)-v;
|
||
|
||
int nv = n;
|
||
|
||
/* remove nv-2 Vertices, creating 1 triangle every time */
|
||
int count = 2*nv; /* error detection */
|
||
|
||
for(int m=0, v=nv-1; nv>2; )
|
||
{
|
||
/* if we loop, it is probably a non-simple polygon */
|
||
if (0 >= (count--))
|
||
{
|
||
//** Triangulate: ERROR - probable bad polygon!
|
||
return false;
|
||
}
|
||
|
||
/* three consecutive vertices in current polygon, <u,v,w> */
|
||
int u = v ; if (nv <= u) u = 0; /* previous */
|
||
v = u+1; if (nv <= v) v = 0; /* new v */
|
||
int w = v+1; if (nv <= w) w = 0; /* next */
|
||
|
||
if ( Snip(contour,u,v,w,nv,V) )
|
||
{
|
||
int a,b,c,s,t;
|
||
|
||
/* true names of the vertices */
|
||
a = V[u]; b = V[v]; c = V[w];
|
||
|
||
/* output Triangle */
|
||
result.push_back( contour[a] );
|
||
result.push_back( contour[b] );
|
||
result.push_back( contour[c] );
|
||
|
||
m++;
|
||
|
||
/* remove v from remaining polygon */
|
||
for(s=v,t=v+1;t<nv;s++,t++) V[s] = V[t]; nv--;
|
||
|
||
/* resest error detection counter */
|
||
count = 2*nv;
|
||
}
|
||
}
|
||
|
||
delete []V;
|
||
|
||
return true;
|
||
}
|
||
|
||
/*
|
||
Decompose the region into a set of triangles
|
||
it does not support polgyon with holes
|
||
|
||
*/
|
||
void CompTriangle::Triangulation()
|
||
{
|
||
if(reg->NoComponents() == 0){
|
||
cout<<"this is not a region"<<endl;
|
||
return;
|
||
}
|
||
if(reg->NoComponents() > 1){
|
||
cout<<"can't handle region with more than one faces"<<endl;
|
||
return;
|
||
}
|
||
|
||
vector<int> no_cycles(reg->Size(), -1);
|
||
for(int i = 0;i < reg->Size();i++){
|
||
HalfSegment hs;
|
||
reg->Get(i, hs);
|
||
if(!hs.IsLeftDomPoint())continue;
|
||
int cycleno = hs.attr.cycleno;
|
||
no_cycles[cycleno] = cycleno;
|
||
}
|
||
|
||
unsigned int no_cyc = 0;
|
||
for(unsigned int i = 0;i < no_cycles.size();i++){
|
||
if(no_cycles[i] != -1) no_cyc++;
|
||
else
|
||
break;
|
||
}
|
||
|
||
if(no_cyc > 1){
|
||
cout<<"polgyon has hole inside, please call NewTriangulation()"<<endl;
|
||
return;
|
||
}
|
||
|
||
|
||
Line* boundary = new Line(0);
|
||
reg->Boundary(boundary);
|
||
// cout<<"boundary "<<*boundary<<endl;
|
||
SimpleLine* sboundary = new SimpleLine(0);
|
||
sboundary->fromLine(*boundary);
|
||
// cout<<"sboundary size "<<sboundary->Size()<<endl;
|
||
vector<MyHalfSegment> mhs;
|
||
//get all the points of the region
|
||
SpacePartition* sp = new SpacePartition();
|
||
if(sboundary->Size() > 0)
|
||
sp->ReorderLine(sboundary, mhs);
|
||
else{
|
||
cout<<"can't covert the boundary to a sline"<<endl;
|
||
boundary->DeleteIfAllowed();
|
||
sboundary->DeleteIfAllowed();
|
||
return;
|
||
}
|
||
boundary->DeleteIfAllowed();
|
||
sboundary->DeleteIfAllowed();
|
||
|
||
/* for(unsigned int i = 0;i < mhs.size();i++)
|
||
mhs[i].Print();*/
|
||
|
||
vector<Point> ps;
|
||
for(unsigned int i = 0;i < mhs.size();i++)
|
||
ps.push_back(mhs[i].from);
|
||
|
||
|
||
/* for(unsigned int i = 0;i < ps.size();i++){
|
||
printf("%.8f %.8f\n",ps[i].GetX(), ps[i].GetY());
|
||
}*/
|
||
|
||
vector<Point> result;
|
||
assert(GetTriangles(ps, result));
|
||
|
||
unsigned int tcount = result.size()/3;
|
||
|
||
for (unsigned int i=0; i<tcount; i++)
|
||
{
|
||
Point p1 = result[i*3+0];
|
||
Point p2 = result[i*3+1];
|
||
Point p3 = result[i*3+2];
|
||
/* printf("Triangle %d => (%.5f,%.5f) (%.5f,%.5f) (%.5f,%.5f)\n", i + 1,
|
||
p1.GetX(), p1.GetY(),
|
||
p2.GetX(), p2.GetY(),
|
||
p3.GetX(), p3.GetY());*/
|
||
|
||
vector<Point> reg_ps;
|
||
|
||
reg_ps.push_back(p1);
|
||
reg_ps.push_back(p2);
|
||
reg_ps.push_back(p3);
|
||
|
||
sp->ComputeRegion(reg_ps, triangles);
|
||
}
|
||
|
||
delete sp;
|
||
|
||
}
|
||
|
||
bool CompTriangle::IsConvex(vector<Point> ps)
|
||
{
|
||
int n = ps.size();
|
||
int i,j,k;
|
||
int flag = 0;
|
||
double z;
|
||
|
||
if (ps.size() < 3){
|
||
cout<<"less than 3 points, it is not a region"<<endl;
|
||
return false;
|
||
}
|
||
for (i=0;i<n;i++) {
|
||
j = (i + 1) % n;
|
||
k = (i + 2) % n;
|
||
// z = (p[j].x - p[i].x) * (p[k].y - p[j].y);
|
||
// z -= (p[j].y - p[i].y) * (p[k].x - p[j].x);
|
||
z = (ps[j].GetX() - ps[i].GetX()) * (ps[k].GetY() - ps[j].GetY());
|
||
z -= (ps[j].GetY() - ps[i].GetY()) * (ps[k].GetX() - ps[j].GetX());
|
||
|
||
if (z < 0)
|
||
flag |= 1;
|
||
else if (z > 0)
|
||
flag |= 2;
|
||
if (flag == 3)
|
||
return false;
|
||
}
|
||
if (flag != 0)
|
||
return true;
|
||
else
|
||
return false;
|
||
|
||
}
|
||
/*
|
||
if the polygon is convex, returns true, otherwise (concave) returns false
|
||
|
||
*/
|
||
bool CompTriangle::PolygonConvex()
|
||
{
|
||
if(reg->NoComponents() == 0){
|
||
cout<<"error: this is not a region"<<endl;
|
||
return false;
|
||
}
|
||
if(reg->NoComponents() > 1 || NoOfCycles() > 1){
|
||
cout<<"error: there is hole inside or several subregions"<<endl;
|
||
return false;
|
||
}
|
||
|
||
Line* boundary = new Line(0);
|
||
reg->Boundary(boundary);
|
||
// cout<<"boundary "<<*boundary<<endl;
|
||
SimpleLine* sboundary = new SimpleLine(0);
|
||
sboundary->fromLine(*boundary);
|
||
// cout<<"sboundary size "<<sboundary->Size()<<endl;
|
||
vector<MyHalfSegment> mhs;
|
||
//get all the points of the region
|
||
SpacePartition* sp = new SpacePartition();
|
||
if(sboundary->Size() > 0)
|
||
sp->ReorderLine(sboundary, mhs);
|
||
else{
|
||
cout<<"can't covert the boundary to a sline"<<endl;
|
||
boundary->DeleteIfAllowed();
|
||
sboundary->DeleteIfAllowed();
|
||
delete sp;
|
||
return false;
|
||
}
|
||
boundary->DeleteIfAllowed();
|
||
sboundary->DeleteIfAllowed();
|
||
delete sp;
|
||
|
||
/* for(unsigned int i = 0;i < mhs.size();i++)
|
||
mhs[i].Print();*/
|
||
|
||
vector<Point> ps;
|
||
for(unsigned int i = 0;i < mhs.size();i++)
|
||
ps.push_back(mhs[i].from);
|
||
/////////////// convex/concave /////////////////////////////
|
||
/* int n = ps.size();
|
||
int i,j,k;
|
||
int flag = 0;
|
||
double z;
|
||
|
||
if (ps.size() < 3){
|
||
cout<<"less than 3 points, it is not a region"<<endl;
|
||
return false;
|
||
}
|
||
for (i=0;i<n;i++) {
|
||
j = (i + 1) % n;
|
||
k = (i + 2) % n;
|
||
// z = (p[j].x - p[i].x) * (p[k].y - p[j].y);
|
||
// z -= (p[j].y - p[i].y) * (p[k].x - p[j].x);
|
||
z = (ps[j].GetX() - ps[i].GetX()) * (ps[k].GetY() - ps[j].GetY());
|
||
z -= (ps[j].GetY() - ps[i].GetY()) * (ps[k].GetX() - ps[j].GetX());
|
||
|
||
if (z < 0)
|
||
flag |= 1;
|
||
else if (z > 0)
|
||
flag |= 2;
|
||
if (flag == 3)
|
||
return false;
|
||
}
|
||
if (flag != 0)
|
||
return true;
|
||
else
|
||
return false;*/
|
||
return IsConvex(ps);
|
||
/////////////////////////////////////////////////////////////////////////
|
||
|
||
}
|
||
|
||
bool CompTriangle::PolygonConvex2(int& error)
|
||
{
|
||
if(reg->NoComponents() == 0){
|
||
cout<<"error: this is not a region"<<endl;
|
||
error = 1;
|
||
return false;
|
||
}
|
||
if(reg->NoComponents() > 1 || NoOfCycles() > 1){
|
||
cout<<"error: there is hole inside or several subregions"<<endl;
|
||
error = 2;
|
||
return false;
|
||
}
|
||
|
||
Line* boundary = new Line(0);
|
||
reg->Boundary(boundary);
|
||
// cout<<"boundary "<<*boundary<<endl;
|
||
SimpleLine* sboundary = new SimpleLine(0);
|
||
sboundary->fromLine(*boundary);
|
||
// cout<<"sboundary size "<<sboundary->Size()<<endl;
|
||
vector<MyHalfSegment> mhs;
|
||
//get all the points of the region
|
||
SpacePartition* sp = new SpacePartition();
|
||
if(sboundary->Size() > 0)
|
||
sp->ReorderLine(sboundary, mhs);
|
||
else{
|
||
error = 3;
|
||
cout<<"can't covert the boundary to a sline"<<endl;
|
||
boundary->DeleteIfAllowed();
|
||
sboundary->DeleteIfAllowed();
|
||
return false;
|
||
}
|
||
boundary->DeleteIfAllowed();
|
||
sboundary->DeleteIfAllowed();
|
||
|
||
/* for(unsigned int i = 0;i < mhs.size();i++)
|
||
mhs[i].Print();*/
|
||
|
||
vector<Point> ps;
|
||
for(unsigned int i = 0;i < mhs.size();i++)
|
||
ps.push_back(mhs[i].from);
|
||
/////////////// convex/concave /////////////////////////////
|
||
error = 0;
|
||
return IsConvex(ps);
|
||
/////////////////////////////////////////////////////////////////////////
|
||
|
||
}
|
||
|
||
/*
|
||
number of vertices is larger than 100.
|
||
it is a concave polgyon with holes inside
|
||
|
||
if it is a complex region, when it needs to compute the shortest path inside.
|
||
we do not call the simple method, but build the dual graph, visual graph and
|
||
an auxiliary relation.
|
||
1:complex region 0 not complex region -1: error
|
||
|
||
*/
|
||
int CompTriangle::ComplexRegion()
|
||
{
|
||
int nocom = reg->NoComponents();
|
||
if(nocom == 0){
|
||
cout<<"error: this is not a region"<<endl;
|
||
return -1;
|
||
}
|
||
if(nocom > 1){
|
||
cout<<"error: several subregions"<<endl;
|
||
return -1;
|
||
}
|
||
|
||
if(reg->Size() < 80) return 0;
|
||
|
||
if(reg->Size() > 150) return 1;//////////complex region
|
||
|
||
vector<int> no_cycles(reg->Size(), -1);
|
||
|
||
for(int i = 0;i < reg->Size();i++){
|
||
HalfSegment hs;
|
||
reg->Get(i, hs);
|
||
if(!hs.IsLeftDomPoint())continue;
|
||
int cycleno = hs.attr.cycleno;
|
||
no_cycles[cycleno] = cycleno;
|
||
}
|
||
|
||
unsigned int no_cyc = 0;
|
||
for(unsigned int i = 0;i < no_cycles.size();i++){
|
||
if(no_cycles[i] != -1) no_cyc++;
|
||
else
|
||
break;
|
||
}
|
||
if(no_cyc < 4) return 0;
|
||
else return 1; /////////there are many holes inside
|
||
}
|
||
|
||
|
||
/*
|
||
get a sequence of triangles where the shoretest path should pass through
|
||
|
||
*/
|
||
void CompTriangle::FindAdj(unsigned int index, vector<bool>& flag,
|
||
vector<int>& adj_list)
|
||
{
|
||
vector<HalfSegment> cur_triangle;
|
||
for(int i = 0;i < triangles[index].Size();i++){
|
||
HalfSegment hs;
|
||
triangles[index].Get(i, hs);
|
||
if(!hs.IsLeftDomPoint())continue;
|
||
cur_triangle.push_back(hs);
|
||
}
|
||
assert(cur_triangle.size() == 3);
|
||
|
||
const double delta_dist = 0.00001;
|
||
for(unsigned int i = 0;i < triangles.size();i++){
|
||
if(flag[i] == true) continue;
|
||
///////////////////get the edges////////////////////////
|
||
vector<HalfSegment> triangle;
|
||
for(int j = 0;j < triangles[i].Size();j++){
|
||
HalfSegment hs;
|
||
triangles[i].Get(j, hs);
|
||
if(!hs.IsLeftDomPoint())continue;
|
||
triangle.push_back(hs);
|
||
}
|
||
assert(triangle.size() == 3);
|
||
////////////////////////////////////////////////////////////
|
||
for(unsigned int k1 = 0;k1 < cur_triangle.size();k1++){
|
||
Point p1 = cur_triangle[k1].GetLeftPoint();
|
||
Point p2 = cur_triangle[k1].GetRightPoint();
|
||
unsigned int k2 = 0;
|
||
for(;k2 < triangle.size();k2++){
|
||
Point p3 = triangle[k2].GetLeftPoint();
|
||
Point p4 = triangle[k2].GetRightPoint();
|
||
if(p1.Distance(p3) < delta_dist && p2.Distance(p4) < delta_dist){
|
||
adj_list.push_back(i);
|
||
flag[i] = true;
|
||
break;
|
||
}
|
||
if(p1.Distance(p4) < delta_dist && p2.Distance(p3) < delta_dist){
|
||
adj_list.push_back(i);
|
||
flag[i] = true;
|
||
break;
|
||
}
|
||
}
|
||
if(k2 != triangle.size())break;
|
||
}
|
||
|
||
}
|
||
|
||
}
|
||
|
||
/*
|
||
get a sequence of triangles from the start point to the end point
|
||
|
||
*/
|
||
void CompTriangle::GetChannel(Point* start, Point* end)
|
||
{
|
||
////////// find the start triangle /////////////////////////
|
||
int index1 = -1;
|
||
int index2 = -1;
|
||
for(unsigned int i = 0;i < triangles.size();i++){
|
||
if(start->Inside(triangles[i])){
|
||
index1 = i;
|
||
break;
|
||
}
|
||
}
|
||
////////// find the end triangle /////////////////////////
|
||
for(unsigned int i = 0;i < triangles.size();i++){
|
||
if(end->Inside(triangles[i])){
|
||
index2 = i;
|
||
break;
|
||
}
|
||
}
|
||
assert(index1 != -1 && index2 != -1);
|
||
cout<<"index1 "<<index1<<" index2 "<<index2<<endl;
|
||
vector<bool> triangle_flag;
|
||
for(unsigned int i = 0;i < triangles.size();i++)
|
||
triangle_flag.push_back(false);
|
||
|
||
triangle_flag[index1] = true;
|
||
|
||
////////////////shortest path algorithm///////////////////////
|
||
priority_queue<SPath_elem> path_queue;
|
||
vector<SPath_elem> expand_path;
|
||
|
||
path_queue.push(SPath_elem(-1, 0, index1, 1));
|
||
expand_path.push_back(SPath_elem(-1,0, index1, 1));
|
||
bool find = false;
|
||
SPath_elem dest;//////////destination
|
||
while(path_queue.empty() == false){
|
||
SPath_elem top = path_queue.top();
|
||
path_queue.pop();
|
||
// top.Print();
|
||
if(top.tri_index == index2){
|
||
cout<<"find the path"<<endl;
|
||
find = true;
|
||
dest = top;
|
||
break;
|
||
}
|
||
////////find its adjacecy element, and push them into queue and path//////
|
||
vector<int> adj_list;
|
||
FindAdj(top.tri_index, triangle_flag, adj_list);
|
||
// cout<<"adjcency_list size "<<adj_list.size()<<endl;
|
||
// cout<<"expand_path_size "<<expand_path.size()<<endl;
|
||
int pos_expand_path = top.cur_index;
|
||
for(unsigned int i = 0;i < adj_list.size();i++){
|
||
int expand_path_size = expand_path.size();
|
||
path_queue.push(SPath_elem(pos_expand_path, expand_path_size,
|
||
adj_list[i], top.weight+1));
|
||
expand_path.push_back(SPath_elem(pos_expand_path, expand_path_size,
|
||
adj_list[i], top.weight+1));
|
||
}
|
||
}
|
||
///////////////construct the path/////////////////////////////////
|
||
if(find){
|
||
vector<int> path_record;
|
||
while(dest.prev_index != -1){
|
||
// sleeve.push_back(triangles[dest.tri_index]);
|
||
path_record.push_back(dest.tri_index);
|
||
dest = expand_path[dest.prev_index];
|
||
}
|
||
// sleeve.push_back(triangles[dest.tri_index]);
|
||
path_record.push_back(dest.tri_index);
|
||
|
||
for(int i = path_record.size() - 1;i >= 0;i--)
|
||
sleeve.push_back(triangles[path_record[i]]);
|
||
}
|
||
|
||
}
|
||
|
||
/*
|
||
build the channel/funnel
|
||
|
||
*/
|
||
void CompTriangle::ConstructConvexChannel1(list<MyPoint>& funnel_front,
|
||
list<MyPoint>& funnel_back,
|
||
Point& newvertex,
|
||
vector<Point>& path, bool front_back)
|
||
{
|
||
// cout<<"ConstructConvexChannel1 "<<endl;
|
||
const double delta_dist = 0.00001;
|
||
//push newvertex into funnel_back
|
||
if(front_back){ //front = newvertex, check funnel_back first,
|
||
// cout<<"front "<<"push into back "<<endl;
|
||
//case1 case2 check another list
|
||
MyPoint mp1;
|
||
MyPoint mp2 = funnel_back.back();
|
||
while(funnel_back.empty() == false){
|
||
MyPoint elem = funnel_back.back();
|
||
// elem.Print();
|
||
HalfSegment hs;
|
||
hs.Set(true, elem.loc, newvertex);
|
||
if(reg->Contains(hs)){
|
||
funnel_back.pop_back();
|
||
mp1 = elem;
|
||
}else break;
|
||
}
|
||
if(funnel_back.empty()){//case 1
|
||
// cout<<"funnel_back empty"<<endl;
|
||
funnel_back.push_back(mp1);
|
||
funnel_back.push_back(MyPoint(newvertex,
|
||
newvertex.Distance(mp1.loc) + mp1.dist));
|
||
}else{
|
||
if(mp1.loc.Distance(mp2.loc) < delta_dist){ //case2
|
||
double l1 = newvertex.Distance(mp2.loc) + mp2.dist;
|
||
|
||
//////////////////////////////
|
||
list<MyPoint>::iterator iter = funnel_front.begin();
|
||
for(;iter != funnel_front.end();iter++){
|
||
Point p = iter->loc;
|
||
HalfSegment hs;
|
||
hs.Set(true, p, newvertex);
|
||
if(reg->Contains(hs))break;
|
||
}
|
||
double l2 = newvertex.Distance(iter->loc) + iter->dist;
|
||
///////////////////////////////
|
||
// cout<<"l1 "<<l1<<" l2 "<<l2<<endl;
|
||
if(l1 < l2 || AlmostEqual(l1, l2)){
|
||
funnel_back.push_back(mp2);
|
||
funnel_back.push_back(MyPoint(newvertex,l1));
|
||
}else{
|
||
while(funnel_front.empty() == false){
|
||
MyPoint elem = funnel_front.front();
|
||
// elem.Print();
|
||
HalfSegment hs;
|
||
hs.Set(true, elem.loc, newvertex);
|
||
if(reg->Contains(hs))break;
|
||
funnel_front.pop_front();
|
||
if(path[path.size() - 1].Distance(elem.loc) > delta_dist)
|
||
path.push_back(elem.loc);
|
||
}
|
||
assert(funnel_front.empty() == false);
|
||
MyPoint top = funnel_front.front();
|
||
path.push_back(top.loc);
|
||
|
||
|
||
//update funnel_back
|
||
funnel_back.clear();
|
||
funnel_back.push_back(top);
|
||
funnel_back.push_back(MyPoint(newvertex,
|
||
newvertex.Distance(top.loc) + top.dist));
|
||
}
|
||
}else{//case 1,find a point in funnel_back directly connected to newvertex
|
||
funnel_back.push_back(mp1);
|
||
funnel_back.push_back(MyPoint(newvertex,
|
||
newvertex.Distance(mp1.loc) + mp1.dist));
|
||
}
|
||
}
|
||
//push newvertex into funnel_front
|
||
}else{ //back = newvertex, check funnel funnel_front first
|
||
// cout<<"back "<<"push into front "<<endl;
|
||
//case1 case2 check another list
|
||
MyPoint mp1;
|
||
MyPoint mp2 = funnel_front.back();
|
||
while(funnel_front.empty() == false){
|
||
MyPoint elem = funnel_front.back();
|
||
// elem.Print();
|
||
HalfSegment hs;
|
||
hs.Set(true, elem.loc, newvertex);
|
||
if(reg->Contains(hs)){
|
||
funnel_front.pop_back();
|
||
mp1 = elem;
|
||
}else break;
|
||
}
|
||
if(funnel_front.empty()){//case 1
|
||
// cout<<"funnel_front empty"<<endl;
|
||
funnel_front.push_back(mp1);
|
||
funnel_front.push_back(MyPoint(newvertex,
|
||
newvertex.Distance(mp1.loc) + mp1.dist));
|
||
}else{
|
||
if(mp1.loc.Distance(mp2.loc) < delta_dist){ //case2
|
||
double l1 = newvertex.Distance(mp2.loc) + mp2.dist;
|
||
////////////////////////////////////////////////
|
||
list<MyPoint>::iterator iter = funnel_back.begin();
|
||
for(;iter != funnel_back.end();iter++){
|
||
Point p = iter->loc;
|
||
HalfSegment hs;
|
||
hs.Set(true, p, newvertex);
|
||
if(reg->Contains(hs))break;
|
||
}
|
||
double l2 = newvertex.Distance(iter->loc) + iter->dist;
|
||
/////////////////////////////////////////////////
|
||
|
||
// cout<<"l1 "<<l1<<" l2 "<<l2<<endl;
|
||
if(l1 < l2 || AlmostEqual(l1, l2)){
|
||
funnel_front.push_back(mp2);
|
||
funnel_front.push_back(MyPoint(newvertex,l1));
|
||
}
|
||
else{
|
||
while(funnel_back.empty() == false){
|
||
MyPoint elem = funnel_back.front();
|
||
HalfSegment hs;
|
||
hs.Set(true, elem.loc, newvertex);
|
||
if(reg->Contains(hs))break;
|
||
funnel_back.pop_front();
|
||
if(path[path.size() - 1].Distance(elem.loc) > delta_dist)
|
||
path.push_back(elem.loc);
|
||
}
|
||
assert(funnel_back.empty() == false);
|
||
MyPoint top = funnel_back.front();
|
||
path.push_back(top.loc);
|
||
|
||
|
||
//update funnel_front
|
||
funnel_front.clear();
|
||
funnel_front.push_back(top);
|
||
funnel_front.push_back(MyPoint(newvertex,
|
||
newvertex.Distance(top.loc) + top.dist));
|
||
}
|
||
}else{//case 1,find a point in funnel_back directly connected to newvertex
|
||
funnel_front.push_back(mp1);
|
||
funnel_front.push_back(MyPoint(newvertex,
|
||
newvertex.Distance(mp1.loc) + mp1.dist));
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
/* list<MyPoint>::iterator iter = funnel_front.begin();
|
||
cout<<"front ";
|
||
for(;iter != funnel_front.end();iter++){
|
||
Point p = iter->loc;
|
||
cout<<p<<" ";
|
||
}
|
||
cout<<endl<<"back ";
|
||
iter = funnel_back.begin();
|
||
for(;iter != funnel_back.end();iter++){
|
||
Point p = iter->loc;
|
||
cout<<p<<" ";
|
||
}
|
||
cout<<endl;
|
||
cout<<"points in path "<<endl;
|
||
for(unsigned int i = 0;i < path.size();i++)
|
||
cout<<path[i]<<" ";
|
||
cout<<endl;*/
|
||
|
||
}
|
||
|
||
/*
|
||
complete the final shortest path
|
||
|
||
*/
|
||
|
||
void CompTriangle::ConstructConvexChannel2(list<MyPoint> funnel_front,
|
||
list<MyPoint> funnel_back,
|
||
Point& newvertex,
|
||
vector<Point>& path, bool front_back)
|
||
{
|
||
// cout<<"ConstructConvexChannel2 "<<endl;
|
||
const double delta_dist = 0.00001;
|
||
//push newvertex into funnel_back
|
||
if(front_back){ //front = newvertex, check funnel_back first,
|
||
// cout<<"front "<<"push into back "<<endl;
|
||
//case1 case2 check another list
|
||
|
||
MyPoint mp1 = funnel_back.back();
|
||
MyPoint mp2 = funnel_back.front();
|
||
while(funnel_back.empty() == false){
|
||
MyPoint elem = funnel_back.back();
|
||
// elem.Print();
|
||
HalfSegment hs;
|
||
|
||
if(elem.loc.Distance(newvertex) < delta_dist){
|
||
funnel_back.pop_back();
|
||
mp1 = elem;
|
||
continue;
|
||
}
|
||
|
||
hs.Set(true, elem.loc, newvertex);
|
||
if(reg->Contains(hs)){
|
||
funnel_back.pop_back();
|
||
mp1 = elem;
|
||
}else break;
|
||
}
|
||
|
||
double l1 = newvertex.Distance(mp1.loc) + mp1.dist;
|
||
////////////////////////////////////////////////
|
||
list<MyPoint>::iterator iter = funnel_front.begin();
|
||
for(;iter != funnel_front.end();iter++){
|
||
Point p = iter->loc;
|
||
HalfSegment hs;
|
||
|
||
if(p.Distance(newvertex) < delta_dist) break;
|
||
|
||
hs.Set(true, p, newvertex);
|
||
if(reg->Contains(hs))break;
|
||
}
|
||
double l2 = newvertex.Distance(iter->loc) + iter->dist;
|
||
/////////////////////////////////////////////////
|
||
|
||
// cout<<"l1 "<<l1<<" l2 "<<l2<<endl;
|
||
if(l1 < l2 || AlmostEqual(l1, l2)){
|
||
|
||
if(funnel_back.empty() == false)
|
||
funnel_back.pop_front();
|
||
|
||
while(funnel_back.empty() == false){
|
||
MyPoint elem = funnel_back.front();
|
||
path.push_back(elem.loc);
|
||
funnel_back.pop_front();
|
||
}
|
||
if(mp1.loc.Distance(mp2.loc) > delta_dist)
|
||
path.push_back(mp1.loc);
|
||
}else{
|
||
MyPoint top = funnel_front.front();
|
||
|
||
if(funnel_front.empty() == false)
|
||
funnel_front.pop_front();
|
||
|
||
HalfSegment hs;
|
||
|
||
if(top.loc.Distance(newvertex) < delta_dist) return;
|
||
|
||
hs.Set(true, top.loc, newvertex);
|
||
if(reg->Contains(hs)) return;
|
||
|
||
while(funnel_front.empty() == false){
|
||
MyPoint elem = funnel_front.front();
|
||
path.push_back(elem.loc);
|
||
////////////////////////////////////////
|
||
HalfSegment hs;
|
||
|
||
if(elem.loc.Distance(newvertex) < delta_dist) break;
|
||
|
||
hs.Set(true, elem.loc, newvertex);
|
||
if(reg->Contains(hs))break;
|
||
///////////////////////////////////////
|
||
funnel_front.pop_front();
|
||
}
|
||
}
|
||
//push newvertex into funnel_front
|
||
}else{ //back = newvertex, check funnel funnel_front first
|
||
// cout<<"back "<<"push into front "<<endl;
|
||
//case1 case2 check another list
|
||
|
||
MyPoint mp1 = funnel_front.back();
|
||
MyPoint mp2 = funnel_front.front();
|
||
while(funnel_front.empty() == false){
|
||
MyPoint elem = funnel_front.back();
|
||
// elem.Print();
|
||
HalfSegment hs;
|
||
|
||
if(elem.loc.Distance(newvertex) < delta_dist){
|
||
funnel_front.pop_back();
|
||
mp1 = elem;
|
||
continue;
|
||
}
|
||
|
||
hs.Set(true, elem.loc, newvertex);
|
||
if(reg->Contains(hs)){
|
||
funnel_front.pop_back();
|
||
mp1 = elem;
|
||
}else break;
|
||
}
|
||
|
||
double l1 = newvertex.Distance(mp1.loc) + mp1.dist;
|
||
/////////////////////////////////////////////
|
||
list<MyPoint>::iterator iter = funnel_back.begin();
|
||
for(;iter != funnel_back.end();iter++){
|
||
Point p = iter->loc;
|
||
HalfSegment hs;
|
||
|
||
if(p.Distance(newvertex) < delta_dist){
|
||
break;
|
||
}
|
||
|
||
hs.Set(true, p, newvertex);
|
||
if(reg->Contains(hs))break;
|
||
}
|
||
double l2 = newvertex.Distance(iter->loc) + iter->dist;
|
||
////////////////////////////////////////////
|
||
|
||
// cout<<"l1 "<<l1<<" l2 "<<l2<<endl;
|
||
if(l1 < l2 || AlmostEqual(l1, l2)){
|
||
if(funnel_front.empty() == false)
|
||
funnel_front.pop_front();
|
||
while(funnel_front.empty() == false){
|
||
MyPoint elem = funnel_front.front();
|
||
path.push_back(elem.loc);
|
||
funnel_front.pop_front();
|
||
}
|
||
if(mp1.loc.Distance(mp2.loc) > delta_dist)
|
||
path.push_back(mp1.loc);
|
||
}
|
||
else{
|
||
MyPoint top = funnel_back.front();
|
||
if(funnel_back.empty() == false){
|
||
funnel_back.pop_front();
|
||
}
|
||
|
||
HalfSegment hs;
|
||
|
||
if(top.loc.Distance(newvertex) < delta_dist)return;
|
||
|
||
hs.Set(true, top.loc, newvertex);
|
||
if(reg->Contains(hs)) return;
|
||
|
||
while(funnel_back.empty() == false){
|
||
MyPoint elem = funnel_back.front();
|
||
path.push_back(elem.loc);
|
||
/////////////////////////////
|
||
HalfSegment hs;
|
||
if(elem.loc.Distance(newvertex) < delta_dist)break;
|
||
|
||
hs.Set(true, elem.loc, newvertex);
|
||
if(reg->Contains(hs))break;
|
||
//////////////////////////////
|
||
funnel_back.pop_front();
|
||
}
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
/*
|
||
geometrical shortest path in a polygon
|
||
Apply the Funnel Algorithm, front point---->point
|
||
The polygon should not have hole inside. !!!
|
||
If it has hole inside, it has to check every possible path.
|
||
|
||
*/
|
||
void CompTriangle::GeoShortestPath(Point* start, Point* end)
|
||
{
|
||
|
||
if(start->Inside(*reg) == false || end->Inside(*reg) == false){
|
||
cout<<"points are not inside the polygon"<<endl;
|
||
return;
|
||
}
|
||
if(AlmostEqual(start->GetX(), end->GetX()) &&
|
||
AlmostEqual(start->GetY(), end->GetY())){
|
||
cout<<"two points are equal"<<endl;
|
||
return;
|
||
}
|
||
|
||
if(PolygonConvex()){ //convex, just use euclidean distance
|
||
// cout<<"a convex polygon"<<endl;
|
||
int edgeno = 0;
|
||
path = new Line(0);
|
||
path->StartBulkLoad();
|
||
HalfSegment hs;
|
||
hs.Set(true, *start, *end);
|
||
hs.attr.edgeno = edgeno++;
|
||
*path += hs;
|
||
hs.SetLeftDomPoint(!hs.IsLeftDomPoint());
|
||
*path += hs;
|
||
path->EndBulkLoad();
|
||
sleeve.push_back(*reg);
|
||
return;
|
||
}
|
||
|
||
// Triangulation();//get a set of triangles, does not support hole
|
||
NewTriangulation();
|
||
if(triangles.size() < 3){
|
||
cout<<"triangulation is not correct"<<endl;
|
||
return;
|
||
}
|
||
/////////////// find the channel /////////////////////////////
|
||
|
||
GetChannel(start, end);
|
||
/////////////////get a sequence of diagonals////////////////////////
|
||
vector<HalfSegment> diagonals;
|
||
const double delta_dist = 0.00001;
|
||
// cout<<"channel size "<<sleeve.size()<<endl;
|
||
for(unsigned int i = 0;i < sleeve.size() - 1;i++){
|
||
vector<HalfSegment> cur_triangle;
|
||
for(int j = 0;j < sleeve[i].Size();j++){
|
||
HalfSegment hs;
|
||
sleeve[i].Get(j, hs);
|
||
if(!hs.IsLeftDomPoint())continue;
|
||
cur_triangle.push_back(hs);
|
||
}
|
||
|
||
vector<HalfSegment> next_triangle;
|
||
for(int j = 0;j < sleeve[i + 1].Size();j++){
|
||
HalfSegment hs;
|
||
sleeve[i + 1].Get(j, hs);
|
||
if(!hs.IsLeftDomPoint())continue;
|
||
next_triangle.push_back(hs);
|
||
}
|
||
for(unsigned int k1 = 0;k1 < cur_triangle.size();k1++){
|
||
Point p1 = cur_triangle[k1].GetLeftPoint();
|
||
Point p2 = cur_triangle[k1].GetRightPoint();
|
||
|
||
unsigned int k2 = 0;
|
||
for(;k2 < next_triangle.size();k2++){
|
||
Point p3 = next_triangle[k2].GetLeftPoint();
|
||
Point p4 = next_triangle[k2].GetRightPoint();
|
||
|
||
if(p1.Distance(p3) < delta_dist && p2.Distance(p4) < delta_dist){
|
||
HalfSegment hs;
|
||
hs.Set(true,p1, p2);
|
||
diagonals.push_back(hs);
|
||
break;
|
||
}
|
||
if(p1.Distance(p4) < delta_dist && p2.Distance(p3) < delta_dist){
|
||
HalfSegment hs;
|
||
hs.Set(true,p1, p2);
|
||
diagonals.push_back(hs);
|
||
break;
|
||
}
|
||
}
|
||
if(k2 != next_triangle.size())break;
|
||
}
|
||
}
|
||
// cout<<"diagnoals size "<<diagonals.size()<<endl;
|
||
|
||
list<MyPoint> funnel_front;
|
||
list<MyPoint> funnel_back;
|
||
Point apex = *start;
|
||
vector<Point> shortest_path;
|
||
|
||
shortest_path.push_back(apex);
|
||
funnel_front.push_back(MyPoint(apex, 0.0));
|
||
funnel_back.push_back(MyPoint(apex, 0.0));
|
||
|
||
bool funnel_front_flag = true;
|
||
|
||
for(unsigned int i = 0;i < diagonals.size();i++){
|
||
Point lp = diagonals[i].GetLeftPoint();
|
||
Point rp = diagonals[i].GetRightPoint();
|
||
if(i == 0){
|
||
funnel_front.push_back(MyPoint(lp, lp.Distance(apex)));
|
||
funnel_back.push_back(MyPoint(rp, rp.Distance(apex)));
|
||
continue;
|
||
}
|
||
Point last_lp = diagonals[i - 1].GetLeftPoint();
|
||
Point last_rp = diagonals[i - 1].GetRightPoint();
|
||
Point newvertex;
|
||
if(lp.Distance(last_lp) < delta_dist ||
|
||
lp.Distance(last_rp) < delta_dist){
|
||
newvertex = rp;
|
||
|
||
// cout<<"newvertex rp" <<newvertex<<endl;
|
||
MyPoint front = funnel_front.back();
|
||
MyPoint back = funnel_back.back();
|
||
|
||
|
||
if(front.loc.Distance(lp) < delta_dist){
|
||
ConstructConvexChannel1(funnel_front, funnel_back,
|
||
newvertex, shortest_path, true);
|
||
funnel_front_flag = true;
|
||
}else if(back.loc.Distance(lp) < delta_dist){
|
||
ConstructConvexChannel1(funnel_front, funnel_back,
|
||
newvertex, shortest_path, false);
|
||
funnel_front_flag = false;
|
||
}else assert(false);
|
||
}
|
||
else if(rp.Distance(last_lp) < delta_dist ||
|
||
rp.Distance(last_rp) < delta_dist){
|
||
newvertex = lp;
|
||
|
||
// cout<<"newvertex lp" <<newvertex<<endl;
|
||
MyPoint front = funnel_front.back();
|
||
MyPoint back = funnel_back.back();
|
||
|
||
|
||
if(front.loc.Distance(rp) < delta_dist){
|
||
ConstructConvexChannel1(funnel_front, funnel_back,
|
||
newvertex, shortest_path, true);
|
||
funnel_front_flag = true;
|
||
}else if(back.loc.Distance(rp) < delta_dist){
|
||
ConstructConvexChannel1(funnel_front, funnel_back,
|
||
newvertex, shortest_path, false);
|
||
funnel_front_flag = false;
|
||
}else assert(false);
|
||
}
|
||
else assert(false);
|
||
}
|
||
|
||
/* for(unsigned int i = 0;i < shortest_path.size();i++)
|
||
cout<<"point in path "<<shortest_path[i]<<endl;*/
|
||
|
||
////////////////// last point //////////////////////////////
|
||
ConstructConvexChannel2(funnel_front, funnel_back,
|
||
*end, shortest_path, funnel_front_flag);
|
||
shortest_path.push_back(*end);
|
||
////////////////////////////////////////////////////////////
|
||
// cout<<"shortest path segments size "<<shortest_path.size()<<endl;
|
||
path = new Line(0);
|
||
path->StartBulkLoad();
|
||
int edgeno = 0;
|
||
for(unsigned int i = 0;i < shortest_path.size() - 1;i++){
|
||
// cout<<"point1 "<<shortest_path[i]<<endl;
|
||
// cout<<"point2 "<<shortest_path[i + 1]<<endl;
|
||
HalfSegment hs;
|
||
Point p1 = shortest_path[i];
|
||
Point p2 = shortest_path[i + 1];
|
||
hs.Set(true, p1, p2);
|
||
hs.attr.edgeno = edgeno++;
|
||
*path += hs;
|
||
hs.SetLeftDomPoint(!hs.IsLeftDomPoint());
|
||
*path += hs;
|
||
}
|
||
path->EndBulkLoad();
|
||
}
|
||
|
||
/*
|
||
select the point on segment to compute the shortest path.
|
||
it goes through the funnel to check the vertex stored and try to find
|
||
sucn an segment which is contained by the polygon and it consists of
|
||
the vertex and the closest point to the vertex in the input segement.
|
||
|
||
*/
|
||
void CompTriangle::SelectPointOnSeg(list<MyPoint> funnel_front,
|
||
list<MyPoint> funnel_back, HalfSegment* end,
|
||
Point& vertex, Point& cp)
|
||
|
||
{
|
||
SpacePartition* sp = new SpacePartition();
|
||
const double delta_dist = 0.00001;
|
||
MyPoint elem_front = funnel_front.back();
|
||
MyPoint elem_back = funnel_back.back();
|
||
if(elem_front.loc.Distance(vertex) < delta_dist){
|
||
sp->GetClosestPoint(*end, elem_front.loc, cp);
|
||
funnel_front.pop_back();
|
||
while(funnel_front.empty() == false){
|
||
MyPoint elem = funnel_front.back();
|
||
Point p;
|
||
sp->GetClosestPoint(*end, elem.loc, p);
|
||
HalfSegment hs;
|
||
hs.Set(true, elem.loc, p);
|
||
if(reg->Contains(hs) == false)break;
|
||
cp = p;
|
||
funnel_front.pop_back();
|
||
}
|
||
}else if(elem_back.loc.Distance(vertex) < delta_dist){
|
||
sp->GetClosestPoint(*end, elem_back.loc, cp);
|
||
funnel_back.pop_back();
|
||
while(funnel_back.empty() == false){
|
||
MyPoint elem = funnel_back.back();
|
||
Point p;
|
||
sp->GetClosestPoint(*end, elem.loc, p);
|
||
HalfSegment hs;
|
||
hs.Set(true, elem.loc, p);
|
||
if(reg->Contains(hs) == false)break;
|
||
cp = p;
|
||
funnel_back.pop_back();
|
||
}
|
||
}else assert(false);
|
||
|
||
delete sp;
|
||
}
|
||
|
||
/*
|
||
compute the shortest path from start point to the end segment
|
||
|
||
*/
|
||
void CompTriangle::PtoSegSPath(Point* start, HalfSegment* end,
|
||
vector<Region>& temp_sleeve, Line* res_line)
|
||
{
|
||
|
||
/////////////////get the channel////////////////////////////
|
||
vector<HalfSegment> diagonals;
|
||
const double delta_dist = 0.00001;
|
||
|
||
for(unsigned int i = 0;i < temp_sleeve.size() - 1;i++){
|
||
vector<HalfSegment> cur_triangle;
|
||
for(int j = 0;j < temp_sleeve[i].Size();j++){
|
||
HalfSegment hs;
|
||
temp_sleeve[i].Get(j, hs);
|
||
if(!hs.IsLeftDomPoint())continue;
|
||
cur_triangle.push_back(hs);
|
||
}
|
||
|
||
vector<HalfSegment> next_triangle;
|
||
for(int j = 0;j < temp_sleeve[i + 1].Size();j++){
|
||
HalfSegment hs;
|
||
temp_sleeve[i + 1].Get(j, hs);
|
||
if(!hs.IsLeftDomPoint())continue;
|
||
next_triangle.push_back(hs);
|
||
}
|
||
for(unsigned int k1 = 0;k1 < cur_triangle.size();k1++){
|
||
Point p1 = cur_triangle[k1].GetLeftPoint();
|
||
Point p2 = cur_triangle[k1].GetRightPoint();
|
||
|
||
unsigned int k2 = 0;
|
||
for(;k2 < next_triangle.size();k2++){
|
||
Point p3 = next_triangle[k2].GetLeftPoint();
|
||
Point p4 = next_triangle[k2].GetRightPoint();
|
||
|
||
if(p1.Distance(p3) < delta_dist && p2.Distance(p4) < delta_dist){
|
||
HalfSegment hs;
|
||
hs.Set(true,p1, p2);
|
||
diagonals.push_back(hs);
|
||
break;
|
||
}
|
||
if(p1.Distance(p4) < delta_dist && p2.Distance(p3) < delta_dist){
|
||
HalfSegment hs;
|
||
hs.Set(true,p1, p2);
|
||
diagonals.push_back(hs);
|
||
break;
|
||
}
|
||
}
|
||
if(k2 != next_triangle.size())break;
|
||
}
|
||
}
|
||
// cout<<"diagnoals size "<<diagonals.size()<<endl;
|
||
|
||
///////////////////////////////////////////////////////////////
|
||
|
||
list<MyPoint> funnel_front;
|
||
list<MyPoint> funnel_back;
|
||
Point apex = *start;
|
||
vector<Point> shortest_path;
|
||
|
||
shortest_path.push_back(apex);
|
||
funnel_front.push_back(MyPoint(apex, 0.0));
|
||
funnel_back.push_back(MyPoint(apex, 0.0));
|
||
|
||
bool funnel_front_flag = true;
|
||
Point newvertex;
|
||
Point newvertex_pair;
|
||
for(unsigned int i = 0;i < diagonals.size();i++){
|
||
Point lp = diagonals[i].GetLeftPoint();
|
||
Point rp = diagonals[i].GetRightPoint();
|
||
if(i == 0){
|
||
funnel_front.push_back(MyPoint(lp, lp.Distance(apex)));
|
||
funnel_back.push_back(MyPoint(rp, rp.Distance(apex)));
|
||
continue;
|
||
}
|
||
Point last_lp = diagonals[i - 1].GetLeftPoint();
|
||
Point last_rp = diagonals[i - 1].GetRightPoint();
|
||
|
||
if(lp.Distance(last_lp) < delta_dist ||
|
||
lp.Distance(last_rp) < delta_dist){
|
||
newvertex = rp;
|
||
newvertex_pair = lp;
|
||
|
||
// cout<<"newvertex rp" <<newvertex<<endl;
|
||
MyPoint front = funnel_front.back();
|
||
MyPoint back = funnel_back.back();
|
||
|
||
if(front.loc.Distance(lp) < delta_dist){
|
||
ConstructConvexChannel1(funnel_front, funnel_back,
|
||
newvertex, shortest_path, true);
|
||
funnel_front_flag = true;
|
||
}else if(back.loc.Distance(lp) < delta_dist){
|
||
ConstructConvexChannel1(funnel_front, funnel_back,
|
||
newvertex, shortest_path, false);
|
||
funnel_front_flag = false;
|
||
}else assert(false);
|
||
}
|
||
else if(rp.Distance(last_lp) < delta_dist ||
|
||
rp.Distance(last_rp) < delta_dist){
|
||
newvertex = lp;
|
||
newvertex_pair = rp;
|
||
|
||
// cout<<"newvertex lp" <<newvertex<<endl;
|
||
MyPoint front = funnel_front.back();
|
||
MyPoint back = funnel_back.back();
|
||
|
||
|
||
if(front.loc.Distance(rp) < delta_dist){
|
||
ConstructConvexChannel1(funnel_front, funnel_back,
|
||
newvertex, shortest_path, true);
|
||
funnel_front_flag = true;
|
||
}else if(back.loc.Distance(rp) < delta_dist){
|
||
ConstructConvexChannel1(funnel_front, funnel_back,
|
||
newvertex, shortest_path, false);
|
||
funnel_front_flag = false;
|
||
}else assert(false);
|
||
}
|
||
else assert(false);
|
||
}
|
||
//////////////////////////////////////////////////////////////
|
||
// cout<<"end halfsegment "<<*end<<endl;
|
||
vector<Point> shortest_path_another;
|
||
for(unsigned int i = 0;i < shortest_path.size();i++)
|
||
shortest_path_another.push_back(shortest_path[i]);
|
||
|
||
// cout<<"newvertex "<<newvertex<<" cp1 "<<cp1<<endl;
|
||
////////////////////////////////////////////
|
||
list<MyPoint> copy_funnel_front;
|
||
list<MyPoint> copy_funnel_back;
|
||
list<MyPoint>::iterator iter;
|
||
for(iter = funnel_front.begin(); iter != funnel_front.end();iter++)
|
||
copy_funnel_front.push_back(*iter);
|
||
for(iter = funnel_back.begin(); iter != funnel_back.end();iter++)
|
||
copy_funnel_back.push_back(*iter);
|
||
|
||
Point cp1, cp2;
|
||
|
||
//////////////////////////////////////////////////////////////////
|
||
|
||
SelectPointOnSeg(funnel_front, funnel_back, end, newvertex, cp1);
|
||
|
||
if(newvertex.Distance(cp1) > delta_dist){
|
||
ConstructConvexChannel2(funnel_front, funnel_back,
|
||
cp1, shortest_path, funnel_front_flag);
|
||
shortest_path.push_back(cp1);
|
||
}else{
|
||
MyPoint top_front = funnel_front.back();
|
||
MyPoint top_back = funnel_back.back();
|
||
if(top_front.loc.Distance(cp1) < delta_dist){
|
||
while(funnel_front.size() > 1){
|
||
MyPoint elem = funnel_front.back();
|
||
funnel_front.pop_back();
|
||
shortest_path.push_back(elem.loc);
|
||
}
|
||
}else if(top_back.loc.Distance(cp1) < delta_dist){
|
||
while(funnel_back.size() > 1){
|
||
MyPoint elem = funnel_back.back();
|
||
funnel_back.pop_back();
|
||
shortest_path.push_back(elem.loc);
|
||
}
|
||
}else assert(false);
|
||
}
|
||
///////////////////////////////////////////////////////////////////////
|
||
// cout<<"path1 size "<<shortest_path.size()<<endl;
|
||
|
||
SelectPointOnSeg(funnel_front, funnel_back, end, newvertex_pair, cp2);
|
||
|
||
// cout<<"newvertex_pair "<<newvertex_pair<<" cp2 "<<cp2<<endl;
|
||
if(newvertex_pair.Distance(cp2) > delta_dist){
|
||
ConstructConvexChannel2(copy_funnel_front, copy_funnel_back,
|
||
cp2, shortest_path_another,
|
||
!funnel_front_flag);
|
||
shortest_path_another.push_back(cp2);
|
||
}else{
|
||
MyPoint top_front = copy_funnel_front.back();
|
||
MyPoint top_back = copy_funnel_back.back();
|
||
if(top_front.loc.Distance(cp2) < delta_dist){
|
||
while(copy_funnel_front.size() > 1){
|
||
MyPoint elem = copy_funnel_front.back();
|
||
copy_funnel_front.pop_back();
|
||
shortest_path_another.push_back(elem.loc);
|
||
}
|
||
}else if(top_back.loc.Distance(cp2) < delta_dist){
|
||
while(copy_funnel_back.size() > 1){
|
||
MyPoint elem = copy_funnel_back.back();
|
||
copy_funnel_back.pop_back();
|
||
shortest_path_another.push_back(elem.loc);
|
||
}
|
||
}else assert(false);
|
||
}
|
||
|
||
// cout<<"path2 size "<<shortest_path_another.size()<<endl;
|
||
|
||
//////////////////////////////////////////////////////////////
|
||
Line* l1 = new Line(0);
|
||
|
||
l1->StartBulkLoad();
|
||
|
||
|
||
int edgeno1 = 0;
|
||
for(unsigned int i = 0;i < shortest_path.size() - 1;i++){
|
||
HalfSegment hs;
|
||
Point p1 = shortest_path[i];
|
||
Point p2 = shortest_path[i + 1];
|
||
hs.Set(true, p1, p2);
|
||
hs.attr.edgeno = edgeno1++;
|
||
*l1 += hs;
|
||
hs.SetLeftDomPoint(!hs.IsLeftDomPoint());
|
||
*l1 += hs;
|
||
}
|
||
l1->EndBulkLoad();
|
||
|
||
Line* l2 = new Line(0);
|
||
l2->StartBulkLoad();
|
||
int edgeno2 = 0;
|
||
for(unsigned int i = 0;i < shortest_path_another.size() - 1;i++){
|
||
HalfSegment hs;
|
||
Point p1 = shortest_path_another[i];
|
||
Point p2 = shortest_path_another[i + 1];
|
||
hs.Set(true, p1, p2);
|
||
hs.attr.edgeno = edgeno2++;
|
||
*l2 += hs;
|
||
hs.SetLeftDomPoint(!hs.IsLeftDomPoint());
|
||
*l2 += hs;
|
||
}
|
||
l2->EndBulkLoad();
|
||
if(l1->Length() < l2->Length())
|
||
*res_line = *l1;
|
||
else
|
||
*res_line = *l2;
|
||
|
||
l1->DeleteIfAllowed();
|
||
l2->DeleteIfAllowed();
|
||
}
|
||
|
||
|
||
/*The following describes a method for determining whether or not a polygon has
|
||
its vertices ordered clockwise or anticlockwise for both convex and concave
|
||
polygons. A polygon will be assumed to be described by N vertices, ordered
|
||
(x0,y0), (x1,y1), (x2,y2), . . . (xn-1,yn-1)
|
||
|
||
A simple test of vertex ordering for convex polygons is based on considerations
|
||
of the cross product between adjacent edges. If the crossproduct is positive
|
||
then it rises above the plane (z axis up out of the plane) and if negative then
|
||
the cross product is into the plane.
|
||
|
||
cross product = ((xi - xi-1),(yi - yi-1)) x ((xi+1 - xi),(yi+1 - yi))
|
||
= (xi - xi-1) * (yi+1 - yi) - (yi - yi-1) * (xi+1 - xi)
|
||
|
||
A positive cross product means we have a counterclockwise polygon.
|
||
|
||
To determine the vertex ordering for concave polygons one can use a result
|
||
from the calculation of polygon areas, where the area is given by
|
||
|
||
A = 1/2*Sum(for (i=0;i<N-1;i++) (xiyi+1 - xi+1yi))
|
||
|
||
If the above expression is positive then the polygon is ordered counter
|
||
clockwise otherwise if it is negative then the polygon vertices are ordered
|
||
clockwise.*/
|
||
|
||
/*
|
||
calculate the number of cycles in a region
|
||
|
||
*/
|
||
unsigned int CompTriangle::NoOfCycles()
|
||
{
|
||
vector<int> no_cycles(reg->Size(), -1);
|
||
|
||
for(int i = 0;i < reg->Size();i++){
|
||
HalfSegment hs;
|
||
reg->Get(i, hs);
|
||
if(!hs.IsLeftDomPoint())continue;
|
||
int cycleno = hs.attr.cycleno;
|
||
no_cycles[cycleno] = cycleno;
|
||
}
|
||
|
||
unsigned int no_cyc = 0;
|
||
for(unsigned int i = 0;i < no_cycles.size();i++){
|
||
if(no_cycles[i] != -1) no_cyc++;
|
||
else
|
||
break;
|
||
}
|
||
return no_cyc;
|
||
}
|
||
/*
|
||
Initialize the point list
|
||
|
||
*/
|
||
|
||
void CompTriangle::PolygonContourPoint(unsigned int no_cyc, int no_p_contour[],
|
||
vector<double>& ps_contour_x,
|
||
vector<double>& ps_contour_y)
|
||
{
|
||
ps_contour_x.push_back(0.0);
|
||
ps_contour_y.push_back(0.0);
|
||
|
||
vector<SimpleLine*> sl_contour;
|
||
|
||
for(unsigned int i = 0;i < no_cyc;i++){
|
||
SimpleLine* sl = new SimpleLine(0);
|
||
sl->StartBulkLoad();
|
||
sl_contour.push_back(sl);
|
||
}
|
||
vector<int> edgenos(no_cyc, 0);
|
||
for(int j = 0;j < reg->Size();j++){
|
||
HalfSegment hs1;
|
||
reg->Get(j, hs1);
|
||
if(!hs1.IsLeftDomPoint()) continue;
|
||
HalfSegment hs2;
|
||
hs2.Set(true, hs1.GetLeftPoint(), hs1.GetRightPoint());
|
||
|
||
hs2.attr.edgeno = edgenos[hs1.attr.cycleno]++;
|
||
*sl_contour[hs1.attr.cycleno] += hs2;
|
||
hs2.SetLeftDomPoint(!hs2.IsLeftDomPoint());
|
||
*sl_contour[hs1.attr.cycleno] += hs2;
|
||
|
||
}
|
||
// cout<<"get all boundary line"<<endl;
|
||
SpacePartition* sp = new SpacePartition();
|
||
|
||
for(size_t i = 0; i < no_cyc; i++){
|
||
|
||
sl_contour[i]->EndBulkLoad();
|
||
vector<MyHalfSegment> mhs;
|
||
SimpleLine* line = sl_contour[i];
|
||
|
||
if(! line->IsDefined()) {
|
||
cout << "Ignoring undefined line" << endl;
|
||
continue;
|
||
}
|
||
|
||
sp->ReorderLine(line, mhs);
|
||
|
||
vector<Point> ps;
|
||
|
||
for(size_t j = 0; j < mhs.size(); j++) {
|
||
ps.push_back(mhs[j].from);
|
||
}
|
||
|
||
bool clock;
|
||
if(0.0f < Area(ps)){//points counter-clockwise order
|
||
clock = false;
|
||
}else{// points clockwise
|
||
clock = true;
|
||
}
|
||
no_p_contour[i] = ps.size();
|
||
if(i == 0){//outer contour, counter_clockwise
|
||
if(clock == false){
|
||
for(unsigned int index = 0;index < ps.size();index++){
|
||
ps_contour_x.push_back(ps[index].GetX());
|
||
ps_contour_y.push_back(ps[index].GetY());
|
||
}
|
||
}else{
|
||
for(unsigned int index = 0;index < ps.size();index++){
|
||
ps_contour_x.push_back(ps[ps.size() - 1 - index].GetX());
|
||
ps_contour_y.push_back(ps[ps.size() - 1 - index].GetY());
|
||
}
|
||
}
|
||
}else{//hole points, should be clockwise
|
||
if(clock == false){
|
||
for(unsigned int index = 0;index < ps.size();index++){
|
||
ps_contour_x.push_back(ps[ps.size() -1 - index].GetX());
|
||
ps_contour_y.push_back(ps[ps.size() -1 - index].GetY());
|
||
}
|
||
}else{
|
||
for(unsigned int index = 0;index < ps.size();index++){
|
||
ps_contour_x.push_back(ps[index].GetX());
|
||
ps_contour_y.push_back(ps[index].GetY());
|
||
}
|
||
}
|
||
}
|
||
|
||
sl_contour[i]->DeleteIfAllowed();
|
||
}
|
||
delete sp;
|
||
|
||
}
|
||
|
||
/*
|
||
the same as PolygonContourPoint, but do not insert (0,0) for the first point
|
||
for each cycle, it inserts the first point to the end to close the region
|
||
|
||
*/
|
||
|
||
void CompTriangle::PolygonContourPoint2(unsigned int no_cyc, int no_p_contour[],
|
||
vector<double>& ps_contour_x,
|
||
vector<double>& ps_contour_y)
|
||
{
|
||
|
||
vector<SimpleLine*> sl_contour;
|
||
|
||
for(unsigned int i = 0;i < no_cyc;i++){
|
||
SimpleLine* sl = new SimpleLine(0);
|
||
sl->StartBulkLoad();
|
||
sl_contour.push_back(sl);
|
||
}
|
||
vector<int> edgenos(no_cyc, 0);
|
||
for(int j = 0;j < reg->Size();j++){
|
||
HalfSegment hs1;
|
||
reg->Get(j, hs1);
|
||
if(!hs1.IsLeftDomPoint()) continue;
|
||
HalfSegment hs2;
|
||
hs2.Set(true, hs1.GetLeftPoint(), hs1.GetRightPoint());
|
||
|
||
hs2.attr.edgeno = edgenos[hs1.attr.cycleno]++;
|
||
*sl_contour[hs1.attr.cycleno] += hs2;
|
||
hs2.SetLeftDomPoint(!hs2.IsLeftDomPoint());
|
||
*sl_contour[hs1.attr.cycleno] += hs2;
|
||
}
|
||
// cout<<"get all boundary line"<<endl;
|
||
SpacePartition* sp = new SpacePartition();
|
||
|
||
for(unsigned int i = 0;i < no_cyc;i++){
|
||
sl_contour[i]->EndBulkLoad();
|
||
vector<MyHalfSegment> mhs;
|
||
sp->ReorderLine(sl_contour[i], mhs);
|
||
vector<Point> ps;
|
||
for(unsigned int j = 0;j < mhs.size();j++)
|
||
ps.push_back(mhs[j].from);
|
||
|
||
bool clock;
|
||
if(0.0f < Area(ps)){//points counter-clockwise order
|
||
clock = false;
|
||
}else{// points clockwise
|
||
clock = true;
|
||
}
|
||
no_p_contour[i] = ps.size();
|
||
if(i == 0){//outer contour, counter_clockwise
|
||
if(clock == false){
|
||
for(unsigned int index = 0;index < ps.size();index++){
|
||
ps_contour_x.push_back(ps[index].GetX());
|
||
ps_contour_y.push_back(ps[index].GetY());
|
||
}
|
||
//////////insert the start point again to close the region///////
|
||
// unsigned int index = 0;
|
||
// ps_contour_x.push_back(ps[index].GetX());
|
||
// ps_contour_y.push_back(ps[index].GetY());
|
||
|
||
}else{
|
||
for(unsigned int index = 0;index < ps.size();index++){
|
||
ps_contour_x.push_back(ps[ps.size() - 1 - index].GetX());
|
||
ps_contour_y.push_back(ps[ps.size() - 1 - index].GetY());
|
||
}
|
||
//////////insert the start point again to close the region///////
|
||
// unsigned int index = 0;
|
||
// ps_contour_x.push_back(ps[ps.size() - 1 - index].GetX());
|
||
// ps_contour_y.push_back(ps[ps.size() - 1 - index].GetY());
|
||
}
|
||
}else{//hole points, should be clockwise
|
||
if(clock == false){
|
||
for(unsigned int index = 0;index < ps.size();index++){
|
||
ps_contour_x.push_back(ps[ps.size() - 1 - index].GetX());
|
||
ps_contour_y.push_back(ps[ps.size() - 1 - index].GetY());
|
||
}
|
||
//////////insert the start point again to close the region///////
|
||
// unsigned int index = 0;
|
||
// ps_contour_x.push_back(ps[ps.size() -1 - index].GetX());
|
||
// ps_contour_y.push_back(ps[ps.size() -1 - index].GetY());
|
||
}else{
|
||
for(unsigned int index = 0;index < ps.size();index++){
|
||
ps_contour_x.push_back(ps[index].GetX());
|
||
ps_contour_y.push_back(ps[index].GetY());
|
||
}
|
||
//////////insert the start point again to close the region///////
|
||
// unsigned int index = 0;
|
||
// ps_contour_x.push_back(ps[index].GetX());
|
||
// ps_contour_y.push_back(ps[index].GetY());
|
||
}
|
||
}
|
||
|
||
sl_contour[i]->DeleteIfAllowed();
|
||
}
|
||
delete sp;
|
||
|
||
}
|
||
|
||
/*
|
||
Decompose a polygon with and without holes into a set of triangles
|
||
Using the implementation by Atul Narkhede and Dinesh Manocha
|
||
|
||
*/
|
||
|
||
void CompTriangle::NewTriangulation()
|
||
{
|
||
|
||
if(reg->NoComponents() == 0){
|
||
cout<<"this is not a region"<<endl;
|
||
return;
|
||
}
|
||
|
||
if(reg->NoComponents() > 1){
|
||
cout<<"can't handle region with more than one face"<<endl;
|
||
return;
|
||
}
|
||
|
||
|
||
////////////////////get the number of cycles////////////////////
|
||
unsigned int no_cyc = NoOfCycles();
|
||
|
||
/* if(no_cyc == 1){
|
||
Triangulation();
|
||
return;
|
||
}*/
|
||
|
||
//the first is the outer cycle
|
||
// cout<<"polgyon with "<<no_cyc - 1<<" holes inside "<<endl;
|
||
|
||
|
||
const int ncontours = no_cyc;
|
||
int no_p_contour[ncontours];
|
||
|
||
vector<double> ps_contour_x;
|
||
vector<double> ps_contour_y;
|
||
|
||
PolygonContourPoint(no_cyc, no_p_contour, ps_contour_x, ps_contour_y);
|
||
|
||
// cout<<"finish creating contour for the polgyon"<<endl;
|
||
// for(unsigned int i = 0;i < no_cyc;i++)
|
||
// cout<<no_p_contour[i]<<endl;
|
||
|
||
// cout<<"no vertices "<<ps_contour_x.size()<<endl;
|
||
|
||
///call the algorithm implemented by Atul Narkhede and Dinesh Manocha ///////
|
||
int result_trig[SEGSIZE][3];
|
||
int (*res_triangles)[3] = &result_trig[0];
|
||
|
||
int no_triangle;
|
||
no_triangle = triangulate_polygon(no_cyc, no_p_contour,
|
||
ps_contour_x, ps_contour_y, res_triangles);
|
||
|
||
// cout<<"no_triangle "<<no_triangle<<endl;
|
||
|
||
assert(0 < no_triangle && no_triangle < SEGSIZE);
|
||
|
||
|
||
SpacePartition* spacepart = new SpacePartition();
|
||
|
||
for (int i = 0; i < no_triangle; i++){
|
||
// printf("triangle #%d: %d %d %d\n", i,
|
||
// res_triangles[i][0], res_triangles[i][1], res_triangles[i][2]);
|
||
|
||
vector<Point> ps_reg;
|
||
Point p1, p2, p3;
|
||
Coord x, y;
|
||
x = ps_contour_x[res_triangles[i][0]];
|
||
y = ps_contour_y[res_triangles[i][0]];
|
||
p1.Set(x, y);
|
||
x = ps_contour_x[res_triangles[i][1]];
|
||
y = ps_contour_y[res_triangles[i][1]];
|
||
p2.Set(x, y);
|
||
x = ps_contour_x[res_triangles[i][2]];
|
||
y = ps_contour_y[res_triangles[i][2]];
|
||
p3.Set(x, y);
|
||
ps_reg.push_back(p1);
|
||
ps_reg.push_back(p2);
|
||
ps_reg.push_back(p3);
|
||
vector<Region> reg;
|
||
spacepart->ComputeRegion(ps_reg, reg);
|
||
triangles.push_back(reg[0]);
|
||
}
|
||
delete spacepart;
|
||
////////////////////////////////////////////////////////////////////
|
||
|
||
}
|
||
|
||
/*
|
||
Decompose a polygon with and without holes into a set of triangles
|
||
Using the implementation by from codeproject
|
||
holes: number of vertices - 2
|
||
without holes: number of vertices - 1 - 2
|
||
|
||
*/
|
||
|
||
void CompTriangle::NewTriangulation2()
|
||
{
|
||
|
||
if(reg->NoComponents() == 0){
|
||
cout<<"this is not a region"<<endl;
|
||
return;
|
||
}
|
||
|
||
if(reg->NoComponents() > 1){
|
||
cout<<"can't handle region with more than one face"<<endl;
|
||
return;
|
||
}
|
||
|
||
|
||
////////////////////get the number of cycles////////////////////
|
||
unsigned int no_cyc = NoOfCycles();
|
||
|
||
if(no_cyc == 1){
|
||
Triangulation();
|
||
return;
|
||
}
|
||
|
||
//the first is the outer cycle
|
||
// cout<<"polgyon with "<<no_cyc - 1<<" holes inside "<<endl;
|
||
|
||
|
||
const int ncontours = no_cyc;
|
||
int no_p_contour[ncontours];
|
||
|
||
vector<double> ps_contour_x;
|
||
vector<double> ps_contour_y;
|
||
|
||
PolygonContourPoint2(no_cyc, no_p_contour, ps_contour_x, ps_contour_y);
|
||
|
||
// cout<<"finish creating contour for the polgyon"<<endl;
|
||
// for(unsigned int i = 0;i < no_cyc;i++)
|
||
// cout<<no_p_contour[i]<<endl;
|
||
|
||
// cout<<"no vertices "<<ps_contour_x.size()<<endl;
|
||
|
||
HPolygon poly;
|
||
int no_triangle = poly.Triangulation2(no_cyc, no_p_contour,
|
||
ps_contour_x, ps_contour_y);
|
||
|
||
// cout<<"no_triangle "<<no_triangle<<endl;
|
||
|
||
|
||
SpacePartition* spacepart = new SpacePartition();
|
||
|
||
for (int i = 0; i < no_triangle; i++){
|
||
|
||
// printf("triangle #%d: %d %d %d\n", i,
|
||
// poly.mtabCell[i].Index(0) + 1,
|
||
// poly.mtabCell[i].Index(1) + 1,
|
||
// poly.mtabCell[i].Index(2) + 1);
|
||
|
||
int index1 = poly.mtabCell[i].Index(0);
|
||
int index2 = poly.mtabCell[i].Index(1);
|
||
int index3 = poly.mtabCell[i].Index(2);
|
||
|
||
// cout<<"( "<<poly.mtabPnt[index1].X()<<" "
|
||
// <<poly.mtabPnt[index1].Y()<<") "
|
||
// <<"( "<<poly.mtabPnt[index2].X()<<" "
|
||
// <<poly.mtabPnt[index2].Y()<<") "
|
||
// <<"( "<<poly.mtabPnt[index3].X()<<" "
|
||
// <<poly.mtabPnt[index3].Y()<<") "<<endl;
|
||
|
||
vector<Point> ps_reg;
|
||
Point p1, p2, p3;
|
||
Coord x, y;
|
||
x = poly.mtabPnt[index1].X();
|
||
y = poly.mtabPnt[index1].Y();
|
||
p1.Set(x, y);
|
||
x = poly.mtabPnt[index2].X();
|
||
y = poly.mtabPnt[index2].Y();
|
||
p2.Set(x, y);
|
||
x = poly.mtabPnt[index3].X();
|
||
y = poly.mtabPnt[index3].Y();
|
||
p3.Set(x, y);
|
||
ps_reg.push_back(p1);
|
||
ps_reg.push_back(p2);
|
||
ps_reg.push_back(p3);
|
||
vector<Region> reg;
|
||
// cout<<p1<<" "<<p2<<" "<<p3<<endl;
|
||
spacepart->ComputeRegion(ps_reg, reg);
|
||
if(reg.size() > 0) //2012.3.9 rounding problem
|
||
triangles.push_back(reg[0]);
|
||
|
||
}
|
||
delete spacepart;
|
||
|
||
////////////////////////////////////////////////////////////////////
|
||
|
||
}
|
||
|
||
/*
|
||
collect all vertices of a polygon together with its two neighbors
|
||
the two halfsegments
|
||
One big region with a lot of holes inside. it collects the vertices of all
|
||
these holes
|
||
|
||
*/
|
||
void CompTriangle::GetAllPoints()
|
||
{
|
||
if(reg->NoComponents() == 0){
|
||
cout<<"this is not a region"<<endl;
|
||
return;
|
||
}
|
||
|
||
////////////////////get the number of cycles, exclude outer contour//////////
|
||
unsigned int no_cyc = NoOfCycles();
|
||
|
||
// cout<<"polgyon with "<<no_cyc<<" holes inside "<<endl;
|
||
|
||
vector<double> ps_contour_x;
|
||
vector<double> ps_contour_y;
|
||
|
||
|
||
ps_contour_x.push_back(0.0);
|
||
ps_contour_y.push_back(0.0);
|
||
|
||
vector<SimpleLine*> sl_contour;
|
||
|
||
for(unsigned int i = 0;i < no_cyc;i++){
|
||
SimpleLine* sl = new SimpleLine(0);
|
||
sl->StartBulkLoad();
|
||
sl_contour.push_back(sl);
|
||
}
|
||
vector<int> edgenos(no_cyc, 0);
|
||
for(int j = 0;j < reg->Size();j++){
|
||
HalfSegment hs1;
|
||
reg->Get(j, hs1);
|
||
// if(!hs1.IsLeftDomPoint() || hs1.attr.cycleno == 0) continue;
|
||
if(!hs1.IsLeftDomPoint()) continue;
|
||
HalfSegment hs2;
|
||
hs2.Set(true, hs1.GetLeftPoint(), hs1.GetRightPoint());
|
||
int cycle_no = hs1.attr.cycleno;
|
||
|
||
hs2.attr.edgeno = edgenos[cycle_no]++;
|
||
*sl_contour[cycle_no] += hs2;
|
||
hs2.SetLeftDomPoint(!hs2.IsLeftDomPoint());
|
||
*sl_contour[cycle_no] += hs2;
|
||
}
|
||
// cout<<"get all boundary line"<<endl;
|
||
SpacePartition* sp = new SpacePartition();
|
||
for(unsigned int i = 0;i < no_cyc;i++){
|
||
sl_contour[i]->EndBulkLoad();
|
||
vector<MyHalfSegment> mhs;
|
||
sp->ReorderLine(sl_contour[i], mhs);
|
||
for(unsigned int j = 0;j < mhs.size();j++){
|
||
plist1.push_back(mhs[j].from);
|
||
reg_id.push_back(i + 1);//cycle_no id, start from 1;
|
||
if(j == 0){
|
||
plist2.push_back(mhs[j + 1].from);
|
||
plist3.push_back(mhs[mhs.size() - 1].from);
|
||
}else if(j == mhs.size() - 1){
|
||
plist2.push_back(mhs[j - 1].from);
|
||
plist3.push_back(mhs[0].from);
|
||
}else{
|
||
plist2.push_back(mhs[j - 1].from);
|
||
plist3.push_back(mhs[j + 1].from);
|
||
}
|
||
}
|
||
}
|
||
delete sp;
|
||
// cout<<plist1.size()<<" "<<plist2.size()<<" "<<plist3.size()<<endl;
|
||
}
|
||
|
||
/*
|
||
get all visible point for the given query point
|
||
using rotational plane sweep algorithm, developed by
|
||
M.Sharir and A.Schorr.
|
||
On Shortest Paths in Polyhedral Spaces, SIAM, Journal of Computing,15(1),1986
|
||
|
||
*/
|
||
string CompTriangle::AllPointsInfo =
|
||
"(rel(tuple((V point)(Neighbor1 point)(Neighbor2 point)(Regid int))))";
|
||
|
||
|
||
ostream& operator<<(ostream& o, const RPoint& rp)
|
||
{
|
||
o<<setprecision(12);
|
||
o<<"p "<<rp.p<<"angle "<<rp.angle<<" dist "<<rp.dist<<endl;
|
||
return o;
|
||
}
|
||
|
||
ostream& operator<<(ostream& o, const MySegDist& seg)
|
||
{
|
||
o<<"from "<<seg.from<<" to "<<seg.to<<" dist "<<seg.dist<<endl;
|
||
return o;
|
||
}
|
||
|
||
/*
|
||
Initialize the event queue, points are sorted by the angle in counter-clockwise
|
||
|
||
*/
|
||
void CompTriangle::InitializeQueue(priority_queue<RPoint>& allps,
|
||
Point& query_p, Point& hp, Point& p,
|
||
SpacePartition* sp, Point* q1,
|
||
Point* q2, int reg_id)
|
||
{
|
||
double angle = sp->GetAngle(query_p, hp, p);
|
||
double dist = query_p.Distance(p);
|
||
if(sp->GetClockwise(query_p, hp, p)){// clockwise
|
||
angle = 2*TM_MYPI - angle;
|
||
}
|
||
RPoint rp(p, angle, dist, reg_id);
|
||
rp.SetNeighbor(*q1, *q2);
|
||
allps.push(rp);
|
||
}
|
||
|
||
|
||
/*
|
||
insert segments that intersect the original sweep line into AVLTree
|
||
|
||
*/
|
||
void CompTriangle::InitializeAVL( multiset<MySegDist>& sss,
|
||
Point& query_p, Point& hp,
|
||
Point& p, Point& neighbor,
|
||
SpacePartition* sp)
|
||
{
|
||
HalfSegment hs1;
|
||
hs1.Set(true, query_p, hp);
|
||
HalfSegment hs2;
|
||
hs2.Set(true, p, neighbor);
|
||
Point ip;
|
||
/////////////////do not insert such segment//////////////////////////////
|
||
///////as it needs more work to determin counter-clockwise or clockwise//
|
||
///////we collect the two endpoints as visible and determine the region
|
||
///face locates on which side of the segment
|
||
if(hs2.Contains(query_p))return;
|
||
|
||
if(hs1.Intersection(hs2, ip)){
|
||
double angle1 = sp->GetAngle(query_p, hp, p);
|
||
double angle2 = sp->GetAngle(query_p, hp, neighbor);
|
||
if(sp->GetClockwise(query_p, hp, p))
|
||
angle1 = 2*TM_MYPI-angle1;
|
||
if(sp->GetClockwise(query_p, hp, neighbor))
|
||
angle2 = 2*TM_MYPI-angle2;
|
||
if(AlmostEqual(angle1, angle2)){
|
||
double d1 = query_p.Distance(p);
|
||
double d2 = query_p.Distance(neighbor);
|
||
if(d1 < d2){
|
||
MySegDist myseg(true, p, neighbor, d1);
|
||
// if(!(*(sss.find(myseg)) == myseg))
|
||
sss.insert(myseg);
|
||
}
|
||
}else{
|
||
double dist = hs2.Distance(query_p);
|
||
MySegDist myseg(true, p, neighbor, dist);
|
||
// if(!(*(sss.find(myseg)) == myseg))
|
||
sss.insert(myseg);
|
||
}
|
||
}
|
||
}
|
||
|
||
void CompTriangle::PrintAVLTree(multiset<MySegDist>& sss, ofstream& outfile)
|
||
{
|
||
outfile<<"AVLTree"<<endl;
|
||
multiset<MySegDist>::iterator start;
|
||
multiset<MySegDist>::iterator end = sss.end();
|
||
for(start = sss.begin();start != end; start++)
|
||
outfile<<*start<<endl;
|
||
}
|
||
|
||
/*
|
||
process the neighbor point of current point from queue,i.e.,
|
||
whether it inserts or deletes the segment
|
||
|
||
*/
|
||
/*void CompTriangle::ProcessNeighbor(multiset<MySegDist>& sss,
|
||
RPoint& rp, Point& query_p,
|
||
Point& neighbor, Point& hp,
|
||
SpacePartition* sp, ofstream& outfile)*/
|
||
|
||
void CompTriangle::ProcessNeighbor(multiset<MySegDist>& sss,
|
||
RPoint& rp, Point& query_p,
|
||
Point& neighbor, Point& hp,
|
||
SpacePartition* sp)
|
||
{
|
||
HalfSegment hs;
|
||
hs.Set(true, rp.p, neighbor);
|
||
// outfile<<"rp.p "<<rp.p<<"neighbor "<<neighbor<<endl;
|
||
if(rp.p.Distance(neighbor) < EPSDIST) return;
|
||
|
||
/////////////////do not insert such segment//////////////////////////////
|
||
///////as it needs more work to determine counter-clockwise or clockwise//
|
||
///////we collect the two endpoints as visible and determine the region
|
||
///face locates on which side of the segment
|
||
if(hs.Contains(query_p)) return;
|
||
|
||
double angle = sp->GetAngle(query_p, hp, neighbor);
|
||
if(sp->GetClockwise(query_p, hp, neighbor))
|
||
angle = 2*TM_MYPI - angle;
|
||
|
||
if(AlmostEqual(angle, rp.angle)){
|
||
// outfile<<"on the same line as query_p "<<endl;
|
||
double d1 = rp.dist;
|
||
double d2 = query_p.Distance(neighbor);
|
||
assert(!AlmostEqual(d1, d2));
|
||
if(d1 < d2){ //insert
|
||
double dist = hs.Distance(query_p);
|
||
MySegDist myseg(true, rp.p, neighbor, dist);
|
||
// outfile<<"insert1 "<<myseg<<endl;
|
||
// if(!(*(sss.find(myseg)) == myseg))
|
||
sss.insert(myseg);
|
||
}else{
|
||
double dist = hs.Distance(query_p);
|
||
MySegDist myseg(true, rp.p, neighbor, dist);
|
||
// outfile<<"remove1 "<<myseg<<endl;
|
||
//erase the element
|
||
multiset<MySegDist>::iterator iter = sss.find(myseg);
|
||
|
||
// assert(iter != sss.end());
|
||
if(iter != sss.end()){
|
||
while(iter != sss.end()){
|
||
if(*iter == myseg){
|
||
sss.erase(iter);
|
||
break;
|
||
}else
|
||
iter++;
|
||
}
|
||
}
|
||
}
|
||
return;
|
||
}
|
||
|
||
if(sp->GetClockwise(query_p, rp.p, neighbor) == false){
|
||
double dist = hs.Distance(query_p);
|
||
MySegDist myseg(true, rp.p, neighbor, dist);
|
||
// outfile<<"insert2 "<<myseg<<endl;
|
||
// if(!(*(sss.find(myseg)) == myseg))
|
||
sss.insert(myseg);
|
||
}else{
|
||
// outfile<<"clockwise"<<endl;
|
||
double dist = hs.Distance(query_p);
|
||
MySegDist myseg(true, rp.p, neighbor, dist);
|
||
// outfile<<"remove2 "<<myseg<<endl;
|
||
//erase the element
|
||
multiset<MySegDist>::iterator iter = sss.find(myseg);
|
||
// assert(iter != sss.end());
|
||
if(iter != sss.end()){
|
||
while(iter != sss.end()){
|
||
if(*iter == myseg){
|
||
sss.erase(iter);
|
||
break;
|
||
}else
|
||
iter++;
|
||
}
|
||
}
|
||
}
|
||
|
||
}
|
||
/*
|
||
using rotational plane sweep algorithm to find visible points.
|
||
the query point should not locate on the outer contour boundary
|
||
Micha Sharir and Amir Schorr
|
||
On Shortest Paths in Polyhedral Spaces, SIAM Journal on Computing. 1986
|
||
|
||
*/
|
||
|
||
void CompTriangle::GetVPoints(Relation* rel1, Relation* rel2,
|
||
Rectangle<2>* bbox, Relation* rel3, int attr_pos)
|
||
{
|
||
// cout<<"attr_pos "<<attr_pos<<endl;
|
||
// ofstream outfile("tmrecord");
|
||
|
||
if(rel1->GetNoTuples() < 1){
|
||
cout<<"query relation is empty"<<endl;
|
||
return;
|
||
}
|
||
Tuple* query_tuple = rel1->GetTuple(1, false);
|
||
Point* query_p =
|
||
new Point(*((Point*)query_tuple->GetAttribute(VisualGraph::QLOC2)));
|
||
query_tuple->DeleteIfAllowed();
|
||
// outfile<<"query point "<<*query_p<<endl;
|
||
Coord xmax = bbox->MaxD(0) + 1.0;
|
||
|
||
Point hp;
|
||
hp.Set(xmax, query_p->GetY());
|
||
HalfSegment hs1;
|
||
hs1.Set(true, *query_p, hp);
|
||
// cout<<"horizonal p "<<hp<<endl;
|
||
|
||
///////////// sort all points by counter clockwise order//////////////////
|
||
priority_queue<RPoint> allps;
|
||
multiset<MySegDist> sss;
|
||
|
||
vector<Point> neighbors;
|
||
|
||
//one segment contains query_p
|
||
//it represents query_p equals to the endpoint(=2) or not(=3)
|
||
int no_contain = 0;
|
||
|
||
int hole_id = 0; //record whether the query point locates on the hole boundary
|
||
SpacePartition* sp = new SpacePartition();
|
||
for(int i = 1;i <= rel2->GetNoTuples();i++){
|
||
Tuple* p_tuple = rel2->GetTuple(i, false);
|
||
Point* p = (Point*)p_tuple->GetAttribute(CompTriangle::V);
|
||
if(AlmostEqual(*query_p, *p)){//equal points are ignored
|
||
p_tuple->DeleteIfAllowed();
|
||
continue;
|
||
}
|
||
Point* q1 = (Point*)p_tuple->GetAttribute(CompTriangle::NEIGHBOR1);
|
||
// outfile<<"vertex "<<*p<<endl;
|
||
// outfile<<sp->GetAngle(*query_p, hp, *p)<<endl;
|
||
Point* q2 = (Point*)p_tuple->GetAttribute(CompTriangle::NEIGHBOR2);
|
||
int reg_id =
|
||
((CcInt*)p_tuple->GetAttribute(CompTriangle::REGID))->GetIntval();
|
||
|
||
HalfSegment hs1;
|
||
hs1.Set(true, *p, *q1);
|
||
HalfSegment hs2;
|
||
hs2.Set(true, *p, *q2);
|
||
if(no_contain < 2 && hs1.Contains(*query_p)){
|
||
/* cout<<"segment contains query points "<<endl;
|
||
cout<<"current it is not supported"<<endl;
|
||
p_tuple->DeleteIfAllowed();
|
||
return;*/
|
||
// cout<<"hs1 "<<hs1<<"q1 "<<*q1<<endl;
|
||
hole_id = reg_id;
|
||
|
||
if(AlmostEqual(*query_p, hs1.GetLeftPoint()))
|
||
neighbors.push_back(hs1.GetRightPoint());
|
||
else if(AlmostEqual(*query_p, hs1.GetRightPoint()))
|
||
neighbors.push_back(hs1.GetLeftPoint());
|
||
else{
|
||
neighbors.push_back(hs1.GetLeftPoint());
|
||
neighbors.push_back(hs1.GetRightPoint());
|
||
no_contain = 2;
|
||
}
|
||
no_contain++;
|
||
}
|
||
if(no_contain < 2 && hs2.Contains(*query_p)){
|
||
// cout<<"hs2 "<<hs2<<"q2 "<<*q2<<endl;
|
||
hole_id = reg_id;
|
||
|
||
if(AlmostEqual(*query_p, hs2.GetLeftPoint()))
|
||
neighbors.push_back(hs2.GetRightPoint());
|
||
else if(AlmostEqual(*query_p, hs2.GetRightPoint()))
|
||
neighbors.push_back(hs2.GetLeftPoint());
|
||
else{
|
||
neighbors.push_back(hs2.GetLeftPoint());
|
||
neighbors.push_back(hs2.GetRightPoint());
|
||
no_contain = 2;
|
||
}
|
||
no_contain++;
|
||
}
|
||
|
||
InitializeAVL(sss,*query_p, hp, *p, *q1, sp);
|
||
InitializeAVL(sss,*query_p, hp, *p, *q2, sp);
|
||
InitializeQueue(allps,*query_p, hp, *p, sp, q1, q2, reg_id);
|
||
|
||
p_tuple->DeleteIfAllowed();
|
||
}
|
||
delete sp;
|
||
|
||
// PrintAVLTree(sss, outfile);
|
||
double last_angle = -1.0;
|
||
|
||
double angle1 = -1.0;
|
||
double angle2 = -1.0;
|
||
// bool face_direction; //false counter-clockwise, true clockwise
|
||
|
||
bool face_direction = true; //false counter-clockwise, true clockwise
|
||
|
||
//determine the region face on which side of the segment
|
||
if(hole_id != 0){
|
||
// cout<<neighbors.size()<<endl;
|
||
assert(neighbors.size() == 2);
|
||
// cout<<neighbors[0]<<" "<<neighbors[1]<<endl;
|
||
assert(!AlmostEqual(neighbors[0], neighbors[1]));
|
||
Tuple* reg_tuple = rel3->GetTuple(hole_id, false);
|
||
Region* r = (Region*)reg_tuple->GetAttribute(attr_pos);
|
||
|
||
Line* boundary = new Line(0);
|
||
r->Boundary(boundary);
|
||
SimpleLine* sboundary = new SimpleLine(0);
|
||
sboundary->fromLine(*boundary);
|
||
vector<MyHalfSegment> mhs;
|
||
//get all the points of the region
|
||
SpacePartition* sp = new SpacePartition();
|
||
if(sboundary->Size() > 0)
|
||
sp->ReorderLine(sboundary, mhs);
|
||
else{
|
||
cout<<"can't covert the boundary to a sline, maybe there is a hole"<<endl;
|
||
boundary->DeleteIfAllowed();
|
||
sboundary->DeleteIfAllowed();
|
||
return;
|
||
}
|
||
boundary->DeleteIfAllowed();
|
||
sboundary->DeleteIfAllowed();
|
||
|
||
vector<Point> ps;
|
||
for(unsigned int i = 0;i < mhs.size();i++)
|
||
ps.push_back(mhs[i].from);
|
||
|
||
angle1 = sp->GetAngle(*query_p, hp, neighbors[0]);
|
||
angle2 = sp->GetAngle(*query_p, hp, neighbors[1]);
|
||
if(sp->GetClockwise(*query_p, hp, neighbors[0]))
|
||
angle1 = 2*TM_MYPI - angle1;
|
||
if(sp->GetClockwise(*query_p, hp, neighbors[1]))
|
||
angle2 = 2*TM_MYPI - angle2;
|
||
|
||
if(angle1 > angle2){
|
||
Point temp = neighbors[0];
|
||
neighbors[0] = neighbors[1];
|
||
neighbors[1] = temp;
|
||
double temp_angle = angle1;
|
||
angle1 = angle2;
|
||
angle2 = temp_angle;
|
||
}
|
||
|
||
//combine with index1 and index2
|
||
//the point with smaller angle and larger angle
|
||
//from smaller angle to larger angle, whether it is counter clockwisr or not
|
||
if(0.0 < Area(ps)) face_direction = false;//counter-clockwise
|
||
else face_direction = true;
|
||
//query_p locates in one segment but not equal to endpoint
|
||
if(no_contain > 2){
|
||
unsigned int index1 = ps.size();
|
||
unsigned int index2 = ps.size();
|
||
for(unsigned int i = 0;i < ps.size();i++){
|
||
if(AlmostEqual(ps[i], neighbors[0])) index1 = i;
|
||
if(AlmostEqual(ps[i], neighbors[1])) index2 = i;
|
||
}
|
||
assert(index1 != ps.size() && index2 != ps.size());
|
||
if(hole_id == 1){
|
||
if(index1 == index2 + 1){
|
||
face_direction = !face_direction;
|
||
}else if(index1 == 0 && index2 == ps.size() - 1){
|
||
face_direction = !face_direction;
|
||
}
|
||
}else{
|
||
if(index1 + 1 == index2){
|
||
face_direction = !face_direction;
|
||
}else if(index1 == ps.size() - 1 && index2 == 0){
|
||
face_direction = !face_direction;
|
||
}
|
||
}
|
||
}else if(no_contain == 2){//query_p equals to one endpoint of a segment
|
||
unsigned int index1 = ps.size();
|
||
unsigned int index2 = ps.size();
|
||
for(unsigned int i = 0;i < ps.size();i++){
|
||
if(AlmostEqual(ps[i], neighbors[0])) index1 = i;
|
||
if(AlmostEqual(ps[i], *query_p)) index2 = i;
|
||
}
|
||
assert(index1 != ps.size() && index2 != ps.size());
|
||
// outfile<<"index1 "<<index1<<" index2 "<<index2<<endl;
|
||
// outfile<<"face direction "<<face_direction<<endl;
|
||
if(hole_id == 1){
|
||
if(index1 == index2 + 1){
|
||
face_direction = !face_direction;
|
||
}else if(index1 == 0 && index2 == ps.size() - 1){
|
||
face_direction = !face_direction;
|
||
}
|
||
}else{
|
||
if(index1 + 1 == index2){
|
||
face_direction = !face_direction;
|
||
}else if(index1 == ps.size() - 1 && index2 == 0){
|
||
face_direction = !face_direction;
|
||
}
|
||
}
|
||
}else assert(false);
|
||
// outfile<<"direction "<<face_direction<<" 1 "<<angle1<<" 2 "<<angle2<<endl;
|
||
// outfile<<"hole_id "<<hole_id<<endl;
|
||
reg_tuple->DeleteIfAllowed();
|
||
}
|
||
|
||
Tuple* reg_tuple = rel3->GetTuple(1, false);
|
||
Region* outer_region = (Region*)reg_tuple->GetAttribute(attr_pos);
|
||
|
||
while(allps.empty() == false){
|
||
RPoint top = allps.top();
|
||
allps.pop();
|
||
////////////////debug/////////////////
|
||
// PrintAVLTree(sss, outfile);
|
||
// outfile<<top<<" "<<top.regid<<endl;
|
||
//////////////////////////////////////
|
||
if(sss.empty()){
|
||
// outfile<<"avltree is emtpy find visible point1"<<endl;
|
||
bool visible = true;
|
||
if(top.regid == 1){//outer boundary
|
||
HalfSegment hs;
|
||
hs.Set(true, *query_p, top.p);
|
||
if(RegContainHS(outer_region, hs) == false)
|
||
visible = false;
|
||
}
|
||
if(visible){
|
||
plist1.push_back(top.p);
|
||
Line* l = new Line(0);
|
||
l->StartBulkLoad();
|
||
HalfSegment hs;
|
||
hs.Set(true, *query_p, top.p);
|
||
hs.attr.edgeno = 0;
|
||
*l += hs;
|
||
hs.SetLeftDomPoint(!hs.IsLeftDomPoint());
|
||
*l += hs;
|
||
l->EndBulkLoad();
|
||
connection.push_back(*l);
|
||
l->DeleteIfAllowed();
|
||
}
|
||
last_angle = top.angle;
|
||
/* ProcessNeighbor(sss, top, *query_p,
|
||
top.n1, hp, sp, outfile);
|
||
ProcessNeighbor(sss, top, *query_p,
|
||
top.n2, hp, sp, outfile);*/
|
||
ProcessNeighbor(sss, top, *query_p,
|
||
top.n1, hp, sp);
|
||
ProcessNeighbor(sss, top, *query_p,
|
||
top.n2, hp, sp);
|
||
continue;
|
||
}
|
||
////////////// visibility checking ///////////////////////////
|
||
if(!AlmostEqual(top.angle, last_angle)){
|
||
multiset<MySegDist>::iterator start = sss.begin();
|
||
double d = query_p->Distance(top.p);
|
||
double mindist = start->dist;
|
||
bool visible = true;
|
||
// outfile<<"d "<<d<<" mindist "<<mindist<<endl;
|
||
|
||
if(top.regid == hole_id){//filter some points on the boundary
|
||
if(face_direction == false){
|
||
if(angle1 < top.angle && top.angle < angle2)visible = false;
|
||
}else{
|
||
if(top.angle < angle1 || top.angle > angle2)visible = false;
|
||
}
|
||
}
|
||
|
||
if(visible){
|
||
if(d < mindist || AlmostEqual(d, mindist)){
|
||
// outfile<<"find visible point2"<<endl;
|
||
}else{
|
||
HalfSegment test_hs;
|
||
test_hs.Set(true, *query_p, top.p);
|
||
while(start->dist < d && start != sss.end()){
|
||
HalfSegment cur_hs;
|
||
cur_hs.Set(true, start->from, start->to);
|
||
Point ip;
|
||
if(test_hs.Intersection(cur_hs, ip)){
|
||
// outfile<<"test_hs "<<test_hs<<"cur_hs "<<cur_hs<<endl;
|
||
// outfile<<ip<<endl;
|
||
if(!AlmostEqual(ip, top.p)){
|
||
// outfile<<"visible false"<<endl;
|
||
// outfile<<"test_hs "<<test_hs<<"cur_hs "<<cur_hs<<endl;
|
||
visible = false;
|
||
break;
|
||
}
|
||
}
|
||
start++;
|
||
}
|
||
}
|
||
}
|
||
|
||
if(visible && top.regid == 1){//outer boundary
|
||
HalfSegment hs;
|
||
hs.Set(true, *query_p, top.p);
|
||
if(RegContainHS(outer_region, hs) == false)
|
||
visible = false;
|
||
}
|
||
|
||
if(visible){
|
||
// outfile<<"find visible point4"<<endl;
|
||
plist1.push_back(top.p);
|
||
Line* l = new Line(0);
|
||
l->StartBulkLoad();
|
||
HalfSegment hs;
|
||
hs.Set(true, *query_p, top.p);
|
||
hs.attr.edgeno = 0;
|
||
*l += hs;
|
||
hs.SetLeftDomPoint(!hs.IsLeftDomPoint());
|
||
*l += hs;
|
||
l->EndBulkLoad();
|
||
connection.push_back(*l);
|
||
l->DeleteIfAllowed();
|
||
}
|
||
}
|
||
// ProcessNeighbor(sss, top, *query_p,top.n1, hp, sp, outfile);
|
||
// ProcessNeighbor(sss, top, *query_p,top.n2, hp, sp, outfile);
|
||
ProcessNeighbor(sss, top, *query_p, top.n1, hp, sp);
|
||
ProcessNeighbor(sss, top, *query_p, top.n2, hp, sp);
|
||
//////////////////////////////////////////////////////////////////
|
||
last_angle = top.angle;
|
||
//////////////////////////////////////////////////////////////
|
||
}
|
||
|
||
reg_tuple->DeleteIfAllowed();
|
||
delete query_p;
|
||
|
||
}
|
||
|
||
/*********************implementation of basgraph********************/
|
||
BaseGraph::BaseGraph():g_id(0),
|
||
node_rel(NULL),
|
||
edge_rel(NULL),
|
||
adj_list(0),
|
||
entry_adj_list(0)
|
||
{
|
||
// cout<<"BaseGraph::BaseGraph()"<<endl;
|
||
}
|
||
|
||
BaseGraph::BaseGraph(ListExpr in_xValue,int in_iErrorPos,
|
||
ListExpr& inout_xErrorInfo,
|
||
bool& inout_bCorrect):g_id(0),
|
||
node_rel(NULL),
|
||
edge_rel(NULL),
|
||
adj_list(0),
|
||
entry_adj_list(0)
|
||
{
|
||
// cout<<"BaseGraph::BaseGraph(ListExpr)"<<endl;
|
||
}
|
||
|
||
BaseGraph::BaseGraph(SmiRecord& in_xValueRecord,size_t& inout_iOffset,
|
||
const ListExpr in_xTypeInfo):
|
||
g_id(0), node_rel(NULL), edge_rel(NULL),
|
||
adj_list(0), entry_adj_list(0)
|
||
{
|
||
// cout<<"BaseGraph::BaseGraph(SmiRecord)"<<endl;
|
||
}
|
||
|
||
BaseGraph::~BaseGraph()
|
||
{
|
||
// cout<<"~BaseGraph()"<<endl;
|
||
if(node_rel != NULL)
|
||
node_rel->Close();
|
||
|
||
if(edge_rel != NULL)
|
||
edge_rel->Close();
|
||
|
||
// adj_list.clean();
|
||
// entry_adj_list.clean();
|
||
|
||
}
|
||
|
||
void BaseGraph::Destroy()
|
||
{
|
||
// cout<<"Destroy()"<<endl;
|
||
if(node_rel != NULL){
|
||
node_rel->Delete();
|
||
node_rel = NULL;
|
||
}
|
||
if(edge_rel != NULL){
|
||
edge_rel->Delete();
|
||
edge_rel = NULL;
|
||
}
|
||
|
||
}
|
||
|
||
ListExpr BaseGraph::BaseGraphProp()
|
||
{
|
||
// cout<<"BaseGraphProp()"<<endl;
|
||
ListExpr examplelist = nl->TextAtom();
|
||
nl->AppendText(examplelist,
|
||
"createdualgraph(<id>,<edge-relation>,<node-relation>)");
|
||
return nl->TwoElemList(
|
||
nl->TwoElemList(nl->StringAtom("Creation"),
|
||
nl->StringAtom("Example Creation")),
|
||
nl->TwoElemList(examplelist,
|
||
nl->StringAtom("let dg=createdualgraph(id,e-rel,n-rel)")));
|
||
}
|
||
|
||
void* BaseGraph::CastBaseGraph(void* addr)
|
||
{
|
||
// cout<<"CastBaseGraph()"<<endl;
|
||
return 0;
|
||
}
|
||
|
||
Word BaseGraph::CloneBaseGraph(const ListExpr typeInfo, const Word& w)
|
||
{
|
||
// cout<<"CloneBaseGraph()"<<endl;
|
||
return SetWord(Address(0));
|
||
}
|
||
|
||
int BaseGraph::SizeOfBaseGraph()
|
||
{
|
||
// cout<<"SizeOfBaseGraph()"<<endl;
|
||
return 0;
|
||
}
|
||
|
||
/*
|
||
Given a nodeid, find all its adjacecny nodes
|
||
|
||
*/
|
||
void BaseGraph::FindAdj(int node_id, vector<bool>& flag, vector<int>& list)
|
||
{
|
||
|
||
ListEntry list_entry;
|
||
entry_adj_list.Get(node_id - 1, list_entry);
|
||
int low = list_entry.low;
|
||
int high = list_entry.high;
|
||
int j = low;
|
||
while(j < high){
|
||
int oid;
|
||
adj_list.Get(j, oid);
|
||
j++;
|
||
if(flag[oid - 1] == false){
|
||
list.push_back(oid);
|
||
flag[oid - 1] = true;
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
void BaseGraph::FindAdj(int node_id, vector<int>& list)
|
||
{
|
||
|
||
ListEntry list_entry;
|
||
entry_adj_list.Get(node_id - 1, list_entry);
|
||
int low = list_entry.low;
|
||
int high = list_entry.high;
|
||
int j = low;
|
||
while(j < high){
|
||
int oid;
|
||
adj_list.Get(j, oid);
|
||
j++;
|
||
list.push_back(oid);
|
||
}
|
||
|
||
}
|
||
|
||
/*How can we find the shortest path for any polygon (with or without holes) and
|
||
any startpoint and endpoint? As far as I know, an exhaustive search is
|
||
required. However, the search can be optimized a bit so that it doesn’t take
|
||
as long as testing every possible path. With the dual graph and visbility graph,
|
||
it can be found efficiently*/
|
||
|
||
/*build a visibility graph, connect the start and end point to the graph*/
|
||
|
||
string DualGraph::NodeTypeInfo =
|
||
"(rel(tuple((Oid int)(Rid int)(Pavement region))))";
|
||
string DualGraph::BTreeNodeTypeInfo =
|
||
"(btree(tuple((Oid int)(Rid int)(Pavement region))) int)";
|
||
string DualGraph::EdgeTypeInfo =
|
||
"(rel(tuple((Oid1 int)(Oid2 int)(Commarea line))))";
|
||
string DualGraph::NodeRTreeTypeInfo = "(rtree (tuple ((oid int)(rid int)\
|
||
(pavement region))) region FALSE)";
|
||
string DualGraph::TriangleTypeInfo1 =
|
||
"(rel(tuple((V1 int)(V2 int)(V3 int)(Centroid point)(Oid int))))";
|
||
string DualGraph::TriangleTypeInfo2 =
|
||
"(rel(tuple((Cycleno int)(Vertex point))))";
|
||
string DualGraph::TriangleTypeInfo3 =
|
||
"(rel(tuple((V1 int)(V2 int)(V3 int)(Centroid point))))";
|
||
string DualGraph::TriangleTypeInfo4 =
|
||
"(rel(tuple((Vid int)(Triid int))))";
|
||
|
||
ListExpr DualGraph::OutDualGraph(ListExpr typeInfo, Word value)
|
||
{
|
||
// cout<<"OutDualGraph()"<<endl;
|
||
DualGraph* dg = (DualGraph*)value.addr;
|
||
return dg->Out(typeInfo);
|
||
}
|
||
|
||
ListExpr DualGraph::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);
|
||
CcInt* oid = (CcInt*)node_tuple->GetAttribute(OID);
|
||
CcInt* rid = (CcInt*)node_tuple->GetAttribute(RID);
|
||
Region* reg = (Region*)node_tuple->GetAttribute(PAVEMENT);
|
||
|
||
ListExpr xRegion = OutRegion(nl->TheEmptyList(),SetWord(reg));
|
||
xNext = nl->FourElemList(nl->IntAtom(g_id),
|
||
nl->IntAtom(oid->GetIntval()),
|
||
nl->IntAtom(rid->GetIntval()),
|
||
xRegion);
|
||
if(bFirst){
|
||
xNode = nl->OneElemList(xNext);
|
||
xLast = xNode;
|
||
bFirst = false;
|
||
}else
|
||
xLast = nl->Append(xLast,xNext);
|
||
node_tuple->DeleteIfAllowed();
|
||
}
|
||
|
||
return nl->TwoElemList(nl->IntAtom(g_id),xNode);
|
||
}
|
||
|
||
Word DualGraph::InDualGraph(ListExpr in_xTypeInfo, ListExpr in_xValue,
|
||
int in_iErrorPos, ListExpr& inout_xErrorInfo,
|
||
bool& inout_bCorrect)
|
||
{
|
||
// cout<<"InDualGraph()"<<endl;
|
||
DualGraph* dg = new DualGraph(in_xValue, in_iErrorPos, inout_xErrorInfo,
|
||
inout_bCorrect);
|
||
if(inout_bCorrect) return SetWord(dg);
|
||
else{
|
||
delete dg;
|
||
return SetWord(Address(0));
|
||
}
|
||
}
|
||
|
||
Word DualGraph::CreateDualGraph(const ListExpr typeInfo)
|
||
{
|
||
// cout<<"CreateDualGraph()"<<endl;
|
||
return SetWord(new DualGraph());
|
||
}
|
||
|
||
void DualGraph::CloseDualGraph(const ListExpr typeInfo, Word& w)
|
||
{
|
||
// cout<<"CloseDualGraph()"<<endl;
|
||
delete static_cast<DualGraph*> (w.addr);
|
||
w.addr = NULL;
|
||
}
|
||
|
||
|
||
void DualGraph::DeleteDualGraph(const ListExpr typeInfo, Word& w)
|
||
{
|
||
// cout<<"DeleteDualGraph()"<<endl;
|
||
DualGraph* dg = (DualGraph*)w.addr;
|
||
// dg->Destroy();
|
||
delete dg;
|
||
w.addr = NULL;
|
||
}
|
||
|
||
bool DualGraph::CheckDualGraph(ListExpr type, ListExpr& errorInfo)
|
||
{
|
||
// cout<<"CheckDualGraph()"<<endl;
|
||
return nl->IsEqual(type, "dualgraph");
|
||
}
|
||
|
||
|
||
|
||
bool DualGraph::SaveDualGraph(SmiRecord& valueRecord, size_t& offset,
|
||
const ListExpr typeInfo, Word& value)
|
||
{
|
||
// cout<<"SaveDualGraph()"<<endl;
|
||
DualGraph* dg = (DualGraph*)value.addr;
|
||
bool result = dg->Save(valueRecord, offset, typeInfo);
|
||
|
||
return result;
|
||
}
|
||
|
||
bool DualGraph::Save(SmiRecord& in_xValueRecord,size_t& inout_iOffset,
|
||
const ListExpr in_xTypeInfo)
|
||
{
|
||
// cout<<"Save()"<<endl;
|
||
/********************Save graph id ****************************/
|
||
in_xValueRecord.Write(&g_id,sizeof(int),inout_iOffset);
|
||
inout_iOffset += sizeof(int);
|
||
|
||
////////////minimum oid - 1/////////////////////////////////////
|
||
in_xValueRecord.Write(&min_tri_oid_1,sizeof(int),inout_iOffset);
|
||
inout_iOffset += sizeof(int);
|
||
|
||
ListExpr xType;
|
||
ListExpr xNumericType;
|
||
/************************save node****************************/
|
||
nl->ReadFromString(NodeTypeInfo,xType);
|
||
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
||
if(!node_rel->Save(in_xValueRecord,inout_iOffset,xNumericType))
|
||
return false;
|
||
|
||
/************************save sorted node****************************/
|
||
nl->ReadFromString(NodeTypeInfo,xType);
|
||
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
||
if(!node_rel_sort->Save(in_xValueRecord,inout_iOffset,xNumericType))
|
||
return false;
|
||
|
||
///////////////////////save rtree on dual graph nodes///////////////////
|
||
if(!rtree_node->Save(in_xValueRecord, inout_iOffset)){
|
||
return false;
|
||
}
|
||
|
||
/************************save edge****************************/
|
||
nl->ReadFromString(EdgeTypeInfo,xType);
|
||
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
||
if(!edge_rel->Save(in_xValueRecord,inout_iOffset,xNumericType))
|
||
return false;
|
||
|
||
|
||
SecondoCatalog *ctlg = SecondoSystem::GetCatalog();
|
||
SmiRecordFile *rf = ctlg->GetFlobFile();
|
||
adj_list.saveToFile(rf, adj_list);
|
||
SmiSize offset = 0;
|
||
size_t bufsize = adj_list.headerSize();
|
||
char* buf = (char*) malloc(bufsize);
|
||
adj_list.serializeHeader(buf,offset);
|
||
assert(offset==bufsize);
|
||
in_xValueRecord.Write(buf, bufsize, inout_iOffset);
|
||
inout_iOffset += bufsize;
|
||
free(buf);
|
||
|
||
entry_adj_list.saveToFile(rf, entry_adj_list);
|
||
offset = 0;
|
||
buf = (char*) malloc(bufsize);
|
||
entry_adj_list.serializeHeader(buf,offset);
|
||
assert(offset==bufsize);
|
||
in_xValueRecord.Write(buf,bufsize, inout_iOffset);
|
||
free(buf);
|
||
inout_iOffset += bufsize;
|
||
|
||
|
||
return true;
|
||
}
|
||
|
||
bool DualGraph::OpenDualGraph(SmiRecord& valueRecord, size_t& offset,
|
||
const ListExpr typeInfo, Word& value)
|
||
{
|
||
// cout<<"OpenDualGraph()"<<endl;
|
||
value.addr = DualGraph::Open(valueRecord, offset, typeInfo);
|
||
bool result = (value.addr != NULL);
|
||
|
||
return result;
|
||
}
|
||
|
||
DualGraph* DualGraph::Open(SmiRecord& valueRecord,size_t& offset,
|
||
const ListExpr typeInfo)
|
||
{
|
||
// cout<<"Open()"<<endl;
|
||
return new DualGraph(valueRecord,offset,typeInfo);
|
||
}
|
||
|
||
DualGraph::~DualGraph()
|
||
{
|
||
// cout<<"~DualGraph()"<<endl;
|
||
if(node_rel_sort != NULL) node_rel_sort->Close();
|
||
if(rtree_node != NULL) delete rtree_node;
|
||
}
|
||
|
||
DualGraph::DualGraph():node_rel_sort(NULL), rtree_node(NULL)
|
||
{
|
||
// cout<<"DualGraph::DualGraph()"<<endl;
|
||
}
|
||
|
||
DualGraph::DualGraph(ListExpr in_xValue,int in_iErrorPos,
|
||
ListExpr& inout_xErrorInfo,
|
||
bool& inout_bCorrect):node_rel_sort(NULL), rtree_node(NULL)
|
||
|
||
{
|
||
// cout<<"DualGraph::DualGraph(ListExpr)"<<endl;
|
||
|
||
}
|
||
|
||
DualGraph::DualGraph(SmiRecord& in_xValueRecord,size_t& inout_iOffset,
|
||
const ListExpr in_xTypeInfo):node_rel_sort(NULL), rtree_node(NULL)
|
||
{
|
||
// cout<<"DualGraph::DualGraph(SmiRecord)"<<endl;
|
||
/***********************Read graph id********************************/
|
||
in_xValueRecord.Read(&g_id,sizeof(int),inout_iOffset);
|
||
inout_iOffset += sizeof(int);
|
||
|
||
/***********************minimum oid -1********************************/
|
||
in_xValueRecord.Read(&min_tri_oid_1,sizeof(int),inout_iOffset);
|
||
inout_iOffset += sizeof(int);
|
||
|
||
ListExpr xType;
|
||
ListExpr xNumericType;
|
||
/***********************Open relation for node*********************/
|
||
nl->ReadFromString(NodeTypeInfo,xType);
|
||
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
||
node_rel = Relation::Open(in_xValueRecord, inout_iOffset, xNumericType);
|
||
if(!node_rel) {
|
||
return;
|
||
}
|
||
|
||
//////////////////////node relation after sorting//////////////////////////
|
||
nl->ReadFromString(NodeTypeInfo,xType);
|
||
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
||
node_rel_sort = Relation::Open(in_xValueRecord, inout_iOffset, xNumericType);
|
||
if(!node_rel_sort) {
|
||
node_rel->Delete();
|
||
return;
|
||
}
|
||
|
||
///////////////////rtree on dual graph sorted nodes////////////////////
|
||
Word xValue;
|
||
if(!(rtree_node->Open(in_xValueRecord,inout_iOffset,
|
||
NodeRTreeTypeInfo,xValue))){
|
||
node_rel->Delete();
|
||
node_rel_sort->Delete();
|
||
return;
|
||
}
|
||
|
||
rtree_node = ( R_Tree<2,TupleId>* ) xValue.addr;
|
||
|
||
/***********************Open relation for edge*********************/
|
||
nl->ReadFromString(EdgeTypeInfo,xType);
|
||
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
||
edge_rel = Relation::Open(in_xValueRecord, inout_iOffset, xNumericType);
|
||
if(!edge_rel) {
|
||
node_rel->Delete();
|
||
node_rel_sort->Delete();
|
||
return;
|
||
}
|
||
|
||
////////////////////adjaency list////////////////////////////////
|
||
size_t bufsize = DbArray<int>::headerSize();
|
||
SmiSize offset = 0;
|
||
char* buf = (char*) malloc(bufsize);
|
||
in_xValueRecord.Read(buf, bufsize, inout_iOffset);
|
||
inout_iOffset += bufsize;
|
||
assert(buf != NULL);
|
||
adj_list.restoreHeader(buf,offset);
|
||
free(buf);
|
||
offset = 0;
|
||
buf = (char*) malloc(bufsize);
|
||
in_xValueRecord.Read(buf, bufsize, inout_iOffset);
|
||
assert(buf != NULL);
|
||
entry_adj_list.restoreHeader(buf,offset);
|
||
inout_iOffset += bufsize;
|
||
free(buf);
|
||
|
||
|
||
}
|
||
|
||
|
||
|
||
/*
|
||
let dg1 = createdualgraph(1, graph_node, graph_edge);
|
||
delete dg1;
|
||
close database;
|
||
quit; //very important, otherwise, it can't create it again
|
||
|
||
start Secondo
|
||
let dg1 = createdualgraph(1, graph_node, graph_edge);
|
||
|
||
*/
|
||
|
||
void DualGraph::Load(int id, Relation* r1, Relation* r2)
|
||
{
|
||
// cout<<"Load()"<<endl;
|
||
g_id = id;
|
||
//////////////////node relation////////////////////
|
||
ListExpr ptrList1 = listutils::getPtrList(r1);
|
||
|
||
string strQuery = "(consume(sort(feed(" + NodeTypeInfo +
|
||
"(ptr " + nl->ToString(ptrList1) + ")))))";
|
||
Word xResult;
|
||
int QueryExecuted = QueryProcessor::ExecuteQuery(strQuery, xResult);
|
||
assert(QueryExecuted);
|
||
node_rel = (Relation*)xResult.addr;
|
||
////////////////////////////////////////////////////////
|
||
/////////////create sorting node relation///////////////
|
||
////////////////////////////////////////////////////////
|
||
LoadSortNode(r1);
|
||
|
||
/////////////////edge relation/////////////////////
|
||
ListExpr ptrList2 = listutils::getPtrList(r2);
|
||
|
||
strQuery = "(consume(sort(feed(" + EdgeTypeInfo +
|
||
"(ptr " + nl->ToString(ptrList2) + ")))))";
|
||
QueryExecuted = QueryProcessor::ExecuteQuery(strQuery, xResult);
|
||
assert(QueryExecuted);
|
||
edge_rel = (Relation*)xResult.addr;
|
||
|
||
////////////adjacency list ////////////////////////////////
|
||
ListExpr ptrList3 = listutils::getPtrList(edge_rel);
|
||
|
||
strQuery = "(createbtree (" + EdgeTypeInfo +
|
||
"(ptr " + nl->ToString(ptrList3) + "))" + "Oid1)";
|
||
|
||
QueryExecuted = QueryProcessor::ExecuteQuery(strQuery,xResult);
|
||
assert(QueryExecuted);
|
||
BTree* btree_node_oid1 = (BTree*)xResult.addr;
|
||
|
||
|
||
ListExpr ptrList4 = listutils::getPtrList(edge_rel);
|
||
|
||
strQuery = "(createbtree (" + EdgeTypeInfo +
|
||
"(ptr " + nl->ToString(ptrList4) + "))" + "Oid2)";
|
||
|
||
QueryExecuted = QueryProcessor::ExecuteQuery(strQuery, xResult);
|
||
assert(QueryExecuted);
|
||
BTree* btree_node_oid2 = (BTree*)xResult.addr;
|
||
|
||
////////////////////////////////////////////////////////////////////////
|
||
/////////////////get minimum triangle oid///////////////////////////////
|
||
////////////////////////////////////////////////////////////////////////
|
||
int min_tri_oid = numeric_limits<int>::max();
|
||
for(int i = 1;i <= node_rel->GetNoTuples();i++){
|
||
Tuple* tri_tuple = node_rel->GetTuple(i, false);
|
||
int tri_oid = ((CcInt*)tri_tuple->GetAttribute(OID))->GetIntval();
|
||
if(tri_oid < min_tri_oid) min_tri_oid = tri_oid;
|
||
tri_tuple->DeleteIfAllowed();
|
||
}
|
||
// cout<<"min tri oid "<<min_tri_oid<<endl;
|
||
min_tri_oid--;
|
||
min_tri_oid_1 = min_tri_oid;
|
||
assert(min_tri_oid_1 >= 0);
|
||
// cout<<"b-tree on edge is finished....."<<endl;
|
||
|
||
for(int i = 1;i <= node_rel->GetNoTuples();i++){
|
||
Tuple* tri_tuple = node_rel->GetTuple(i, false);
|
||
int tri_oid = ((CcInt*)tri_tuple->GetAttribute(OID))->GetIntval();
|
||
tri_tuple->DeleteIfAllowed();
|
||
|
||
CcInt* nodeid = new CcInt(true, tri_oid);
|
||
|
||
BTreeIterator* btree_iter1 = btree_node_oid1->ExactMatch(nodeid);
|
||
int start = adj_list.Size();
|
||
// cout<<"start "<<start<<endl;
|
||
while(btree_iter1->Next()){
|
||
Tuple* edge_tuple = edge_rel->GetTuple(btree_iter1->GetId(), false);
|
||
int oid = ((CcInt*)edge_tuple->GetAttribute(OIDSECOND))->GetIntval();
|
||
// adj_list.Append(oid);
|
||
adj_list.Append(oid - min_tri_oid_1);//actually, it is node tuple id >= 1
|
||
edge_tuple->DeleteIfAllowed();
|
||
}
|
||
delete btree_iter1;
|
||
|
||
BTreeIterator* btree_iter2 = btree_node_oid2->ExactMatch(nodeid);
|
||
while(btree_iter2->Next()){
|
||
Tuple* edge_tuple = edge_rel->GetTuple(btree_iter2->GetId(), false);
|
||
int oid = ((CcInt*)edge_tuple->GetAttribute(OIDFIRST))->GetIntval();
|
||
// adj_list.Append(oid);
|
||
adj_list.Append(oid - min_tri_oid_1);//actually, it is node tuple id >= 1
|
||
edge_tuple->DeleteIfAllowed();
|
||
}
|
||
delete btree_iter2;
|
||
int end = adj_list.Size();
|
||
entry_adj_list.Append(ListEntry(start, end));
|
||
|
||
delete nodeid;
|
||
}
|
||
|
||
delete btree_node_oid1;
|
||
delete btree_node_oid2;
|
||
|
||
/* for(int i = 0;i < entry_adj_list.Size();i++){
|
||
cout<<"i "<<i + 1<<endl;
|
||
ListEntry list_entry;
|
||
entry_adj_list.Get(i, list_entry);
|
||
int low = list_entry.low;
|
||
int high = list_entry.high;
|
||
int j = low;
|
||
cout<<"adjaency list low"<<low<<"high "<<high<<endl;
|
||
while(j < high){
|
||
int oid;
|
||
adj_list.Get(j, oid);
|
||
cout<<"oid "<<oid<<" ";
|
||
j++;
|
||
}
|
||
cout<<endl;
|
||
}*/
|
||
|
||
}
|
||
|
||
/*
|
||
sort the dual graph node by the bounding box of the region (triangle)
|
||
|
||
*/
|
||
void DualGraph::LoadSortNode(Relation* r1)
|
||
{
|
||
|
||
ListExpr ptrList1 = listutils::getPtrList(r1);
|
||
string strQuery = "(consume(sortby(feed(" + NodeTypeInfo +
|
||
"(ptr " + nl->ToString(ptrList1) + ")))((Pavement asc))))";
|
||
|
||
// cout<<strQuery<<endl;
|
||
Word xResult;
|
||
int QueryExecuted = QueryProcessor::ExecuteQuery(strQuery, xResult);
|
||
assert(QueryExecuted);
|
||
node_rel_sort = (Relation*)xResult.addr;
|
||
|
||
|
||
// for(int i = 1;i <= node_rel_sort->GetNoTuples();i++){
|
||
// Tuple* tuple = node_rel_sort->GetTuple(i, false);
|
||
// int oid = ((CcInt*)tuple->GetAttribute(OID))->GetIntval();
|
||
// cout<<"oid "<<oid<<endl;
|
||
// tuple->DeleteIfAllowed();
|
||
// }
|
||
|
||
ListExpr ptrList2 = listutils::getPtrList(node_rel_sort);
|
||
|
||
strQuery = "(bulkloadrtree(addid(feed (" + NodeTypeInfo +
|
||
" (ptr " + nl->ToString(ptrList2) + ")))) Pavement)";
|
||
|
||
QueryExecuted = QueryProcessor::ExecuteQuery ( strQuery, xResult );
|
||
assert ( QueryExecuted );
|
||
rtree_node = ( R_Tree<2,TupleId>* ) xResult.addr;
|
||
|
||
}
|
||
|
||
/*
|
||
find all triangles that intersect the input line and return all tid of these
|
||
traingles
|
||
|
||
*/
|
||
void DualGraph::LineIntersectTri(Line* l, vector<Line>& line_list)
|
||
{
|
||
DFTraverse(rtree_node, rtree_node->RootRecordId(), l, line_list);
|
||
}
|
||
|
||
/*
|
||
Using depth first method to travese the R-tree to find all triangles
|
||
intersecting the line and record the triangle tuple id
|
||
|
||
*/
|
||
|
||
void DualGraph::DFTraverse(R_Tree<2,TupleId>* rtree, SmiRecordId adr,
|
||
Line* line, vector<Line>& line_list)
|
||
{
|
||
const double delta_dist = 0.001;
|
||
R_TreeNode<2,TupleId>* node = rtree->GetMyNode(adr,false,
|
||
rtree->MinEntries(0), rtree->MaxEntries(0));
|
||
for(int j = 0;j < node->EntryCount();j++){
|
||
if(node->IsLeaf()){
|
||
R_TreeLeafEntry<2,TupleId> e =
|
||
(R_TreeLeafEntry<2,TupleId>&)(*node)[j];
|
||
Tuple* dg_tuple = node_rel_sort->GetTuple(e.info, false);
|
||
Region* candi_reg =
|
||
(Region*)dg_tuple->GetAttribute(DualGraph::PAVEMENT);
|
||
|
||
Line* res = new Line(0);
|
||
line->Intersection(*candi_reg, *res);
|
||
|
||
if(res->Length() > delta_dist){
|
||
line_list.push_back(*res);
|
||
}
|
||
res->DeleteIfAllowed();
|
||
dg_tuple->DeleteIfAllowed();
|
||
}else{
|
||
R_TreeInternalEntry<2> e =
|
||
(R_TreeInternalEntry<2>&)(*node)[j];
|
||
if(e.box.Intersects(line->BoundingBox())){
|
||
DFTraverse(rtree, e.pointer, line, line_list);
|
||
}
|
||
}
|
||
}
|
||
delete node;
|
||
|
||
}
|
||
|
||
/*
|
||
find which triangle contains the point
|
||
|
||
*/
|
||
int DualGraph::GetTriId_OfPoint(Point& loc)
|
||
{
|
||
vector<int> tri_oid_list;
|
||
DFTraverse2(rtree_node, rtree_node->RootRecordId(), loc, tri_oid_list);
|
||
if(tri_oid_list.size() > 0) return tri_oid_list[0];
|
||
else
|
||
return -1;
|
||
}
|
||
|
||
/*
|
||
find which triangle contains the point
|
||
|
||
*/
|
||
void DualGraph::DFTraverse2(R_Tree<2,TupleId>* rtree, SmiRecordId adr,
|
||
Point& loc, vector<int>& tri_oid_list)
|
||
{
|
||
R_TreeNode<2,TupleId>* node = rtree->GetMyNode(adr,false,
|
||
rtree->MinEntries(0), rtree->MaxEntries(0));
|
||
for(int j = 0;j < node->EntryCount();j++){
|
||
if(node->IsLeaf()){
|
||
R_TreeLeafEntry<2,TupleId> e =
|
||
(R_TreeLeafEntry<2,TupleId>&)(*node)[j];
|
||
Tuple* dg_tuple = node_rel_sort->GetTuple(e.info, false);
|
||
Region* candi_reg =
|
||
(Region*)dg_tuple->GetAttribute(PAVEMENT);
|
||
|
||
if(loc.Inside(*candi_reg)){
|
||
int oid = ((CcInt*)dg_tuple->GetAttribute(OID))->GetIntval();
|
||
tri_oid_list.push_back(oid);
|
||
}
|
||
dg_tuple->DeleteIfAllowed();
|
||
}else{
|
||
R_TreeInternalEntry<2> e =
|
||
(R_TreeInternalEntry<2>&)(*node)[j];
|
||
if(loc.Inside(e.box)){
|
||
DFTraverse2(rtree, e.pointer, loc, tri_oid_list);
|
||
}
|
||
}
|
||
}
|
||
delete node;
|
||
|
||
}
|
||
|
||
/*
|
||
find all triangles that their distances to the input point is smaller than
|
||
the given distance threshold
|
||
|
||
*/
|
||
void DualGraph::DFTraverse3(R_Tree<2,TupleId>* rtree, SmiRecordId adr,
|
||
Point& loc, vector<int>& tri_oid_list, double dist)
|
||
{
|
||
R_TreeNode<2,TupleId>* node = rtree->GetMyNode(adr,false,
|
||
rtree->MinEntries(0), rtree->MaxEntries(0));
|
||
for(int j = 0;j < node->EntryCount();j++){
|
||
if(node->IsLeaf()){
|
||
R_TreeLeafEntry<2,TupleId> e =
|
||
(R_TreeLeafEntry<2,TupleId>&)(*node)[j];
|
||
Tuple* dg_tuple = node_rel_sort->GetTuple(e.info, false);
|
||
Region* candi_reg =
|
||
(Region*)dg_tuple->GetAttribute(PAVEMENT);
|
||
|
||
if(candi_reg->Distance(loc) < dist){
|
||
tri_oid_list.push_back(e.info);
|
||
}
|
||
dg_tuple->DeleteIfAllowed();
|
||
}else{
|
||
R_TreeInternalEntry<2> e =
|
||
(R_TreeInternalEntry<2>&)(*node)[j];
|
||
if(loc.Distance(e.box) < dist){
|
||
DFTraverse3(rtree, e.pointer, loc, tri_oid_list, dist);
|
||
}
|
||
}
|
||
}
|
||
delete node;
|
||
|
||
}
|
||
|
||
/*
|
||
calculate a path connecting two cells for generating metro routes
|
||
|
||
*/
|
||
void DualGraph::Path_Weight(int start, int end, vector<int>& path)
|
||
{
|
||
// cout<<"start "<<start<<" end "<<end<<endl;
|
||
|
||
vector<bool> area_flag;
|
||
for(int i = 1;i <= node_rel->GetNoTuples();i++)
|
||
area_flag.push_back(false);
|
||
|
||
area_flag[start - 1] = true;
|
||
|
||
////////////////shortest path algorithm///////////////////////
|
||
priority_queue<SPath_elem> path_queue;
|
||
vector<SPath_elem> expand_path;
|
||
|
||
path_queue.push(SPath_elem(-1, 0, start, 1));
|
||
expand_path.push_back(SPath_elem(-1, 0, start, 1));
|
||
bool find = false;
|
||
SPath_elem dest;//////////destination
|
||
|
||
while(path_queue.empty() == false){
|
||
SPath_elem top = path_queue.top();
|
||
path_queue.pop();
|
||
// top.Print();
|
||
|
||
if(top.tri_index == end){
|
||
// cout<<"find the path"<<endl;
|
||
find = true;
|
||
dest = top;
|
||
break;
|
||
}
|
||
////////find its adjacecy element, and push them into queue and path//////
|
||
vector<int> adj_list;
|
||
FindAdj(top.tri_index, area_flag, adj_list);
|
||
|
||
int pos_expand_path = top.cur_index;
|
||
for(unsigned int i = 0;i < adj_list.size();i++){
|
||
int expand_path_size = expand_path.size();
|
||
path_queue.push(SPath_elem(pos_expand_path, expand_path_size,
|
||
adj_list[i], top.weight+1));
|
||
expand_path.push_back(SPath_elem(pos_expand_path, expand_path_size,
|
||
adj_list[i], top.weight+1));
|
||
}
|
||
|
||
|
||
area_flag[top.tri_index - 1] = true;
|
||
|
||
}
|
||
|
||
if(find){
|
||
vector<int> path_record;
|
||
while(dest.prev_index != -1){
|
||
// sleeve.push_back(triangles[dest.tri_index]);
|
||
path_record.push_back(dest.tri_index);
|
||
dest = expand_path[dest.prev_index];
|
||
}
|
||
// sleeve.push_back(triangles[dest.tri_index]);
|
||
path_record.push_back(dest.tri_index);
|
||
|
||
for(int i = path_record.size() - 1;i >= 0;i--){
|
||
// cout<<"oid "<<path_record[i]<<endl;
|
||
path.push_back(path_record[i]);
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
Walk_SP::Walk_SP()
|
||
{
|
||
dg = NULL;
|
||
vg = NULL;
|
||
rel1 = NULL;
|
||
rel2 = NULL;
|
||
count = 0;
|
||
resulttype = NULL;
|
||
rel3 = NULL;
|
||
rel4 = NULL;
|
||
btree = NULL;
|
||
}
|
||
Walk_SP::Walk_SP(DualGraph* g1, VisualGraph* g2, Relation* r1,
|
||
Relation* r2):dg(g1), vg(g2),rel1(r1), rel2(r2), count(0),
|
||
resulttype(NULL), rel3(NULL), rel4(NULL), btree(NULL)
|
||
{
|
||
|
||
}
|
||
|
||
Walk_SP:: ~Walk_SP()
|
||
{
|
||
if(resulttype != NULL) delete resulttype;
|
||
}
|
||
|
||
|
||
|
||
|
||
/*
|
||
using visiblity graph to find the shortest path
|
||
first connects the start and end point to the VG, and then applies A star
|
||
algorithm
|
||
1. (rel (tuple ((v1 int) (v2 int) (v3 int) (centroid point)))):
|
||
for each triangle, we represent it by its three vertices id
|
||
the value of v1 v2 and v3 is the tuple id of the vertex in visibility graph
|
||
with v1, v2 and v3, we can get the point of the vertex
|
||
|
||
2. (rel (tuple ((vid int) (triid int))))
|
||
it records the vertex id and the triangle id
|
||
|
||
these two parameters are used to find all triangles that a vertex belongs to
|
||
|
||
*/
|
||
void Walk_SP::WalkShortestPath(Line* res)
|
||
{
|
||
// cout<<"WalkShortestPath"<<endl;
|
||
if(rel1->GetNoTuples() != 1 || rel2->GetNoTuples() != 1){
|
||
cout<<"input query relation is not correct"<<endl;
|
||
return;
|
||
}
|
||
Tuple* t1 = rel1->GetTuple(1, false);
|
||
int oid1 = ((CcInt*)t1->GetAttribute(VisualGraph::QOID))->GetIntval();
|
||
Point* p1 = (Point*)t1->GetAttribute(VisualGraph::QLOC2);
|
||
Point loc1(*p1);
|
||
t1->DeleteIfAllowed();
|
||
|
||
Tuple* t2 = rel2->GetTuple(1, false);
|
||
int oid2 = ((CcInt*)t2->GetAttribute(VisualGraph::QOID))->GetIntval();
|
||
Point* p2 = (Point*)t2->GetAttribute(VisualGraph::QLOC2);
|
||
Point loc2(*p2);
|
||
t2->DeleteIfAllowed();
|
||
|
||
// cout<<"tri_id1 "<<oid1<<" tri_id2 "<<oid2<<endl;
|
||
// cout<<"loc1 "<<loc1<<" loc2 "<<loc2<<endl;
|
||
oid1 -= dg->min_tri_oid_1;
|
||
oid2 -= dg->min_tri_oid_1;
|
||
|
||
int no_node_graph = dg->No_Of_Node();
|
||
if(oid1 < 1 || oid1 > no_node_graph){
|
||
cout<<"loc1 does not exist"<<endl;
|
||
return;
|
||
}
|
||
if(oid2 < 1 || oid2 > no_node_graph){
|
||
cout<<"loc2 does not exist"<<endl;
|
||
return;
|
||
}
|
||
if(AlmostEqual(loc1,loc2)){
|
||
cout<<"start location equals to end location"<<endl;
|
||
return;
|
||
}
|
||
Tuple* tuple1 = dg->GetNodeRel()->GetTuple(oid1, false);
|
||
Region* reg1 = (Region*)tuple1->GetAttribute(DualGraph::PAVEMENT);
|
||
|
||
CompTriangle* ct1 = new CompTriangle(reg1);
|
||
assert(ct1->PolygonConvex());
|
||
delete ct1;
|
||
|
||
if(loc1.Inside(*reg1) == false){
|
||
tuple1->DeleteIfAllowed();
|
||
cout<<"point1 is not inside the polygon"<<endl;
|
||
return;
|
||
}
|
||
Tuple* tuple2 = dg->GetNodeRel()->GetTuple(oid2, false);
|
||
Region* reg2 = (Region*)tuple2->GetAttribute(DualGraph::PAVEMENT);
|
||
|
||
CompTriangle* ct2 = new CompTriangle(reg2);
|
||
assert(ct2->PolygonConvex());
|
||
delete ct2;
|
||
|
||
if(loc2.Inside(*reg2) == false){
|
||
tuple1->DeleteIfAllowed();
|
||
tuple2->DeleteIfAllowed();
|
||
cout<<"point2 is not inside the polygon"<<endl;
|
||
return;
|
||
}
|
||
tuple1->DeleteIfAllowed();
|
||
tuple2->DeleteIfAllowed();
|
||
|
||
////////////////////////////////////////////////////
|
||
////////debuging euclidean connection//////////////
|
||
// oid1 = 34450 - dg->min_tri_oid_1;
|
||
// oid2 = 34430 - dg->min_tri_oid_1;
|
||
// loc1.Set(24164.01, 15711.896);
|
||
// loc2.Set(24170.12, 15720.85);
|
||
|
||
//////////////////////////////////////////////////
|
||
|
||
WalkShortestPath2(oid1, oid2, loc1, loc2, res);
|
||
|
||
}
|
||
|
||
/*
|
||
test shortest path for pedestrian
|
||
|
||
*/
|
||
void Walk_SP::TestWalkShortestPath(int tid1, int tid2)
|
||
{
|
||
// cout<<"WalkShortestPath"<<endl;
|
||
clock_t start, finish;
|
||
start = clock();
|
||
|
||
Tuple* t1 = rel1->GetTuple(tid1, false);
|
||
int oid1 = ((CcInt*)t1->GetAttribute(VisualGraph::QOID))->GetIntval();
|
||
Point* p1 = (Point*)t1->GetAttribute(VisualGraph::QLOC2);
|
||
Point loc1(*p1);
|
||
|
||
Tuple* t2 = rel2->GetTuple(tid2, false);
|
||
int oid2 = ((CcInt*)t2->GetAttribute(VisualGraph::QOID))->GetIntval();
|
||
Point* p2 = (Point*)t2->GetAttribute(VisualGraph::QLOC2);
|
||
Point loc2(*p2);
|
||
|
||
// cout<<"tri_id1 "<<oid1<<" tri_id2 "<<oid2<<endl;
|
||
// cout<<"loc1 "<<loc1<<" loc2 "<<loc2<<endl;
|
||
oid1 -= dg->min_tri_oid_1;
|
||
oid2 -= dg->min_tri_oid_1;
|
||
|
||
int no_node_graph = dg->No_Of_Node();
|
||
if(oid1 < 1 || oid1 > no_node_graph){
|
||
cout<<"loc1 does not exist"<<endl;
|
||
return;
|
||
}
|
||
if(oid2 < 1 || oid2 > no_node_graph){
|
||
cout<<"loc2 does not exist"<<endl;
|
||
return;
|
||
}
|
||
if(AlmostEqual(loc1,loc2)){
|
||
cout<<"start location equals to end location"<<endl;
|
||
return;
|
||
}
|
||
Tuple* tuple1 = dg->GetNodeRel()->GetTuple(oid1, false);
|
||
Region* reg1 = (Region*)tuple1->GetAttribute(DualGraph::PAVEMENT);
|
||
|
||
CompTriangle* ct1 = new CompTriangle(reg1);
|
||
assert(ct1->PolygonConvex());
|
||
delete ct1;
|
||
|
||
if(loc1.Inside(*reg1) == false){
|
||
tuple1->DeleteIfAllowed();
|
||
cout<<"point1 is not inside the polygon"<<endl;
|
||
return;
|
||
}
|
||
Tuple* tuple2 = dg->GetNodeRel()->GetTuple(oid2, false);
|
||
Region* reg2 = (Region*)tuple2->GetAttribute(DualGraph::PAVEMENT);
|
||
|
||
CompTriangle* ct2 = new CompTriangle(reg2);
|
||
assert(ct2->PolygonConvex());
|
||
delete ct2;
|
||
|
||
if(loc2.Inside(*reg2) == false){
|
||
tuple1->DeleteIfAllowed();
|
||
tuple2->DeleteIfAllowed();
|
||
cout<<"point2 is not inside the polygon"<<endl;
|
||
return;
|
||
}
|
||
tuple1->DeleteIfAllowed();
|
||
tuple2->DeleteIfAllowed();
|
||
|
||
if(oid1 == oid2){/////////////start and end point are located on the same tri
|
||
Line* res = new Line(0);
|
||
res->StartBulkLoad();
|
||
/////////////////////////////////////////////////////
|
||
HalfSegment hs;
|
||
hs.Set(true, loc1, loc2);
|
||
hs.attr.edgeno = 0;
|
||
*res += hs;
|
||
hs.SetLeftDomPoint(!hs.IsLeftDomPoint());
|
||
*res += hs;
|
||
/////////////////////////////////////////////////////
|
||
res->EndBulkLoad();
|
||
oids1.push_back(tid1); //vertex id
|
||
oids2.push_back(tid2); //vertex id
|
||
path.push_back(*res);
|
||
// double len = res->Length();
|
||
// printf("Euclidean length: %.4f Walk length: %.4f\n",loc1.Distance(loc2),len);
|
||
res->DeleteIfAllowed();
|
||
return;
|
||
}
|
||
|
||
///////////////////////////////////////////////////////////////////////
|
||
///////////////////check Eudlidean Connection//////////////////////////
|
||
//////////////////////////////////////////////////////////////////////
|
||
|
||
if(EuclideanConnect2(oid1, loc1, oid2, loc2)){
|
||
Line* res = new Line(0);
|
||
res->StartBulkLoad();
|
||
/////////////////////////////////////////////////////
|
||
HalfSegment hs;
|
||
hs.Set(true, loc1, loc2);
|
||
hs.attr.edgeno = 0;
|
||
*res += hs;
|
||
hs.SetLeftDomPoint(!hs.IsLeftDomPoint());
|
||
*res += hs;
|
||
/////////////////////////////////////////////////////
|
||
res->EndBulkLoad();
|
||
oids1.push_back(tid1); //vertex id
|
||
oids2.push_back(tid2); //vertex id
|
||
path.push_back(*res);
|
||
res->DeleteIfAllowed();
|
||
// double len = res->Length();
|
||
// printf("Euclidean length: %.4f Walk length: %.4f\n",loc1.Distance(loc2),len);
|
||
return;
|
||
}
|
||
|
||
///////////////////////////////////////////////////////////////////////
|
||
priority_queue<WPath_elem> path_queue;
|
||
vector<WPath_elem> expand_path;
|
||
////////////////find all visibility nodes to start node/////////
|
||
///////connect them to the visibility graph/////////////////////
|
||
VGraph* vg1 = new VGraph(dg, NULL, rel3, vg->GetNodeRel());
|
||
vg1->GetVisibilityNode(oid1, loc1);
|
||
|
||
assert(vg1->oids1.size() == vg1->p_list.size());
|
||
|
||
if(vg1->oids1.size() == 1){//start point equasl to triangle vertex
|
||
double w = loc1.Distance(loc2);
|
||
path_queue.push(WPath_elem(-1, 0, vg1->oids1[0], w, loc1, 0.0));
|
||
expand_path.push_back(WPath_elem(-1, 0, vg1->oids1[0], w, loc1, 0.0));
|
||
|
||
}else{
|
||
double w = loc1.Distance(loc2);
|
||
path_queue.push(WPath_elem(-1, 0, -1, w, loc1,0.0));//start location
|
||
expand_path.push_back(WPath_elem(-1, 0, -1, w, loc1,0.0));//start location
|
||
int prev_index = 0;
|
||
// cout<<"vnode id ";
|
||
for(unsigned int i = 0;i < vg1->oids1.size();i++){
|
||
// cout<<vg1->oids1[i]<<" ";
|
||
int expand_path_size = expand_path.size();
|
||
double d = loc1.Distance(vg1->p_list[i]);
|
||
w = d + vg1->p_list[i].Distance(loc2);
|
||
path_queue.push(WPath_elem(prev_index, expand_path_size,
|
||
vg1->oids1[i], w, vg1->p_list[i], d));
|
||
expand_path.push_back(WPath_elem(prev_index, expand_path_size,
|
||
vg1->oids1[i], w, vg1->p_list[i], d));
|
||
}
|
||
}
|
||
// cout<<endl;
|
||
delete vg1;
|
||
////////////////find all visibility nodes to the end node/////////
|
||
VGraph* vg2 = new VGraph(dg, NULL, rel3, vg->GetNodeRel());
|
||
vg2->GetVisibilityNode(oid2, loc2);
|
||
|
||
assert(vg2->oids1.size() == vg2->p_list.size());
|
||
//if the end node equals to triangle vertex.
|
||
//it can be connected by adjacency list
|
||
//we don't conenct it to the visibility graph
|
||
if(vg2->oids1.size() == 1){
|
||
// cout<<"end point id "<<vg2->oids1[0]<<endl;
|
||
}
|
||
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(AlmostEqual(top.loc, loc2)){
|
||
// cout<<"find the path"<<endl;
|
||
find = true;
|
||
dest = top;
|
||
break;
|
||
}
|
||
//do not consider the start point
|
||
//if it is 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;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
///////////////////////////////////////////////////////////////
|
||
}
|
||
|
||
delete neighbor_end;
|
||
delete vg2;
|
||
/////////////construct path///////////////////////////////////////////
|
||
double len = 0.0;
|
||
if(find){
|
||
Line* l = new Line(0);
|
||
l->StartBulkLoad();
|
||
while(dest.prev_index != -1){
|
||
Point p1 = dest.loc;
|
||
dest = expand_path[dest.prev_index];
|
||
Point p2 = dest.loc;
|
||
/////////////////////////////////////////////////////
|
||
HalfSegment hs;
|
||
hs.Set(true, p1, p2);
|
||
hs.attr.edgeno = 0;
|
||
*l += hs;
|
||
hs.SetLeftDomPoint(!hs.IsLeftDomPoint());
|
||
*l += hs;
|
||
/////////////////////////////////////////////////////
|
||
}
|
||
oids1.push_back(tid1); //vertex id
|
||
oids2.push_back(tid2); //vertex id
|
||
|
||
l->EndBulkLoad();
|
||
path.push_back(*l);
|
||
len = l->Length();
|
||
l->DeleteIfAllowed();
|
||
|
||
finish = clock();
|
||
printf("tid1: %d, tid2: %d, Euclidean: %.4f Walk: %.4f Time: %f\n",
|
||
tid1, tid2, loc1.Distance(loc2),len,
|
||
(double)(finish - start) / CLOCKS_PER_SEC);
|
||
}
|
||
}
|
||
|
||
/*
|
||
called by WalkShortestPath
|
||
|
||
*/
|
||
void Walk_SP::WalkShortestPath2(int oid1, int oid2, Point loc1, Point loc2,
|
||
Line* res)
|
||
{
|
||
// cout<<"WalkShortestPath2"<<endl;
|
||
// cout<<"tri_id1 "<<oid1<<" tri_id2 "<<oid2<<endl;
|
||
// cout<<"loc1 "<<loc1<<" loc2 "<<loc2<<endl;
|
||
|
||
if(oid1 == oid2){/////////////start and end point are located on the same tri
|
||
res->StartBulkLoad();
|
||
/////////////////////////////////////////////////////
|
||
if(!AlmostEqual(loc1, loc2)){/////////two locations are equal
|
||
HalfSegment hs;
|
||
hs.Set(true, loc1, loc2);
|
||
hs.attr.edgeno = 0;
|
||
*res += hs;
|
||
hs.SetLeftDomPoint(!hs.IsLeftDomPoint());
|
||
*res += hs;
|
||
}
|
||
/////////////////////////////////////////////////////
|
||
res->EndBulkLoad();
|
||
// double len = res->Length();
|
||
// printf("Euclidean length: %.4f Walk length: %.4f\n",loc1.Distance(loc2),len);
|
||
return;
|
||
}
|
||
///////////////////////////////////////////////////////////////////////
|
||
///////////////////check Eudlidean Connection//////////////////////////
|
||
///////////////////////////////////////////////////////////////////////
|
||
// clock_t start, finish;
|
||
// start = clock();
|
||
|
||
if(EuclideanConnect2(oid1, loc1, oid2, loc2)){
|
||
res->StartBulkLoad();
|
||
/////////////////////////////////////////////////////
|
||
HalfSegment hs;
|
||
hs.Set(true, loc1, loc2);
|
||
hs.attr.edgeno = 0;
|
||
*res += hs;
|
||
hs.SetLeftDomPoint(!hs.IsLeftDomPoint());
|
||
*res += hs;
|
||
/////////////////////////////////////////////////////
|
||
res->EndBulkLoad();
|
||
// double len = res->Length();
|
||
// printf("Euclidean length: %.4f Walk length: %.4f\n",loc1.Distance(loc2),len);
|
||
return;
|
||
}
|
||
// finish = clock();
|
||
// printf("Time: %f\n",(double)(finish - start) / CLOCKS_PER_SEC);
|
||
|
||
///////////////////////////////////////////////////////////////////////
|
||
priority_queue<WPath_elem> path_queue;
|
||
vector<WPath_elem> expand_path;
|
||
////////////////find all visibility nodes to start node/////////
|
||
///////connect them to the visibility graph/////////////////////
|
||
VGraph* vg1 = new VGraph(dg, NULL, rel3, vg->GetNodeRel());
|
||
|
||
vg1->GetVisibilityNode(oid1, loc1);
|
||
|
||
assert(vg1->oids1.size() == vg1->p_list.size());
|
||
|
||
if(vg1->oids1.size() == 1){//start point equasl to triangle vertex
|
||
double w = loc1.Distance(loc2);
|
||
path_queue.push(WPath_elem(-1, 0, vg1->oids1[0], w, loc1, 0.0));
|
||
expand_path.push_back(WPath_elem(-1, 0, vg1->oids1[0], w, loc1, 0.0));
|
||
|
||
}else{
|
||
double w = loc1.Distance(loc2);
|
||
path_queue.push(WPath_elem(-1, 0, -1, w, loc1,0.0));//start location
|
||
expand_path.push_back(WPath_elem(-1, 0, -1, w, loc1,0.0));//start location
|
||
int prev_index = 0;
|
||
// cout<<"vnode id ";
|
||
for(unsigned int i = 0;i < vg1->oids1.size();i++){
|
||
// cout<<vg1->oids1[i]<<" ";
|
||
int expand_path_size = expand_path.size();
|
||
double d = loc1.Distance(vg1->p_list[i]);
|
||
w = d + vg1->p_list[i].Distance(loc2);
|
||
path_queue.push(WPath_elem(prev_index, expand_path_size,
|
||
vg1->oids1[i], w, vg1->p_list[i], d));
|
||
expand_path.push_back(WPath_elem(prev_index, expand_path_size,
|
||
vg1->oids1[i], w, vg1->p_list[i], d));
|
||
}
|
||
}
|
||
|
||
delete vg1;
|
||
////////////////find all visibility nodes to the end node/////////
|
||
VGraph* vg2 = new VGraph(dg, NULL, rel3, vg->GetNodeRel());
|
||
|
||
vg2->GetVisibilityNode(oid2, loc2);
|
||
|
||
assert(vg2->oids1.size() == vg2->p_list.size());
|
||
//if the end node equals to triangle vertex.
|
||
//it can be connected by adjacency list
|
||
//we don't conenct it to the visibility graph
|
||
if(vg2->oids1.size() == 1){
|
||
// cout<<"end point id "<<vg2->oids1[0]<<endl;
|
||
}
|
||
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);
|
||
|
||
// clock_t start, finish;
|
||
// start = clock();
|
||
|
||
WPath_elem dest;
|
||
while(path_queue.empty() == false){
|
||
WPath_elem top = path_queue.top();
|
||
path_queue.pop();
|
||
// cout<<"top elem "<<endl;
|
||
// top.Print();
|
||
|
||
if(AlmostEqual(top.loc, loc2)){
|
||
// cout<<"find the path"<<endl;
|
||
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;
|
||
// cout<<"neighbor "<<endl;
|
||
// expand_path[expand_path.size() - 1].Print();
|
||
}
|
||
}
|
||
|
||
////////////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;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
///////////////////////////////////////////////////////////////
|
||
}
|
||
|
||
|
||
// finish = clock();
|
||
// printf("Time: %f\n",(double)(finish - start) / CLOCKS_PER_SEC);
|
||
|
||
delete neighbor_end;
|
||
delete vg2;
|
||
/////////////construct path///////////////////////////////////////////
|
||
//double len = 0.0;
|
||
if(find){
|
||
res->StartBulkLoad();
|
||
while(dest.prev_index != -1){
|
||
Point p1 = dest.loc;
|
||
dest = expand_path[dest.prev_index];
|
||
Point p2 = dest.loc;
|
||
/////////////////////////////////////////////////////
|
||
HalfSegment hs;
|
||
hs.Set(true, p1, p2);
|
||
hs.attr.edgeno = 0;
|
||
*res += hs;
|
||
hs.SetLeftDomPoint(!hs.IsLeftDomPoint());
|
||
*res += hs;
|
||
/////////////////////////////////////////////////////
|
||
}
|
||
res->EndBulkLoad();
|
||
//len = res->Length();
|
||
}
|
||
}
|
||
|
||
/*
|
||
check whether the two points can be directly reachable by a line
|
||
|
||
*/
|
||
bool Walk_SP::EuclideanConnect(Point loc1, Point loc2)
|
||
{
|
||
Line* l = new Line(0);
|
||
l->StartBulkLoad();
|
||
HalfSegment hs;
|
||
hs.Set(true, loc1, loc2);
|
||
hs.attr.edgeno = 0;
|
||
*l += hs;
|
||
hs.SetLeftDomPoint(!hs.IsLeftDomPoint());
|
||
*l += hs;
|
||
l->EndBulkLoad();
|
||
double len1 = l->Length();
|
||
double len2 = 0.0;
|
||
DFTraverse2(dg->rtree_node, dg->rtree_node->RootRecordId(),
|
||
l, len2);
|
||
l->DeleteIfAllowed();
|
||
|
||
// cout<<"l1: "<<len1<<"l2: "<<len2<<endl;
|
||
|
||
if(fabs(len1 - len2) < 0.01) return true;
|
||
|
||
return false;
|
||
}
|
||
|
||
/*
|
||
Using depth first method to travese the R-tree to find all triangles
|
||
intersecting the line and calculate the total intersection length
|
||
|
||
*/
|
||
void Walk_SP::DFTraverse2(R_Tree<2,TupleId>* rtree, SmiRecordId adr,
|
||
Line* line, double& l)
|
||
{
|
||
const double delta_area = 0.01;
|
||
R_TreeNode<2,TupleId>* node = rtree->GetMyNode(adr,false,
|
||
rtree->MinEntries(0), rtree->MaxEntries(0));
|
||
for(int j = 0;j < node->EntryCount();j++){
|
||
if(node->IsLeaf()){
|
||
R_TreeLeafEntry<2,TupleId> e =
|
||
(R_TreeLeafEntry<2,TupleId>&)(*node)[j];
|
||
Tuple* dg_tuple = dg->node_rel_sort->GetTuple(e.info, false);
|
||
Region* candi_reg =
|
||
(Region*)dg_tuple->GetAttribute(DualGraph::PAVEMENT);
|
||
Line* len = new Line(0);
|
||
|
||
/* int oid =
|
||
((CcInt*)dg_tuple->GetAttribute(DualGraph::OID))->GetIntval();
|
||
cout<<oid<<endl;*/
|
||
|
||
// line->Intersection(*candi_reg, *len); //crashes once for Houston
|
||
MyIntersection(*line, *candi_reg, *len);
|
||
|
||
if(candi_reg->Area() > delta_area && len->Length() > 0.0){
|
||
l += len->Length();
|
||
}
|
||
len->DeleteIfAllowed();
|
||
dg_tuple->DeleteIfAllowed();
|
||
}else{
|
||
R_TreeInternalEntry<2> e =
|
||
(R_TreeInternalEntry<2>&)(*node)[j];
|
||
if(e.box.Intersects(line->BoundingBox())){
|
||
DFTraverse2(rtree, e.pointer, line, l);
|
||
}
|
||
}
|
||
}
|
||
delete node;
|
||
|
||
}
|
||
|
||
|
||
/*
|
||
check whether the two points can be directly reachable by a line
|
||
|
||
*/
|
||
bool Walk_SP::EuclideanConnect2(int oid1, Point loc1, int oid2, Point loc2)
|
||
{
|
||
// cout<<"EuclideanConnect2 oid1 "<<oid1<<" oid2 "<<oid2<<endl;
|
||
Line* l = new Line(0);
|
||
l->StartBulkLoad();
|
||
HalfSegment hs;
|
||
hs.Set(true, loc1, loc2);
|
||
hs.attr.edgeno = 0;
|
||
*l += hs;
|
||
hs.SetLeftDomPoint(!hs.IsLeftDomPoint());
|
||
*l += hs;
|
||
l->EndBulkLoad();
|
||
|
||
Tuple* node_tuple = dg->GetNodeRel()->GetTuple(oid1, false);
|
||
Region* reg = (Region*)node_tuple->GetAttribute(DualGraph::PAVEMENT);
|
||
Line* res = new Line(0);
|
||
MyIntersection(*l, *reg, *res);
|
||
res->DeleteIfAllowed();
|
||
node_tuple->DeleteIfAllowed();
|
||
|
||
bool flag = true;
|
||
// oid1 -= dg->min_tri_oid_1;
|
||
// oid2 -= dg->min_tri_oid_1;
|
||
|
||
int start_tri = oid1;
|
||
int last_tri = oid1;
|
||
|
||
bool find = false;
|
||
while(flag){
|
||
vector<int> adj_list;
|
||
// cout<<"tri "<<start_tri + dg->min_tri_oid_1 <<endl;
|
||
dg->FindAdj(start_tri, adj_list);////find all neighbor triangles
|
||
unsigned int i = 0;
|
||
/* cout<<start_tri + dg->min_tri_oid_1
|
||
<<" neighbor size "<<adj_list.size()<<endl;*/
|
||
for(;i < adj_list.size();i++){
|
||
|
||
Tuple* tuple = dg->GetNodeRel()->GetTuple(adj_list[i], false);
|
||
Region* reg = (Region*)tuple->GetAttribute(DualGraph::PAVEMENT);
|
||
int tri_id =
|
||
((CcInt*)tuple->GetAttribute(DualGraph::OID))->GetIntval();
|
||
// cout<<"neighbor id "<<tri_id<<endl;
|
||
tri_id -= dg->min_tri_oid_1;
|
||
if(tri_id == last_tri){
|
||
tuple->DeleteIfAllowed();
|
||
continue;
|
||
}
|
||
Line* res = new Line(0);
|
||
MyIntersection(*l, *reg, *res);
|
||
if(res->Length() > 0.0){
|
||
|
||
last_tri = start_tri;
|
||
start_tri = tri_id;
|
||
res->DeleteIfAllowed();
|
||
tuple->DeleteIfAllowed();
|
||
break;
|
||
}
|
||
res->DeleteIfAllowed();
|
||
tuple->DeleteIfAllowed();
|
||
}
|
||
if(i == adj_list.size()){
|
||
flag = false;
|
||
}else if(start_tri == oid2){
|
||
find = true;
|
||
flag = false;
|
||
}
|
||
}
|
||
|
||
l->DeleteIfAllowed();
|
||
|
||
return find;
|
||
}
|
||
|
||
/*
|
||
Randomly generates points inside pavement polygon
|
||
1) randomly selects a polygon/polygon
|
||
2) randomly generates a number between [xmin,xmax], and [ymin,ymax]
|
||
|
||
*/
|
||
|
||
void Walk_SP::GenerateData1(int no_p)
|
||
{
|
||
int no_node_graph = rel1->GetNoTuples();
|
||
|
||
// struct timeval tval;
|
||
// struct timezone tzone;
|
||
// gettimeofday(&tval, &tzone);
|
||
// srand48(tval.tv_sec);
|
||
|
||
for (int i = 1; i <= no_p;){
|
||
// int m = lrand48() % no_node_graph + 1;
|
||
|
||
int m = GetRandom() % no_node_graph + 1;
|
||
|
||
Tuple* tuple = rel1->GetTuple(m, false);
|
||
int oid = ((CcInt*)tuple->GetAttribute(DualGraph::OID))->GetIntval();
|
||
Region* reg = (Region*)tuple->GetAttribute(DualGraph::PAVEMENT);
|
||
|
||
if(reg->Area() < 0.5){ //too small area, not useful for a human
|
||
tuple->DeleteIfAllowed();
|
||
continue;
|
||
}
|
||
|
||
/*neighbor triangles for testing Euclidean connection*/
|
||
// if(!(oid == 96621 || oid == 96619 || oid == 97639)){
|
||
// tuple->DeleteIfAllowed();
|
||
// continue;
|
||
// }
|
||
|
||
BBox<2> bbox = reg->BoundingBox();
|
||
int xx = (int)(bbox.MaxD(0) - bbox.MinD(0)) + 1;
|
||
int yy = (int)(bbox.MaxD(1) - bbox.MinD(1)) + 1;
|
||
|
||
Point p1;
|
||
Point p2;
|
||
bool inside = false;
|
||
int count = 1;
|
||
while(inside == false && count <= 100){
|
||
|
||
int x = GetRandom() % (xx*100);
|
||
int y = GetRandom() % (yy*100);
|
||
|
||
|
||
double coord_x = x/100.0;
|
||
double coord_y = y/100.0;
|
||
|
||
Coord x_cord = coord_x + bbox.MinD(0);
|
||
Coord y_cord = coord_y + bbox.MinD(1);
|
||
p2.Set(x_cord, y_cord);
|
||
p1.Set(coord_x, coord_y); //set back to relative position
|
||
//lower the precision
|
||
Modify_Point_3(p1);
|
||
Modify_Point_3(p2);
|
||
inside = p2.Inside(*reg);
|
||
count++;
|
||
}
|
||
if(inside){
|
||
// oids.push_back(m);
|
||
oids.push_back(oid);
|
||
q_loc1.push_back(p1);
|
||
q_loc2.push_back(p2);
|
||
i++;
|
||
}
|
||
tuple->DeleteIfAllowed();
|
||
}
|
||
}
|
||
|
||
/*
|
||
Randomly generates points inside pavement polygon
|
||
1) randomly selects a polygon/polygon
|
||
2) randomly generates a vertex of the triangle
|
||
3) the point equals to one of triangle vertices
|
||
|
||
*/
|
||
|
||
void Walk_SP::GenerateData2(int no_p)
|
||
{
|
||
int no_node_graph = rel1->GetNoTuples();
|
||
|
||
for (int i = 1; i <= no_p;i++){
|
||
int m = GetRandom() % no_node_graph + 1;
|
||
|
||
Tuple* tuple = rel1->GetTuple(m, false);
|
||
int oid = ((CcInt*)tuple->GetAttribute(DualGraph::OID))->GetIntval();
|
||
Region* reg = (Region*)tuple->GetAttribute(DualGraph::PAVEMENT);
|
||
Points* ps = new Points(0);
|
||
reg->Vertices(ps);
|
||
|
||
|
||
unsigned index = GetRandom() % 3;
|
||
|
||
Point p2;
|
||
ps->Get(index, p2);
|
||
BBox<2> bbox = reg->BoundingBox();
|
||
Point p1(true, p2.GetX() - bbox.MinD(0), p2.GetY() - bbox.MinD(1));
|
||
|
||
// oids.push_back(m);
|
||
oids.push_back(oid);
|
||
q_loc1.push_back(p1);//relative position in the polygon
|
||
q_loc2.push_back(p2);//absolute position
|
||
|
||
ps->DeleteIfAllowed();
|
||
tuple->DeleteIfAllowed();
|
||
}
|
||
}
|
||
|
||
/*
|
||
Randomly generates points inside pavement polygon
|
||
1) randomly selects a polygon/polygon
|
||
2) randomly generates a vertex of the triangle
|
||
3) the vertex is the internal point of a triangle. not on the edge
|
||
|
||
*/
|
||
|
||
void Walk_SP::GenerateData3(int no_p)
|
||
{
|
||
int no_node_graph = rel1->GetNoTuples();
|
||
// struct timeval tval;
|
||
// struct timezone tzone;
|
||
|
||
// gettimeofday(&tval, &tzone);
|
||
// srand48(tval.tv_sec);
|
||
|
||
for (int i = 1; i <= no_p;){
|
||
|
||
// int m = lrand48() % no_node_graph + 1;
|
||
|
||
int m = GetRandom() % no_node_graph + 1;
|
||
|
||
Tuple* tuple = rel1->GetTuple(m, false);
|
||
int oid = ((CcInt*)tuple->GetAttribute(DualGraph::OID))->GetIntval();
|
||
Region* reg = (Region*)tuple->GetAttribute(DualGraph::PAVEMENT);
|
||
|
||
if(reg->Area() < 0.5){ //too small area, not useful for a human
|
||
tuple->DeleteIfAllowed();
|
||
continue;
|
||
}
|
||
BBox<2> bbox = reg->BoundingBox();
|
||
int xx = (int)(bbox.MaxD(0) - bbox.MinD(0)) + 1;
|
||
int yy = (int)(bbox.MaxD(1) - bbox.MinD(1)) + 1;
|
||
|
||
Point p1;
|
||
Point p2;
|
||
bool inside = false;
|
||
int count = 1;
|
||
vector<HalfSegment> segs;
|
||
for(int j = 0;j < reg->Size();j++){
|
||
HalfSegment hs;
|
||
reg->Get(j,hs);
|
||
if(!hs.IsLeftDomPoint())continue;
|
||
segs.push_back(hs);
|
||
}
|
||
|
||
while(inside == false && count <= 100){
|
||
|
||
int x = GetRandom() % (xx*100);
|
||
int y = GetRandom() % (yy*100);
|
||
|
||
double coord_x = x/100.0;
|
||
double coord_y = y/100.0;
|
||
|
||
Coord x_cord = coord_x + bbox.MinD(0);
|
||
Coord y_cord = coord_y + bbox.MinD(1);
|
||
p2.Set(x_cord, y_cord);
|
||
p1.Set(coord_x, coord_y); //set back to relative position
|
||
//lower the precision
|
||
Modify_Point_3(p1);
|
||
Modify_Point_3(p2);
|
||
inside = p2.Inside(*reg);
|
||
for(unsigned int k = 0;k < segs.size();k++){
|
||
if(segs[k].Contains(p2)){
|
||
inside = false;
|
||
break;
|
||
}
|
||
}
|
||
count++;
|
||
}
|
||
if(inside){
|
||
// oids.push_back(m);
|
||
oids.push_back(oid);
|
||
q_loc1.push_back(p1);
|
||
q_loc2.push_back(p2);
|
||
i++;
|
||
}
|
||
tuple->DeleteIfAllowed();
|
||
}
|
||
}
|
||
|
||
/*
|
||
create a random point on the given triangle
|
||
|
||
*/
|
||
bool Walk_SP::GenerateData4(int tid)
|
||
{
|
||
if(rel1 == NULL){
|
||
cout<<"realtion no initialize "<<endl;
|
||
return false;
|
||
}
|
||
int no_node_graph = rel1->GetNoTuples();
|
||
assert(1 <= tid && tid <= no_node_graph);
|
||
|
||
Tuple* tuple = rel1->GetTuple(tid, false);
|
||
int oid = ((CcInt*)tuple->GetAttribute(DualGraph::OID))->GetIntval();
|
||
Region* reg = (Region*)tuple->GetAttribute(DualGraph::PAVEMENT);
|
||
|
||
if(reg->Area() < 0.5){ //too small area, not useful for a human
|
||
tuple->DeleteIfAllowed();
|
||
return false;
|
||
}
|
||
|
||
|
||
BBox<2> bbox = reg->BoundingBox();
|
||
int xx = (int)(bbox.MaxD(0) - bbox.MinD(0)) + 1;
|
||
int yy = (int)(bbox.MaxD(1) - bbox.MinD(1)) + 1;
|
||
|
||
Point p1;
|
||
Point p2;
|
||
bool inside = false;
|
||
int count_tmp = 1;
|
||
while(inside == false && count_tmp <= 100){
|
||
|
||
int x = GetRandom() % (xx*100);
|
||
int y = GetRandom() % (yy*100);
|
||
|
||
|
||
double coord_x = x/100.0;
|
||
double coord_y = y/100.0;
|
||
|
||
Coord x_cord = coord_x + bbox.MinD(0);
|
||
Coord y_cord = coord_y + bbox.MinD(1);
|
||
p2.Set(x_cord, y_cord);
|
||
p1.Set(coord_x, coord_y); //set back to relative position
|
||
//lower the precision
|
||
Modify_Point_3(p1);
|
||
Modify_Point_3(p2);
|
||
inside = p2.Inside(*reg);
|
||
count_tmp++;
|
||
}
|
||
tuple->DeleteIfAllowed();
|
||
if(inside){
|
||
// oids.push_back(m);
|
||
oids.push_back(oid);
|
||
q_loc1.push_back(p1);
|
||
q_loc2.push_back(p2);
|
||
return true;
|
||
}
|
||
|
||
return false;
|
||
|
||
}
|
||
|
||
|
||
/*
|
||
set pavement rid
|
||
|
||
*/
|
||
void Walk_SP::SetPaveRid(R_Tree<2,TupleId>* rtree)
|
||
{
|
||
|
||
SmiRecordId adr = rtree->RootRecordId();
|
||
for(int i = 1;i <= rel1->GetNoTuples();i++){
|
||
Tuple* tri_tuple = rel1->GetTuple(i, false);
|
||
int oid = ((CcInt*)tri_tuple->GetAttribute(DualGraph::OID))->GetIntval();
|
||
Region* reg = (Region*)tri_tuple->GetAttribute(DualGraph::PAVEMENT);
|
||
vector<int> r_id_list;
|
||
|
||
DFTraverse(rtree, adr, reg, r_id_list);
|
||
|
||
// cout<<"tid "<<i <<" oid "<<oid<<endl;
|
||
|
||
if(r_id_list.size() == 0){
|
||
cout<<"do not find road "<<endl;
|
||
cout<<"tid "<<i <<" oid "<<oid<<endl;
|
||
// break;
|
||
continue;
|
||
}
|
||
|
||
for(unsigned int j = 0;j < r_id_list.size();j++){
|
||
oid_list.push_back(oid);
|
||
rid_list.push_back(r_id_list[j]);
|
||
reg_list.push_back(*reg);
|
||
}
|
||
|
||
tri_tuple->DeleteIfAllowed();
|
||
}
|
||
|
||
}
|
||
|
||
/*
|
||
Using depth first method to travese the R-tree to find the big pavement
|
||
intersects the triangle (decomposed from the big pavement)
|
||
|
||
*/
|
||
void Walk_SP::DFTraverse(R_Tree<2,TupleId>* rtree, SmiRecordId adr, Region* reg,
|
||
vector<int>& r_id_list)
|
||
{
|
||
R_TreeNode<2,TupleId>* node = rtree->GetMyNode(adr,false,
|
||
rtree->MinEntries(0), rtree->MaxEntries(0));
|
||
for(int j = 0;j < node->EntryCount();j++){
|
||
if(node->IsLeaf()){
|
||
R_TreeLeafEntry<2,TupleId> e =
|
||
(R_TreeLeafEntry<2,TupleId>&)(*node)[j];
|
||
Tuple* dg_tuple2 = rel2->GetTuple(e.info, false);
|
||
Region* candi_reg =
|
||
(Region*)dg_tuple2->GetAttribute(DualGraph::PAVEMENT);
|
||
if(reg->Intersects(*candi_reg)){
|
||
int rid =
|
||
((CcInt*)dg_tuple2->GetAttribute(DualGraph::RID))->GetIntval();
|
||
unsigned int i = 0;
|
||
for(;i < r_id_list.size();i++)
|
||
if(r_id_list[i] == rid)break;
|
||
if(i == r_id_list.size())
|
||
r_id_list.push_back(rid);
|
||
}
|
||
dg_tuple2->DeleteIfAllowed();
|
||
}else{
|
||
R_TreeInternalEntry<2> e =
|
||
(R_TreeInternalEntry<2>&)(*node)[j];
|
||
if(e.box.Intersects(reg->BoundingBox())){
|
||
DFTraverse(rtree, e.pointer, reg, r_id_list);
|
||
}
|
||
}
|
||
}
|
||
delete node;
|
||
|
||
}
|
||
|
||
|
||
/*
|
||
map points in pavements to gpoints
|
||
|
||
*/
|
||
void Walk_SP::PaveLocToGP(Network* n)
|
||
{
|
||
//rel1 query locations , rel2 dgnode
|
||
for(int i = 1;i <= rel1->GetNoTuples();i++){
|
||
Tuple* tuple1 = rel1->GetTuple(i, false);
|
||
int oid = ((CcInt*)tuple1->GetAttribute(VisualGraph::QOID))->GetIntval();
|
||
Point* loc = (Point*)tuple1->GetAttribute(VisualGraph::QLOC2);
|
||
|
||
/////////////////find which road the pavement corresponds to////////
|
||
CcInt* search_id = new CcInt(true, oid);
|
||
BTreeIterator* btree_iter = btree->ExactMatch(search_id);
|
||
vector<int> route_id_list;
|
||
while(btree_iter->Next()){
|
||
Tuple* tuple = rel2->GetTuple(btree_iter->GetId(), false);
|
||
int rid = ((CcInt*)tuple->GetAttribute(DualGraph::RID))->GetIntval();
|
||
route_id_list.push_back(rid);
|
||
tuple->DeleteIfAllowed();
|
||
}
|
||
delete btree_iter;
|
||
delete search_id;
|
||
|
||
// for(unsigned int i = 0;i < route_id_list.size();i++)
|
||
// cout<<"rid "<<route_id_list[i]<<endl;
|
||
|
||
// cout<<"oid "<<oid<<" rid "<<rid<<endl;
|
||
|
||
PaveLocToGPoint(loc, n, route_id_list);//more robustness
|
||
|
||
tuple1->DeleteIfAllowed();
|
||
|
||
// break;
|
||
}
|
||
|
||
|
||
}
|
||
|
||
/*
|
||
for a point, location in pavement, find its mapping gpoint
|
||
|
||
*/
|
||
struct MyPoint_Id:public MyPoint{
|
||
int id;
|
||
MyPoint_Id(){}
|
||
MyPoint_Id(const Point& p, double d, int i):
|
||
MyPoint(p,d),id(i){}
|
||
MyPoint_Id(const MyPoint_Id& mpi):
|
||
MyPoint(mpi), id(mpi.id){}
|
||
MyPoint_Id& operator=(const MyPoint_Id& mpi)
|
||
{
|
||
MyPoint::operator=(mpi);
|
||
id = mpi.id;
|
||
return *this;
|
||
}
|
||
void Print()
|
||
{
|
||
cout<<" loc " <<loc<<" dist "<<dist<<" id "<<id<<endl;
|
||
}
|
||
};
|
||
|
||
|
||
/*
|
||
pavement location to gpoint
|
||
|
||
*/
|
||
bool Walk_SP::PaveLocToGPoint(Point* loc, Network* n,
|
||
vector<int> route_id_list)
|
||
{
|
||
vector<MyPoint_Id> mp_list;
|
||
for(unsigned int i = 0;i < route_id_list.size();i++){
|
||
int rid = route_id_list[i];
|
||
Tuple* route_tuple = n->GetRoute(rid);
|
||
SimpleLine* l = (SimpleLine*)route_tuple->GetAttribute(ROUTE_CURVE);
|
||
// cout<<"l : "<<l->Length()<<endl;
|
||
|
||
for(int j = 0;j < l->Size();j++){
|
||
HalfSegment hs;
|
||
l->Get(j, hs);
|
||
if(!hs.IsLeftDomPoint())continue;
|
||
|
||
SpacePartition* sp = new SpacePartition();
|
||
Point res;
|
||
double dist = sp->GetClosestPoint(hs, *loc, res);
|
||
delete sp;
|
||
MyPoint_Id mp(res, dist, rid);
|
||
mp_list.push_back(mp);
|
||
}
|
||
route_tuple->DeleteIfAllowed();
|
||
}
|
||
assert(mp_list.size() > 0);
|
||
sort(mp_list.begin(), mp_list.end());
|
||
|
||
// cout<<"rid "<<mp_list[0].id<<" neighbor "<<mp_list[0].loc<<endl;
|
||
|
||
Tuple* route_tuple = n->GetRoute(mp_list[0].id);
|
||
SimpleLine* sl = (SimpleLine*)route_tuple->GetAttribute(ROUTE_CURVE);
|
||
bool s =
|
||
((CcBool*)route_tuple->GetAttribute(ROUTE_STARTSSMALLER))->GetBoolval();
|
||
double pos;
|
||
bool ok = sl->AtPoint(mp_list[0].loc, s, pos);
|
||
////////////MyAtPoint()////////////////
|
||
|
||
if(ok){
|
||
GPoint gp(true, n->GetId(), mp_list[0].id, pos);
|
||
route_tuple->DeleteIfAllowed();
|
||
p_list.push_back(mp_list[0].loc);
|
||
gp_list.push_back(gp);
|
||
}
|
||
|
||
return ok;
|
||
|
||
}
|
||
|
||
/*
|
||
type constructors
|
||
|
||
*/
|
||
VGraph::VGraph()
|
||
{
|
||
dg = NULL;
|
||
rel1 = NULL;
|
||
rel2 = NULL;
|
||
rel3 = NULL;
|
||
count = 0;
|
||
resulttype = NULL;
|
||
vg = NULL;
|
||
}
|
||
VGraph::VGraph(DualGraph* g, Relation* r1, Relation* r2, Relation* r3):dg(g),
|
||
rel1(r1), rel2(r2), rel3(r3), count(0), resulttype(NULL), vg(NULL)
|
||
{
|
||
|
||
}
|
||
VGraph::VGraph(VisualGraph* g):dg(NULL),
|
||
rel1(NULL), rel2(NULL), rel3(NULL), count(0), resulttype(NULL), vg(g)
|
||
{
|
||
|
||
}
|
||
VGraph:: ~VGraph()
|
||
{
|
||
if(resulttype != NULL) delete resulttype;
|
||
}
|
||
/*
|
||
get all adjacent nodes for a given node. dual graph
|
||
|
||
*/
|
||
|
||
void VGraph::GetAdjNodeDG(int oid)
|
||
{
|
||
if(oid <= dg->min_tri_oid_1 ||
|
||
oid > dg->min_tri_oid_1 + dg->node_rel->GetNoTuples()){
|
||
cout<<"invalid oid "<<oid<<endl;
|
||
cout<<"minimum oid "<<dg->min_tri_oid_1 + 1<<endl;
|
||
cout<<"maximum oid "
|
||
<<dg->min_tri_oid_1 + dg->node_rel->GetNoTuples()<<endl;
|
||
return;
|
||
}
|
||
|
||
cout<<"total "<< dg->GetNodeRel()->GetNoTuples()<<" nodes "<<endl;
|
||
|
||
vector<int> adj_list;
|
||
assert(dg->min_tri_oid_1 >= 0);
|
||
dg->FindAdj(oid - dg->min_tri_oid_1, adj_list);
|
||
|
||
for(unsigned int i = 0;i < adj_list.size();i++){
|
||
|
||
Tuple* node_tuple = dg->GetNodeRel()->GetTuple(adj_list[i], false);
|
||
CcInt* tri_id = (CcInt*)node_tuple->GetAttribute(DualGraph::OID);
|
||
Region* reg = (Region*)node_tuple->GetAttribute(DualGraph::PAVEMENT);
|
||
oids1.push_back(tri_id->GetIntval());
|
||
regs.push_back(*reg);
|
||
node_tuple->DeleteIfAllowed();
|
||
|
||
}
|
||
|
||
}
|
||
|
||
/*
|
||
get all adjacent nodes for a given node. visibility graph
|
||
|
||
*/
|
||
|
||
void VGraph::GetAdjNodeVG(int oid)
|
||
{
|
||
if(oid < 1 || oid > vg->GetNodeRel()->GetNoTuples()){
|
||
cout<<"invalid oid "<<oid<<endl;
|
||
return;
|
||
}
|
||
cout<<"total "<<vg->GetNodeRel()->GetNoTuples()<<" nodes "<<endl;
|
||
|
||
Tuple* node_tuple = vg->GetNodeRel()->GetTuple(oid, false);
|
||
Point* query_p = (Point*)node_tuple->GetAttribute(VisualGraph::LOC);
|
||
Point query_loc(*query_p);
|
||
node_tuple->DeleteIfAllowed();
|
||
|
||
vector<int> adj_list;
|
||
vg->FindAdj(oid, adj_list);
|
||
for(unsigned int i = 0;i < adj_list.size();i++){
|
||
node_tuple = vg->GetNodeRel()->GetTuple(adj_list[i], false);
|
||
CcInt* id = (CcInt*)node_tuple->GetAttribute(VisualGraph::OID);
|
||
Point* loc = (Point*)node_tuple->GetAttribute(VisualGraph::LOC);
|
||
oids1.push_back(id->GetIntval());
|
||
p_list.push_back(*loc);
|
||
////////////////////////////////////////////////
|
||
Line* l = new Line(0);
|
||
l->StartBulkLoad();
|
||
HalfSegment hs;
|
||
hs.Set(true, query_loc, *loc);
|
||
hs.attr.edgeno = 0;
|
||
*l += hs;
|
||
hs.SetLeftDomPoint(!hs.IsLeftDomPoint());
|
||
*l += hs;
|
||
l->EndBulkLoad();
|
||
line.push_back(*l);
|
||
l->DeleteIfAllowed();
|
||
////////////////////////////////////////////////
|
||
node_tuple->DeleteIfAllowed();
|
||
}
|
||
|
||
}
|
||
|
||
|
||
/*
|
||
get the visibile points for one vertex
|
||
|
||
*/
|
||
|
||
void VGraph::GetVNodeOnVertex(int vid, Point* query_p)
|
||
{
|
||
CcInt* vertex_id = new CcInt(true, vid);
|
||
BTreeIterator* btreeiter = btree->ExactMatch(vertex_id);
|
||
while(btreeiter->Next()){
|
||
Tuple* ver_tri = rel4->GetTuple(btreeiter->GetId(), false);
|
||
int triangle_id =
|
||
((CcInt*)ver_tri->GetAttribute(DualGraph::TRIID))->GetIntval();
|
||
|
||
// cout<<"tid_start "<<tid_start<<endl;
|
||
// cout<<"triangle_id "<<triangle_id<<endl;
|
||
///////////for debuging///////////////////////
|
||
assert((triangle_id - dg->min_tri_oid_1) >= 1);
|
||
triangle_id = triangle_id - dg->min_tri_oid_1;
|
||
assert(triangle_id >= 1 && triangle_id <= rel2->GetNoTuples());
|
||
Tuple* tri_tuple = rel2->GetTuple(triangle_id, false);
|
||
int v1 =((CcInt*)tri_tuple->GetAttribute(DualGraph::V1))->GetIntval();
|
||
int v2 =((CcInt*)tri_tuple->GetAttribute(DualGraph::V2))->GetIntval();
|
||
int v3 =((CcInt*)tri_tuple->GetAttribute(DualGraph::V3))->GetIntval();
|
||
tri_tuple->DeleteIfAllowed();
|
||
|
||
vector<int> vid_list;
|
||
if(v1 == vid){
|
||
vid_list.push_back(v2);
|
||
vid_list.push_back(v3);
|
||
for(unsigned int i = 0;i < vid_list.size();i++){
|
||
unsigned int j = 0;
|
||
for(;j < oids1.size();j++){
|
||
if(vid_list[i] == oids1[j]) break;
|
||
}
|
||
if(j == oids1.size()){
|
||
oids1.push_back(vid_list[i]);
|
||
}
|
||
}
|
||
GetVisibleNode2(triangle_id, query_p, 3);
|
||
|
||
}else if(v2 == vid){
|
||
vid_list.push_back(v1);
|
||
vid_list.push_back(v3);
|
||
for(unsigned int i = 0;i < vid_list.size();i++){
|
||
unsigned int j = 0;
|
||
for(;j < oids1.size();j++){
|
||
if(vid_list[i] == oids1[j]) break;
|
||
}
|
||
if(j == oids1.size()){
|
||
oids1.push_back(vid_list[i]);
|
||
}
|
||
}
|
||
GetVisibleNode2(triangle_id, query_p, 2);
|
||
}else if(v3 == vid){
|
||
vid_list.push_back(v1);
|
||
vid_list.push_back(v2);
|
||
for(unsigned int i = 0;i < vid_list.size();i++){
|
||
unsigned int j = 0;
|
||
for(;j < oids1.size();j++){
|
||
if(vid_list[i] == oids1[j]) break;
|
||
}
|
||
if(j == oids1.size()){
|
||
oids1.push_back(vid_list[i]);
|
||
}
|
||
}
|
||
GetVisibleNode2(triangle_id, query_p, 1);
|
||
}else assert(false);
|
||
|
||
ver_tri->DeleteIfAllowed();
|
||
}
|
||
delete btreeiter;
|
||
delete vertex_id;
|
||
}
|
||
|
||
|
||
/*
|
||
create the edge relation for the visibility graph
|
||
|
||
*/
|
||
void VGraph::GetVGEdge()
|
||
{
|
||
// cout<<dg->min_tri_oid_1<<endl;
|
||
for(int i = 1;i <= rel1->GetNoTuples();i++){
|
||
|
||
Tuple* vertex_tuple = rel1->GetTuple(i, false);
|
||
int vid =
|
||
((CcInt*)vertex_tuple->GetAttribute(VisualGraph::OID))->GetIntval();
|
||
Point* p1 = (Point*)vertex_tuple->GetAttribute(VisualGraph::LOC);
|
||
|
||
// if(vid != 1200){
|
||
// vertex_tuple->DeleteIfAllowed();
|
||
// continue;
|
||
// }
|
||
|
||
GetVNodeOnVertex(vid, p1);
|
||
for(unsigned int j = 0;j < oids1.size();j++){
|
||
oids2.push_back(vid);
|
||
oids3.push_back(oids1[j]);
|
||
/////////////////////////
|
||
Tuple* loc_tuple2 = rel3->GetTuple(oids1[j], false);
|
||
Point* p2 = (Point*)loc_tuple2->GetAttribute(VisualGraph::LOC);
|
||
/////////////////////////
|
||
Line* l = new Line(0);
|
||
l->StartBulkLoad();
|
||
HalfSegment hs;
|
||
hs.Set(true, *p1, *p2);
|
||
hs.attr.edgeno = 0;
|
||
*l += hs;
|
||
hs.SetLeftDomPoint(!hs.IsLeftDomPoint());
|
||
*l += hs;
|
||
l->EndBulkLoad();
|
||
line.push_back(*l);
|
||
l->DeleteIfAllowed();
|
||
loc_tuple2->DeleteIfAllowed();
|
||
}
|
||
vertex_tuple->DeleteIfAllowed();
|
||
oids1.clear();
|
||
}
|
||
|
||
}
|
||
|
||
inline bool VGraph::Collineation(Point& p1, Point& p2, Point& p3)
|
||
{
|
||
if(AlmostEqual(p1.GetX(), p2.GetX())){
|
||
if(AlmostEqual(p2.GetX(), p3.GetX())) return true;
|
||
}
|
||
if(AlmostEqual(p1.GetY(), p2.GetY())){
|
||
if(AlmostEqual(p2.GetY(), p3.GetY())) return true;
|
||
}
|
||
double k1 = (p1.GetY() - p2.GetY())/(p1.GetX() - p2.GetX());
|
||
double k2 = (p2.GetY() - p3.GetY())/(p2.GetX() - p3.GetX());
|
||
if(AlmostEqual(k1, k2)) return true;
|
||
return false;
|
||
}
|
||
|
||
/*
|
||
it checks whether vertex (vp) is inside the clamp structure constructed by
|
||
vertex and two points endp1, endp2
|
||
|
||
*/
|
||
bool VGraph::CheckVisibility1(Clamp& clamp, Point& checkp, int vp)
|
||
{
|
||
// cout<<"CheckVisibility1()"<<endl;
|
||
// clamp.Print();
|
||
// cout<<"checkp " <<checkp<<endl;
|
||
|
||
bool visibility;
|
||
/////////it checks whether the angle1 + angle2 is equal to clamp angle
|
||
//but it has some drawbacks that when angle1(2) is 0
|
||
//it can't well determine whether checkp is inside the clamp or not
|
||
|
||
/* SpacePartition* sp = new SpacePartition();
|
||
|
||
double angle1 = sp->GetAngle(clamp.apex, clamp.foot1, checkp);
|
||
double angle2 = sp->GetAngle(clamp.apex, checkp, clamp.foot2);
|
||
|
||
cout<<setprecision(8);
|
||
cout<<"angle1 "<<angle1<<" angle2 "<<angle2<<endl;
|
||
cout<<"clamp angle "<<clamp.angle<<endl;
|
||
|
||
//it is possible that d1 is smaller than d2 and in this case
|
||
//the angle is also very small. it occurs that when the two feet are very
|
||
//very,very far away from the apex. so, the angle is almost equal to 0.
|
||
|
||
if(AlmostEqual(angle1, 0.0)){
|
||
delete sp;
|
||
return false;
|
||
}
|
||
if(AlmostEqual(angle2, 0.0)){
|
||
delete sp;
|
||
return false;
|
||
}
|
||
const double pi = 3.14159;
|
||
const double delta = 1.0*pi/360.0; //deviation 1 degree
|
||
////////////////////////////////////////////////////////////////////////
|
||
// if the degree is smaller than 1 degree. we think it is the same ///
|
||
///////////////////////////////////////////////////////////////////////
|
||
|
||
if(fabs(clamp.angle - (angle1 + angle2) ) < delta)
|
||
visibility = true;
|
||
else
|
||
visibility = false;
|
||
|
||
delete sp; */
|
||
|
||
////it checks whether the polygon constructed by apex, foot1(2),
|
||
///checkp,foot2(1) is a convex or concave.
|
||
// if checkp is outside the angle formed by two line (apex,foot1)(apex,foot2)
|
||
//then, the angle apex-foot1(2)-checkp is larger than 180.
|
||
|
||
vector<Point> ps;
|
||
ps.push_back(clamp.apex);
|
||
ps.push_back(clamp.foot1);
|
||
ps.push_back(checkp);
|
||
ps.push_back(clamp.foot2);
|
||
CompTriangle* ct = new CompTriangle();
|
||
visibility = ct->IsConvex(ps);//convex. checkp is inside
|
||
delete ct;
|
||
|
||
if(visibility){
|
||
//it is impossible that clamp.apex, foot1(2), checkp are on the same line
|
||
//and checkp locates between clamp.apex and foot1(2)
|
||
//because in this case, checkp should be found first
|
||
//because we start from the triangle that queryp locates and the inside
|
||
//checking condition
|
||
|
||
bool flag1 = Collineation(clamp.apex, clamp.foot1, checkp);
|
||
bool flag2 = Collineation(clamp.apex, clamp.foot2, checkp);
|
||
// cout<<"flag1 "<<flag1<<" flag2 "<<flag2<<endl;
|
||
if(flag1 || flag2) return false;
|
||
return true;
|
||
}else return false;
|
||
|
||
}
|
||
/*
|
||
Get the intersection point between halfsegment (p1,p2) and
|
||
radial p3->p4, store the results in ip
|
||
if it has, returns true, otherwise returns false
|
||
|
||
*/
|
||
|
||
bool VGraph::GetIntersectionPoint(Point& p1, Point& p2,
|
||
Clamp& clamp, Point& ip, bool flag)
|
||
{
|
||
Point p3;
|
||
Point p4;
|
||
if(flag){
|
||
p3 = clamp.apex;
|
||
p4 = clamp.foot1;
|
||
}else{
|
||
p3 = clamp.apex;
|
||
p4 = clamp.foot2;
|
||
}
|
||
|
||
Coord x, y;
|
||
//get the intersection point
|
||
if(AlmostEqual(p1.GetX(), p2.GetX())){
|
||
if(AlmostEqual(p3.GetX(), p4.GetX())) return false; //parallel
|
||
|
||
double a = (p3.GetY() - p4.GetY())/(p3.GetX() - p4.GetX());
|
||
double b = p3.GetY() - a*p3.GetX();
|
||
x = p1.GetX();
|
||
y = a*x + b;
|
||
}else if(AlmostEqual(p1.GetY(), p2.GetY())){
|
||
if(AlmostEqual(p3.GetY(), p4.GetY())) return false; //parallel
|
||
if(AlmostEqual(p3.GetX(), p4.GetX())){
|
||
x = p3.GetX();
|
||
y = p1.GetY();
|
||
}else{
|
||
double a = (p3.GetY() - p4.GetY())/(p3.GetX() - p4.GetX());
|
||
double b = p3.GetY() - a*p3.GetX();
|
||
y = p1.GetY();
|
||
x = (y - b)/a;
|
||
}
|
||
}else{
|
||
double a1 = (p1.GetY() - p2.GetY())/(p1.GetX() - p2.GetX());
|
||
double b1 = p1.GetY() - a1*p1.GetX();
|
||
if(AlmostEqual(p3.GetX(), p4.GetX())){
|
||
x = p3.GetX();
|
||
y = a1*x + b1;
|
||
}else{
|
||
double a2 = (p3.GetY() - p4.GetY())/(p3.GetX() - p4.GetX());
|
||
double b2 = p3.GetY() - a2*p3.GetX();
|
||
|
||
if(AlmostEqual(a1, a2)) return false;//parallel
|
||
x = (b2-b1)/(a1-a2);
|
||
y = a1*x + b1;
|
||
}
|
||
}
|
||
ip.Set(x, y);
|
||
//check whether it is available
|
||
HalfSegment hs;
|
||
hs.Set(true,p1,p2);
|
||
if(hs.Contains(ip)){
|
||
if(AlmostEqual(p3.GetX(), p4.GetX())){
|
||
if(p3.GetY() < p4.GetY()){
|
||
if(AlmostEqual(y, p3.GetY()) || y > p3.GetY()) return true;
|
||
else
|
||
return false;
|
||
}else{
|
||
if(AlmostEqual(y, p3.GetY()) || y < p3.GetY()) return true;
|
||
else
|
||
return false;
|
||
}
|
||
}else{
|
||
if(p3.GetX() < p4.GetX()){
|
||
if(x > p3.GetX() || AlmostEqual(x, p3.GetX())) return true;
|
||
else
|
||
return false;
|
||
}else{
|
||
if(x < p3.GetX() || AlmostEqual(x, p3.GetX())) return true;
|
||
else
|
||
return false;
|
||
}
|
||
}
|
||
}else
|
||
return false;
|
||
}
|
||
|
||
/*
|
||
it checks whether the segment(checkp1, checkp2) is inside the clamp structure
|
||
Different from CheckVisibility1, now if checkp is on the line (apex,foot1) or
|
||
(apex, foot2), it might also return false.
|
||
one is outside and one is on the line. it returns false.
|
||
|
||
*/
|
||
|
||
bool VGraph::CheckVisibility2(Clamp& clamp, Point& checkp1, Point& checkp2)
|
||
{
|
||
// cout<<"CheckVisibility2()"<<endl;
|
||
// clamp.Print();
|
||
// cout<<"checkp1 "<<checkp1<<" checkp2 "<<checkp2<<endl;
|
||
|
||
//checkp1 is outside clamp
|
||
//it checks whether seg(checkp1,checkp2) is outside clamp
|
||
bool visibility;
|
||
//get the intersection point between seg and clamp
|
||
vector<Point> intersection_points;
|
||
|
||
Point p1;
|
||
if(GetIntersectionPoint(checkp1, checkp2, clamp, p1, true))
|
||
intersection_points.push_back(p1);
|
||
Point p2;
|
||
if(GetIntersectionPoint(checkp1, checkp2, clamp, p2, false))
|
||
intersection_points.push_back(p2);
|
||
|
||
//the number of intersection point
|
||
//0 return false
|
||
//1 if intersection point is not checkp2, return true, otherwise false
|
||
//2 return true
|
||
|
||
// cout<<"intersection_points.size() "<<intersection_points.size()<<endl;
|
||
if(intersection_points.size() == 0) visibility = false;
|
||
if(intersection_points.size() == 2) visibility = true;
|
||
if(intersection_points.size() == 1){
|
||
// cout<<"checkp2 "<<checkp2<<endl;
|
||
// cout<<"intersection [0] "<<intersection_points[0]<<endl;
|
||
if(AlmostEqual(checkp2, intersection_points[0])) visibility = true;
|
||
else
|
||
visibility = false;
|
||
// assert(!AlmostEqual(checkp1, intersection_points[0]));
|
||
// it can be equal when checkp1 is on the line but further than foot1 or foot2
|
||
}
|
||
|
||
return visibility;
|
||
}
|
||
|
||
struct HSNode{
|
||
HalfSegment hs;
|
||
HSNode* next;
|
||
HSNode(){next=NULL;}
|
||
HSNode(HalfSegment& seg,HSNode* pointer):hs(seg),next(pointer){}
|
||
};
|
||
|
||
/*
|
||
Check whether two halfsemgnets cross
|
||
|
||
*/
|
||
bool VGraph::MyCross(const HalfSegment& hs1, const HalfSegment& hs2)
|
||
{
|
||
Point p1 = hs1.GetLeftPoint();
|
||
Point p2 = hs1.GetRightPoint();
|
||
|
||
Point p3 = hs2.GetLeftPoint();
|
||
Point p4 = hs2.GetRightPoint();
|
||
|
||
Coord x, y;
|
||
Point ip;
|
||
if(MyAlmostEqual(p1.GetX(), p2.GetX())){
|
||
if(MyAlmostEqual(p3.GetX(), p4.GetX())) return false; //parallel
|
||
|
||
double a = (p3.GetY() - p4.GetY())/(p3.GetX() - p4.GetX());
|
||
double b = p3.GetY() - a*p3.GetX();
|
||
x = p1.GetX();
|
||
y = a*x + b;
|
||
}else if(MyAlmostEqual(p1.GetY(), p2.GetY())){
|
||
if(MyAlmostEqual(p3.GetY(), p4.GetY())) return false; //parallel
|
||
if(MyAlmostEqual(p3.GetX(), p4.GetX())){
|
||
x = p3.GetX();
|
||
y = p1.GetY();
|
||
}else{
|
||
double a = (p3.GetY() - p4.GetY())/(p3.GetX() - p4.GetX());
|
||
double b = p3.GetY() - a*p3.GetX();
|
||
y = p1.GetY();
|
||
x = (y - b)/a;
|
||
}
|
||
}else{
|
||
double a1 = (p1.GetY() - p2.GetY())/(p1.GetX() - p2.GetX());
|
||
double b1 = p1.GetY() - a1*p1.GetX();
|
||
if(MyAlmostEqual(p3.GetX(), p4.GetX())){
|
||
x = p3.GetX();
|
||
y = a1*x + b1;
|
||
}else{
|
||
double a2 = (p3.GetY() - p4.GetY())/(p3.GetX() - p4.GetX());
|
||
double b2 = p3.GetY() - a2*p3.GetX();
|
||
|
||
if(MyAlmostEqual(a1, a2)) return false;//parallel
|
||
x = (b2-b1)/(a1-a2);
|
||
y = a1*x + b1;
|
||
}
|
||
}
|
||
|
||
if(MyAlmostEqual(x,p1.GetX()) && MyAlmostEqual(y,p1.GetY())) return false;
|
||
if(MyAlmostEqual(x,p2.GetX()) && MyAlmostEqual(y,p2.GetY())) return false;
|
||
if(MyAlmostEqual(x,p3.GetX()) && MyAlmostEqual(y,p3.GetY())) return false;
|
||
if(MyAlmostEqual(x,p4.GetX()) && MyAlmostEqual(y,p4.GetY())) return false;
|
||
ip.Set(x,y);
|
||
if(hs1.Contains(ip) && hs2.Contains(ip))
|
||
return true;
|
||
return false;
|
||
}
|
||
|
||
/*
|
||
check whether the halfsegment is inside the triangle region
|
||
|
||
1) it can't use the method that first union all triangles and
|
||
region.contain(line). because it doesn't work for some very small triangles
|
||
(edges are very close to each other). it reports redundant segments.
|
||
2) it can't use the method that it compares the length of the intersection
|
||
line between (hs and all triangle regions). because if the point is very close
|
||
to the triangle edge. it can't create a segment (the length is very small)
|
||
|
||
*/
|
||
bool VGraph::PathContainHS(vector<int> tri_list, HalfSegment hs)
|
||
{
|
||
// cout<<"PathContainHS() "<<"HS "<<hs<<endl;
|
||
|
||
/* double len1 = hs.Length();
|
||
assert(tri_list.size() > 0);
|
||
Line* l = new Line(0);
|
||
l->StartBulkLoad();
|
||
hs.attr.edgeno = 0;
|
||
*l += hs;
|
||
hs.SetLeftDomPoint(!hs.IsLeftDomPoint());
|
||
*l += hs;
|
||
l->EndBulkLoad();
|
||
double len2 = 0.0;
|
||
for(unsigned int i = 0;i < tri_list.size();i++){
|
||
cout<<"tri id "<<tri_list[i]<<endl;
|
||
Tuple* tri = dg->GetNodeRel()->GetTuple(tri_list[i], false);
|
||
Region* reg = (Region*)tri->GetAttribute(DualGraph::PAVEMENT);
|
||
if(reg->Area() > 0.0){
|
||
Line* inter_l = new Line(0);
|
||
l->Intersection(*reg,*inter_l);//it has numeric problem
|
||
if(inter_l->Size() > 0){
|
||
cout<<"inter_l length "<<inter_l->Length()<<endl;
|
||
len2 += inter_l->Length();
|
||
}
|
||
delete inter_l;
|
||
}
|
||
tri->DeleteIfAllowed();
|
||
}
|
||
delete l;
|
||
cout<<"len1 "<<len1<<" len2 "<<len2<<endl;
|
||
|
||
if(AlmostEqual(len1, len2)) return true;
|
||
return false;*/
|
||
|
||
///////////////////another implementation ////////////////////////////
|
||
////////the method above has numeric problem ////////////////////////
|
||
|
||
HSNode* head = new HSNode();
|
||
HSNode* prev = head;
|
||
HSNode* cur = prev->next;
|
||
|
||
Tuple* tri = dg->GetNodeRel()->GetTuple(tri_list[0], false);
|
||
Region* reg = (Region*)tri->GetAttribute(DualGraph::PAVEMENT);
|
||
for(int i = 0;i < reg->Size();i++){
|
||
HalfSegment hs;
|
||
reg->Get(i, hs);
|
||
if(!hs.IsLeftDomPoint()) continue;
|
||
HSNode* hsnode = new HSNode(hs,NULL);
|
||
cur = hsnode;
|
||
prev->next = cur;
|
||
prev = cur;
|
||
cur = cur->next;
|
||
}
|
||
tri->DeleteIfAllowed();
|
||
|
||
|
||
for(unsigned int i = 1;i < tri_list.size();i++){
|
||
|
||
tri = dg->GetNodeRel()->GetTuple(tri_list[i], false);
|
||
reg = (Region*)tri->GetAttribute(DualGraph::PAVEMENT);
|
||
for(int j = 0;j < reg->Size();j++){
|
||
HalfSegment hs;
|
||
reg->Get(j, hs);
|
||
if(!hs.IsLeftDomPoint())continue;
|
||
prev = head;
|
||
cur = prev->next;
|
||
Point lp1 = hs.GetLeftPoint();
|
||
Point rp1 = hs.GetRightPoint();
|
||
bool insert = true;
|
||
while(cur != NULL && insert){//to find all block segments
|
||
Point lp2 = cur->hs.GetLeftPoint();
|
||
Point rp2 = cur->hs.GetRightPoint();
|
||
if((AlmostEqual(lp1,lp2) && AlmostEqual(rp1, rp2))||
|
||
(AlmostEqual(lp1,rp2) && AlmostEqual(rp1, lp2))){ //delete it
|
||
HSNode* temp = cur;
|
||
cur = cur->next;
|
||
prev->next = cur;
|
||
delete temp;
|
||
insert = false;
|
||
}else{
|
||
prev = cur;
|
||
cur = cur->next;
|
||
}
|
||
}
|
||
if(insert){ //insert the halfsegment
|
||
assert(cur == NULL);
|
||
HSNode* node = new HSNode(hs, NULL);
|
||
cur = node;
|
||
prev->next = cur;
|
||
}
|
||
}
|
||
tri->DeleteIfAllowed();
|
||
}
|
||
|
||
bool cross = false;
|
||
prev = head;
|
||
cur = prev->next;
|
||
|
||
while(cur != NULL){
|
||
// cout<<"cur hs "<<cur->hs<<endl;
|
||
if(cross == false)
|
||
cross = MyCross(hs,cur->hs);
|
||
// cout<<"cross "<<MyCross(hs,cur->hs)<<endl;
|
||
HSNode* node = prev;
|
||
prev = cur;
|
||
cur = cur->next;
|
||
delete node;
|
||
}
|
||
|
||
return !cross;
|
||
}
|
||
|
||
/*
|
||
Depth first searching on the dual graph to find all visible vertices
|
||
|
||
*/
|
||
void VGraph::DFTraverse(int tri_id, Clamp& clamp, int pre_id, int type1)
|
||
{
|
||
// cout<<"DFTraverse()"<<endl;
|
||
// cout<<"tri_id "<<tri_id<<" pre_id "<<pre_id<<" type "<<type1<<endl;
|
||
// clamp.Print();
|
||
|
||
vector<int> adj_list;
|
||
dg->FindAdj(tri_id, adj_list);
|
||
|
||
//get the vertex
|
||
Tuple* tri_tuple = rel2->GetTuple(tri_id, false);
|
||
int v1 =((CcInt*)tri_tuple->GetAttribute(DualGraph::V1))->GetIntval();
|
||
int v2 =((CcInt*)tri_tuple->GetAttribute(DualGraph::V2))->GetIntval();
|
||
int v3 =((CcInt*)tri_tuple->GetAttribute(DualGraph::V3))->GetIntval();
|
||
tri_tuple->DeleteIfAllowed();
|
||
Triangle tri1(v1, v2, v3);
|
||
// cout<<"v1 "<<v1<<"v2 "<<v2<<" v3 "<<v3<<endl;
|
||
// cout<<"adj_list size "<<adj_list.size()<<endl;
|
||
for(unsigned int i = 0;i < adj_list.size();i++){
|
||
// cout<<" adj_list DF "<<adj_list[i]<<" i "<<i<<endl;
|
||
if(adj_list[i] == pre_id) continue;
|
||
tri_tuple = rel2->GetTuple(adj_list[i], false);
|
||
int ver1 =((CcInt*)tri_tuple->GetAttribute(DualGraph::V1))->GetIntval();
|
||
int ver2 =((CcInt*)tri_tuple->GetAttribute(DualGraph::V2))->GetIntval();
|
||
int ver3 =((CcInt*)tri_tuple->GetAttribute(DualGraph::V3))->GetIntval();
|
||
tri_tuple->DeleteIfAllowed();
|
||
///////////////////////////////////////////////////////////////////////
|
||
Tuple* loc_tuple1 = rel3->GetTuple(ver1, false);
|
||
Point* p1 = (Point*)loc_tuple1->GetAttribute(VisualGraph::LOC);
|
||
Point foot1(*p1);
|
||
loc_tuple1->DeleteIfAllowed();
|
||
Tuple* loc_tuple2 = rel3->GetTuple(ver2, false);
|
||
Point* p2 = (Point*)loc_tuple2->GetAttribute(VisualGraph::LOC);
|
||
Point foot2(*p2);
|
||
loc_tuple2->DeleteIfAllowed();
|
||
Tuple* loc_tuple3 = rel3->GetTuple(ver3, false);
|
||
Point* p3 = (Point*)loc_tuple3->GetAttribute(VisualGraph::LOC);
|
||
Point foot3(*p3);
|
||
loc_tuple3->DeleteIfAllowed();
|
||
///////////////////////////////////////////////////////////////////////
|
||
Triangle tri2(ver1, ver2, ver3);
|
||
int sharetype1 = tri2.ShareEdge(tri1);
|
||
int sharetype2 = tri1.ShareEdge(tri2);
|
||
// cout<<"sharetype1 "<<sharetype1<<" sharetype2 "<<sharetype2<<endl;
|
||
if(type1 != 4){
|
||
if(sharetype2 != type1) continue;
|
||
}
|
||
|
||
bool visibility;
|
||
switch(sharetype1){
|
||
case 1:
|
||
// cout<<"case1"<<endl;
|
||
|
||
visibility = CheckVisibility1(clamp, foot3, ver3);
|
||
if(visibility){
|
||
// cout<<"visibility"<<endl;
|
||
HalfSegment hs;
|
||
hs.Set(true, clamp.apex, foot3);
|
||
//split the clamp into 2
|
||
|
||
oids1.push_back(ver3);
|
||
p_list.push_back(foot3);
|
||
Point ip;
|
||
|
||
Clamp clamp1(clamp.apex, foot3, clamp.foot1);
|
||
if(GetIntersectionPoint(foot3,foot1,clamp1,ip,false))
|
||
DFTraverse(adj_list[i], clamp1, tri_id, 2);
|
||
if(GetIntersectionPoint(foot3,foot2,clamp1,ip,false))
|
||
DFTraverse(adj_list[i], clamp1, tri_id, 3);
|
||
|
||
Clamp clamp2(clamp.apex, foot3, clamp.foot2);
|
||
if(GetIntersectionPoint(foot3,foot1,clamp2,ip,false))
|
||
DFTraverse(adj_list[i], clamp2, tri_id, 2);
|
||
if(GetIntersectionPoint(foot3,foot2,clamp2,ip,false))
|
||
DFTraverse(adj_list[i], clamp2, tri_id, 3);
|
||
|
||
}else{
|
||
// bool flag1 = CheckVisibility2(clamp, foot3, foot1);
|
||
// bool flag2 = CheckVisibility2(clamp, foot3, foot2);
|
||
// cout<<"flag1 "<<flag1<<" flag2 "<<flag2<<endl;
|
||
|
||
if(CheckVisibility2(clamp, foot3, foot1)){
|
||
DFTraverse(adj_list[i], clamp, tri_id, 2);
|
||
}
|
||
if(CheckVisibility2(clamp, foot3, foot2)){
|
||
DFTraverse(adj_list[i], clamp, tri_id, 3);
|
||
}
|
||
}
|
||
break;
|
||
case 2:
|
||
// cout<<"case2"<<endl;
|
||
visibility = CheckVisibility1(clamp, foot2, ver2);
|
||
if(visibility){
|
||
// cout<<"visibility"<<endl;
|
||
HalfSegment hs;
|
||
hs.Set(true, clamp.apex, foot2);
|
||
//split the clamp into 2
|
||
oids1.push_back(ver2);
|
||
p_list.push_back(foot2);
|
||
Point ip;
|
||
|
||
Clamp clamp1(clamp.apex, foot2, clamp.foot1);
|
||
if(GetIntersectionPoint(foot2,foot1,clamp1,ip,false))
|
||
DFTraverse(adj_list[i], clamp1, tri_id, 1);
|
||
if(GetIntersectionPoint(foot2,foot3,clamp1,ip,false))
|
||
DFTraverse(adj_list[i], clamp1, tri_id, 3);
|
||
|
||
Clamp clamp2(clamp.apex, foot2, clamp.foot2);
|
||
if(GetIntersectionPoint(foot2,foot1,clamp2,ip,false))
|
||
DFTraverse(adj_list[i], clamp2, tri_id, 1);
|
||
if(GetIntersectionPoint(foot2,foot3,clamp2,ip,false))
|
||
DFTraverse(adj_list[i], clamp2, tri_id, 3);
|
||
|
||
}else{
|
||
if(CheckVisibility2(clamp, foot2, foot1)){
|
||
DFTraverse(adj_list[i], clamp, tri_id, 1);
|
||
}
|
||
|
||
if(CheckVisibility2(clamp, foot2, foot3)){
|
||
DFTraverse(adj_list[i], clamp, tri_id, 3);
|
||
}
|
||
}
|
||
break;
|
||
case 3:
|
||
// cout<<"case3"<<endl;
|
||
visibility = CheckVisibility1(clamp, foot1, ver1);
|
||
|
||
if(visibility){
|
||
// cout<<"visibility"<<endl;
|
||
HalfSegment hs;
|
||
hs.Set(true, clamp.apex, foot1);
|
||
//split the clamp into 2
|
||
|
||
|
||
oids1.push_back(ver1);
|
||
p_list.push_back(foot1);
|
||
Point ip;
|
||
Clamp clamp1(clamp.apex, foot1, clamp.foot2);
|
||
if(GetIntersectionPoint(foot1,foot2,clamp1,ip,false))
|
||
DFTraverse(adj_list[i], clamp1, tri_id, 1);
|
||
if(GetIntersectionPoint(foot1,foot3,clamp1,ip,false))
|
||
DFTraverse(adj_list[i], clamp1, tri_id, 2);
|
||
|
||
Clamp clamp2(clamp.apex, foot1, clamp.foot1);
|
||
if(GetIntersectionPoint(foot1,foot2,clamp2,ip,false))
|
||
DFTraverse(adj_list[i], clamp2, tri_id, 1);
|
||
if(GetIntersectionPoint(foot1,foot3,clamp2,ip,false))
|
||
DFTraverse(adj_list[i], clamp2, tri_id, 2);
|
||
|
||
}else{
|
||
|
||
if(CheckVisibility2(clamp, foot1, foot2)){
|
||
DFTraverse(adj_list[i], clamp, tri_id, 1);
|
||
}
|
||
|
||
if(CheckVisibility2(clamp, foot1, foot3)){
|
||
DFTraverse(adj_list[i], clamp, tri_id, 2);
|
||
}
|
||
|
||
}
|
||
break;
|
||
default: assert(false);
|
||
}
|
||
// cout<<"out of switch"<<endl;
|
||
}
|
||
// cout<<"finish loop"<<endl;
|
||
|
||
}
|
||
|
||
/*
|
||
for each vertex, it returns which triangle it belongs to (vid,triid)
|
||
|
||
*/
|
||
void VGraph::DecomposeTriangle()
|
||
{
|
||
for(int i = 1;i <= rel1->GetNoTuples();i++){
|
||
Tuple* tri_tuple = rel1->GetTuple(i, false);
|
||
int v1 = ((CcInt*)tri_tuple->GetAttribute(DualGraph::V1))->GetIntval();
|
||
int v2 = ((CcInt*)tri_tuple->GetAttribute(DualGraph::V2))->GetIntval();
|
||
int v3 = ((CcInt*)tri_tuple->GetAttribute(DualGraph::V3))->GetIntval();
|
||
int triid =
|
||
((CcInt*)tri_tuple->GetAttribute(DualGraph::TOID))->GetIntval();
|
||
oids1.push_back(v1);
|
||
oids2.push_back(triid);
|
||
oids1.push_back(v2);
|
||
oids2.push_back(triid);
|
||
oids1.push_back(v3);
|
||
oids2.push_back(triid);
|
||
tri_tuple->DeleteIfAllowed();
|
||
}
|
||
|
||
}
|
||
|
||
/*
|
||
find all triangles that contain vertex (vid) and depth first searching
|
||
|
||
*/
|
||
void VGraph::FindTriContainVertex(int vid, int tri_id, Point* query_p)
|
||
{
|
||
// cout<<"FindTriContainVertex() "<<endl;
|
||
// cout<<"vid "<<vid<<"tri_id "<<tri_id<<endl;
|
||
|
||
CcInt* vertex_id = new CcInt(true, vid);
|
||
BTreeIterator* btreeiter = btree->ExactMatch(vertex_id);
|
||
while(btreeiter->Next()){
|
||
Tuple* ver_tri = rel4->GetTuple(btreeiter->GetId(), false);
|
||
int triangle_id =
|
||
((CcInt*)ver_tri->GetAttribute(DualGraph::TRIID))->GetIntval();
|
||
if(triangle_id != tri_id){
|
||
// cout<<"triangle_id "<<triangle_id<<endl;
|
||
Tuple* tri_tuple = rel2->GetTuple(triangle_id, false);
|
||
int v1 =((CcInt*)tri_tuple->GetAttribute(DualGraph::V1))->GetIntval();
|
||
int v2 =((CcInt*)tri_tuple->GetAttribute(DualGraph::V2))->GetIntval();
|
||
int v3 =((CcInt*)tri_tuple->GetAttribute(DualGraph::V3))->GetIntval();
|
||
/////////////////////////////////////////////////////////////////////
|
||
Tuple* loc_tuple1 = rel3->GetTuple(v1, false);
|
||
Point* p1 = (Point*)loc_tuple1->GetAttribute(VisualGraph::LOC);
|
||
Point foot1(*p1);
|
||
loc_tuple1->DeleteIfAllowed();
|
||
Tuple* loc_tuple2 = rel3->GetTuple(v2, false);
|
||
Point* p2 = (Point*)loc_tuple2->GetAttribute(VisualGraph::LOC);
|
||
Point foot2(*p2);
|
||
loc_tuple2->DeleteIfAllowed();
|
||
Tuple* loc_tuple3 = rel3->GetTuple(v3, false);
|
||
Point* p3 = (Point*)loc_tuple3->GetAttribute(VisualGraph::LOC);
|
||
Point foot3(*p3);
|
||
loc_tuple3->DeleteIfAllowed();
|
||
///////////////////////////////////////////////////////////////////////
|
||
|
||
// cout<<"v1 "<<v1<<" v2 "<<v2<<" v3 "<<v3<<endl;
|
||
|
||
vector<int> vid_list;
|
||
if(v1 == vid){
|
||
vid_list.push_back(v2);
|
||
vid_list.push_back(v3);
|
||
|
||
for(unsigned int i = 0;i < vid_list.size();i++){
|
||
unsigned int j = 0;
|
||
for(;j < oids1.size();j++){
|
||
if(vid_list[i] == oids1[j]) break;
|
||
}
|
||
if(j == oids1.size()){
|
||
oids1.push_back(vid_list[i]);
|
||
|
||
Tuple* loc_tuple = rel3->GetTuple(vid_list[i], false);
|
||
Point* p = (Point*)loc_tuple->GetAttribute(VisualGraph::LOC);
|
||
p_list.push_back(*p);
|
||
loc_tuple->DeleteIfAllowed();
|
||
|
||
}
|
||
}
|
||
|
||
Clamp clamp(*query_p, foot2, foot3);
|
||
DFTraverse(triangle_id, clamp, tri_id, 3);
|
||
|
||
}else if(v2 == vid){
|
||
vid_list.push_back(v1);
|
||
vid_list.push_back(v3);
|
||
for(unsigned int i = 0;i < vid_list.size();i++){
|
||
unsigned int j = 0;
|
||
for(;j < oids1.size();j++){
|
||
if(vid_list[i] == oids1[j]) break;
|
||
}
|
||
if(j == oids1.size()){
|
||
|
||
oids1.push_back(vid_list[i]);
|
||
Tuple* loc_tuple = rel3->GetTuple(vid_list[i], false);
|
||
Point* p = (Point*)loc_tuple->GetAttribute(VisualGraph::LOC);
|
||
p_list.push_back(*p);
|
||
loc_tuple->DeleteIfAllowed();
|
||
|
||
}
|
||
}
|
||
|
||
Clamp clamp(*query_p, foot1, foot3);
|
||
DFTraverse(triangle_id, clamp, tri_id, 2);
|
||
|
||
}else if(v3 == vid){
|
||
vid_list.push_back(v1);
|
||
vid_list.push_back(v2);
|
||
for(unsigned int i = 0;i < vid_list.size();i++){
|
||
unsigned int j = 0;
|
||
for(;j < oids1.size();j++){
|
||
if(vid_list[i] == oids1[j]) break;
|
||
}
|
||
if(j == oids1.size()){
|
||
oids1.push_back(vid_list[i]);
|
||
|
||
Tuple* loc_tuple = rel3->GetTuple(vid_list[i], false);
|
||
Point* p = (Point*)loc_tuple->GetAttribute(VisualGraph::LOC);
|
||
p_list.push_back(*p);
|
||
loc_tuple->DeleteIfAllowed();
|
||
|
||
}
|
||
}
|
||
|
||
Clamp clamp(*query_p, foot1, foot2);
|
||
DFTraverse(triangle_id, clamp, tri_id, 1);
|
||
}else assert(false);
|
||
tri_tuple->DeleteIfAllowed();
|
||
}
|
||
ver_tri->DeleteIfAllowed();
|
||
}
|
||
delete btreeiter;
|
||
delete vertex_id;
|
||
}
|
||
|
||
/*
|
||
check the triangle with the only given type
|
||
|
||
*/
|
||
|
||
void VGraph::GetVisibleNode2(int tri_id, Point* query_p, int type)
|
||
{
|
||
|
||
//cout<<"GetVisibleNode2() "<<"query tri_id "<<tri_id + dg->min_tri_oid_1<<endl;
|
||
|
||
const double pi = 3.14159;
|
||
const double delta = 0.0001;
|
||
|
||
vector<int> adj_list;
|
||
dg->FindAdj(tri_id, adj_list);
|
||
|
||
Tuple* tri_tuple1 = rel2->GetTuple(tri_id, false);
|
||
int v1 =((CcInt*)tri_tuple1->GetAttribute(DualGraph::V1))->GetIntval();
|
||
int v2 =((CcInt*)tri_tuple1->GetAttribute(DualGraph::V2))->GetIntval();
|
||
int v3 =((CcInt*)tri_tuple1->GetAttribute(DualGraph::V3))->GetIntval();
|
||
tri_tuple1->DeleteIfAllowed();
|
||
Triangle tri1(v1, v2, v3);
|
||
// cout<<"v1 "<<v1<<" v2 "<<v2<<" v3 "<<v3<<endl;
|
||
///////////////////////////////////////////////////////////////////////
|
||
for(unsigned int i = 0;i < adj_list.size();i++){
|
||
// cout<<"adj_list GVN "<<adj_list[i] + dg->min_tri_oid_1<<endl;
|
||
Tuple* tri_tuple = rel2->GetTuple(adj_list[i], false);
|
||
int ver1 =((CcInt*)tri_tuple->GetAttribute(DualGraph::V1))->GetIntval();
|
||
int ver2 =((CcInt*)tri_tuple->GetAttribute(DualGraph::V2))->GetIntval();
|
||
int ver3 =((CcInt*)tri_tuple->GetAttribute(DualGraph::V3))->GetIntval();
|
||
tri_tuple->DeleteIfAllowed();
|
||
// cout<<"ver1 "<<ver1<<" ver2 "<<ver2<<" ver3 "<<ver3<<endl;
|
||
///////////////////////////////////////////////////////////////////////
|
||
Tuple* loc_tuple1 = rel3->GetTuple(ver1, false);
|
||
Point* p1 = (Point*)loc_tuple1->GetAttribute(VisualGraph::LOC);
|
||
Point foot1(*p1);
|
||
loc_tuple1->DeleteIfAllowed();
|
||
Tuple* loc_tuple2 = rel3->GetTuple(ver2, false);
|
||
Point* p2 = (Point*)loc_tuple2->GetAttribute(VisualGraph::LOC);
|
||
Point foot2(*p2);
|
||
loc_tuple2->DeleteIfAllowed();
|
||
Tuple* loc_tuple3 = rel3->GetTuple(ver3, false);
|
||
Point* p3 = (Point*)loc_tuple3->GetAttribute(VisualGraph::LOC);
|
||
Point foot3(*p3);
|
||
loc_tuple3->DeleteIfAllowed();
|
||
///////////////////////////////////////////////////////////////////////
|
||
Triangle tri2(ver1, ver2, ver3);
|
||
int sharetype1 = tri2.ShareEdge(tri1);
|
||
int sharetype2 = tri1.ShareEdge(tri2);
|
||
if(sharetype2 != type) continue;
|
||
|
||
|
||
Point clamp_foot1;
|
||
Point clamp_foot2;
|
||
if(sharetype1 == 1){
|
||
clamp_foot1 = foot1;
|
||
clamp_foot2 = foot2;
|
||
}
|
||
else if(sharetype1 == 2){
|
||
clamp_foot1 = foot1;
|
||
clamp_foot2 = foot3;
|
||
}
|
||
else if(sharetype1 == 3){
|
||
clamp_foot1 = foot2;
|
||
clamp_foot2 = foot3;
|
||
}
|
||
else assert(false);
|
||
|
||
double d1 = query_p->Distance(clamp_foot1);
|
||
double d2 = query_p->Distance(clamp_foot2);
|
||
|
||
//apex foot1(2),checkp on the same line because apex=foot1(2)
|
||
if(AlmostEqual(d1*d2, 0.0)){
|
||
continue;
|
||
}
|
||
|
||
Clamp clamp(*query_p, clamp_foot1, clamp_foot2);
|
||
|
||
//DFTraverse(adj_list[i], clamp1, tri_id,0);
|
||
//1. triangle to be expanded 2. clamp 3. previous triangle
|
||
//4. edge can't be expanded
|
||
//a special case that the clamp's angle can be 180. but this can only
|
||
//happen at the start time. because when the procedure proceeds, the
|
||
//clamp angle always becomes smaller and smaller
|
||
bool visibility;
|
||
switch(sharetype1){
|
||
case 1:
|
||
// cout<<"case1"<<endl;
|
||
|
||
if(fabs(clamp.angle - pi) < delta )
|
||
visibility = true;
|
||
else
|
||
visibility = CheckVisibility1(clamp, foot3, ver3);
|
||
if(visibility){
|
||
// cout<<"visibility"<<endl;
|
||
HalfSegment hs;
|
||
hs.Set(true, clamp.apex, foot3);
|
||
//split the clamp into 2
|
||
//insert the point into the result;
|
||
oids1.push_back(ver3);
|
||
p_list.push_back(foot3);
|
||
//split the clamp
|
||
Clamp clamp1(*query_p, clamp.foot1, foot3);
|
||
DFTraverse(adj_list[i], clamp1, tri_id, 2);
|
||
Clamp clamp2(*query_p, foot3, clamp.foot2);
|
||
DFTraverse(adj_list[i], clamp2, tri_id, 3);
|
||
}else{
|
||
if(CheckVisibility2(clamp, foot3, foot1)){
|
||
DFTraverse(adj_list[i], clamp, tri_id, 2);
|
||
}
|
||
|
||
if(CheckVisibility2(clamp, foot3, foot2)){
|
||
DFTraverse(adj_list[i], clamp, tri_id, 3);
|
||
}
|
||
}
|
||
break;
|
||
case 2:
|
||
// cout<<"case2"<<endl;
|
||
if(fabs(clamp.angle - pi) < delta)
|
||
visibility = true;
|
||
else
|
||
visibility = CheckVisibility1(clamp, foot2, ver2);
|
||
if(visibility){
|
||
// cout<<"visibility"<<endl;
|
||
HalfSegment hs;
|
||
hs.Set(true, clamp.apex, foot2);
|
||
//split the clamp into 2
|
||
|
||
oids1.push_back(ver2);
|
||
p_list.push_back(foot2);
|
||
Clamp clamp1(*query_p, clamp.foot1, foot2);
|
||
DFTraverse(adj_list[i], clamp1, tri_id, 1);
|
||
Clamp clamp2(*query_p, foot2, clamp.foot2);
|
||
DFTraverse(adj_list[i], clamp2, tri_id, 3);
|
||
|
||
}else{
|
||
|
||
if(CheckVisibility2(clamp, foot2, foot1)){
|
||
DFTraverse(adj_list[i], clamp, tri_id, 1);
|
||
}
|
||
|
||
if(CheckVisibility2(clamp, foot2, foot3)){
|
||
DFTraverse(adj_list[i], clamp, tri_id, 3);
|
||
}
|
||
|
||
}
|
||
break;
|
||
case 3:
|
||
// cout<<"case3"<<endl;
|
||
if(fabs(clamp.angle - pi) < delta)
|
||
visibility = true;
|
||
else
|
||
visibility = CheckVisibility1(clamp, foot1, ver1);
|
||
if(visibility){
|
||
// cout<<"visibility"<<endl;
|
||
HalfSegment hs;
|
||
hs.Set(true, clamp.apex, foot1);
|
||
//split the clamp into 2
|
||
|
||
oids1.push_back(ver1);
|
||
p_list.push_back(foot1);
|
||
Clamp clamp1(*query_p, clamp.foot2, foot1);
|
||
DFTraverse(adj_list[i], clamp1, tri_id, 2);
|
||
Clamp clamp2(*query_p, foot1, clamp.foot1);
|
||
DFTraverse(adj_list[i], clamp2, tri_id, 1);
|
||
|
||
}else{
|
||
if(CheckVisibility2(clamp, foot1, foot2)){
|
||
DFTraverse(adj_list[i], clamp, tri_id, 1);
|
||
}
|
||
|
||
if(CheckVisibility2(clamp, foot1, foot3)){
|
||
DFTraverse(adj_list[i], clamp, tri_id, 2);
|
||
}
|
||
}
|
||
break;
|
||
default: assert(false);
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
/*
|
||
check whether the query point equals to one of the vertices
|
||
if it is. it uses another method to find the clamp.
|
||
each triangle having the query point is considered as a clamp
|
||
|
||
*/
|
||
bool VGraph::GetVNode_QV(int tri_id, Point* query_p, int v1, int v2, int v3)
|
||
{
|
||
Tuple* tuple1 = rel3->GetTuple(v1, false);
|
||
Point* p1 = (Point*)tuple1->GetAttribute(VisualGraph::LOC);
|
||
Point vp1(*p1);
|
||
Tuple* tuple2 = rel3->GetTuple(v2, false);
|
||
Point* p2 = (Point*)tuple2->GetAttribute(VisualGraph::LOC);
|
||
Point vp2(*p2);
|
||
Tuple* tuple3 = rel3->GetTuple(v3, false);
|
||
Point* p3 = (Point*)tuple3->GetAttribute(VisualGraph::LOC);
|
||
Point vp3(*p3);
|
||
tuple1->DeleteIfAllowed();
|
||
tuple2->DeleteIfAllowed();
|
||
tuple3->DeleteIfAllowed();
|
||
int type = 0;
|
||
if(AlmostEqual(vp1, *query_p)) type = 1;
|
||
else if(AlmostEqual(vp2, *query_p)) type = 2;
|
||
else if(AlmostEqual(vp3, *query_p)) type = 3;
|
||
|
||
switch(type){
|
||
case 1:
|
||
oids1.push_back(v2);
|
||
oids1.push_back(v3);
|
||
|
||
for(unsigned int i = 0;i < oids1.size();i++){
|
||
Tuple* loc_tuple = rel3->GetTuple(oids1[i], false);
|
||
Point* p = (Point*)loc_tuple->GetAttribute(VisualGraph::LOC);
|
||
p_list.push_back(*p);
|
||
loc_tuple->DeleteIfAllowed();
|
||
}
|
||
|
||
FindTriContainVertex(v1, tri_id, query_p);
|
||
GetVisibleNode2(tri_id, query_p, 3);
|
||
break;
|
||
case 2:
|
||
oids1.push_back(v1);
|
||
oids1.push_back(v3);
|
||
for(unsigned int i = 0;i < oids1.size();i++){
|
||
Tuple* loc_tuple = rel3->GetTuple(oids1[i], false);
|
||
Point* p = (Point*)loc_tuple->GetAttribute(VisualGraph::LOC);
|
||
p_list.push_back(*p);
|
||
loc_tuple->DeleteIfAllowed();
|
||
}
|
||
FindTriContainVertex(v2, tri_id, query_p);
|
||
GetVisibleNode2(tri_id, query_p, 2);
|
||
|
||
break;
|
||
case 3:
|
||
oids1.push_back(v1);
|
||
oids1.push_back(v2);
|
||
for(unsigned int i = 0;i < oids1.size();i++){
|
||
Tuple* loc_tuple = rel3->GetTuple(oids1[i], false);
|
||
Point* p = (Point*)loc_tuple->GetAttribute(VisualGraph::LOC);
|
||
p_list.push_back(*p);
|
||
loc_tuple->DeleteIfAllowed();
|
||
}
|
||
FindTriContainVertex(v3, tri_id, query_p);
|
||
GetVisibleNode2(tri_id, query_p, 1);
|
||
break;
|
||
}
|
||
if(type != 0)return true;
|
||
else return false;
|
||
|
||
}
|
||
|
||
/*
|
||
find all visible nodes for query_p
|
||
in some cases, there are numberic problems or java display numberic.
|
||
|
||
*/
|
||
|
||
|
||
void VGraph::GetVisibleNode1(int tri_id, Point* query_p)
|
||
{
|
||
|
||
// cout<<"GetVisibleNode1() "<<"query tri_id "<<tri_id<<endl;
|
||
|
||
const double pi = 3.14159;
|
||
const double delta = 0.0001;
|
||
|
||
vector<int> adj_list;
|
||
dg->FindAdj(tri_id, adj_list);
|
||
assert(oids1.size() == 3);
|
||
int v1 = oids1[0];
|
||
int v2 = oids1[1];
|
||
int v3 = oids1[2];
|
||
Triangle tri1(v1, v2, v3);
|
||
|
||
///////////////////////////////////////////////////////////////////////
|
||
for(unsigned int i = 0;i < adj_list.size();i++){
|
||
// cout<<"adj_list GVN "<<adj_list[i]<<endl;
|
||
Tuple* tri_tuple = rel2->GetTuple(adj_list[i], false);
|
||
int ver1 =((CcInt*)tri_tuple->GetAttribute(DualGraph::V1))->GetIntval();
|
||
int ver2 =((CcInt*)tri_tuple->GetAttribute(DualGraph::V2))->GetIntval();
|
||
int ver3 =((CcInt*)tri_tuple->GetAttribute(DualGraph::V3))->GetIntval();
|
||
tri_tuple->DeleteIfAllowed();
|
||
|
||
///////////////////////////////////////////////////////////////////////
|
||
Tuple* loc_tuple1 = rel3->GetTuple(ver1, false);
|
||
Point* p1 = (Point*)loc_tuple1->GetAttribute(VisualGraph::LOC);
|
||
Point foot1(*p1);
|
||
loc_tuple1->DeleteIfAllowed();
|
||
Tuple* loc_tuple2 = rel3->GetTuple(ver2, false);
|
||
Point* p2 = (Point*)loc_tuple2->GetAttribute(VisualGraph::LOC);
|
||
Point foot2(*p2);
|
||
loc_tuple2->DeleteIfAllowed();
|
||
Tuple* loc_tuple3 = rel3->GetTuple(ver3, false);
|
||
Point* p3 = (Point*)loc_tuple3->GetAttribute(VisualGraph::LOC);
|
||
Point foot3(*p3);
|
||
loc_tuple3->DeleteIfAllowed();
|
||
///////////////////////////////////////////////////////////////////////
|
||
Triangle tri2(ver1, ver2, ver3);
|
||
int sharetype = tri2.ShareEdge(tri1);
|
||
Clamp clamp12(*query_p, foot1, foot2);
|
||
Clamp clamp13(*query_p, foot1, foot3);
|
||
Clamp clamp23(*query_p, foot2, foot3);
|
||
|
||
//DFTraverse(adj_list[i], clamp1, tri_id,0);
|
||
//1. triangle to be expanded 2. clamp 3. previous triangle
|
||
//4. edge can't be expanded
|
||
//a special case that the clamp's angle can be 180. but this can only
|
||
//happen at the start time. because when the procedure proceeds, the
|
||
//clamp angle always becomes smaller and smaller
|
||
bool visibility;
|
||
switch(sharetype){
|
||
case 1:
|
||
|
||
// cout<<"case1"<<endl;
|
||
if(fabs(clamp12.angle - pi) < delta )
|
||
visibility = true;
|
||
else
|
||
visibility = CheckVisibility1(clamp12, foot3, ver3);
|
||
if(visibility){
|
||
// cout<<"visibility"<<endl;
|
||
HalfSegment hs;
|
||
hs.Set(true, clamp12.apex, foot3);
|
||
//split the clamp into 2
|
||
|
||
//insert the point into the result;
|
||
oids1.push_back(ver3);
|
||
p_list.push_back(foot3);
|
||
//split the clamp
|
||
Clamp clamp1(*query_p, clamp12.foot1, foot3);
|
||
DFTraverse(adj_list[i], clamp1, tri_id, 2);
|
||
Clamp clamp2(*query_p, foot3, clamp12.foot2);
|
||
DFTraverse(adj_list[i], clamp2, tri_id, 3);
|
||
|
||
}else{
|
||
if(CheckVisibility2(clamp12, foot3, foot1)){
|
||
DFTraverse(adj_list[i], clamp12, tri_id, 2);
|
||
}
|
||
|
||
if(CheckVisibility2(clamp12, foot3, foot2)){
|
||
DFTraverse(adj_list[i], clamp12, tri_id, 3);
|
||
}
|
||
}
|
||
break;
|
||
case 2:
|
||
// cout<<"case2"<<endl;
|
||
if(fabs(clamp13.angle - pi) < delta)
|
||
visibility = true;
|
||
else
|
||
visibility = CheckVisibility1(clamp13, foot2, ver2);
|
||
if(visibility){
|
||
// cout<<"visibility"<<endl;
|
||
HalfSegment hs;
|
||
hs.Set(true, clamp13.apex, foot2);
|
||
//split the clamp into 2
|
||
|
||
oids1.push_back(ver2);
|
||
p_list.push_back(foot2);
|
||
Clamp clamp1(*query_p, clamp13.foot1, foot2);
|
||
DFTraverse(adj_list[i], clamp1, tri_id, 1);
|
||
Clamp clamp2(*query_p, foot2, clamp13.foot2);
|
||
DFTraverse(adj_list[i], clamp2, tri_id, 3);
|
||
|
||
}else{
|
||
|
||
if(CheckVisibility2(clamp13, foot2, foot1)){
|
||
DFTraverse(adj_list[i], clamp13, tri_id, 1);
|
||
}
|
||
|
||
if(CheckVisibility2(clamp13, foot2, foot3)){
|
||
DFTraverse(adj_list[i], clamp13, tri_id, 3);
|
||
}
|
||
|
||
}
|
||
break;
|
||
case 3:
|
||
// cout<<"case3"<<endl;
|
||
if(fabs(clamp23.angle - pi) < delta)
|
||
visibility = true;
|
||
else
|
||
visibility = CheckVisibility1(clamp23, foot1, ver1);
|
||
if(visibility){
|
||
// cout<<"visibility"<<endl;
|
||
HalfSegment hs;
|
||
hs.Set(true, clamp23.apex, foot1);
|
||
//split the clamp into 2
|
||
oids1.push_back(ver1);
|
||
p_list.push_back(foot1);
|
||
Clamp clamp1(*query_p, clamp23.foot2, foot1);
|
||
DFTraverse(adj_list[i], clamp1, tri_id, 2);
|
||
Clamp clamp2(*query_p, foot1, clamp23.foot1);
|
||
DFTraverse(adj_list[i], clamp2, tri_id, 1);
|
||
|
||
}else{
|
||
if(CheckVisibility2(clamp23, foot1, foot2)){
|
||
DFTraverse(adj_list[i], clamp23, tri_id, 1);
|
||
}
|
||
|
||
if(CheckVisibility2(clamp23, foot1, foot3)){
|
||
DFTraverse(adj_list[i], clamp23, tri_id, 2);
|
||
}
|
||
}
|
||
break;
|
||
default: assert(false);
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
/*
|
||
for walk shortest path algorithm
|
||
it tries to connect the query point to the visiblity graph.
|
||
if the query point locates in the visiblity graph.
|
||
then it does not connect. because the adjacency can be later found by the
|
||
adjacency list
|
||
|
||
*/
|
||
void VGraph::GetVisibilityNode(int tri_id, Point query_p)
|
||
{
|
||
assert(1 <= tri_id && tri_id <= rel2->GetNoTuples());
|
||
/////////three vertices of the triangle////////////////////////
|
||
Tuple* tri_tuple1 = rel2->GetTuple(tri_id, false);
|
||
int v1 =((CcInt*)tri_tuple1->GetAttribute(DualGraph::V1))->GetIntval();
|
||
int v2 =((CcInt*)tri_tuple1->GetAttribute(DualGraph::V2))->GetIntval();
|
||
int v3 =((CcInt*)tri_tuple1->GetAttribute(DualGraph::V3))->GetIntval();
|
||
tri_tuple1->DeleteIfAllowed();
|
||
|
||
///if the query_p equals to one of the triangle vertices ///
|
||
|
||
Tuple* tuple1 = rel3->GetTuple(v1, false);
|
||
Point* p1 = (Point*)tuple1->GetAttribute(VisualGraph::LOC);
|
||
Point vp1(*p1);
|
||
Tuple* tuple2 = rel3->GetTuple(v2, false);
|
||
Point* p2 = (Point*)tuple2->GetAttribute(VisualGraph::LOC);
|
||
Point vp2(*p2);
|
||
Tuple* tuple3 = rel3->GetTuple(v3, false);
|
||
Point* p3 = (Point*)tuple3->GetAttribute(VisualGraph::LOC);
|
||
Point vp3(*p3);
|
||
tuple1->DeleteIfAllowed();
|
||
tuple2->DeleteIfAllowed();
|
||
tuple3->DeleteIfAllowed();
|
||
int type = 0;
|
||
if(AlmostEqual(vp1, query_p)) type = 1;
|
||
else if(AlmostEqual(vp2, query_p)) type = 2;
|
||
else if(AlmostEqual(vp3, query_p)) type = 3;
|
||
|
||
/////////////////////////////////////////////////////////////
|
||
switch(type){
|
||
case 0:
|
||
oids1.push_back(v1);
|
||
oids1.push_back(v2);
|
||
oids1.push_back(v3);
|
||
p_list.push_back(vp1);
|
||
p_list.push_back(vp2);
|
||
p_list.push_back(vp3);
|
||
///////searching in the dual graph to find all visible vertices////
|
||
GetVisibleNode1(tri_id, &query_p);
|
||
break;
|
||
//if it equals to one of the vertices of the triangle, it directly
|
||
//put the vertex and return.
|
||
//its visibile vertices can be found by adjacency list
|
||
case 1:
|
||
oids1.push_back(v1);
|
||
p_list.push_back(vp1);
|
||
break;
|
||
case 2:
|
||
oids1.push_back(v2);
|
||
p_list.push_back(vp2);
|
||
break;
|
||
case 3:
|
||
oids1.push_back(v3);
|
||
p_list.push_back(vp3);
|
||
break;
|
||
default:assert(false);
|
||
}
|
||
|
||
}
|
||
|
||
/*
|
||
for a given point, find all its visible nodes
|
||
connect the point to the visibility graph node
|
||
rel1--query location relation
|
||
rel2--triangle relation v1 int v2 int v3 int
|
||
rel3--vertex relation1 (oid int) (loc point)
|
||
rel4--vertex relation2 (vid(oid) int) (triid int)
|
||
|
||
*/
|
||
void VGraph::GetVNode()
|
||
{
|
||
if(rel1->GetNoTuples() < 1){
|
||
cout<<"query relation is empty"<<endl;
|
||
return;
|
||
}
|
||
Tuple* query_tuple = rel1->GetTuple(1, false);
|
||
int query_oid =
|
||
((CcInt*)query_tuple->GetAttribute(VisualGraph::QOID))->GetIntval();
|
||
Point* query_p =
|
||
new Point(*((Point*)query_tuple->GetAttribute(VisualGraph::QLOC2)));
|
||
query_tuple->DeleteIfAllowed();
|
||
|
||
query_oid -= dg->min_tri_oid_1;
|
||
assert(1 <= query_oid && query_oid <= dg->node_rel->GetNoTuples());
|
||
/////////three vertices of the triangle////////////////////////
|
||
Tuple* tri_tuple1 = rel2->GetTuple(query_oid, false);
|
||
int v1 =((CcInt*)tri_tuple1->GetAttribute(DualGraph::V1))->GetIntval();
|
||
int v2 =((CcInt*)tri_tuple1->GetAttribute(DualGraph::V2))->GetIntval();
|
||
int v3 =((CcInt*)tri_tuple1->GetAttribute(DualGraph::V3))->GetIntval();
|
||
tri_tuple1->DeleteIfAllowed();
|
||
|
||
///if the query_p equals to one of the triangle vertices ///
|
||
if(GetVNode_QV(query_oid, query_p,v1,v2,v3)){
|
||
}else{
|
||
//////////////////////////////////////////////////////////////////////////
|
||
////////three vertices of the triangle that the point is located in///////
|
||
//////////////////////////////////////////////////////////////////////////
|
||
oids1.push_back(v1);
|
||
oids1.push_back(v2);
|
||
oids1.push_back(v3);
|
||
for(unsigned int i = 0;i < oids1.size();i++){
|
||
Tuple* loc_tuple = rel3->GetTuple(oids1[i], false);
|
||
Point* p = (Point*)loc_tuple->GetAttribute(VisualGraph::LOC);
|
||
p_list.push_back(*p);
|
||
loc_tuple->DeleteIfAllowed();
|
||
}
|
||
///////////searching in the dual graph to find all visible vertices//////
|
||
GetVisibleNode1(query_oid, query_p);
|
||
}
|
||
|
||
///////build a halfsegment between query point and its visibility point////
|
||
for(unsigned int i = 0;i < p_list.size();i++){
|
||
Line* l = new Line(0);
|
||
l->StartBulkLoad();
|
||
HalfSegment hs;
|
||
hs.Set(true, p_list[i], *query_p);
|
||
hs.attr.edgeno = 0;
|
||
*l += hs;
|
||
hs.SetLeftDomPoint(!hs.IsLeftDomPoint());
|
||
*l += hs;
|
||
l->EndBulkLoad();
|
||
line.push_back(*l);
|
||
l->DeleteIfAllowed();
|
||
}
|
||
delete query_p;
|
||
}
|
||
|
||
|
||
/*
|
||
create a relation for the vertices of the region with the cycleno
|
||
|
||
*/
|
||
void RegVertex::CreateVertex()
|
||
{
|
||
/* //naive method to compute the cycle of a region
|
||
vector<int> cycle;
|
||
for(int i = 0;i < reg->Size();i++){
|
||
HalfSegment hs;
|
||
reg->Get(i, hs);
|
||
if(!hs.IsLeftDomPoint())continue;
|
||
int cycle_no = hs.attr.cycleno;
|
||
unsigned int j = 0;
|
||
for(;j < cycle.size();j++)
|
||
if(cycle[j] == cycle_no) break;
|
||
if(j == cycle.size()) cycle.push_back(cycle_no);
|
||
}
|
||
cout<<"polgyon with "<<cycle.size()<<" cycles inside "<<endl;*/
|
||
CompTriangle* ct = new CompTriangle(reg);
|
||
unsigned int no_cyc = ct->NoOfCycles();
|
||
assert(no_cyc > 0);
|
||
|
||
//const int ncontours = no_cyc;
|
||
//int no_p_contour[ncontours];
|
||
|
||
vector<double> ps_contour_x;
|
||
vector<double> ps_contour_y;
|
||
|
||
vector<SimpleLine*> sl_contour;
|
||
|
||
for(unsigned int i = 0;i < no_cyc;i++){
|
||
SimpleLine* sl = new SimpleLine(0);
|
||
sl->StartBulkLoad();
|
||
sl_contour.push_back(sl);
|
||
}
|
||
vector<int> edgenos(no_cyc, 0);
|
||
for(int j = 0;j < reg->Size();j++){
|
||
HalfSegment hs1;
|
||
reg->Get(j, hs1);
|
||
if(!hs1.IsLeftDomPoint()) continue;
|
||
HalfSegment hs2;
|
||
hs2.Set(true, hs1.GetLeftPoint(), hs1.GetRightPoint());
|
||
|
||
hs2.attr.edgeno = edgenos[hs1.attr.cycleno]++;
|
||
*sl_contour[hs1.attr.cycleno] += hs2;
|
||
hs2.SetLeftDomPoint(!hs2.IsLeftDomPoint());
|
||
*sl_contour[hs1.attr.cycleno] += hs2;
|
||
|
||
}
|
||
|
||
SpacePartition* sp = new SpacePartition();
|
||
|
||
for(unsigned int i = 0;i < no_cyc;i++){
|
||
// cout<<"i "<<i<<endl;
|
||
sl_contour[i]->EndBulkLoad();
|
||
vector<MyHalfSegment> mhs;
|
||
|
||
sp->ReorderLine(sl_contour[i], mhs);
|
||
vector<Point> ps;
|
||
for(unsigned int j = 0;j < mhs.size();j++)
|
||
ps.push_back(mhs[j].from);
|
||
|
||
bool clock;
|
||
if(0.0f < ct->Area(ps)){//points counter-clockwise order
|
||
clock = false;
|
||
}else{// points clockwise
|
||
clock = true;
|
||
}
|
||
//no_p_contour[i] = ps.size();
|
||
if(i == 0){//outer contour, counter_clockwise
|
||
if(clock == false){
|
||
for(unsigned int index = 0;index < ps.size();index++){
|
||
// ps_contour_x.push_back(ps[index].GetX());
|
||
// ps_contour_y.push_back(ps[index].GetY());
|
||
regnodes.push_back(ps[index]);
|
||
cycleno.push_back(i);
|
||
|
||
}
|
||
}else{
|
||
for(unsigned int index = 0;index < ps.size();index++){
|
||
// ps_contour_x.push_back(ps[ps.size() - 1 - index].GetX());
|
||
// ps_contour_y.push_back(ps[ps.size() - 1 - index].GetY());
|
||
regnodes.push_back(ps[ps.size() - 1 - index]);
|
||
cycleno.push_back(i);
|
||
}
|
||
}
|
||
}else{//hole points, should be clockwise
|
||
if(clock == false){
|
||
for(unsigned int index = 0;index < ps.size();index++){
|
||
// ps_contour_x.push_back(ps[ps.size() -1 - index].GetX());
|
||
// ps_contour_y.push_back(ps[ps.size() -1 - index].GetY());
|
||
regnodes.push_back(ps[ps.size() - 1 - index]);
|
||
cycleno.push_back(i);
|
||
}
|
||
}else{
|
||
for(unsigned int index = 0;index < ps.size();index++){
|
||
// ps_contour_x.push_back(ps[index].GetX());
|
||
// ps_contour_y.push_back(ps[index].GetY());
|
||
regnodes.push_back(ps[index]);
|
||
cycleno.push_back(i);
|
||
}
|
||
}
|
||
}
|
||
|
||
sl_contour[i]->DeleteIfAllowed();
|
||
}
|
||
delete ct;
|
||
delete sp;
|
||
}
|
||
|
||
/*
|
||
for each triangle, it returns the number of each point and the centroid
|
||
|
||
*/
|
||
void RegVertex::TriangulationNew()
|
||
{
|
||
CompTriangle* ct = new CompTriangle(reg);
|
||
unsigned int no_cyc = ct->NoOfCycles();
|
||
assert(no_cyc > 0);
|
||
|
||
const int ncontours = no_cyc;
|
||
int no_p_contour[ncontours];
|
||
|
||
vector<double> ps_contour_x;//start from 1
|
||
vector<double> ps_contour_y;//start from 1
|
||
|
||
ct->PolygonContourPoint(no_cyc, no_p_contour, ps_contour_x, ps_contour_y);
|
||
int result_trig[SEGSIZE][3];
|
||
int (*res_triangles)[3] = &result_trig[0];
|
||
|
||
int no_triangle;
|
||
no_triangle = triangulate_polygon(no_cyc, no_p_contour,
|
||
ps_contour_x, ps_contour_y, res_triangles);
|
||
|
||
// cout<<"no_triangle "<<no_triangle<<endl;
|
||
|
||
assert(0 < no_triangle && no_triangle < SEGSIZE);
|
||
for (int i = 0; i < no_triangle; i++){
|
||
Coord x, y;
|
||
|
||
x = ps_contour_x[res_triangles[i][0]];
|
||
y = ps_contour_y[res_triangles[i][0]];
|
||
|
||
x += ps_contour_x[res_triangles[i][1]];
|
||
y += ps_contour_y[res_triangles[i][1]];
|
||
|
||
x += ps_contour_x[res_triangles[i][2]];
|
||
y += ps_contour_y[res_triangles[i][2]];
|
||
v1_list.push_back(res_triangles[i][0]);
|
||
v2_list.push_back(res_triangles[i][1]);
|
||
v3_list.push_back(res_triangles[i][2]);
|
||
//calculate the centroid point
|
||
Point p;
|
||
p.Set(x/3.0, y/3.0);
|
||
regnodes.push_back(p);
|
||
}
|
||
|
||
delete ct;
|
||
}
|
||
|
||
/*
|
||
for each triangle, it returns the number of each point and the triangle
|
||
|
||
*/
|
||
void RegVertex::TriangulationExt()
|
||
{
|
||
CompTriangle* ct = new CompTriangle(reg);
|
||
unsigned int no_cyc = ct->NoOfCycles();
|
||
assert(no_cyc > 0);
|
||
|
||
const int ncontours = no_cyc;
|
||
int no_p_contour[ncontours];
|
||
|
||
vector<double> ps_contour_x;//start from 1
|
||
vector<double> ps_contour_y;//start from 1
|
||
|
||
ct->PolygonContourPoint(no_cyc, no_p_contour, ps_contour_x, ps_contour_y);
|
||
int result_trig[SEGSIZE][3];
|
||
int (*res_triangles)[3] = &result_trig[0];
|
||
|
||
int no_triangle;
|
||
no_triangle = triangulate_polygon(no_cyc, no_p_contour,
|
||
ps_contour_x, ps_contour_y, res_triangles);
|
||
|
||
// cout<<"no_triangle "<<no_triangle<<endl;
|
||
|
||
assert(0 < no_triangle && no_triangle < SEGSIZE);
|
||
for (int i = 0; i < no_triangle; i++){
|
||
Coord x1, y1;
|
||
Coord x2, y2;
|
||
Coord x3, y3;
|
||
|
||
x1 = ps_contour_x[res_triangles[i][0]];
|
||
y1 = ps_contour_y[res_triangles[i][0]];
|
||
|
||
x2 = ps_contour_x[res_triangles[i][1]];
|
||
y2 = ps_contour_y[res_triangles[i][1]];
|
||
|
||
x3 = ps_contour_x[res_triangles[i][2]];
|
||
y3 = ps_contour_y[res_triangles[i][2]];
|
||
|
||
v1_list.push_back(res_triangles[i][0]);
|
||
v2_list.push_back(res_triangles[i][1]);
|
||
v3_list.push_back(res_triangles[i][2]);
|
||
|
||
Point p1(true, x1, y1);
|
||
Point p2(true, x2, y2);
|
||
Point p3(true, x3, y3);
|
||
|
||
vector<Point> ps_list;
|
||
ps_list.push_back(p1);
|
||
ps_list.push_back(p2);
|
||
ps_list.push_back(p3);
|
||
SpacePartition* sp = new SpacePartition();
|
||
vector<Region> reg_list;
|
||
sp->ComputeRegion(ps_list, reg_list);
|
||
tri_list.push_back(reg_list[0]);
|
||
delete sp;
|
||
}
|
||
delete ct;
|
||
}
|
||
|
||
/*
|
||
for each triangle, it returns the number of each point and the centroid
|
||
|
||
*/
|
||
void RegVertex::TriangulationNew2()
|
||
{
|
||
CompTriangle* ct = new CompTriangle(reg);
|
||
unsigned int no_cyc = ct->NoOfCycles();
|
||
assert(no_cyc > 0);
|
||
|
||
const int ncontours = no_cyc;
|
||
int no_p_contour[ncontours];
|
||
|
||
vector<double> ps_contour_x;//start from 0
|
||
vector<double> ps_contour_y;//start from 0
|
||
|
||
ct->PolygonContourPoint2(no_cyc, no_p_contour, ps_contour_x, ps_contour_y);
|
||
|
||
HPolygon poly;
|
||
int no_triangle = poly.Triangulation2(no_cyc, no_p_contour,
|
||
ps_contour_x, ps_contour_y);
|
||
|
||
// cout<<"no_triangle "<<no_triangle<<endl;
|
||
SpacePartition* spacepart = new SpacePartition();
|
||
|
||
for (int i = 0; i < no_triangle; i++){
|
||
Coord x, y;
|
||
int index1 = poly.mtabCell[i].Index(0);
|
||
int index2 = poly.mtabCell[i].Index(1);
|
||
int index3 = poly.mtabCell[i].Index(2);
|
||
|
||
x = poly.mtabPnt[index1].X();
|
||
y = poly.mtabPnt[index1].Y();
|
||
|
||
x += poly.mtabPnt[index2].X();
|
||
y += poly.mtabPnt[index2].Y();;
|
||
|
||
x += poly.mtabPnt[index3].X();
|
||
y += poly.mtabPnt[index3].Y();;
|
||
|
||
// v1_list.push_back(index1 + 1);
|
||
// v2_list.push_back(index2 + 1);
|
||
// v3_list.push_back(index3 + 1);
|
||
|
||
// v1_list.push_back(poly.p_id_list[index1]);
|
||
// v2_list.push_back(poly.p_id_list[index2]);
|
||
// v3_list.push_back(poly.p_id_list[index3]);
|
||
|
||
// //calculate the centroid point
|
||
// Point p;
|
||
// p.Set(x/3.0, y/3.0);
|
||
// regnodes.push_back(p);
|
||
|
||
///////////////////2012.3.9 rounding problem //////////
|
||
Point p1(true, poly.mtabPnt[index1].X(), poly.mtabPnt[index1].Y());
|
||
Point p2(true, poly.mtabPnt[index2].X(), poly.mtabPnt[index2].Y());
|
||
Point p3(true, poly.mtabPnt[index3].X(), poly.mtabPnt[index3].Y());
|
||
vector<Point> ps_list;
|
||
ps_list.push_back(p1);
|
||
ps_list.push_back(p2);
|
||
ps_list.push_back(p3);
|
||
vector<Region> reg;
|
||
spacepart->ComputeRegion(ps_list, reg);
|
||
///////////////////////////////////////////////
|
||
if(reg.size() > 0){
|
||
//calculate the centroid point
|
||
Point p;
|
||
p.Set(x/3.0, y/3.0);
|
||
regnodes.push_back(p);
|
||
v1_list.push_back(poly.p_id_list[index1]);
|
||
v2_list.push_back(poly.p_id_list[index2]);
|
||
v3_list.push_back(poly.p_id_list[index3]);
|
||
}
|
||
}
|
||
|
||
delete ct;
|
||
delete spacepart;
|
||
}
|
||
|
||
void RegVertex::TriangulationExt2()
|
||
{
|
||
CompTriangle* ct = new CompTriangle(reg);
|
||
unsigned int no_cyc = ct->NoOfCycles();
|
||
assert(no_cyc > 0);
|
||
|
||
const int ncontours = no_cyc;
|
||
int no_p_contour[ncontours];
|
||
|
||
vector<double> ps_contour_x;//start from 0
|
||
vector<double> ps_contour_y;//start from 0
|
||
|
||
ct->PolygonContourPoint2(no_cyc, no_p_contour, ps_contour_x, ps_contour_y);
|
||
|
||
HPolygon poly;
|
||
int no_triangle = poly.Triangulation2(no_cyc, no_p_contour,
|
||
ps_contour_x, ps_contour_y);
|
||
|
||
// cout<<"no_triangle "<<no_triangle<<endl;
|
||
|
||
for (int i = 0; i < no_triangle; i++){
|
||
Coord x1, y1;
|
||
Coord x2, y2;
|
||
Coord x3, y3;
|
||
int index1 = poly.mtabCell[i].Index(0);
|
||
int index2 = poly.mtabCell[i].Index(1);
|
||
int index3 = poly.mtabCell[i].Index(2);
|
||
|
||
x1 = poly.mtabPnt[index1].X();
|
||
y1 = poly.mtabPnt[index1].Y();
|
||
|
||
x2 = poly.mtabPnt[index2].X();
|
||
y2 = poly.mtabPnt[index2].Y();;
|
||
|
||
x3 = poly.mtabPnt[index3].X();
|
||
y3 = poly.mtabPnt[index3].Y();;
|
||
|
||
// v1_list.push_back(index1 + 1);
|
||
// v2_list.push_back(index2 + 1);
|
||
// v3_list.push_back(index3 + 1);
|
||
|
||
// v1_list.push_back(poly.p_id_list[index1]);
|
||
// v2_list.push_back(poly.p_id_list[index2]);
|
||
// v3_list.push_back(poly.p_id_list[index3]);
|
||
|
||
|
||
Point p1(true, x1, y1);
|
||
Point p2(true, x2, y2);
|
||
Point p3(true, x3, y3);
|
||
|
||
vector<Point> ps_list;
|
||
ps_list.push_back(p1);
|
||
ps_list.push_back(p2);
|
||
ps_list.push_back(p3);
|
||
SpacePartition* sp = new SpacePartition();
|
||
vector<Region> reg_list;
|
||
sp->ComputeRegion(ps_list, reg_list);
|
||
// tri_list.push_back(reg_list[0]);
|
||
if(reg_list.size() > 0){ /////////2012.3.9 rounding problem
|
||
tri_list.push_back(reg_list[0]);
|
||
v1_list.push_back(poly.p_id_list[index1]);
|
||
v2_list.push_back(poly.p_id_list[index2]);
|
||
v3_list.push_back(poly.p_id_list[index3]);
|
||
}
|
||
delete sp;
|
||
}
|
||
|
||
delete ct;
|
||
}
|
||
|
||
/*
|
||
For each triangle, it sets the number of neighbors it has already.
|
||
If the numbers of two vertices are consecutive and they belong to the same
|
||
cycle, then the edge connecting them is the boundary. Thus, there is no triangle
|
||
adjacent to it by this edge. So we increase the number of neighbor. As for a
|
||
triangle, the maximum neighbor it can have is 3 (three edges).
|
||
|
||
*/
|
||
|
||
void SetNeighbor(Triangle& tri, vector<int>& no_points_cycles,
|
||
vector<int>& index_contour)
|
||
{
|
||
//v1 and v2 are consecutive boundary points
|
||
if(tri.c1 == tri.c2){
|
||
if(fabs(tri.v1 - tri.v2) == 1){
|
||
tri.neighbor_no++;
|
||
}
|
||
|
||
else if(tri.v1 == index_contour[tri.c1] && //first
|
||
tri.v2 == index_contour[tri.c1] + no_points_cycles[tri.c2] - 1)//last
|
||
tri.neighbor_no++;
|
||
|
||
else if(tri.v2 == index_contour[tri.c1] &&
|
||
tri.v1 == index_contour[tri.c1] + no_points_cycles[tri.c1] - 1)
|
||
tri.neighbor_no++;
|
||
}
|
||
//v1 and v3 are consecutive boundary points
|
||
if(tri.c1 == tri.c3){
|
||
if(fabs(tri.v1 - tri.v3) == 1){
|
||
tri.neighbor_no++;
|
||
}
|
||
|
||
else if(tri.v1 == index_contour[tri.c1] &&
|
||
tri.v3 == index_contour[tri.c3] + no_points_cycles[tri.c3] - 1){
|
||
tri.neighbor_no++;
|
||
}
|
||
|
||
else if(tri.v3 == index_contour[tri.c3] &&
|
||
tri.v1 == index_contour[tri.c1] + no_points_cycles[tri.c1] - 1)
|
||
tri.neighbor_no++;
|
||
}
|
||
//v2 and v3 are consecutive boundary points
|
||
if(tri.c2 == tri.c3){
|
||
if(fabs(tri.v2 - tri.v3) == 1)
|
||
tri.neighbor_no++;
|
||
|
||
else if(tri.v2 == index_contour[tri.c2] &&
|
||
tri.v3 == index_contour[tri.c3] + no_points_cycles[tri.c3] - 1)
|
||
tri.neighbor_no++;
|
||
|
||
else if(tri.v3 == index_contour[tri.c3] &&
|
||
tri.v2 == index_contour[tri.c2] + no_points_cycles[tri.c2] - 1){
|
||
tri.neighbor_no++;
|
||
}
|
||
}
|
||
}
|
||
|
||
/*
|
||
get the dual graph edge relation. if two triangles have the same edge, an edge
|
||
in dual graph is created. Each node corresponds to a triangle.
|
||
1. number the vertex. order them by z-order
|
||
2. use a list
|
||
3. find the neighbor by the number of vertex instead of intersection detecting
|
||
|
||
*/
|
||
void RegVertex::GetDGEdge()
|
||
{
|
||
//the number it stores is the number of points inside
|
||
//cycleno->number of points
|
||
vector<int> no_points_cycles(rel2->GetNoTuples(), 0);
|
||
|
||
vector<int> vertex_cycleno; //vertex -> cycleno
|
||
vector<Point> vertex_point;
|
||
//relation (cycleno int)(vertex point)
|
||
for(int i = 1;i <= rel2->GetNoTuples();i++){
|
||
Tuple* t = rel2->GetTuple(i, false);
|
||
int cycleno = ((CcInt*)t->GetAttribute(DualGraph::CYCLENO))->GetIntval();
|
||
Point* p = (Point*)t->GetAttribute(DualGraph::VERTEX);
|
||
vertex_cycleno.push_back(cycleno);
|
||
vertex_point.push_back(*p);
|
||
t->DeleteIfAllowed();
|
||
no_points_cycles[cycleno]++;
|
||
}
|
||
|
||
vector<int> index_contour;
|
||
unsigned int no_cyc = 0;
|
||
for(unsigned int i = 0;i < no_points_cycles.size();i++){
|
||
// cout<<"no_cyc "<<i<<" points "<<no_points_cycles[i]<<endl;
|
||
if(i == 0) index_contour.push_back(1);
|
||
else index_contour.push_back(index_contour[index_contour.size() - 1] +
|
||
no_points_cycles[i - 1]);
|
||
|
||
// cout<<"start index "<<index_contour[index_contour.size() - 1]<<endl;
|
||
if(no_points_cycles[i] > 0) no_cyc++;
|
||
else
|
||
break;
|
||
}
|
||
|
||
// cout<<"no of cycles "<<no_cyc<<endl;
|
||
|
||
TriNode* head = new TriNode();
|
||
TriNode* trinode;
|
||
for(int i = 1;i <= rel1->GetNoTuples();i++){
|
||
Tuple* t = rel1->GetTuple(i, false);
|
||
int v1 = ((CcInt*)t->GetAttribute(DualGraph::V1))->GetIntval();
|
||
int v2 = ((CcInt*)t->GetAttribute(DualGraph::V2))->GetIntval();
|
||
int v3 = ((CcInt*)t->GetAttribute(DualGraph::V3))->GetIntval();
|
||
int oid = ((CcInt*)t->GetAttribute(DualGraph::TOID))->GetIntval();
|
||
int c1 = vertex_cycleno[v1 - 1];
|
||
int c2 = vertex_cycleno[v2 - 1];
|
||
int c3 = vertex_cycleno[v3 - 1];
|
||
|
||
/* if(!(oid == 93 || oid == 94 || oid == 95)){
|
||
t->DeleteIfAllowed();
|
||
continue;
|
||
}*/
|
||
|
||
Triangle tri(oid, v1, v2, v3, c1, c2, c3);
|
||
SetNeighbor(tri, no_points_cycles, index_contour);
|
||
|
||
// cout<<"new elem ";
|
||
// tri.Print();
|
||
|
||
trinode = new TriNode(tri,NULL);
|
||
////////////////traverse the list //////////////////////////////
|
||
if(i == 1){
|
||
head->next = trinode;
|
||
t->DeleteIfAllowed();
|
||
continue;
|
||
}
|
||
TriNode* prev = head;
|
||
TriNode* cur = prev->next;
|
||
bool insert = true;
|
||
while(cur != NULL && insert){
|
||
// cout<<" cur elem in list ";
|
||
// cur->tri.Print();
|
||
|
||
int sharetype = trinode->tri.ShareEdge(cur->tri);
|
||
// cout<<"sharetype "<<sharetype<<endl;
|
||
if(sharetype > 0){ //find a common edge
|
||
// cout<<"oid1 "<<trinode->tri.oid<<"oid2 "<<cur->tri.oid<<endl;
|
||
|
||
////////////adjacent list///////////////////////////////
|
||
v1_list.push_back(trinode->tri.oid);
|
||
v2_list.push_back(cur->tri.oid);
|
||
|
||
Point p1, p2;
|
||
switch(sharetype){
|
||
case 1:
|
||
p1 = vertex_point[tri.v1 - 1];
|
||
p2 = vertex_point[tri.v2 - 1];
|
||
break;
|
||
case 2:
|
||
p1 = vertex_point[tri.v1 - 1];
|
||
p2 = vertex_point[tri.v3 - 1];
|
||
break;
|
||
case 3:
|
||
p1 = vertex_point[tri.v2 - 1];
|
||
p2 = vertex_point[tri.v3 - 1];
|
||
break;
|
||
default:
|
||
assert(false);
|
||
}
|
||
|
||
/* hs.Set(true, p1, p2);
|
||
Line* l = new Line(0);
|
||
l->StartBulkLoad();
|
||
hs.attr.edgeno = 0;
|
||
*l += hs;
|
||
hs.SetLeftDomPoint(!hs.IsLeftDomPoint());
|
||
*l += hs;
|
||
l->EndBulkLoad();
|
||
line.push_back(*l);
|
||
delete l;*/
|
||
|
||
|
||
Line* l = new Line(0);
|
||
l->StartBulkLoad();
|
||
// if(!AlmostEqual(p1, p2)){
|
||
HalfSegment hs;
|
||
hs.Set(true, p1, p2);
|
||
hs.attr.edgeno = 0;
|
||
*l += hs;
|
||
hs.SetLeftDomPoint(!hs.IsLeftDomPoint());
|
||
*l += hs;
|
||
// }
|
||
l->EndBulkLoad();
|
||
line.push_back(*l);
|
||
l->DeleteIfAllowed();
|
||
|
||
|
||
//////////////////////////////////////////////////////
|
||
//trinode
|
||
trinode->tri.neighbor_no++;
|
||
if(trinode->tri.neighbor_no == 3){
|
||
// cout<<"do not insert new"<<endl;
|
||
insert = false;
|
||
delete trinode;
|
||
}
|
||
|
||
//cur
|
||
cur->tri.neighbor_no++;
|
||
if(cur->tri.neighbor_no == 3){//find all neighbors
|
||
// cout<<"delete cur "<<endl;
|
||
TriNode* temp = cur;
|
||
prev->next = cur->next;
|
||
cur = cur->next;
|
||
delete temp;
|
||
}else{
|
||
prev = cur;
|
||
cur = cur->next;
|
||
}
|
||
}else{
|
||
prev = cur;
|
||
cur = cur->next;
|
||
}
|
||
}
|
||
if(insert){
|
||
prev->next = trinode;
|
||
}
|
||
///////////////////////////////////////////////////////////////
|
||
t->DeleteIfAllowed();
|
||
}
|
||
//for debuging, detect whether there are some elements not processed
|
||
if(head->next){
|
||
cout<<"it should not come here. ";
|
||
cout<<"there are some elements not processed in the list"<<endl;
|
||
TriNode* temp = head->next;
|
||
while(temp){
|
||
temp->tri.Print();
|
||
cout<<vertex_point[temp->tri.v1 - 1]<<" "
|
||
<<vertex_point[temp->tri.v2 - 1]<<" "
|
||
<<vertex_point[temp->tri.v3 - 1]<<" "<<endl;
|
||
|
||
temp = temp->next;
|
||
}
|
||
assert(false);
|
||
}
|
||
delete head;
|
||
|
||
}
|
||
|
||
/*
|
||
two triangles sharing the same edge
|
||
|
||
*/
|
||
void RegVertex::ShareEdge(Region* reg1, Region* reg2, int oid1,
|
||
int oid2, vector<vector<int> >& adj_node)
|
||
{
|
||
for(int i = 0;i < reg1->Size();i++){
|
||
HalfSegment hs1;
|
||
reg1->Get(i, hs1);
|
||
for(int j = 0;j < reg2->Size();j++){
|
||
HalfSegment hs2;
|
||
reg2->Get(j, hs2);
|
||
if((AlmostEqual(hs1.GetLeftPoint(), hs2.GetLeftPoint())&&
|
||
AlmostEqual(hs1.GetRightPoint(), hs2.GetRightPoint())) ||
|
||
(AlmostEqual(hs1.GetRightPoint(), hs2.GetLeftPoint()) &&
|
||
AlmostEqual(hs1.GetLeftPoint(), hs2.GetRightPoint()))){
|
||
if(adj_node[oid2 - 1].size() == 0){
|
||
Line* l = new Line(0);
|
||
l->StartBulkLoad();
|
||
hs1.attr.edgeno = 0;
|
||
*l += hs1;
|
||
hs1.SetLeftDomPoint(!hs1.IsLeftDomPoint());
|
||
*l += hs1;
|
||
l->EndBulkLoad();
|
||
line.push_back(*l);
|
||
l->DeleteIfAllowed();
|
||
v1_list.push_back(oid1);
|
||
v2_list.push_back(oid2);
|
||
adj_node[oid1 - 1].push_back(oid2);
|
||
}else{
|
||
unsigned int index = 0;
|
||
for(;index < adj_node[oid2 - 1].size();index++){
|
||
if(adj_node[oid2 - 1][index] == oid1)break;
|
||
}
|
||
if(index == adj_node[oid2 - 1].size()){
|
||
Line* l = new Line(0);
|
||
l->StartBulkLoad();
|
||
hs1.attr.edgeno = 0;
|
||
*l += hs1;
|
||
hs1.SetLeftDomPoint(!hs1.IsLeftDomPoint());
|
||
*l += hs1;
|
||
l->EndBulkLoad();
|
||
line.push_back(*l);
|
||
l->DeleteIfAllowed();
|
||
v1_list.push_back(oid1);
|
||
v2_list.push_back(oid2);
|
||
adj_node[oid1 - 1].push_back(oid2);
|
||
}
|
||
}
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
/*
|
||
Using depth first method to travese the R-tree to find all neighbors for the
|
||
triangle (oid,reg)
|
||
|
||
*/
|
||
void RegVertex::DFTraverse(R_Tree<2,TupleId>* rtree,
|
||
SmiRecordId adr,int oid, Region* reg,
|
||
vector<vector<int> >& adj_node)
|
||
{
|
||
R_TreeNode<2,TupleId>* node = rtree->GetMyNode(adr,false,
|
||
rtree->MinEntries(0), rtree->MaxEntries(0));
|
||
for(int j = 0;j < node->EntryCount();j++){
|
||
if(node->IsLeaf()){
|
||
R_TreeLeafEntry<2,TupleId> e =
|
||
(R_TreeLeafEntry<2,TupleId>&)(*node)[j];
|
||
Tuple* dg_tuple2 = rel1->GetTuple(e.info,false);
|
||
Region* candi_reg =
|
||
(Region*)dg_tuple2->GetAttribute(DualGraph::PAVEMENT);
|
||
// cout<<"e.info "<<e.info<<endl;
|
||
// cout<<"Area "<<candi_reg->Area()<<endl;
|
||
int cand_oid =
|
||
((CcInt*)dg_tuple2->GetAttribute(DualGraph::OID))->GetIntval();
|
||
// if(oid != (int)e.info){
|
||
if(oid != cand_oid){
|
||
// ShareEdge(reg, candi_reg, oid, e.info, adj_node);
|
||
ShareEdge(reg, candi_reg, oid, cand_oid, adj_node);
|
||
}
|
||
dg_tuple2->DeleteIfAllowed();
|
||
}else{
|
||
R_TreeInternalEntry<2> e =
|
||
(R_TreeInternalEntry<2>&)(*node)[j];
|
||
// if(reg->Intersects(e.box)){
|
||
if(reg->Intersects(Region(e.box))){
|
||
DFTraverse(rtree, e.pointer, oid, reg, adj_node);
|
||
}
|
||
}
|
||
}
|
||
delete node;
|
||
}
|
||
|
||
/*
|
||
for each triangle, it searches all its neighbors by traversing the RTree
|
||
it creates the edge relation for dual graph.
|
||
depth-first is a little faster than breadth-first
|
||
in create berlin and houston data, we have an unique oid for each IFOB.
|
||
so the value of oid may not start from 1. not the same as tuple id
|
||
!!!Be Careful!!!
|
||
|
||
*/
|
||
void RegVertex::GetDGEdgeRTree(R_Tree<2,TupleId>* rtree)
|
||
{
|
||
SmiRecordId adr = rtree->RootRecordId();
|
||
|
||
int max_no = 0;
|
||
for(int i = 1;i <= rel1->GetNoTuples();i++){
|
||
Tuple* dg_tuple = rel1->GetTuple(i, false);
|
||
int oid = ((CcInt*)dg_tuple->GetAttribute(DualGraph::OID))->GetIntval();
|
||
if(oid > max_no) max_no = oid;
|
||
dg_tuple->DeleteIfAllowed();
|
||
}
|
||
|
||
// vector<vector<int> > adj_node(rel1->GetNoTuples());
|
||
vector<vector<int> > adj_node(max_no);//oid may not start from 1, e.g., 3000
|
||
|
||
for(int i = 1;i <= rel1->GetNoTuples();i++){
|
||
// for(int i = 1;i <= 500;i++){
|
||
Tuple* dg_tuple1 = rel1->GetTuple(i, false);
|
||
int oid = ((CcInt*)dg_tuple1->GetAttribute(DualGraph::OID))->GetIntval();
|
||
Region* reg =
|
||
(Region*)dg_tuple1->GetAttribute(DualGraph::PAVEMENT);
|
||
///////////////////traverse RTree//////////////////////////////////
|
||
/* queue<SmiRecordId> record_list;
|
||
record_list.push(adr);
|
||
while(record_list.empty() == false){ // width first method
|
||
SmiRecordId node_recid = record_list.front();
|
||
record_list.pop();
|
||
R_TreeNode<2,TupleId>* node = rtree->GetMyNode(node_recid,false,
|
||
rtree->MinEntries(0), rtree->MaxEntries(0));
|
||
for(int j = 0;j < node->EntryCount();j++){
|
||
if(node->IsLeaf()){
|
||
R_TreeLeafEntry<2,TupleId> e =
|
||
(R_TreeLeafEntry<2,TupleId>&)(*node)[j];
|
||
Tuple* dg_tuple2 = rel1->GetTuple(e.info,false);
|
||
Region* candi_reg =
|
||
(Region*)dg_tuple2->GetAttribute(DualGraph::PAVEMENT);
|
||
if(oid != e.info){
|
||
// cout<<"find neighbor "<<oid<<" "<<e.info<<endl;
|
||
ShareEdge(reg, candi_reg,oid,e.info, adj_node);
|
||
}
|
||
dg_tuple2->DeleteIfAllowed();
|
||
}else{
|
||
R_TreeInternalEntry<2> e =
|
||
(R_TreeInternalEntry<2>&)(*node)[j];
|
||
if(reg->Intersects(e.box))
|
||
record_list.push(e.pointer);
|
||
}
|
||
}
|
||
delete node;
|
||
}*/
|
||
/////////////////depth first method////////////////////////////////////
|
||
DFTraverse(rtree, adr, oid, reg, adj_node);
|
||
//////////////////////////////////////////////////////////////////////
|
||
dg_tuple1->DeleteIfAllowed();
|
||
}
|
||
}
|
||
|
||
string VisualGraph::NodeTypeInfo =
|
||
"(rel(tuple((Oid int)(Loc point))))";
|
||
string VisualGraph::EdgeTypeInfo =
|
||
"(rel(tuple((Oid1 int)(Oid2 int)(Connection line))))";
|
||
string VisualGraph::QueryTypeInfo =
|
||
"(rel(tuple((Oid int)(Loc1 point)(Loc2 point))))";
|
||
|
||
VisualGraph::~VisualGraph()
|
||
{
|
||
// cout<<"~VisualGraph()"<<endl;
|
||
}
|
||
|
||
VisualGraph::VisualGraph()
|
||
{
|
||
// cout<<"VisualGraph::VisualGraph()"<<endl;
|
||
}
|
||
|
||
VisualGraph::VisualGraph(ListExpr in_xValue,int in_iErrorPos,
|
||
ListExpr& inout_xErrorInfo,
|
||
bool& inout_bCorrect)
|
||
{
|
||
// cout<<"VisualGraph::VisualGraph(ListExpr)"<<endl;
|
||
}
|
||
|
||
VisualGraph::VisualGraph(SmiRecord& in_xValueRecord,size_t& inout_iOffset,
|
||
const ListExpr in_xTypeInfo)
|
||
{
|
||
// cout<<"VisualGraph::VisualGraph(SmiRecord)"<<endl;
|
||
/***********************Read graph id********************************/
|
||
in_xValueRecord.Read(&g_id,sizeof(int),inout_iOffset);
|
||
inout_iOffset += sizeof(int);
|
||
|
||
|
||
ListExpr xType;
|
||
ListExpr xNumericType;
|
||
/***********************Open relation for node*********************/
|
||
nl->ReadFromString(NodeTypeInfo,xType);
|
||
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
||
node_rel = Relation::Open(in_xValueRecord, inout_iOffset, xNumericType);
|
||
if(!node_rel) {
|
||
return;
|
||
}
|
||
/***********************Open relation for edge*********************/
|
||
nl->ReadFromString(EdgeTypeInfo,xType);
|
||
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
||
edge_rel = Relation::Open(in_xValueRecord, inout_iOffset, xNumericType);
|
||
if(!edge_rel) {
|
||
node_rel->Delete();
|
||
return;
|
||
}
|
||
|
||
////////////////////adjaency list////////////////////////////////
|
||
size_t bufsize = DbArray<int>::headerSize();
|
||
SmiSize offset = 0;
|
||
char* buf = (char*) malloc(bufsize);
|
||
in_xValueRecord.Read(buf, bufsize, inout_iOffset);
|
||
inout_iOffset += bufsize;
|
||
assert(buf != NULL);
|
||
adj_list.restoreHeader(buf,offset);
|
||
free(buf);
|
||
offset = 0;
|
||
buf = (char*) malloc(bufsize);
|
||
in_xValueRecord.Read(buf, bufsize, inout_iOffset);
|
||
assert(buf != NULL);
|
||
entry_adj_list.restoreHeader(buf,offset);
|
||
inout_iOffset += bufsize;
|
||
free(buf);
|
||
|
||
}
|
||
|
||
void VisualGraph::Load(int id, Relation* r1, Relation* r2)
|
||
{
|
||
// cout<<"VisualGraph::Load()"<<endl;
|
||
g_id = id;
|
||
//////////////////node relation////////////////////
|
||
ListExpr ptrList1 = listutils::getPtrList(r1);
|
||
|
||
string strQuery = "(consume(sort(feed(" + NodeTypeInfo +
|
||
"(ptr " + nl->ToString(ptrList1) + ")))))";
|
||
Word xResult;
|
||
int QueryExecuted = QueryProcessor::ExecuteQuery(strQuery, xResult);
|
||
assert(QueryExecuted);
|
||
node_rel = (Relation*)xResult.addr;
|
||
|
||
/////////////////edge relation/////////////////////
|
||
ListExpr ptrList2 = listutils::getPtrList(r2);
|
||
|
||
strQuery = "(consume(sort(feed(" + EdgeTypeInfo +
|
||
"(ptr " + nl->ToString(ptrList2) + ")))))";
|
||
QueryExecuted = QueryProcessor::ExecuteQuery(strQuery, xResult);
|
||
assert(QueryExecuted);
|
||
edge_rel = (Relation*)xResult.addr;
|
||
|
||
////////////adjacency list ////////////////////////////////
|
||
ListExpr ptrList3 = listutils::getPtrList(edge_rel);
|
||
|
||
strQuery = "(createbtree (" + EdgeTypeInfo +
|
||
"(ptr " + nl->ToString(ptrList3) + "))" + "Oid1)";
|
||
QueryExecuted = QueryProcessor::ExecuteQuery(strQuery,xResult);
|
||
assert(QueryExecuted);
|
||
BTree* btree_node_oid1 = (BTree*)xResult.addr;
|
||
|
||
|
||
// cout<<"b-tree on edge is finished....."<<endl;
|
||
|
||
for(int i = 1;i <= node_rel->GetNoTuples();i++){
|
||
CcInt* nodeid = new CcInt(true, i);
|
||
BTreeIterator* btree_iter1 = btree_node_oid1->ExactMatch(nodeid);
|
||
int start = adj_list.Size();
|
||
// cout<<"start "<<start<<endl;
|
||
while(btree_iter1->Next()){
|
||
Tuple* edge_tuple = edge_rel->GetTuple(btree_iter1->GetId(), false);
|
||
int oid = ((CcInt*)edge_tuple->GetAttribute(OIDSECOND))->GetIntval();
|
||
adj_list.Append(oid);
|
||
edge_tuple->DeleteIfAllowed();
|
||
}
|
||
delete btree_iter1;
|
||
|
||
int end = adj_list.Size();
|
||
entry_adj_list.Append(ListEntry(start, end));
|
||
// cout<<"end "<<end<<endl;
|
||
delete nodeid;
|
||
}
|
||
|
||
delete btree_node_oid1;
|
||
|
||
}
|
||
|
||
ListExpr VisualGraph::OutVisualGraph(ListExpr typeInfo, Word value)
|
||
{
|
||
// cout<<"OutVisualGraph()"<<endl;
|
||
VisualGraph* vg = (VisualGraph*)value.addr;
|
||
return vg->Out(typeInfo);
|
||
}
|
||
|
||
ListExpr VisualGraph::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 <= edge_rel->GetNoTuples();i++){
|
||
Tuple* edge_tuple = edge_rel->GetTuple(i, false);
|
||
CcInt* oid1 = (CcInt*)edge_tuple->GetAttribute(OIDFIRST);
|
||
CcInt* oid2 = (CcInt*)edge_tuple->GetAttribute(OIDSECOND);
|
||
Line* connection = (Line*)edge_tuple->GetAttribute(CONNECTION);
|
||
|
||
ListExpr xline = OutLine(nl->TheEmptyList(),SetWord(connection));
|
||
xNext = nl->FourElemList(nl->IntAtom(g_id),
|
||
nl->IntAtom(oid1->GetIntval()),
|
||
nl->IntAtom(oid2->GetIntval()),
|
||
xline);
|
||
if(bFirst){
|
||
xNode = nl->OneElemList(xNext);
|
||
xLast = xNode;
|
||
bFirst = false;
|
||
}else
|
||
xLast = nl->Append(xLast,xNext);
|
||
edge_tuple->DeleteIfAllowed();
|
||
}
|
||
return nl->TwoElemList(nl->IntAtom(g_id),xNode);
|
||
}
|
||
|
||
bool VisualGraph::CheckVisualGraph(ListExpr type, ListExpr& errorInfo)
|
||
{
|
||
// cout<<"CheckVisualGraph()"<<endl;
|
||
return nl->IsEqual(type, "visualgraph");
|
||
}
|
||
|
||
void VisualGraph::CloseVisualGraph(const ListExpr typeInfo, Word& w)
|
||
{
|
||
// cout<<"CloseVisualGraph()"<<endl;
|
||
delete static_cast<VisualGraph*> (w.addr);
|
||
w.addr = NULL;
|
||
}
|
||
|
||
void VisualGraph::DeleteVisualGraph(const ListExpr typeInfo, Word& w)
|
||
{
|
||
// cout<<"DeleteVisualGraph()"<<endl;
|
||
VisualGraph* vg = (VisualGraph*)w.addr;
|
||
delete vg;
|
||
w.addr = NULL;
|
||
}
|
||
|
||
Word VisualGraph::CreateVisualGraph(const ListExpr typeInfo)
|
||
{
|
||
// cout<<"CreateVisualGraph()"<<endl;
|
||
return SetWord(new VisualGraph());
|
||
}
|
||
|
||
Word VisualGraph::InVisualGraph(ListExpr in_xTypeInfo,
|
||
ListExpr in_xValue,
|
||
int in_iErrorPos, ListExpr& inout_xErrorInfo,
|
||
bool& inout_bCorrect)
|
||
{
|
||
// cout<<"InVisualGraph()"<<endl;
|
||
VisualGraph* vg = new VisualGraph(in_xValue, in_iErrorPos, inout_xErrorInfo,
|
||
inout_bCorrect);
|
||
if(inout_bCorrect) return SetWord(vg);
|
||
else{
|
||
delete vg;
|
||
return SetWord(Address(0));
|
||
}
|
||
}
|
||
|
||
|
||
bool VisualGraph::OpenVisualGraph(SmiRecord& valueRecord, size_t& offset,
|
||
const ListExpr typeInfo, Word& value)
|
||
{
|
||
// cout<<"OpenVisualGraph()"<<endl;
|
||
value.addr = VisualGraph::Open(valueRecord, offset, typeInfo);
|
||
bool result = (value.addr != NULL);
|
||
|
||
return result;
|
||
}
|
||
|
||
VisualGraph* VisualGraph::Open(SmiRecord& valueRecord,size_t& offset,
|
||
const ListExpr typeInfo)
|
||
{
|
||
|
||
return new VisualGraph(valueRecord,offset,typeInfo);
|
||
}
|
||
|
||
bool VisualGraph::SaveVisualGraph(SmiRecord& valueRecord, size_t& offset,
|
||
const ListExpr typeInfo, Word& value)
|
||
{
|
||
// cout<<"SaveVisualGraph()"<<endl;
|
||
VisualGraph* vg = (VisualGraph*)value.addr;
|
||
bool result = vg->Save(valueRecord, offset, typeInfo);
|
||
|
||
return result;
|
||
}
|
||
|
||
bool VisualGraph::Save(SmiRecord& in_xValueRecord,size_t& inout_iOffset,
|
||
const ListExpr in_xTypeInfo)
|
||
{
|
||
|
||
// cout<<"Save()"<<endl;
|
||
/********************Save graph id ****************************/
|
||
in_xValueRecord.Write(&g_id,sizeof(int),inout_iOffset);
|
||
inout_iOffset += sizeof(int);
|
||
|
||
|
||
ListExpr xType;
|
||
ListExpr xNumericType;
|
||
/************************save node****************************/
|
||
nl->ReadFromString(NodeTypeInfo,xType);
|
||
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
||
if(!node_rel->Save(in_xValueRecord,inout_iOffset,xNumericType))
|
||
return false;
|
||
|
||
/************************save edge****************************/
|
||
nl->ReadFromString(EdgeTypeInfo,xType);
|
||
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
||
if(!edge_rel->Save(in_xValueRecord,inout_iOffset,xNumericType))
|
||
return false;
|
||
|
||
|
||
SecondoCatalog *ctlg = SecondoSystem::GetCatalog();
|
||
SmiRecordFile *rf = ctlg->GetFlobFile();
|
||
adj_list.saveToFile(rf, adj_list);
|
||
SmiSize offset = 0;
|
||
size_t bufsize = adj_list.headerSize();
|
||
char* buf = (char*) malloc(bufsize);
|
||
adj_list.serializeHeader(buf,offset);
|
||
assert(offset==bufsize);
|
||
in_xValueRecord.Write(buf, bufsize, inout_iOffset);
|
||
inout_iOffset += bufsize;
|
||
free(buf);
|
||
|
||
entry_adj_list.saveToFile(rf, entry_adj_list);
|
||
offset = 0;
|
||
buf = (char*) malloc(bufsize);
|
||
entry_adj_list.serializeHeader(buf,offset);
|
||
assert(offset==bufsize);
|
||
in_xValueRecord.Write(buf,bufsize, inout_iOffset);
|
||
free(buf);
|
||
inout_iOffset += bufsize;
|
||
|
||
return true;
|
||
|
||
}
|
||
|
||
/*
|
||
checks whether the region halfsegment self intersects
|
||
|
||
*/
|
||
bool Hole::NoSelfIntersects(Region* r)
|
||
{
|
||
for(int i = 0;i < r->Size();i++){
|
||
HalfSegment hs1;
|
||
r->Get(i, hs1);
|
||
if(!hs1.IsLeftDomPoint())continue;
|
||
for(int j = 0;j < r->Size();j++){
|
||
HalfSegment hs2;
|
||
r->Get(j, hs2);
|
||
if(!hs2.IsLeftDomPoint() || i == j)continue;
|
||
Point ip;
|
||
if(hs1.Intersection(hs2, ip)){
|
||
if(!AlmostEqual(ip, hs1.GetLeftPoint()) &&
|
||
!AlmostEqual(ip, hs1.GetRightPoint()) &&
|
||
!AlmostEqual(ip, hs2.GetLeftPoint()) &&
|
||
!AlmostEqual(ip, hs2.GetRightPoint()))
|
||
return false;
|
||
}
|
||
}
|
||
}
|
||
return true;
|
||
}
|
||
/*
|
||
collect the holes of a region
|
||
|
||
*/
|
||
void Hole::GetHole(Region* r)
|
||
{
|
||
CompTriangle* ct = new CompTriangle(r);
|
||
unsigned int no_cyc = ct->NoOfCycles();//ignore the first cycle
|
||
delete ct;
|
||
|
||
// cout<<"holes "<<no_cyc<<endl;
|
||
|
||
vector<int> edgeno;
|
||
vector<int> partnerno;
|
||
for(unsigned int i = 0;i < no_cyc;i++){
|
||
Region* new_reg = new Region(0);
|
||
new_reg->StartBulkLoad();
|
||
new_reg->EndBulkLoad();
|
||
regs.push_back(*new_reg);
|
||
new_reg->DeleteIfAllowed();
|
||
edgeno.push_back(0);
|
||
partnerno.push_back(0);
|
||
}
|
||
// cout<<"here "<<r->Size()<<endl;
|
||
for(unsigned int i = 0;i < no_cyc;i++){
|
||
regs[i].StartBulkLoad();
|
||
}
|
||
|
||
for(int i = 0;i < r->Size();i++){
|
||
// cout<<"i1 "<<i<<endl;
|
||
HalfSegment hs;
|
||
r->Get(i, hs);
|
||
if(!hs.IsLeftDomPoint()) continue;
|
||
HalfSegment temp_hs;
|
||
temp_hs.Set(true, hs.GetLeftPoint(), hs.GetRightPoint());
|
||
temp_hs.SetLeftDomPoint(hs.IsLeftDomPoint());
|
||
temp_hs.attr.faceno = 0;
|
||
int cycle_no = hs.attr.cycleno;
|
||
// cout<<"cycle_no "<<cycle_no<<endl;
|
||
temp_hs.attr.cycleno = 0;
|
||
temp_hs.attr.edgeno = edgeno[cycle_no]++;
|
||
temp_hs.attr.partnerno = partnerno[cycle_no]++;
|
||
temp_hs.attr.insideAbove = !temp_hs.attr.insideAbove;
|
||
regs[cycle_no] += hs;
|
||
hs.SetLeftDomPoint(!hs.IsLeftDomPoint());
|
||
regs[cycle_no] += hs;
|
||
// cout<<hs<<endl;
|
||
}
|
||
for(unsigned int i = 0;i < no_cyc;i++){
|
||
// cout<<"i "<<i<<endl;
|
||
regs[i].SetNoComponents(1);
|
||
regs[i].EndBulkLoad(true, false, false, false);
|
||
}
|
||
|
||
}
|
||
|
||
/*
|
||
from the input data file, it creates a lot of contours
|
||
collect regions from original data, where each tuple is a halfsegment
|
||
|
||
*/
|
||
struct MHSNode{
|
||
MyHalfSegment mhs;
|
||
MHSNode* next;
|
||
MHSNode(MyHalfSegment hs, MHSNode* pointer):mhs(hs),next(pointer){}
|
||
};
|
||
|
||
bool RegionCom(const Region& r1, const Region& r2)
|
||
{
|
||
return r1.Area() > r2.Area();
|
||
}
|
||
|
||
/*
|
||
query getcontour('Transportationmode/Polygon-Data/GermanyPPPoly') count;
|
||
read polygon data from a file
|
||
|
||
*/
|
||
void Hole::GetContour()
|
||
{
|
||
Coord x1, y1, x2, y2;
|
||
int index = 0;
|
||
MHSNode* head = new MHSNode(MyHalfSegment(),NULL);
|
||
|
||
Points* ps = new Points(0);
|
||
ps->StartBulkLoad();
|
||
|
||
while( !in.eof()){
|
||
in>>index;
|
||
if(!in.good())
|
||
break;
|
||
in>>x1;
|
||
if(!in.good())
|
||
break;
|
||
in>>y1;
|
||
if(!in.good())
|
||
break;
|
||
in>>x2;
|
||
if(!in.good())
|
||
break;
|
||
in>>y2;
|
||
if(!in.good())
|
||
break;
|
||
// printf("%.12f %.12f %.12f %.12f\n",x1,y1,x2,y2);
|
||
Point p1(true,x1,y1);
|
||
Point p2(true,x2,y2);
|
||
MyHalfSegment hs(true,p1,p2);
|
||
if(AlmostEqual(p1,p2)) continue;
|
||
// if(index > 10000)break;
|
||
|
||
MHSNode* node = new MHSNode(hs,NULL);
|
||
node->next = head->next;
|
||
head->next = node;
|
||
|
||
*ps += p1;
|
||
*ps += p2;
|
||
}
|
||
ps->EndBulkLoad();
|
||
|
||
BBox<2> bbox;
|
||
double min[2];
|
||
double max[2];
|
||
const double delta = 5.0;
|
||
|
||
min[0] = ps->BoundingBox().MinD(0) - delta;
|
||
min[1] = ps->BoundingBox().MinD(1) - delta;
|
||
max[0] = ps->BoundingBox().MaxD(0) + delta;
|
||
max[1] = ps->BoundingBox().MaxD(1) + delta;
|
||
bbox.Set(true, min, max);
|
||
|
||
Region* outer_contour = new Region(bbox);
|
||
// GrahamScan::convexHull(ps,outer_contour);
|
||
regs.push_back(*outer_contour);//the first is the outer contour
|
||
outer_contour->DeleteIfAllowed();
|
||
|
||
|
||
////////////////////////////////////////////////
|
||
while(head->next != NULL){
|
||
list<MyHalfSegment> contours;
|
||
MHSNode* prev = head;
|
||
MHSNode* cur = head->next;
|
||
contours.push_back(cur->mhs);
|
||
|
||
prev->next = cur->next;
|
||
MHSNode* temp = cur;
|
||
delete temp;
|
||
MyHalfSegment front = contours.front();
|
||
MyHalfSegment back = contours.back();
|
||
|
||
while(1){
|
||
cur = head->next;
|
||
prev = head;
|
||
while(cur != NULL){
|
||
if(AlmostEqual(front.from, cur->mhs.to)){
|
||
contours.push_front(cur->mhs);
|
||
prev->next = cur->next;
|
||
delete cur;
|
||
break;
|
||
}
|
||
if(AlmostEqual(front.from, cur->mhs.from)){
|
||
cur->mhs.Exchange();
|
||
contours.push_front(cur->mhs);
|
||
prev->next = cur->next;
|
||
delete cur;
|
||
break;
|
||
}
|
||
if(AlmostEqual(back.to, cur->mhs.from)){
|
||
contours.push_back(cur->mhs);
|
||
prev->next = cur->next;
|
||
delete cur;
|
||
break;
|
||
}
|
||
if(AlmostEqual(back.to, cur->mhs.to)){
|
||
cur->mhs.Exchange();
|
||
contours.push_back(cur->mhs);
|
||
prev->next = cur->next;
|
||
delete cur;
|
||
break;
|
||
}
|
||
prev = cur;
|
||
cur = cur->next;
|
||
}
|
||
front = contours.front();
|
||
back = contours.back();
|
||
// cout<<"front ";front.Print();
|
||
// cout<<"back "; back.Print();
|
||
if(AlmostEqual(front.from, back.to) && contours.size() > 2){
|
||
// cout<<"cycle found "<<contours.size()<<endl;
|
||
vector<Point> ps;
|
||
while(contours.empty() == false){
|
||
MyHalfSegment top = contours.front();
|
||
contours.pop_front();
|
||
ps.push_back(top.from);
|
||
}
|
||
SpacePartition* sp = new SpacePartition();
|
||
CompTriangle* ct = new CompTriangle();
|
||
vector<Region> regions;
|
||
if(ct->Area(ps) > 0){
|
||
sp->ComputeRegion(ps,regions);
|
||
regs1.push_back(regions[0]);
|
||
regs2.push_back(regions[0]);
|
||
}else{
|
||
vector<Point> temp_ps;
|
||
for(int i = ps.size() - 1;i >= 0;i--)
|
||
temp_ps.push_back(ps[i]);
|
||
sp->ComputeRegion(temp_ps,regions);
|
||
regs1.push_back(regions[0]);
|
||
regs2.push_back(regions[0]);
|
||
}
|
||
delete ct;
|
||
delete sp;
|
||
contours.clear();
|
||
break;
|
||
}
|
||
if(cur == NULL){
|
||
contours.clear();
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
sort(regs1.begin(),regs1.end(), RegionCom);
|
||
sort(regs2.begin(),regs2.end(), RegionCom);
|
||
|
||
for(unsigned int i = 0;i < regs1.size();i++){
|
||
unsigned int j = 0;
|
||
// cout<<regs1[i].Area()<<endl;
|
||
for(;j < regs2.size();j++){
|
||
if(i == j) continue;
|
||
/* if(regs1[i].Inside(regs2[j]) ||
|
||
regs1[i].Intersects(regs2[j]) ||
|
||
regs2[j].Inside(regs1[i])) break;*/
|
||
if(regs1[i].Intersects(regs2[j])) break;
|
||
|
||
}
|
||
//no self-intersection segments are allowed
|
||
if(j == regs2.size() &&
|
||
NoSelfIntersects(®s1[i]))regs.push_back(regs1[i]);
|
||
}
|
||
delete head;
|
||
ps->DeleteIfAllowed();
|
||
}
|
||
|
||
/*
|
||
create no_reg regions(cycles)
|
||
|
||
*/
|
||
void Hole::GetContour(unsigned int no_reg)
|
||
{
|
||
vector<Point> contour;
|
||
vector<Region> regions;
|
||
SpacePartition* sp = new SpacePartition();
|
||
//////////////////the outer contour/////////////////////////////////
|
||
contour.push_back(Point(true,0.0,0.0));
|
||
contour.push_back(Point(true,100000.0,0.0));
|
||
contour.push_back(Point(true,100000.0,100000.0));
|
||
contour.push_back(Point(true,0.0,100000.0));
|
||
sp->ComputeRegion(contour,regions);
|
||
regs.push_back(regions[0]);
|
||
////////////////////////////////////////////////////////
|
||
// struct timeval tval;
|
||
// struct timezone tzone;
|
||
// gettimeofday(&tval, &tzone);
|
||
// srand48(tval.tv_sec);
|
||
|
||
unsigned int reg_count = no_reg;
|
||
|
||
while(no_reg > 1){
|
||
|
||
// int px = lrand48() % 98700 + 600;
|
||
// int py = lrand48() % 98700 + 600;
|
||
int px = GetRandom() % 98700 + 600;
|
||
int py = GetRandom() % 98700 + 600;
|
||
|
||
// int radius = lrand48() % 496 + 5;//5-500 10-1000
|
||
|
||
int radius = GetRandom() % 496 + 5;//5-500 10-1000
|
||
|
||
contour.clear();
|
||
regions.clear();
|
||
contour.push_back(Point(true, px - radius, py - radius));
|
||
contour.push_back(Point(true, px + radius, py - radius));
|
||
contour.push_back(Point(true, px + radius, py + radius));
|
||
contour.push_back(Point(true, px - radius, py + radius));
|
||
sp->ComputeRegion(contour,regions);
|
||
unsigned int i = 1;
|
||
for(;i < regs.size();i++){
|
||
if(regs[i].Intersects(regions[0]))break;
|
||
}
|
||
if(i == regs.size()){
|
||
///create convex hull
|
||
Points* outer_ps = new Points(0);
|
||
// int outer_ps_no = lrand48() % 191 + 10;///10-200
|
||
|
||
int outer_ps_no = GetRandom() % 191 + 10;///10-200
|
||
|
||
// int outer_ps_no = radius;///10-200
|
||
double xmin = px - radius;
|
||
double ymin = py - radius;
|
||
outer_ps->StartBulkLoad();
|
||
vector<Point> temp_ps;
|
||
while(outer_ps_no > 0){
|
||
// int x = lrand48() %(2*radius*100);
|
||
// int y = lrand48() %(2*radius*100);
|
||
|
||
int x = GetRandom() %(2*radius*100);
|
||
int y = GetRandom() %(2*radius*100);
|
||
|
||
double coord_x = x/100.0 + xmin;
|
||
double coord_y = y/100.0 + ymin;
|
||
Point newp(true,coord_x,coord_y);
|
||
|
||
if(newp.Inside(regions[0])){
|
||
outer_ps_no--;
|
||
*outer_ps += newp;
|
||
temp_ps.push_back(newp);
|
||
}
|
||
}
|
||
outer_ps->EndBulkLoad();
|
||
|
||
if(no_reg % 3 == 0){
|
||
Region* newregion = new Region(0);
|
||
GrahamScan::convexHull(outer_ps,newregion);
|
||
regs.push_back(*newregion);
|
||
newregion->DeleteIfAllowed();
|
||
}
|
||
else if(no_reg % 3 == 1){
|
||
Region* newregion = new Region(0);
|
||
DiscoverContour(outer_ps,newregion);
|
||
regs.push_back(*newregion);
|
||
newregion->DeleteIfAllowed();
|
||
}
|
||
else{
|
||
Region* newregion = new Region(outer_ps->BoundingBox());
|
||
regs.push_back(*newregion);
|
||
newregion->DeleteIfAllowed();
|
||
}
|
||
outer_ps->DeleteIfAllowed();
|
||
/////////////////////////////////////////////////
|
||
// regs.push_back(regions[0]);
|
||
no_reg--;
|
||
}
|
||
}
|
||
delete sp;
|
||
assert(reg_count == regs.size());
|
||
}
|
||
|
||
void Hole::SpacePartitioning(vector<Point> ps, vector<HalfSegment>& hs_segs,
|
||
Point sf, Point sl)
|
||
{
|
||
// cout<<"sf "<<sf<<" sl "<<sl<<endl;
|
||
/* for(unsigned int i = 0;i < ps.size();i++)
|
||
cout<<ps[i]<<endl; */
|
||
|
||
if(ps.size() == 0){
|
||
HalfSegment hs;
|
||
hs.Set(true, sf, sl);
|
||
hs_segs.push_back(hs);
|
||
}else{
|
||
Point mid_p1 = ps[0];
|
||
Point mid_p2(true, (sf.GetX()+sl.GetX())/2,(sf.GetY()+sl.GetY())/2);
|
||
|
||
if(AlmostEqual(mid_p1.GetX(), mid_p2.GetX())){
|
||
//it seldomly happens
|
||
if(AlmostEqual(sf.GetX(), sl.GetX())) assert(false);
|
||
vector<Point> ls;
|
||
vector<Point> rs;
|
||
for(unsigned int i = 0;i < ps.size();i++){
|
||
if(AlmostEqual(ps[i], mid_p1) ||
|
||
AlmostEqual(ps[i], mid_p1)) continue;
|
||
if(ps[i].GetX() < mid_p1.GetX() ||
|
||
AlmostEqual(ps[i].GetX(), mid_p1.GetX()))
|
||
ls.push_back(ps[i]);
|
||
else
|
||
rs.push_back(ps[i]);
|
||
}
|
||
|
||
if(sf.GetX() < mid_p1.GetX()){
|
||
// cout<<"1 "<<"left "<<endl;
|
||
SpacePartitioning(ls, hs_segs, sf, mid_p1);
|
||
// cout<<"1 "<<"right "<<endl;
|
||
SpacePartitioning(rs, hs_segs, mid_p1, sl);
|
||
}else{
|
||
// cout<<"1 "<<"left "<<endl;
|
||
SpacePartitioning(ls, hs_segs, sl, mid_p1);
|
||
// cout<<"1 "<<"right "<<endl;
|
||
SpacePartitioning(rs, hs_segs, mid_p1, sf);
|
||
}
|
||
|
||
}else if(AlmostEqual(mid_p1.GetY(), mid_p2.GetY())){
|
||
//it seldomly happens
|
||
if(AlmostEqual(sf.GetY(), sl.GetY())) assert(false);
|
||
vector<Point> ls;
|
||
vector<Point> rs;
|
||
for(unsigned int i = 0;i < ps.size();i++){
|
||
if(AlmostEqual(ps[i], mid_p1) ||
|
||
AlmostEqual(ps[i], mid_p1)) continue;
|
||
if(ps[i].GetY() < mid_p1.GetY() ||
|
||
AlmostEqual(ps[i].GetY(), mid_p1.GetY()))
|
||
ls.push_back(ps[i]);
|
||
else
|
||
rs.push_back(ps[i]);
|
||
}
|
||
if(sf.GetY() < mid_p1.GetY()){
|
||
// cout<<"2 "<<"left "<<endl;
|
||
SpacePartitioning(ls, hs_segs, sf, mid_p1);
|
||
// cout<<"2 "<<"right "<<endl;
|
||
SpacePartitioning(rs, hs_segs, mid_p1, sl);
|
||
}else{
|
||
// cout<<"2 "<<"left "<<endl;
|
||
SpacePartitioning(ls, hs_segs, sl, mid_p1);
|
||
// cout<<"2 "<<"right "<<endl;
|
||
SpacePartitioning(rs, hs_segs, mid_p1, sf);
|
||
}
|
||
}else{
|
||
vector<Point> ls;
|
||
vector<Point> rs;
|
||
double a = (mid_p1.GetY() - mid_p2.GetY())/
|
||
(mid_p1.GetX() - mid_p2.GetX());
|
||
double b = mid_p1.GetY() - a*mid_p1.GetX();
|
||
for(unsigned int i = 0;i < ps.size();i++){
|
||
if(AlmostEqual(ps[i], mid_p1) ||
|
||
AlmostEqual(ps[i], mid_p1)) continue;
|
||
if(ps[i].GetY() < (a*ps[i].GetX() + b)||
|
||
AlmostEqual(ps[i].GetY(), (a*ps[i].GetX() + b)))
|
||
ls.push_back(ps[i]);
|
||
else
|
||
rs.push_back(ps[i]);
|
||
}
|
||
if(sf.GetY() < a*sf.GetX() + b){
|
||
// cout<<"3 "<<"left "<<endl;
|
||
SpacePartitioning(ls, hs_segs, sf, mid_p1);
|
||
// cout<<"3 "<<"right "<<endl;
|
||
SpacePartitioning(rs, hs_segs, mid_p1, sl);
|
||
}else{
|
||
// cout<<"3 "<<"left "<<endl;
|
||
SpacePartitioning(ls, hs_segs, sl, mid_p1);
|
||
// cout<<"3 "<<"right "<<endl;
|
||
SpacePartitioning(rs, hs_segs, mid_p1, sf);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/*
|
||
create a polygon by SpacePartitioning method
|
||
|
||
*/
|
||
|
||
void Hole::SpacePartitioning(Points* gen_ps, vector<HalfSegment>& hs_segs)
|
||
{
|
||
vector<Point> ps1;
|
||
for(int i = 0;i < gen_ps->Size();i++){
|
||
Point temp_p;
|
||
gen_ps->Get(i, temp_p);
|
||
ps1.push_back(temp_p);
|
||
}
|
||
|
||
Point sf = ps1[0];
|
||
Point sl = ps1[1];
|
||
//cout<<"sf "<<sf<<" sl "<<sl<<endl;
|
||
/* for(unsigned int i = 0;i < ps1.size();i++)
|
||
cout<<"ps1 "<<ps1[i]<<endl; */
|
||
|
||
if(AlmostEqual(sf.GetX(), sl.GetX())){
|
||
vector<Point> ls;
|
||
vector<Point> rs;
|
||
for(unsigned int i = 0;i < ps1.size();i++){
|
||
if(AlmostEqual(ps1[i], sf) || AlmostEqual(ps1[i],sl)) continue;
|
||
if(ps1[i].GetX() < sf.GetX() || AlmostEqual(ps1[i].GetX(), sf.GetX()))
|
||
ls.push_back(ps1[i]);
|
||
else
|
||
rs.push_back(ps1[i]);
|
||
}
|
||
// cout<<"1 "<<"left "<<endl;
|
||
SpacePartitioning(ls, hs_segs, sf, sl);
|
||
// cout<<"1 "<<"right "<<endl;
|
||
SpacePartitioning(rs, hs_segs, sf, sl);
|
||
}else if(AlmostEqual(sf.GetY(), sl.GetY())){
|
||
vector<Point> ls;
|
||
vector<Point> rs;
|
||
for(unsigned int i = 0;i < ps1.size();i++){
|
||
if(AlmostEqual(ps1[i], sf) || AlmostEqual(ps1[i],sl)) continue;
|
||
if(ps1[i].GetY() < sf.GetY() || AlmostEqual(ps1[i].GetY(), sf.GetY()))
|
||
ls.push_back(ps1[i]);
|
||
else
|
||
rs.push_back(ps1[i]);
|
||
}
|
||
// cout<<"2 "<<"left "<<endl;
|
||
SpacePartitioning(ls, hs_segs, sf, sl);
|
||
// cout<<"2 "<<"right "<<endl;
|
||
SpacePartitioning(rs, hs_segs, sf, sl);
|
||
}else{
|
||
vector<Point> ls;
|
||
vector<Point> rs;
|
||
double a = (sf.GetY() - sl.GetY())/(sf.GetX() - sl.GetX());
|
||
double b = sf.GetY() - a*sf.GetX();
|
||
for(unsigned int i = 0;i < ps1.size();i++){
|
||
if(AlmostEqual(ps1[i], sf) || AlmostEqual(ps1[i],sl)) continue;
|
||
if(ps1[i].GetY() < (a*ps1[i].GetX() + b)||
|
||
AlmostEqual(ps1[i].GetY(), (a*ps1[i].GetX() + b)))
|
||
ls.push_back(ps1[i]);
|
||
else
|
||
rs.push_back(ps1[i]);
|
||
}
|
||
// cout<<"3 "<<"left "<<endl;
|
||
SpacePartitioning(ls, hs_segs, sf, sl);
|
||
// cout<<"3 "<<"right "<<endl;
|
||
SpacePartitioning(rs, hs_segs, sf, sl);
|
||
}
|
||
|
||
}
|
||
void Hole::GetPolygon(int no_ps)
|
||
{
|
||
struct timeval tval;
|
||
struct timezone tzone;
|
||
|
||
gettimeofday(&tval, &tzone);
|
||
srand48(tval.tv_sec);
|
||
vector<Point> ps1;
|
||
if(no_ps < 3){
|
||
cout<<"at least three points"<<endl;
|
||
return;
|
||
}
|
||
Points* gen_ps = new Points(0);
|
||
gen_ps->StartBulkLoad();
|
||
while(no_ps > 0){
|
||
// int x = lrand48() %100000;
|
||
// int y = lrand48() %100000;
|
||
int x = GetRandom() % 100000;
|
||
int y = GetRandom() % 100000;
|
||
|
||
double coord_x = x/100.0;
|
||
double coord_y = y/100.0;
|
||
Point p(true,coord_x, coord_y);
|
||
*gen_ps += p;
|
||
no_ps--;
|
||
}
|
||
gen_ps->EndBulkLoad();
|
||
Region* reg = new Region(0);
|
||
DiscoverContour(gen_ps, reg);//store the polygon in regs
|
||
regs.push_back(*reg);
|
||
reg->DeleteIfAllowed();
|
||
gen_ps->DeleteIfAllowed();
|
||
}
|
||
|
||
/*
|
||
using the space partitining method to create randomly polygon by a given set
|
||
of vertices
|
||
|
||
*/
|
||
void Hole::DiscoverContour(Points* gen_ps, Region* r)
|
||
{
|
||
vector<HalfSegment> hs_segs;
|
||
SpacePartitioning(gen_ps, hs_segs);
|
||
MHSNode* head = new MHSNode(MyHalfSegment(),NULL);
|
||
for(unsigned int i = 0;i < hs_segs.size();i++){
|
||
MHSNode* node = new MHSNode(
|
||
MyHalfSegment(true,hs_segs[i].GetLeftPoint(),
|
||
hs_segs[i].GetRightPoint()),NULL);
|
||
node->next = head->next;
|
||
head->next = node;
|
||
}
|
||
DiscoverContour(head, r);
|
||
delete head;
|
||
}
|
||
/*
|
||
given a set of segments, it discovers whether a cycle exists. if yes, a region
|
||
is returned
|
||
|
||
*/
|
||
void Hole::DiscoverContour(MHSNode* head, Region* r)
|
||
{
|
||
list<MyHalfSegment> contours;
|
||
MHSNode* prev = head;
|
||
MHSNode* cur = head->next;
|
||
contours.push_back(cur->mhs);
|
||
|
||
prev->next = cur->next;
|
||
MHSNode* temp = cur;
|
||
delete temp;
|
||
MyHalfSegment front = contours.front();
|
||
MyHalfSegment back = contours.back();
|
||
|
||
while(1){
|
||
cur = head->next;
|
||
prev = head;
|
||
while(cur != NULL){
|
||
if(AlmostEqual(front.from, cur->mhs.to)){
|
||
contours.push_front(cur->mhs);
|
||
prev->next = cur->next;
|
||
delete cur;
|
||
break;
|
||
}
|
||
if(AlmostEqual(front.from, cur->mhs.from)){
|
||
cur->mhs.Exchange();
|
||
contours.push_front(cur->mhs);
|
||
prev->next = cur->next;
|
||
delete cur;
|
||
break;
|
||
}
|
||
if(AlmostEqual(back.to, cur->mhs.from)){
|
||
contours.push_back(cur->mhs);
|
||
prev->next = cur->next;
|
||
delete cur;
|
||
break;
|
||
}
|
||
if(AlmostEqual(back.to, cur->mhs.to)){
|
||
cur->mhs.Exchange();
|
||
contours.push_back(cur->mhs);
|
||
prev->next = cur->next;
|
||
delete cur;
|
||
break;
|
||
}
|
||
prev = cur;
|
||
cur = cur->next;
|
||
}
|
||
front = contours.front();
|
||
back = contours.back();
|
||
if(AlmostEqual(front.from, back.to) && contours.size() > 2){
|
||
vector<Point> ps;
|
||
while(contours.empty() == false){
|
||
MyHalfSegment top = contours.front();
|
||
contours.pop_front();
|
||
ps.push_back(top.from);
|
||
}
|
||
SpacePartition* sp = new SpacePartition();
|
||
vector<Region> regions;
|
||
sp->ComputeRegion(ps,regions);
|
||
*r = regions[0];
|
||
delete sp;
|
||
contours.clear();
|
||
break;
|
||
}
|
||
if(cur == NULL){
|
||
contours.clear();
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
///////////////////////////////////////////////////////////////////////
|
||
////////////////// get the maximum area rectangle in a region/////////
|
||
//////////////////////////////////////////////////////////////////////
|
||
bool SortByY(const MyPoint& mp1, const MyPoint& mp2)
|
||
{
|
||
if(mp1.loc.GetY() < mp2.loc.GetY() ||
|
||
AlmostEqual(mp1.loc.GetY(), mp2.loc.GetY())) return false;
|
||
return true;
|
||
}
|
||
|
||
/*
|
||
locate which Quadrant the point belongs to
|
||
|
||
*/
|
||
int GetQuadrant(double x, double y, Rectangle<2> reg_box)
|
||
{
|
||
double m_x = (reg_box.MinD(0) + reg_box.MaxD(0))/2;
|
||
double m_y = (reg_box.MinD(1) + reg_box.MaxD(1))/2;
|
||
if(x < m_x || AlmostEqual(x, m_x)){
|
||
if(y < m_y || AlmostEqual(y, m_y ))return 3;
|
||
else
|
||
return 2;
|
||
}else{
|
||
if(y < m_y || AlmostEqual(y, m_y ))return 4;
|
||
else
|
||
return 1;
|
||
}
|
||
return -1;
|
||
}
|
||
|
||
|
||
/*
|
||
the region should only have one face.
|
||
it can be convex or concave, but without holes
|
||
if the polygon is a triangle, we can directly get the maximum rectangle
|
||
|
||
*/
|
||
Rectangle<2> GetMaxRect(Region* reg)
|
||
{
|
||
if(reg->NoComponents() != 1){
|
||
cout<<"only one face is allowed"<<endl;
|
||
return Rectangle<2>(false);
|
||
|
||
}
|
||
|
||
CompTriangle* ct = new CompTriangle(reg);
|
||
unsigned int no_cyc = ct->NoOfCycles();
|
||
|
||
if(no_cyc != 1){
|
||
cout<<"has holes inside or no cycle"<<endl;
|
||
delete ct;
|
||
return Rectangle<2>(false);
|
||
|
||
}
|
||
|
||
|
||
Line* boundary = new Line(0);
|
||
reg->Boundary(boundary);
|
||
|
||
SimpleLine* sboundary = new SimpleLine(0);
|
||
sboundary->fromLine(*boundary);
|
||
|
||
vector<MyHalfSegment> mhs;
|
||
|
||
SpacePartition* sp = new SpacePartition();
|
||
if(sboundary->Size() > 0)
|
||
sp->ReorderLine(sboundary, mhs);
|
||
else{
|
||
cout<<"can't covert the boundary to a sline"<<endl;
|
||
boundary->DeleteIfAllowed();
|
||
sboundary->DeleteIfAllowed();
|
||
delete sp;
|
||
delete ct;
|
||
return Rectangle<2>(false);
|
||
|
||
}
|
||
|
||
vector<Point> ps;
|
||
for(unsigned int i = 0;i < mhs.size();i++)
|
||
ps.push_back(mhs[i].from);
|
||
|
||
if(ct->IsConvex(ps) == false){
|
||
cout<<"concave polygon"<<endl;
|
||
delete ct;
|
||
return Rectangle<2>(false);
|
||
|
||
}
|
||
|
||
///////////////////////////////////////////////////////////////////////
|
||
/////////////// finish checking //////////////////////////////////////
|
||
//////////////////////////////////////////////////////////////////////
|
||
|
||
Rectangle<2> reg_box = reg->BoundingBox();
|
||
// cout<<"ps size "<<ps.size()<<endl;
|
||
for(unsigned int i = 0;i < ps.size();i++){
|
||
double x = ps[i].GetX();
|
||
double y = ps[i].GetY();
|
||
assert(!(x < 0.0 || y < 0.0));
|
||
int range = GetQuadrant(x, y, reg_box);
|
||
assert(range > 0);
|
||
switch(range){
|
||
case 1:
|
||
x = floor(x);
|
||
y = floor(y);
|
||
break;
|
||
case 2:
|
||
x = ceil(x);
|
||
y = floor(y);
|
||
break;
|
||
case 3:
|
||
x = ceil(x);
|
||
y = ceil(y);
|
||
break;
|
||
case 4:
|
||
x = floor(x);
|
||
y = ceil(y);
|
||
break;
|
||
}
|
||
ps[i].Set(x,y);
|
||
// cout<<"x "<<x<<" y "<<y<<endl;
|
||
|
||
if(i > 0){
|
||
Point p1 = ps[i - 1];
|
||
Point p2 = ps[i];
|
||
if(AlmostEqual(p1, p2)){
|
||
boundary->DeleteIfAllowed();
|
||
sboundary->DeleteIfAllowed();
|
||
|
||
delete sp;
|
||
delete ct;
|
||
|
||
return Rectangle<2>(false);
|
||
}
|
||
}
|
||
|
||
/////////////////////////////////////////////////////////////////
|
||
//more checking, three points collineation, cannot be a region///
|
||
////////////////////////////////////////////////////////////////
|
||
if(ps.size() == 3){
|
||
SpacePartition* sp = new SpacePartition();
|
||
if(sp->Collineation(ps[0], ps[1], ps[2])){
|
||
delete sp;
|
||
return Rectangle<2>(false);
|
||
}
|
||
|
||
delete sp;
|
||
}
|
||
}
|
||
|
||
boundary->DeleteIfAllowed();
|
||
sboundary->DeleteIfAllowed();
|
||
|
||
if(AlmostEqual(ps[0], ps[ps.size() - 1])){
|
||
delete sp;
|
||
delete ct;
|
||
return Rectangle<2>(false);
|
||
}
|
||
|
||
vector<Region> regs;
|
||
sp->ComputeRegion(ps, regs);
|
||
|
||
delete sp;
|
||
delete ct;
|
||
|
||
|
||
if(ct->GetClockwise(ps) == false){
|
||
vector<Point> temp_ps;
|
||
for(int i = ps.size() - 1; i >= 0;i--)
|
||
temp_ps.push_back(ps[i]);
|
||
ps.clear();
|
||
for(unsigned int i = 0;i < temp_ps.size();i++)
|
||
ps.push_back(temp_ps[i]);
|
||
}
|
||
|
||
if(ps.size() >= 3){
|
||
vector<GeomPoint> polygon;
|
||
for(unsigned int i = 0;i < ps.size();i++){
|
||
GeomPoint gp(ps[i].GetX(), ps[i].GetY());
|
||
polygon.push_back(gp);
|
||
}
|
||
|
||
MaxRect max_rect;
|
||
max_rect.Init();
|
||
max_rect.SetPoint(polygon);
|
||
if(max_rect.computeEdgeList()){
|
||
max_rect.computeLargestRectangle();
|
||
if(max_rect.result != -1)
|
||
return max_rect.RectList[max_rect.result];
|
||
else
|
||
return Rectangle<2>(false);
|
||
}else
|
||
return Rectangle<2>(false);
|
||
}
|
||
|
||
return Rectangle<2>(false);
|
||
}
|
||
|
||
/*
|
||
simple and approximate method to get a rectangle from a polygon.
|
||
the method above takes too much time
|
||
|
||
*/
|
||
Rectangle<2> GetMaxRect2(Region* reg)
|
||
{
|
||
if(reg->NoComponents() != 1){
|
||
cout<<"only one face is allowed"<<endl;
|
||
return Rectangle<2>(false);
|
||
|
||
}
|
||
|
||
CompTriangle* ct = new CompTriangle(reg);
|
||
unsigned int no_cyc = ct->NoOfCycles();
|
||
|
||
if(no_cyc != 1){
|
||
cout<<"has holes inside or no cycle"<<endl;
|
||
delete ct;
|
||
return Rectangle<2>(false);
|
||
|
||
}
|
||
delete ct;
|
||
|
||
Rectangle<2> bbox = reg->BoundingBox();
|
||
double mid_x = (bbox.MinD(0) + bbox.MaxD(0))/2;
|
||
double mid_y = (bbox.MinD(1) + bbox.MaxD(1))/2;
|
||
|
||
|
||
double dist_delta1;
|
||
double dist_delta2;
|
||
if(GetRandom() % 2 ==0){
|
||
dist_delta1 = 5.0;
|
||
dist_delta2 = 3.0;
|
||
}else{
|
||
dist_delta1 = 3.0;
|
||
dist_delta2 = 5.0;
|
||
}
|
||
|
||
double min[2], max[2];
|
||
min[0] = mid_x - dist_delta1;
|
||
max[0] = mid_x + dist_delta1;
|
||
min[1] = mid_y - dist_delta2;
|
||
max[1] = mid_y + dist_delta2;
|
||
Rectangle<2> max_bbox(true, min, max);
|
||
if(RegContainRect(reg, max_bbox)){
|
||
bool valid = true;
|
||
Rectangle<2> last_box = max_bbox;
|
||
while(valid){
|
||
|
||
dist_delta1 += dist_delta1;
|
||
dist_delta2 += dist_delta2;
|
||
|
||
min[0] = mid_x - dist_delta1;
|
||
max[0] = mid_x + dist_delta1;
|
||
min[1] = mid_y - dist_delta2;
|
||
max[1] = mid_y + dist_delta2;
|
||
Rectangle<2> temp_bbox(true, min, max);
|
||
if(RegContainRect(reg, temp_bbox) && temp_bbox.Area() < maxi_rect_area){
|
||
last_box = temp_bbox;
|
||
}else{
|
||
valid = false;
|
||
}
|
||
}
|
||
return last_box;
|
||
}else{
|
||
return Rectangle<2>(false);
|
||
}
|
||
|
||
}
|
||
|
||
/////////////////////////////////////////////////////////////////////////
|
||
//////////// the following implementation from /////////////////////////
|
||
////H. Alt, D. Hsu, and J. Snoeyink. ////////////////////////////////////
|
||
////////Computing the largest inscribed isothetic rectangle. ///////////
|
||
//////////In Proc. 7th Canadian Conf. Comput. Geom.,///////////////////
|
||
////////////Universit'e Laval, Qu'ebec, August 1995, pp. 67--72./////////
|
||
//////// the original code is by Java, I conver it to C, c++/////////////
|
||
/////////////////////////////////////////////////////////////////////////
|
||
|
||
void MaxRect::SetPoint(vector<GeomPoint>& list)
|
||
{
|
||
for(unsigned int i = 0;i < list.size();i++){
|
||
// geo_p_list.push_back(list[i]);
|
||
int x = list[i].x;
|
||
int y = list[i].y;
|
||
GeomPoint p(x,y);
|
||
|
||
// this.polygon.add(p);
|
||
if (geo_p_list.size() <2){
|
||
geo_p_list.push_back(p);
|
||
status = 1;
|
||
changed = true;
|
||
}else if (geo_p_list.size() == 2){
|
||
GeomPoint ha = geo_p_list[0];
|
||
GeomPoint hb = geo_p_list[1];
|
||
if (onLeft(ha, hb, p)){
|
||
geo_p_list.push_back(p);
|
||
status = 2;
|
||
changed = true;
|
||
}else{
|
||
GeomPoint q = geo_p_list[1];
|
||
geo_p_list[1] = p;
|
||
geo_p_list.push_back(q);
|
||
status = 2;
|
||
}
|
||
}else{
|
||
geo_p_list.push_back(p);
|
||
}
|
||
}
|
||
|
||
|
||
}
|
||
|
||
|
||
bool MaxRect::onLeft(GeomPoint a, GeomPoint b, GeomPoint c)
|
||
{
|
||
int area = (b.x -a.x)*(c.y - a.y) - (c.x - a.x)*(b.y - a.y);
|
||
return (area<0);
|
||
}
|
||
|
||
bool MaxRect::pointOutside(GeomPoint p)
|
||
{//, int start, int stop){
|
||
|
||
bool ptIn = true, currIn, prevIn = true;
|
||
|
||
GeomPoint a = geo_p_list[0];
|
||
GeomPoint b;
|
||
|
||
for(unsigned int i=0; i<geo_p_list.size(); i++){
|
||
b = geo_p_list[(i+1)%geo_p_list.size()];
|
||
currIn = onLeft(a, b, p);
|
||
ptIn = ptIn && currIn;
|
||
a = b;
|
||
|
||
if(prevIn && !currIn){ start = i;} //next point outside, 1st tangent found
|
||
if(!prevIn && currIn){ stop = i;} // 2nd tangent
|
||
prevIn = currIn;
|
||
|
||
}
|
||
return !ptIn;
|
||
}
|
||
|
||
|
||
bool MaxRect::computeEdgeList()
|
||
{
|
||
GeomPoint a,b;
|
||
a = geo_p_list[geo_p_list.size()-1];
|
||
for(unsigned int i = 0; i< geo_p_list.size(); i++){
|
||
b = (GeomPoint)geo_p_list[i];
|
||
//b = (GeomPoint)this.elementAt(i+1);
|
||
|
||
if (i==0){
|
||
g_xmin = a.x;
|
||
g_xmax = a.x;
|
||
g_ymin = a.y;
|
||
g_ymax = a.y;
|
||
}
|
||
else{
|
||
if (a.x < g_xmin){
|
||
g_xmin = a.x;
|
||
}
|
||
if (a.x > g_xmax){
|
||
g_xmax = a.x;
|
||
yxmax = a.y;
|
||
}
|
||
if (a.y < g_ymin){
|
||
g_ymin = a.y;
|
||
}
|
||
if (a.y > g_ymax){
|
||
g_ymax = a.y;
|
||
}
|
||
}
|
||
if(a.x == b.x) return false;
|
||
|
||
GeomEdge* e = new GeomEdge(a,b);
|
||
geo_e_list.push_back(*e);
|
||
a = b;
|
||
delete e;
|
||
} //for
|
||
return true;
|
||
}
|
||
|
||
|
||
/*
|
||
compute y intersection with an edge
|
||
first pixel completely inside
|
||
ceil function if edge is on top, floor otherwise
|
||
(+y is down)
|
||
|
||
*/
|
||
inline int MaxRect::yIntersect(int xi, GeomEdge e)
|
||
{
|
||
|
||
int y;
|
||
double yfirst = (e.m) * (xi-0.5) + e.b;
|
||
double ylast = (e.m) * (xi+0.5) + e.b;
|
||
|
||
if (!e.isTop){
|
||
y = (int)floor(MIN(yfirst, ylast));
|
||
}
|
||
else {
|
||
y = (int)ceil(MAX(yfirst, ylast));
|
||
}
|
||
return y;
|
||
}
|
||
|
||
/*
|
||
find largest pixel completely inside
|
||
look through all edges for intersection
|
||
|
||
*/
|
||
int MaxRect::xIntersect(int y){
|
||
int x=0;
|
||
double x0=0, x1=0;
|
||
for(unsigned int i=0; i< geo_p_list.size(); i++){
|
||
GeomEdge e = geo_e_list[i];
|
||
if (e.isRight && e.ymin <= y && e.ymax >= y){
|
||
x0 = (double)(y+0.5 - e.b)/e.m;
|
||
x1 = (double)(y-0.5 - e.b)/e.m;
|
||
}
|
||
}
|
||
x = (int)floor(MIN(x0,x1));
|
||
//System.out.println("xIntersect, x is " + x);
|
||
return x;
|
||
}
|
||
|
||
|
||
GeomEdge MaxRect::findEdge(int x, bool isTop)
|
||
{
|
||
GeomEdge e;
|
||
GeomEdge emax= geo_e_list[0];
|
||
//int count = 0;
|
||
for (unsigned int i=0; i< geo_p_list.size(); i++){
|
||
e = geo_e_list[i];
|
||
if (e.xmin == x){
|
||
if (e.xmax != e.xmin){
|
||
if ((e.isTop && isTop)||(!e.isTop && !isTop)){
|
||
emax = e;
|
||
}
|
||
}
|
||
}
|
||
|
||
}
|
||
return emax;
|
||
}
|
||
/*
|
||
to get more precise data:
|
||
for the coordinates of original point, we can multiply the value by 1000.
|
||
because the original code only uses the type int.
|
||
in the end, we have to div the value by 1000.
|
||
This depends on the application requirment
|
||
|
||
*/
|
||
void MaxRect::computeLargestRectangle(){
|
||
|
||
changed = false;
|
||
|
||
GeomEdge top, bottom;
|
||
int ymax, ymin, xright, xlo, xhi;
|
||
int area, maxArea = 0;
|
||
int width, height, maxh=0, maxw=0;
|
||
|
||
/* all 2-corner and 3-corner largest rectangles */
|
||
int aAC=0,aBD=0,aABC=0,aABD=0,aACD=0,aBCD=0;
|
||
GeomPoint pAC, pBD, pABC, pABD, pACD, pBCD;
|
||
int hAC=0,wAC=0,hBD=0,wBD=0,hABC=0,wABC=0,hABD=0,wABD=0;
|
||
int hACD=0,wACD=0,hBCD=0,wBCD=0;
|
||
bool onA, onB, onC, onD;
|
||
|
||
GeomPoint maxp(0, 0);
|
||
pAC = maxp;
|
||
pBD = maxp;
|
||
pABC = maxp;
|
||
pABD = maxp;
|
||
pACD = maxp;
|
||
pBCD = maxp;
|
||
|
||
|
||
vector<GeomPoint> xint;
|
||
|
||
for(int i=0;i< g_ymax;i++){
|
||
int x = xIntersect(i);
|
||
GeomPoint px(x, i);
|
||
xint.push_back(px);
|
||
// cout<<px.x<<" "<<px.y<<endl;
|
||
}
|
||
|
||
// cout<<"g_xmin "<<g_xmin<<" g_xmax "<<g_xmax
|
||
// <<" g_ymin "<<g_ymin<<" g_ymax "<<g_ymax<<endl;
|
||
|
||
//find first top and bottom edges
|
||
top = findEdge(g_xmin, true);
|
||
bottom = findEdge(g_xmin, false);
|
||
|
||
//scan for rectangle left position
|
||
for(int xi= g_xmin; xi< g_xmax;xi++){
|
||
|
||
ymin = yIntersect(xi, top);
|
||
ymax = yIntersect(xi, bottom);
|
||
// cout<<"xi "<<xi<<" ymin "<<ymin<<" ymax "<<ymax<<endl;
|
||
|
||
for(int ylo = ymax;ylo>= ymin;ylo--){//ylo from to to bottom
|
||
// cout<<"ylo "<<ylo<<"ymin "<<ymin<<"ymax "<<ymax<<endl;
|
||
for(int yhi = ymin; yhi<= ymax; yhi++){
|
||
|
||
// cout<<"yhi "<<yhi<<endl;
|
||
|
||
if (yhi>ylo){
|
||
|
||
onA = (yhi == ymax && !bottom.isRight);
|
||
onD = (ylo == ymin && !top.isRight);
|
||
|
||
//xIntersect(ylo,edgeList);
|
||
xlo = (int)((GeomPoint)xint[ylo]).x;
|
||
//xIntersect(yhi,edgeList);
|
||
xhi = (int)((GeomPoint)xint[yhi]).x;
|
||
|
||
xright = maxp.min(xlo,xhi);
|
||
onC = (xright == xlo && yxmax >= ylo);
|
||
onB = (xright == xhi && yxmax <= yhi);
|
||
|
||
height = yhi-ylo;
|
||
width = xright - xi;
|
||
|
||
if (!fixed){
|
||
}//!fixed
|
||
else{
|
||
int fixedWidth =
|
||
(int)ceil( ((double)height*fixedX)/((double)fixedY));
|
||
if (fixedWidth <= width){
|
||
width = fixedWidth;
|
||
}
|
||
else{
|
||
width = 0;
|
||
}
|
||
}
|
||
area = width * height;
|
||
//AC
|
||
if (onA && onC && !onB && !onD){
|
||
if (area > aAC){
|
||
aAC = area;
|
||
// pAC = new GeomPoint(xi, ylo);
|
||
pAC.x = xi;
|
||
pAC.y = ylo;
|
||
// cout<<" xi "<<xi<<" ylo "<<ylo<<endl;
|
||
hAC = height;
|
||
wAC = width;
|
||
}
|
||
}
|
||
//BD
|
||
if (onB && onD && !onA && !onC){
|
||
if (area > aBD){
|
||
aBD = area;
|
||
// pBD = new GeomPoint(xi, ylo);
|
||
pBD.x = xi;
|
||
pBD.y = ylo;
|
||
|
||
hBD = height;
|
||
wBD = width;
|
||
}
|
||
}
|
||
//ABC
|
||
if (onA && onB && onC){
|
||
if (area > aABC){
|
||
aABC = area;
|
||
// pABC = new GeomPoint(xi, ylo);
|
||
pABC.x = xi;
|
||
pABC.y = ylo;
|
||
|
||
hABC = height;
|
||
wABC = width;
|
||
}
|
||
}
|
||
//ABD
|
||
if (onA && onB && onD){
|
||
if (area > aABD){
|
||
aABD = area;
|
||
// pABD = new GeomPoint(xi, ylo);
|
||
pABD.x = xi;
|
||
pABD.y = ylo;
|
||
|
||
hABD = height;
|
||
wABD = width;
|
||
}
|
||
}
|
||
//ACD
|
||
if (onA && onC && onD){
|
||
if (area > aACD){
|
||
aACD = area;
|
||
// pACD = new GeomPoint(xi, ylo);
|
||
pACD.x = xi;
|
||
pACD.y = ylo;
|
||
|
||
hACD = height;
|
||
wACD = width;
|
||
}
|
||
}
|
||
//BCD
|
||
if (onB && onC && onD){
|
||
if (area > aBCD){
|
||
aBCD = area;
|
||
// pBCD = new GeomPoint(xi, ylo);
|
||
pBCD.x = xi;
|
||
pBCD.y = ylo;
|
||
|
||
hBCD = height;
|
||
wBCD = width;
|
||
}
|
||
}
|
||
|
||
if(area>maxArea){
|
||
maxArea = area;
|
||
// maxp = new GeomPoint(xi, ylo);
|
||
maxp.x = xi;
|
||
maxp.y = ylo;
|
||
|
||
maxw = width;
|
||
maxh = height;
|
||
|
||
}
|
||
}//yhi > ylo
|
||
}//for yhi
|
||
}//for ylo
|
||
if (xi == top.xmax){
|
||
top = findEdge(xi, true);
|
||
}
|
||
if(xi == bottom.xmax){
|
||
bottom = findEdge(xi, false);
|
||
}
|
||
}//xi
|
||
|
||
rectp = maxp;
|
||
recth = maxh;
|
||
rectw = maxw;
|
||
|
||
|
||
/* RectList.push_back(Rectangle<2>(true, pAC.x, pAC.y, wAC, hAC));
|
||
RectList.push_back(Rectangle<2>(true, pBD.x, pBD.y, wBD, hBD));
|
||
RectList.push_back(Rectangle<2>(true, pABC.x, pABC.y, wABC, hABC));
|
||
RectList.push_back(Rectangle<2>(true, pABD.x, pABD.y, wABD, hABD));
|
||
RectList.push_back(Rectangle<2>(true, pACD.x, pACD.y, wACD, hACD));
|
||
RectList.push_back(Rectangle<2>(true, pBCD.x, pBCD.y, wBCD, hBCD));
|
||
RectList.push_back(Rectangle<2>(true, maxp.x, maxp.y, maxw, maxh));*/
|
||
|
||
double x_1 = pAC.x;
|
||
double x_2 = pAC.x + wAC;
|
||
double y_1 = pAC.y;
|
||
double y_2 = pAC.y + hAC;
|
||
// Rectangle<2> rect(true, x_1, x_2, y_1, y_2);
|
||
|
||
// cout<<"x1 "<<x_1<<" x2 "<<x_2<<" y1 "<<y_1<<" y2 "<<y_2<<endl;
|
||
{
|
||
double minMax[] = {x_1, x_2, y_1, y_2};
|
||
RectList.push_back(Rectangle<2>(true,minMax));
|
||
}
|
||
x_1 = pBD.x; x_2 = x_1 + wBD; y_1 = pBD.y; y_2 = pBD.y + hBD;
|
||
// cout<<"x1 "<<x_1<<" x2 "<<x_2<<" y1 "<<y_1<<" y2 "<<y_2<<endl;
|
||
{
|
||
double minMax[] = {x_1, x_2, y_1, y_2};
|
||
RectList.push_back(Rectangle<2>(true,minMax ));
|
||
}
|
||
|
||
x_1 = pABC.x; x_2 = x_1 + wABC; y_1 = pABC.y; y_2 = y_1 + hABC;
|
||
// cout<<"x1 "<<x_1<<" x2 "<<x_2<<" y1 "<<y_1<<" y2 "<<y_2<<endl;
|
||
{
|
||
double minMax[] = { x_1, x_2, y_1, y_2};
|
||
RectList.push_back(Rectangle<2>(true,minMax ));
|
||
}
|
||
|
||
x_1 = pABD.x; x_2 = x_1 + wABD; y_1 = pABD.y; y_2 = y_1 + hABD;
|
||
// cout<<"x1 "<<x_1<<" x2 "<<x_2<<" y1 "<<y_1<<" y2 "<<y_2<<endl;
|
||
{
|
||
double minMax[] = { x_1, x_2, y_1, y_2};
|
||
RectList.push_back(Rectangle<2>(true, minMax));
|
||
}
|
||
|
||
x_1 = pACD.x; x_2 = x_1 + wACD; y_1 = pACD.y; y_2 = y_1 + hACD;
|
||
// cout<<"x1 "<<x_1<<" x2 "<<x_2<<" y1 "<<y_1<<" y2 "<<y_2<<endl;
|
||
{
|
||
double minMax[] = {x_1, x_2, y_1, y_2};
|
||
RectList.push_back(Rectangle<2>(true,minMax ));
|
||
}
|
||
|
||
x_1 = pBCD.x; x_2 = x_1 + wBCD; y_1 = pBCD.y; y_2 = y_1 + hBCD;
|
||
// cout<<"x1 "<<x_1<<" x2 "<<x_2<<" y1 "<<y_1<<" y2 "<<y_2<<endl;
|
||
{
|
||
double minMax[] = { x_1, x_2, y_1, y_2 };
|
||
RectList.push_back(Rectangle<2>(true, minMax));
|
||
}
|
||
|
||
x_1 = maxp.x; x_2 = x_1 + maxw; y_1 = maxp.y; y_2 = y_1 + maxh;
|
||
// cout<<"x1 "<<x_1<<" x2 "<<x_2<<" y1 "<<y_1<<" y2 "<<y_2<<endl;
|
||
{
|
||
double minMax[] = {x_1, x_2, y_1, y_2};
|
||
RectList.push_back(Rectangle<2>(true, minMax));
|
||
}
|
||
|
||
|
||
float rect_area = 0.0;
|
||
result = -1;
|
||
for(unsigned int i = 0;i < RectList.size();i++){
|
||
// cout<<RectList[i]<<" area "<<RectList[i].Area()<<endl;
|
||
if(RectList[i].IsDefined() == false){
|
||
result = -1;
|
||
return;
|
||
}
|
||
if(RectList[i].Area() > rect_area){
|
||
rect_area = RectList[i].Area();
|
||
result = i;
|
||
}
|
||
}
|
||
// cout<<RectList[index]<<endl;
|
||
}
|
||
////////////////////////////////////////////////////////////////////////////
|
||
////////////////////////////////////////////////////////////////////////////
|
||
////////////////////////////////////////////////////////////////////////////
|
||
string MaxRect::BuildingRectTypeInfo =
|
||
"(rel (tuple ((Reg_id int) (GeoData rect) (Poly_id int) (Reg_type int))))";
|
||
|
||
string MaxRect::RegionElemTypeInfo =
|
||
"(rel (tuple ((Id int) (Covarea region))))";
|
||
|
||
string MaxRect::BuildingRectExtTypeInfo =
|
||
"(rel (tuple ((Reg_id int) (GeoData rect) (Poly_id int) (Reg_type int) \
|
||
(Building_type int) (Building_type2 string) (Building_id int))))";
|
||
|
||
string MaxRect::BuildingParaInfo = "(rel (tuple ((Para real))))";
|
||
|
||
/*
|
||
remove some dirty data for regions. two subregions intersect at a point
|
||
|
||
*/
|
||
void MaxRect::RemoveDirty(int attr1, int attr2)
|
||
{
|
||
// cout<<"attr1 "<<attr1<<" attr2 "<<attr2<<endl;
|
||
|
||
for(int i = 1;i <= rel1->GetNoTuples();i++){
|
||
Tuple* region_tuple = rel1->GetTuple(i, false);
|
||
int reg_id = ((CcInt*)region_tuple->GetAttribute(attr1))->GetIntval();
|
||
Region* r = (Region*)region_tuple->GetAttribute(attr2);
|
||
if(reg_id == 1){ //the outer cycle
|
||
reg_id_list.push_back(reg_id);
|
||
reg_list.push_back(*r);
|
||
region_tuple->DeleteIfAllowed();
|
||
continue;
|
||
}
|
||
|
||
CompTriangle* ct = new CompTriangle(r);
|
||
int error; //0-concave 1 non-region 2 hole or faces 3 dirty region
|
||
bool convex = ct->PolygonConvex2(error);
|
||
if(convex){ //convex polygon
|
||
reg_id_list.push_back(reg_id);
|
||
reg_list.push_back(*r);
|
||
}else if(convex == false && error == 0){ //concave polygon
|
||
reg_id_list.push_back(reg_id);
|
||
reg_list.push_back(*r);
|
||
}else{
|
||
// cout<<"dirty data"<<endl;
|
||
if(error == 3){ //ignore the first outer cycle, non-region dirty
|
||
RemoveDirtyRegion(reg_id, r);
|
||
|
||
// break;
|
||
}
|
||
}
|
||
|
||
delete ct;
|
||
region_tuple->DeleteIfAllowed();
|
||
}
|
||
|
||
}
|
||
|
||
/*
|
||
a point that appears four times. it is a vertex that two regions intersect
|
||
|
||
*/
|
||
void MaxRect::RemoveDirtyRegion(int regid, Region* reg)
|
||
{
|
||
vector<MyPoint> ps_list;
|
||
vector<HalfSegment> hs_list;
|
||
for(int i = 0;i < reg->Size();i++){
|
||
HalfSegment hs;
|
||
reg->Get(i, hs);
|
||
if(!hs.IsLeftDomPoint())continue;
|
||
Point lp = hs.GetLeftPoint();
|
||
Point rp = hs.GetRightPoint();
|
||
if(ps_list.size() == 0){
|
||
ps_list.push_back(MyPoint(lp, 1));
|
||
ps_list.push_back(MyPoint(rp, 1));
|
||
}else{
|
||
unsigned int j;
|
||
for(j = 0;j < ps_list.size();j++){
|
||
if(AlmostEqual(ps_list[j].loc, lp)){
|
||
ps_list[j].dist++;
|
||
break;
|
||
}
|
||
}
|
||
if(j == ps_list.size())ps_list.push_back(MyPoint(lp, 1));
|
||
|
||
for(j = 0;j < ps_list.size();j++){
|
||
if(AlmostEqual(ps_list[j].loc, rp)){
|
||
ps_list[j].dist++;
|
||
break;
|
||
}
|
||
}
|
||
if(j == ps_list.size())ps_list.push_back(MyPoint(rp, 1));
|
||
}
|
||
HalfSegment temp_hs(true, hs.GetLeftPoint(), hs.GetRightPoint());
|
||
hs_list.push_back(temp_hs);
|
||
}
|
||
|
||
Point dirty_p;
|
||
for(unsigned int i = 0;i <ps_list.size();i++){
|
||
// ps_list[i].Print();
|
||
if((int)(ps_list[i].dist) == 4)dirty_p = ps_list[i].loc;
|
||
}
|
||
|
||
// cout<<"dirty point "<<dirty_p<<endl;
|
||
|
||
vector<unsigned int> index_list;
|
||
for(unsigned int i = 0;i < hs_list.size();i++){
|
||
HalfSegment hs = hs_list[i];
|
||
if(AlmostEqual(hs.GetLeftPoint(), dirty_p))index_list.push_back(i);
|
||
if(AlmostEqual(hs.GetRightPoint(), dirty_p))index_list.push_back(i);
|
||
}
|
||
|
||
assert(index_list.size() == 4); //four halfsegments
|
||
// cout<<hs_list.size()<<endl;
|
||
vector<HalfSegment> new_hs_list;
|
||
for(unsigned int i = 0;i < hs_list.size();i++){
|
||
unsigned int j = 0;
|
||
for(;j < index_list.size();j++)
|
||
if(i == index_list[j])break;
|
||
|
||
if(j == index_list.size())new_hs_list.push_back(hs_list[i]);
|
||
}
|
||
// cout<<new_hs_list.size()<<endl;
|
||
|
||
|
||
vector<SimpleLine> sl_contour;
|
||
|
||
for(unsigned int i = 0;i < index_list.size();i++){
|
||
|
||
for(unsigned int j = i + 1;j < index_list.size();j++){
|
||
SimpleLine* sl = new SimpleLine(0);
|
||
sl->StartBulkLoad();
|
||
|
||
vector<HalfSegment> sl_hs_list;
|
||
|
||
HalfSegment hs1 = hs_list[index_list[i]];
|
||
HalfSegment hs2 = hs_list[index_list[j]];
|
||
|
||
vector<HalfSegment> cut_hs_list;
|
||
for(unsigned int k = 0;k < index_list.size();k++){
|
||
if(index_list[k] != index_list[i] &&
|
||
index_list[k] != index_list[j])
|
||
cut_hs_list.push_back(hs_list[index_list[k]]);
|
||
}
|
||
|
||
|
||
int edgeno = 0;
|
||
for(unsigned int k1 = 0;k1 < new_hs_list.size();k1++){
|
||
HalfSegment hs = new_hs_list[k1];
|
||
|
||
unsigned int k2 = 0;
|
||
for(;k2 < cut_hs_list.size();k2++){
|
||
if(hs.Intersects(cut_hs_list[k2]))break;
|
||
}
|
||
if(k2 == cut_hs_list.size()){
|
||
hs.attr.edgeno = edgeno++;
|
||
*sl += hs;
|
||
hs.SetLeftDomPoint(!hs.IsLeftDomPoint());
|
||
*sl += hs;
|
||
}
|
||
}
|
||
*sl += hs1;
|
||
hs1.SetLeftDomPoint(!hs1.IsLeftDomPoint());
|
||
*sl += hs1;
|
||
|
||
*sl += hs2;
|
||
hs2.SetLeftDomPoint(!hs2.IsLeftDomPoint());
|
||
*sl += hs2;
|
||
|
||
|
||
sl->EndBulkLoad();
|
||
if(sl->Length() > 0)
|
||
sl_contour.push_back(*sl);
|
||
// cout<<sl->Length()<<endl;
|
||
sl->DeleteIfAllowed();
|
||
}
|
||
}
|
||
|
||
//////////// get the refinement region ///////////////////
|
||
for(unsigned int i = 0;i < sl_contour.size();i++){
|
||
if(IsCycle(&sl_contour[i])){
|
||
// cout<<"a cycle"<<endl;
|
||
// reg_id_list.push_back(regid);
|
||
// sl_list.push_back(sl_contour[i]);
|
||
SpacePartition* sp = new SpacePartition();
|
||
vector<MyHalfSegment> mhs;
|
||
sp->ReorderLine(&sl_contour[i], mhs);
|
||
|
||
vector<Point> ps;
|
||
for(unsigned int j = 0;j < mhs.size();j++){
|
||
ps.push_back(mhs[j].from);
|
||
}
|
||
vector<Region> regs;
|
||
sp->ComputeRegion(ps, regs);
|
||
if(regs.size() > 0 ){
|
||
reg_id_list.push_back(regid);
|
||
reg_list.push_back(regs[0]);
|
||
}
|
||
delete sp;
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
/*
|
||
check whether the simpleline is a cycle
|
||
|
||
*/
|
||
bool MaxRect::IsCycle(SimpleLine* sl)
|
||
{
|
||
|
||
vector<MyPoint> ps_list;
|
||
|
||
for(int i = 0;i < sl->Size();i++){
|
||
HalfSegment hs;
|
||
sl->Get(i, hs);
|
||
if(!hs.IsLeftDomPoint())continue;
|
||
// cout<<hs<<endl;
|
||
Point lp = hs.GetLeftPoint();
|
||
Point rp = hs.GetRightPoint();
|
||
if(ps_list.size() == 0){
|
||
ps_list.push_back(MyPoint(lp, 1));
|
||
ps_list.push_back(MyPoint(rp, 1));
|
||
}else{
|
||
unsigned int j;
|
||
for(j = 0;j < ps_list.size();j++){
|
||
if(AlmostEqual(ps_list[j].loc, lp)){
|
||
ps_list[j].dist++;
|
||
break;
|
||
}
|
||
}
|
||
if(j == ps_list.size())ps_list.push_back(MyPoint(lp, 1));
|
||
|
||
for(j = 0;j < ps_list.size();j++){
|
||
if(AlmostEqual(ps_list[j].loc, rp)){
|
||
ps_list[j].dist++;
|
||
break;
|
||
}
|
||
}
|
||
if(j == ps_list.size())ps_list.push_back(MyPoint(rp, 1));
|
||
}
|
||
}
|
||
for(unsigned int i = 0;i < ps_list.size();i++){
|
||
if((int)ps_list[i].dist != 2) return false;
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
|
||
/*
|
||
get neighbor triangles to get convex polygons
|
||
|
||
*/
|
||
void MaxRect::ConvexReg(int attr1, int attr2)
|
||
{
|
||
// cout<<"attr1 "<<attr1<<" attr2 "<<attr2<<endl;
|
||
|
||
for(int i = 1;i <= rel1->GetNoTuples();i++){
|
||
Tuple* region_tuple = rel1->GetTuple(i, false);
|
||
int reg_id = ((CcInt*)region_tuple->GetAttribute(attr1))->GetIntval();
|
||
// cout<<"reg_id "<<reg_id<<endl;
|
||
|
||
/* if(reg_id != 2572){
|
||
region_tuple->DeleteIfAllowed();
|
||
continue;
|
||
}*/
|
||
|
||
Region* r = (Region*)region_tuple->GetAttribute(attr2);
|
||
CompTriangle* ct = new CompTriangle(r);
|
||
int error;
|
||
bool convex = ct->PolygonConvex2(error);
|
||
if(convex){ //convex polygon
|
||
reg_id_list.push_back(reg_id);
|
||
reg_list.push_back(*r);
|
||
|
||
}else if(convex == false && error == 0){ //concave polygon
|
||
///decompose the convex polygon into several convex polygons ///
|
||
// cout<<"reg_id "<<reg_id<<endl;
|
||
CompTriangle* ct1 = new CompTriangle(r);
|
||
ct1->NewTriangulation();
|
||
// cout<<ct1->triangles.size()<<endl;
|
||
MergeTriangle(ct1, reg_id);
|
||
delete ct1;
|
||
|
||
}
|
||
delete ct;
|
||
region_tuple->DeleteIfAllowed();
|
||
}
|
||
|
||
}
|
||
|
||
/*
|
||
merge triangles to get convex polygons
|
||
|
||
*/
|
||
|
||
void MaxRect::MergeTriangle(CompTriangle* ct, int reg_id)
|
||
{
|
||
vector<Region> convex_list;
|
||
vector<bool> mark_list;
|
||
for(unsigned int i = 0;i < ct->triangles.size();i++)
|
||
mark_list.push_back(false);
|
||
|
||
for(unsigned int i = 0;i < ct->triangles.size();i++){
|
||
if(mark_list[i]) continue;
|
||
Region* r1 = &(ct->triangles[i]);
|
||
|
||
if(r1->Area() > mini_reg_area){
|
||
convex_list.push_back(*r1);
|
||
mark_list[i] = true;
|
||
continue;
|
||
}
|
||
|
||
unsigned int j = i + 1;
|
||
for(;j < ct->triangles.size();j++){
|
||
Region* r2 = &(ct->triangles[j]);
|
||
if(mark_list[j] == false && NeighborTriangle(r1,r2)){
|
||
Region* res = new Region(0);
|
||
r1->Union(*r2, *res);
|
||
convex_list.push_back(*res);
|
||
res->DeleteIfAllowed();
|
||
|
||
mark_list[j] = true;
|
||
break;
|
||
}
|
||
}
|
||
if(j != ct->triangles.size())
|
||
mark_list[i] = true;
|
||
}
|
||
|
||
for(unsigned int i = 0;i < mark_list.size();i++)
|
||
if(mark_list[i] == false)convex_list.push_back(ct->triangles[i]);
|
||
|
||
|
||
vector<Region> res_list;
|
||
for(unsigned int i = 0;i < convex_list.size();i++){
|
||
CompTriangle* ct1 = new CompTriangle(&convex_list[i]);
|
||
if(ct1->PolygonConvex()){
|
||
res_list.push_back(convex_list[i]);
|
||
}
|
||
delete ct1;
|
||
}
|
||
|
||
vector<bool> flag_list;
|
||
for(unsigned int i = 0;i < res_list.size();i++){
|
||
flag_list.push_back(true);
|
||
}
|
||
|
||
for(unsigned int i = 0;i < res_list.size();i++){
|
||
if(flag_list[i] == false)continue;
|
||
Region* r1 = &(res_list[i]);
|
||
if(r1->Area() > mini_reg_area){
|
||
// cout<<"mini area "<<mini_reg_area<<" r1 "<<r1->Area()<<endl;
|
||
reg_id_list.push_back(reg_id);
|
||
reg_list.push_back(*r1);
|
||
flag_list[i] = false;
|
||
|
||
for(unsigned int j = i + 1;j < res_list.size();j++){
|
||
Region* r2 = &(res_list[j]);
|
||
if(r1->BoundingBox().Distance(r2->BoundingBox()) < 50.0){
|
||
flag_list[j] = false;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
/*
|
||
two triangles share one edge
|
||
|
||
*/
|
||
bool MaxRect::NeighborTriangle(Region* reg1, Region* reg2)
|
||
{
|
||
for(int i = 0;i < reg1->Size();i++){
|
||
HalfSegment hs1;
|
||
reg1->Get(i, hs1);
|
||
for(int j = 0;j < reg2->Size();j++){
|
||
HalfSegment hs2;
|
||
reg2->Get(j, hs2);
|
||
if((AlmostEqual(hs1.GetLeftPoint(), hs2.GetLeftPoint())&&
|
||
AlmostEqual(hs1.GetRightPoint(), hs2.GetRightPoint())) ||
|
||
(AlmostEqual(hs1.GetRightPoint(), hs2.GetLeftPoint()) &&
|
||
AlmostEqual(hs1.GetLeftPoint(), hs2.GetRightPoint()))){
|
||
return true;
|
||
}
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
/*
|
||
check whether a region contains a rectangle
|
||
|
||
*/
|
||
bool RegContainRect(Region* reg, Rectangle<2>& rect)
|
||
{
|
||
Point p1(true, rect.MinD(0), rect.MinD(1));
|
||
Point p2(true, rect.MaxD(0), rect.MinD(1));
|
||
Point p3(true, rect.MaxD(0), rect.MaxD(1));
|
||
Point p4(true, rect.MinD(0), rect.MaxD(1));
|
||
|
||
HalfSegment hs1(true, p1, p2);
|
||
HalfSegment hs2(true, p2, p3);
|
||
HalfSegment hs3(true, p3, p4);
|
||
HalfSegment hs4(true, p1, p4);
|
||
|
||
if(RegContainHS(reg, hs1) && RegContainHS(reg, hs2) &&
|
||
RegContainHS(reg, hs3) && RegContainHS(reg, hs4))return true;
|
||
return false;
|
||
}
|
||
|
||
/*
|
||
for the input relation, it gets a maximum rectangle for each region
|
||
|
||
*/
|
||
void MaxRect::GetRectangle1(int attr1, int attr2, Relation* building_para)
|
||
{
|
||
if(building_para->GetNoTuples() == 0){
|
||
cout<<"para relation empty"<<endl;
|
||
return;
|
||
}
|
||
Tuple* para_tuple = building_para->GetTuple(1, false);
|
||
float area_para = ((CcReal*)para_tuple->GetAttribute(0))->GetRealval();
|
||
para_tuple->DeleteIfAllowed();
|
||
|
||
|
||
int reg_id = 1;
|
||
for(int i = 1;i <= rel1->GetNoTuples();i++){
|
||
// for(int i = 1;i <= 50;i++){
|
||
|
||
Tuple* poly_tuple = rel1->GetTuple(i, false);
|
||
int poly_id = ((CcInt*)poly_tuple->GetAttribute(attr1))->GetIntval();
|
||
Region* poly = (Region*)poly_tuple->GetAttribute(attr2);
|
||
|
||
if(poly_id == 1){
|
||
poly_tuple->DeleteIfAllowed();
|
||
continue;
|
||
}
|
||
|
||
// cout<<"poly_id "<<poly_id<<endl;
|
||
|
||
CompTriangle* ct = new CompTriangle(poly);
|
||
ct->NewTriangulation();
|
||
// cout<<ct->triangles.size()<<endl;
|
||
|
||
vector<Rectangle<2> > rect_box_list;
|
||
|
||
for(unsigned int j = 0;j < ct->triangles.size();j++){
|
||
if(ct->triangles[j].Area() > mini_tri_area &&
|
||
ct->triangles[j].Area() < maxi_tri_area){
|
||
// printf("%f\n",ct->triangles[j].Area());
|
||
// if(ct->triangles[j].Area() > 28000.0) poly_count++;
|
||
|
||
if(ValidRegion(&ct->triangles[j])){//coordinates should be positive
|
||
|
||
Rectangle<2> rect_box(false);
|
||
|
||
// if(type == "Berlin"){
|
||
// rect_box = GetMaxRect(&ct->triangles[j]);
|
||
// }else if(type == "Houston"){
|
||
// if(ct->triangles[j].Area() > 0.9 * maxi_tri_area){
|
||
// rect_box = GetMaxRect(&ct->triangles[j]);
|
||
// }else{
|
||
// rect_box = GetMaxRect2(&ct->triangles[j]);
|
||
// }
|
||
// }else {
|
||
// assert(false);
|
||
// }
|
||
|
||
if(ct->triangles[j].Area() > area_para * maxi_tri_area){
|
||
rect_box = GetMaxRect(&ct->triangles[j]);
|
||
}else{
|
||
rect_box = GetMaxRect2(&ct->triangles[j]);
|
||
}
|
||
|
||
|
||
// cout<<rect_box<<endl;
|
||
if(rect_box.IsDefined()){
|
||
double x = fabs(rect_box.MaxD(0) - rect_box.MinD(0));
|
||
double y = fabs(rect_box.MaxD(1) - rect_box.MinD(1));
|
||
double min = MIN(x,y);
|
||
double max = MAX(x,y);
|
||
if(rect_box.Area() > mini_rect_area &&
|
||
rect_box.Area() < maxi_rect_area && (max / min < 5.0)){
|
||
|
||
if(RegContainRect(poly, rect_box))
|
||
rect_box_list.push_back(rect_box);
|
||
}
|
||
}
|
||
}else{
|
||
Rectangle<2> bbox = ct->triangles[j].BoundingBox();
|
||
double minx = bbox.MinD(0);
|
||
double miny = bbox.MinD(1);
|
||
double tran_x = fabs(minx) + 1.0;
|
||
double tran_y = fabs(miny) + 1.0;
|
||
Region* r = new Region(0);
|
||
ct->triangles[j].Translate(tran_x, tran_y, *r);
|
||
assert(ValidRegion(r));
|
||
|
||
Rectangle<2> rect_box(false);
|
||
|
||
// if(type == "Berlin"){
|
||
// rect_box = GetMaxRect(r);
|
||
// }else if(type == "Houston"){
|
||
// if(r->Area() > 0.9 * maxi_tri_area){
|
||
// rect_box = GetMaxRect(r);
|
||
// }else{
|
||
// rect_box = GetMaxRect2(r);
|
||
// }
|
||
// }else{
|
||
// assert(false);
|
||
//
|
||
// }
|
||
|
||
if(r->Area() > area_para * maxi_tri_area){
|
||
rect_box = GetMaxRect(r);
|
||
}else{
|
||
rect_box = GetMaxRect2(r);
|
||
}
|
||
|
||
if(rect_box.IsDefined()){
|
||
double x = fabs(rect_box.MaxD(0) - rect_box.MinD(0));
|
||
double y = fabs(rect_box.MaxD(1) - rect_box.MinD(1));
|
||
double min = MIN(x,y);
|
||
double max = MAX(x,y);
|
||
if(rect_box.Area() > mini_rect_area &&
|
||
rect_box.Area() < maxi_rect_area && (max / min < 5.0)){
|
||
double mini[2], maxi[2];
|
||
mini[0] = rect_box.MinD(0) - tran_x;
|
||
mini[1] = rect_box.MinD(1) - tran_y;
|
||
maxi[0] = rect_box.MaxD(0) - tran_x;
|
||
maxi[1] = rect_box.MaxD(1) - tran_y;
|
||
Rectangle<2>* res_box = new Rectangle<2>(true, mini, maxi);
|
||
|
||
if(RegContainRect(poly, rect_box))
|
||
rect_box_list.push_back(*res_box);
|
||
|
||
delete res_box;
|
||
}
|
||
}
|
||
delete r;
|
||
}
|
||
}
|
||
|
||
}
|
||
delete ct;
|
||
poly_tuple->DeleteIfAllowed();
|
||
|
||
//////////the distance between two buildings should be large////////
|
||
for(unsigned int k1 = 0;k1 < rect_box_list.size();k1++){
|
||
Rectangle<2> bbox1 = rect_box_list[k1];
|
||
unsigned int k2 = k1;
|
||
for(k2 += 1;k2 < rect_box_list.size();k2++){
|
||
Rectangle<2> bbox2 = rect_box_list[k2];
|
||
if(bbox1.Distance(bbox2) < mini_dist_build) break;
|
||
}
|
||
if(k2 == rect_box_list.size()){
|
||
|
||
/* reg_id_list.push_back(reg_id);
|
||
rect_list.push_back(bbox1);
|
||
poly_id_list.push_back(poly_id);
|
||
reg_id++;*/
|
||
|
||
// if(bbox1.Area() < 4000.0 || bbox1.Area() > 8500.0){
|
||
if(bbox1.Area() < 4000.0){/////we do not have the airport now. 2011.8
|
||
reg_id_list.push_back(reg_id);
|
||
rect_list.push_back(bbox1);
|
||
poly_id_list.push_back(poly_id);
|
||
reg_id++;
|
||
}else{//set this value considering airport
|
||
/////////decompose the large rectangle to have more ////////////
|
||
/////////keep large region for airport ///////////////////
|
||
float w = bbox1.MaxD(0) - bbox1.MinD(0);
|
||
float h = bbox1.MaxD(1) - bbox1.MinD(1);
|
||
int row = w/length_limit;
|
||
int col = h/length_limit;
|
||
|
||
double x_min = bbox1.MinD(0);
|
||
// double x_max = bbox1.MaxD(0);
|
||
double y_min = bbox1.MinD(1);
|
||
// double y_max = bbox1.MaxD(1);
|
||
///////35 x 30 ///////////////////
|
||
double x = 35.0;
|
||
double y = 30.0;
|
||
// cout<<"row "<<row<<" col "<<col<<endl;
|
||
if(row == 0 || col == 0){
|
||
reg_id_list.push_back(reg_id);
|
||
rect_list.push_back(bbox1);
|
||
poly_id_list.push_back(poly_id);
|
||
reg_id++;
|
||
}else{
|
||
|
||
for(int index1 = 0;index1 < row;index1++){
|
||
double x1 = x_min + index1*length_limit;
|
||
double x2 = x1 + x;
|
||
for(int index2 = 0;index2 < col;index2++){
|
||
double y1 = y_min + index2*length_limit;
|
||
double y2 = y1 + y;
|
||
|
||
double min[2], max[2];
|
||
min[0] = x1; max[0] = x2;
|
||
min[1] = y1; max[1] = y2;
|
||
Rectangle<2> temp_box(true, min, max);
|
||
|
||
if(bbox1.Contains(temp_box)){
|
||
reg_id_list.push_back(reg_id);
|
||
rect_list.push_back(temp_box);
|
||
poly_id_list.push_back(poly_id);
|
||
reg_id++;
|
||
}
|
||
}
|
||
}/////end for
|
||
}///end else
|
||
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
/*
|
||
check whether all coordinates are positive. because for the function
|
||
GetMaxRect(), all coordinates should be positive
|
||
|
||
*/
|
||
bool MaxRect::ValidRegion(Region* r)
|
||
{
|
||
for(int i = 0;i < r->Size();i++){
|
||
HalfSegment hs;
|
||
r->Get(i, hs);
|
||
if(!hs.IsLeftDomPoint())continue;
|
||
Point lp = hs.GetLeftPoint();
|
||
Point rp = hs.GetRightPoint();
|
||
if(lp.GetX() < 0.0)return false;
|
||
if(lp.GetY() < 0.0)return false;
|
||
if(rp.GetX() < 0.0)return false;
|
||
if(rp.GetY() < 0.0)return false;
|
||
}
|
||
return true;
|
||
}
|
||
|
||
/*
|
||
for each start point,
|
||
choose the one that is the closest to the polygon boundary
|
||
record which side it belongs to
|
||
|
||
*/
|
||
void MaxRect::SetStartAndEndPoint(Region* r,
|
||
vector<Point>& build_sp_list,
|
||
vector<Point>& build_ep_list)
|
||
{
|
||
SpacePartition* s_p = new SpacePartition();
|
||
|
||
for(unsigned int i = 0;i < build_sp_list.size();i++){
|
||
vector<MyPoint> point_dist_list;
|
||
for(int j = 0;j < r->Size();j++){
|
||
HalfSegment hs;
|
||
r->Get(j, hs);
|
||
if(!hs.IsLeftDomPoint())continue;
|
||
|
||
double d;
|
||
Point cp(true, 0, 0);
|
||
|
||
d = s_p->GetClosestPoint(hs, build_sp_list[i], cp);
|
||
MyPoint mpe(cp, d);
|
||
point_dist_list.push_back(mpe);
|
||
}
|
||
sort(point_dist_list.begin(), point_dist_list.end());
|
||
|
||
// for(unsigned int k = 0;k < point_dist_list.size();k++)
|
||
// point_dist_list[k].Print();
|
||
|
||
build_ep_list.push_back(point_dist_list[0].loc);
|
||
}
|
||
delete s_p;
|
||
|
||
}
|
||
|
||
/////////////////////////////////////////////////////////////////////////////
|
||
////////////////////////////////////////////////////////////////////////////
|
||
|
||
/*
|
||
load the pointers to all types of buildings
|
||
|
||
*/
|
||
void MaxRect::OpenBuilding()
|
||
{
|
||
|
||
for(unsigned int i = 0;i < ARR_SIZE(str_build_type);i++){
|
||
if(i == 0){
|
||
build_pointer.push_back(NULL);
|
||
continue;
|
||
}
|
||
bool found = false;
|
||
ListExpr xObjectList = SecondoSystem::GetCatalog()->ListObjects();
|
||
xObjectList = nl->Rest(xObjectList);
|
||
while(!nl->IsEmpty(xObjectList)){
|
||
// Next element in list
|
||
ListExpr xCurrent = nl->First(xObjectList);
|
||
xObjectList = nl->Rest(xObjectList);
|
||
// Type of object is at fourth position in list
|
||
ListExpr xObjectType = nl->First(nl->Fourth(xCurrent));
|
||
if(nl->IsAtom(xObjectType) &&
|
||
nl->SymbolValue(xObjectType) == "building"){
|
||
|
||
// Get name of the graph
|
||
ListExpr xObjectName = nl->Second(xCurrent);
|
||
string strObjectName = nl->SymbolValue(xObjectName);
|
||
|
||
// Load object to find out the id
|
||
Word xValue;
|
||
bool bDefined;
|
||
bool bOk = SecondoSystem::GetCatalog()->GetObject(strObjectName,
|
||
xValue,
|
||
bDefined);
|
||
if(!bDefined || !bOk){
|
||
// Undefined
|
||
continue;
|
||
}
|
||
Building* building = (Building*)xValue.addr;
|
||
|
||
if(building->GetType() == i){
|
||
build_pointer.push_back(building);
|
||
found = true;
|
||
break;
|
||
}else{
|
||
SecondoSystem::GetCatalog()->CloseObject(nl->SymbolAtom( "building" ),
|
||
xValue);
|
||
}
|
||
}
|
||
}
|
||
if(found == false)
|
||
build_pointer.push_back(NULL);
|
||
|
||
}
|
||
}
|
||
|
||
void MaxRect::CloseBuilding()
|
||
{
|
||
for(unsigned int i = 0;i < ARR_SIZE(str_build_type);i++){
|
||
if(build_pointer[i] != NULL){
|
||
Word xValue;
|
||
xValue.addr = build_pointer[i];
|
||
SecondoSystem::GetCatalog()->CloseObject(nl->SymbolAtom( "building" ),
|
||
xValue);
|
||
}
|
||
}
|
||
}
|
||
|
||
/*
|
||
for each building, it opens and closes the indoor graph
|
||
|
||
*/
|
||
void MaxRect::OpenIndoorGraph()
|
||
{
|
||
for(unsigned int i = 0;i < build_pointer.size();i++){
|
||
if(build_pointer[i] == NULL){
|
||
igraph_pointer.push_back(NULL);
|
||
continue;
|
||
}
|
||
igraph_pointer.push_back(build_pointer[i]->OpenIndoorGraph());
|
||
}
|
||
}
|
||
|
||
/*
|
||
read indoor paths of each building from disk files
|
||
|
||
*/
|
||
void MaxRect::LoadIndoorPaths(vector< map<int, Line3D> >& paths,
|
||
vector< map<int, Line3D> >& rooms)
|
||
{
|
||
for(unsigned int i = 0;i < build_pointer.size();i++){
|
||
if(build_pointer[i] != NULL){
|
||
// cout<<i<<" "<<str_build_type[build_pointer[i]->GetType()]<<endl;
|
||
|
||
map<int, Line3D> path_list;
|
||
map<int, Line3D> room_id_list;
|
||
|
||
build_pointer[i]->LoadPaths(path_list, room_id_list);
|
||
|
||
paths.push_back(path_list);
|
||
rooms.push_back(room_id_list);//store groom id for each point3d
|
||
|
||
}else{
|
||
map<int, Line3D> path_list;
|
||
map<int, Line3D> room_id_list;
|
||
|
||
paths.push_back(path_list);
|
||
rooms.push_back(room_id_list);//store groom id for each point3d
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
void MaxRect::CloseIndoorGraph()
|
||
{
|
||
for(unsigned int i = 0;i < igraph_pointer.size();i++){
|
||
if(igraph_pointer[i] == NULL){
|
||
continue;
|
||
}
|
||
build_pointer[i]->CloseIndoorGraph(igraph_pointer[i]);
|
||
}
|
||
}
|
||
|
||
/*
|
||
|
||
build the path between the entrance of the building and pavement area
|
||
which point to select on the polygon boundary:
|
||
which point to set as the entrance of the building on the rectangle
|
||
create the path from building entrance to pavement area
|
||
|
||
*/
|
||
void MaxRect::PathToBuilding(Space* gl_sp)
|
||
{
|
||
// cout<<"build the connection between the entrance of building and pavement"
|
||
// <<endl;
|
||
|
||
Pavement* pave = gl_sp->LoadPavement(IF_REGION);
|
||
DualGraph* dg = pave->GetDualGraph();
|
||
|
||
////////////////load all buildings and indoor graphs////////////////////////
|
||
OpenBuilding();
|
||
OpenIndoorGraph();
|
||
|
||
// for(unsigned int i = 0;i < build_pointer.size();i++){
|
||
// if(build_pointer[i] != NULL)cout<<GetBuildingStr(i)<<endl;
|
||
// if(igraph_pointer[i] != NULL)cout<<GetBuildingStr(i)<<endl;
|
||
// }
|
||
|
||
////////////////////////////////////////////////////////////////////
|
||
|
||
/////for each original polygon, it collects all rectangles inside /////
|
||
//////select point from the polygon boundary //////
|
||
/////for each rectangle, it also selects a point on its boundary///////
|
||
for(int i = 1;i <= rel2->GetNoTuples();i++){
|
||
Tuple* poly_tuple = rel2->GetTuple(i, false);
|
||
int poly_id = ((CcInt*)poly_tuple->GetAttribute(REGID))->GetIntval();
|
||
|
||
CcInt* search_id = new CcInt(true, poly_id);
|
||
BTreeIterator* btree_iter = btree->ExactMatch(search_id);
|
||
vector<int> rect_tid_list;
|
||
while(btree_iter->Next()){
|
||
Tuple* tuple = rel1->GetTuple(btree_iter->GetId(), false);
|
||
int poly_id2 = ((CcInt*)tuple->GetAttribute(POLY_ID_EXT))->GetIntval();
|
||
assert(poly_id == poly_id2);
|
||
rect_tid_list.push_back(btree_iter->GetId());
|
||
tuple->DeleteIfAllowed();
|
||
}
|
||
delete btree_iter;
|
||
delete search_id;
|
||
|
||
if(rect_tid_list.size() > 0){
|
||
Region* poly = (Region*)poly_tuple->GetAttribute(COVAREA);
|
||
|
||
CreateEntranceforBuilding(poly, rect_tid_list, dg);
|
||
}
|
||
|
||
poly_tuple->DeleteIfAllowed();
|
||
|
||
}
|
||
|
||
|
||
pave->CloseDualGraph(dg);
|
||
gl_sp->ClosePavement(pave);
|
||
|
||
/////////////close all buildings and indoor graphs//////////////////////
|
||
CloseIndoorGraph();
|
||
CloseBuilding();
|
||
|
||
}
|
||
|
||
|
||
/////////////////////////////////////////////////////////////////////////////
|
||
/////////////////////////////////////////////////////////////////////////////
|
||
|
||
/*
|
||
create the path in the polygon for the building entrance where the entrances of
|
||
a building is selected from the indoor floor plan
|
||
|
||
*/
|
||
void MaxRect::CreateEntranceforBuilding(Region* r,
|
||
vector<int>& tid_list, DualGraph* dg)
|
||
{
|
||
HalfSegment hs;
|
||
r->Get(0, hs);
|
||
Point boundary_p = hs.GetLeftPoint();
|
||
vector<Rectangle<2> > hole_list;
|
||
|
||
for(unsigned int i = 0;i < tid_list.size();i++){
|
||
Tuple* rect_tuple = rel1->GetTuple(tid_list[i], false);
|
||
Rectangle<2>* rect = (Rectangle<2>*)rect_tuple->GetAttribute(GEODATA_EXT);
|
||
hole_list.push_back(*rect);
|
||
rect_tuple->DeleteIfAllowed();
|
||
}
|
||
|
||
////////////////create a region using these rectangels as holes/////////////
|
||
for(unsigned int i = 0;i < tid_list.size();i++){
|
||
Tuple* rect_tuple = rel1->GetTuple(tid_list[i], false);
|
||
|
||
int reg_id = ((CcInt*)rect_tuple->GetAttribute(REG_ID_EXT))->GetIntval();
|
||
Rectangle<2>* rect = (Rectangle<2>*)rect_tuple->GetAttribute(GEODATA_EXT);
|
||
int build_type =
|
||
((CcInt*)rect_tuple->GetAttribute(BUILDING_TYPE))->GetIntval();
|
||
if(build_type == 0 ||
|
||
(build_type > 1 && build_pointer[build_type] == NULL)){
|
||
rect_tuple->DeleteIfAllowed();
|
||
continue;
|
||
}
|
||
|
||
vector<Point> build_sp_list;
|
||
vector<Point> build_ep_list;
|
||
if(build_type > 1){
|
||
BuildingEntrance(build_type, rect, build_sp_list);
|
||
SetStartAndEndPoint(r, build_sp_list, build_ep_list);
|
||
}else{/////////////entrance for personal apartment
|
||
BuildingEntranceHouse(rect, build_sp_list, build_ep_list, r);
|
||
}
|
||
|
||
for(unsigned int j = 0;j < build_sp_list.size();j++){
|
||
Point sp = build_sp_list[j];
|
||
Point ep = build_ep_list[j];
|
||
|
||
reg_id_list.push_back(reg_id);
|
||
sp_list.push_back(sp);
|
||
// ep_list.push_back(ep);
|
||
// MapToPavement(dg, ep);
|
||
/////build the path from building entrance to pavement area//////
|
||
Path_BuildingPave(sp, ep, rect, r, dg);
|
||
/////////////which entrance it is//////////////////////////
|
||
sp_index_list.push_back(j + 1);
|
||
}
|
||
|
||
rect_tuple->DeleteIfAllowed();
|
||
}
|
||
|
||
}
|
||
|
||
|
||
/*
|
||
set the building entrance point according to the floor plan
|
||
|
||
*/
|
||
void MaxRect::BuildingEntrance(int build_type, Rectangle<2>* rect,
|
||
vector<Point>& build_sp_list)
|
||
{
|
||
double min[2]={0,0};
|
||
double max[2]={1,1};
|
||
Rectangle<2> build_area(true, min, max);
|
||
vector<Point> door_list;
|
||
///////////////get the floor plan for 2D areas and entrance point//////////
|
||
Get2DAreadAndDoor(build_type, build_area, door_list);
|
||
|
||
double length = build_area.MaxD(0) - build_area.MinD(0);
|
||
double width = build_area.MaxD(1) - build_area.MinD(1);
|
||
|
||
double length_new = rect->MaxD(0) - rect->MinD(0);
|
||
double width_new = rect->MaxD(1) - rect->MinD(1);
|
||
|
||
const double delta = 0.001;
|
||
for(unsigned int i = 0;i < door_list.size();i++){
|
||
double scale_x = (door_list[i].GetX() - build_area.MinD(0))/length;
|
||
double scale_y = (door_list[i].GetY() - build_area.MinD(1))/width;
|
||
double new_x;
|
||
if(fabs(scale_x) < delta){
|
||
new_x = rect->MinD(0);
|
||
}else{
|
||
new_x = rect->MinD(0) + scale_x*length_new;
|
||
}
|
||
|
||
double new_y;
|
||
if(fabs(scale_y) < delta){
|
||
new_y = rect->MinD(1);
|
||
}else{
|
||
new_y = rect->MinD(1) + scale_y* width_new;
|
||
}
|
||
|
||
Point new_door(true, new_x, new_y);
|
||
build_sp_list.push_back(new_door);
|
||
}
|
||
|
||
}
|
||
|
||
/*
|
||
set the building entrance point for personal apartments
|
||
|
||
*/
|
||
void MaxRect::BuildingEntranceHouse(Rectangle<2>* rect,
|
||
vector<Point>& build_sp_list,
|
||
vector<Point>& build_ep_list, Region* r)
|
||
{
|
||
double min_x = rect->MinD(0);
|
||
double max_x = rect->MaxD(0);
|
||
|
||
double min_y = rect->MinD(1);
|
||
double max_y = rect->MaxD(1);
|
||
|
||
Point p1(true, (min_x + max_x)/2, min_y);
|
||
Point p2(true, (min_x + max_x)/2, max_y);
|
||
Point p3(true, min_x, (min_y + max_y)/2);
|
||
Point p4(true, max_x, (min_y + max_y)/2);
|
||
|
||
build_sp_list.push_back(p1);
|
||
build_sp_list.push_back(p2);
|
||
build_sp_list.push_back(p3);
|
||
build_sp_list.push_back(p4);
|
||
|
||
|
||
SpacePartition* s_p = new SpacePartition();
|
||
vector<MyPoint_Ext> point_dist_list;
|
||
|
||
for(unsigned int i = 0;i < build_sp_list.size();i++){
|
||
for(int j = 0;j < r->Size();j++){
|
||
HalfSegment hs;
|
||
r->Get(j, hs);
|
||
if(!hs.IsLeftDomPoint())continue;
|
||
|
||
double d;
|
||
Point cp(true, 0, 0);
|
||
|
||
d = s_p->GetClosestPoint(hs, build_sp_list[i], cp);
|
||
MyPoint_Ext mpe(build_sp_list[i], cp, d, 0.0);
|
||
point_dist_list.push_back(mpe);
|
||
}
|
||
}
|
||
delete s_p;
|
||
sort(point_dist_list.begin(), point_dist_list.end());
|
||
|
||
build_sp_list.clear();
|
||
build_ep_list.clear();
|
||
|
||
build_sp_list.push_back(point_dist_list[0].loc);
|
||
build_ep_list.push_back(point_dist_list[0].loc2);
|
||
|
||
}
|
||
|
||
/*
|
||
get the 2d area for a building and the location of entrance door from the
|
||
floor plan(indoor graph)
|
||
|
||
*/
|
||
void MaxRect::Get2DAreadAndDoor(int build_type, Rectangle<2>& build_area,
|
||
vector<Point>& door_list)
|
||
{
|
||
Building* build = build_pointer[build_type];
|
||
IndoorGraph* ig = igraph_pointer[build_type];
|
||
if(build == NULL || ig == NULL){
|
||
cout<<"such a building or indoor graph are not loaded"<<endl;
|
||
return;
|
||
}
|
||
R_Tree<3, TupleId>* rtree = build->GetRTree();
|
||
Rectangle<3> bbox = rtree->BoundingBox();
|
||
|
||
double min[2], max[2];
|
||
min[0] = bbox.MinD(0);
|
||
min[1] = bbox.MinD(1);
|
||
max[0] = bbox.MaxD(0);
|
||
max[1] = bbox.MaxD(1);
|
||
build_area.Set(true, min, max);
|
||
|
||
// cout<<"2D building area "<<build_area;
|
||
// cout<<"building graph: "<<GetBuildingStr(ig->GetGraphType())<<endl;
|
||
|
||
ig->GetEntranceDoor(door_list);
|
||
|
||
// cout<<"number of entrance "<<door_list.size()<<endl;
|
||
|
||
// for(unsigned int i = 0;i < door_list.size();i++)
|
||
// cout<<door_list[i]<<endl;
|
||
|
||
}
|
||
|
||
|
||
|
||
/*
|
||
find the closest point in pavement for the input location
|
||
|
||
*/
|
||
void MaxRect::MapToPavement(DualGraph* dg, Point loc)
|
||
{
|
||
SmiRecordId root_id = dg->rtree_node->RootRecordId();
|
||
vector<int> tri_oid_list;
|
||
const double dist = 5.0;
|
||
dg->DFTraverse3(dg->rtree_node, root_id, loc, tri_oid_list, dist);
|
||
|
||
if(tri_oid_list.size() == 0){
|
||
cout<<loc<<endl;
|
||
cout<<"!!! should not happen: no mapping point"<<endl;
|
||
}
|
||
|
||
|
||
double d = dist + dist;
|
||
unsigned int index = 0;
|
||
for(unsigned int i = 0;i < tri_oid_list.size();i++){
|
||
Tuple* tuple = dg->node_rel_sort->GetTuple(tri_oid_list[i], false);
|
||
Region* reg = (Region*)tuple->GetAttribute(DualGraph::PAVEMENT);
|
||
// int oid = ((CcInt*)tuple->GetAttribute(DualGraph::OID))->GetIntval();
|
||
double d2 = reg->Distance(loc);
|
||
// cout<<"oid "<<oid<<" dist "<<d2<<endl;
|
||
if(d2 < d){
|
||
d = d2;
|
||
index = i;
|
||
}
|
||
tuple->DeleteIfAllowed();
|
||
}
|
||
|
||
Tuple* tuple = dg->node_rel_sort->GetTuple(tri_oid_list[index], false);
|
||
Region* reg = (Region*)tuple->GetAttribute(DualGraph::PAVEMENT);
|
||
|
||
vector<MyPoint> point_dist_list;
|
||
SpacePartition* s_p = new SpacePartition();
|
||
for(int i = 0;i < reg->Size();i++){
|
||
HalfSegment hs;
|
||
reg->Get(i, hs);
|
||
if(!hs.IsLeftDomPoint())continue;
|
||
|
||
double d1;
|
||
Point cp(true, 0, 0);
|
||
d1 = s_p->GetClosestPoint(hs, loc, cp);
|
||
MyPoint mpe(cp, d1);
|
||
point_dist_list.push_back(mpe);
|
||
|
||
}
|
||
delete s_p;
|
||
|
||
sort(point_dist_list.begin(), point_dist_list.end());
|
||
Point map_loc = point_dist_list[0].loc;
|
||
ep_list2.push_back(map_loc);
|
||
int tri_oid = ((CcInt*)tuple->GetAttribute(DualGraph::OID))->GetIntval();
|
||
// cout<<"tri_oid "<<tri_oid<<endl;
|
||
|
||
Rectangle<2> bbox = reg->BoundingBox();
|
||
tuple->DeleteIfAllowed();
|
||
|
||
// if(map_loc.Distance(loc) > 1.0) cout<<map_loc.Distance(loc)<<endl;
|
||
|
||
////////////////generic location////////////////////////////////
|
||
///////relative position inside the triangle///////////////////
|
||
//////////////////////////////////////////////////////////////////
|
||
Loc temp_loc(map_loc.GetX() - bbox.MinD(0), map_loc.GetY() - bbox.MinD(1));
|
||
GenLoc gloc(tri_oid, temp_loc);
|
||
|
||
genloc_list.push_back(gloc);
|
||
}
|
||
|
||
/*
|
||
create the path from building entrance to pavement area
|
||
the path should not accorss the building rectangle
|
||
|
||
*/
|
||
void MaxRect::Path_BuildingPave(Point sp, Point ep, Rectangle<2>* rect,
|
||
Region* r, DualGraph* dg)
|
||
{
|
||
//////////////////////////////////////////////////////////////////////////
|
||
//////////get the rectangle boundary line excluding the segment//////////
|
||
////////////containing the start point///////////////////////////////////
|
||
/////////////////////////////////////////////////////////////////////////
|
||
Region* temp_reg = new Region(*rect);
|
||
Line* boundary_temp = new Line(0);
|
||
temp_reg->Boundary(boundary_temp);
|
||
|
||
Line* boundary = new Line(0);
|
||
boundary->StartBulkLoad();
|
||
int edgeno = 0;
|
||
for(int i = 0;i < boundary_temp->Size();i++){
|
||
HalfSegment hs;
|
||
boundary_temp->Get(i, hs);
|
||
if(!hs.IsLeftDomPoint() || hs.Contains(sp)) continue;
|
||
HalfSegment new_hs(true, hs.GetLeftPoint(), hs.GetRightPoint());
|
||
new_hs.attr.edgeno = edgeno++;
|
||
*boundary += new_hs;
|
||
// new_hs.SetLeftDomPoint(!hs.IsLeftDomPoint());
|
||
new_hs.SetLeftDomPoint(!new_hs.IsLeftDomPoint());
|
||
*boundary += new_hs;
|
||
}
|
||
boundary->EndBulkLoad();
|
||
|
||
//////////////////////////////////////////////////////////////
|
||
//////////////direction connection between sp and ep/////////
|
||
/////////////////////////////////////////////////////////////
|
||
Line* path = new Line(0);
|
||
if(AlmostEqual(sp, ep)){
|
||
path_list.push_back(*path);
|
||
|
||
ep_list.push_back(ep);
|
||
MapToPavement(dg, ep);
|
||
}else{
|
||
path->StartBulkLoad();
|
||
HalfSegment hs(true, sp, ep);
|
||
hs.attr.edgeno = 0;
|
||
*path += hs;
|
||
hs.SetLeftDomPoint(!hs.IsLeftDomPoint());
|
||
*path += hs;
|
||
path->EndBulkLoad();
|
||
assert(path->Length() > 0.0);
|
||
Points* ps = new Points(0);
|
||
path->Crossings(*boundary, *ps);
|
||
|
||
// cout<<ps->Size()<<endl;
|
||
|
||
if(ps->Size() == 0){
|
||
path_list.push_back(*path);
|
||
ep_list.push_back(ep);
|
||
MapToPavement(dg, ep);
|
||
}
|
||
else if(ps->Size() == 1){////////a new end point
|
||
//////////////////////////////////////////////////////////////////
|
||
////////////select one of the closest vertex to sp////////////////
|
||
/////////plus the path from sp to the closet point on pavement///
|
||
////////////////////////////////////////////////////////////////
|
||
|
||
Point p1(true, rect->MinD(0), rect->MinD(1));
|
||
Point p2(true, rect->MaxD(0), rect->MinD(1));
|
||
Point p3(true, rect->MaxD(0), rect->MaxD(1));
|
||
Point p4(true, rect->MinD(0), rect->MaxD(1));
|
||
vector<Point> p_list;
|
||
p_list.push_back(p1);
|
||
p_list.push_back(p2);
|
||
p_list.push_back(p3);
|
||
p_list.push_back(p4);
|
||
|
||
vector<MyPoint_Ext> mp_list;
|
||
SpacePartition* s_p = new SpacePartition();
|
||
for(unsigned int i = 0;i < p_list.size();i++){
|
||
|
||
for(int j = 0;j < r->Size();j++){
|
||
HalfSegment temp_hs;
|
||
r->Get(j, temp_hs);
|
||
if(!temp_hs.IsLeftDomPoint())continue;
|
||
|
||
double d;
|
||
Point cp(true, 0, 0);
|
||
d = s_p->GetClosestPoint(temp_hs, p_list[i], cp);
|
||
|
||
MyPoint_Ext mpe(p_list[i], cp, d, 0.0);
|
||
mp_list.push_back(mpe);
|
||
}
|
||
}
|
||
delete s_p;
|
||
sort(mp_list.begin(), mp_list.end());
|
||
Point cp_border = mp_list[0].loc;
|
||
Point new_ep = mp_list[0].loc2;
|
||
|
||
//////////////////////////////////////////////////////////////////
|
||
///////////////new path has two parts: sp to cpborder,///////////
|
||
//////////////// cpborder to ep /////////////////////////////////
|
||
/////////////////////////////////////////////////////////////////
|
||
Line* path2 = new Line(0);
|
||
path2->StartBulkLoad();
|
||
int edgeno = 0;
|
||
|
||
if(!AlmostEqual(cp_border, new_ep)){
|
||
HalfSegment hs(true, cp_border, new_ep);
|
||
hs.attr.edgeno = edgeno++;
|
||
*path2 += hs;
|
||
hs.SetLeftDomPoint(!hs.IsLeftDomPoint());
|
||
*path2 += hs;
|
||
}
|
||
|
||
PathOnBorder(boundary_temp, sp, cp_border, path2, edgeno);
|
||
|
||
path2->EndBulkLoad();
|
||
path_list.push_back(*path2);
|
||
path2->DeleteIfAllowed();
|
||
|
||
ep_list.push_back(new_ep);
|
||
MapToPavement(dg, new_ep);
|
||
}else assert(false);
|
||
|
||
ps->DeleteIfAllowed();
|
||
}
|
||
|
||
///////////////////////////////////////////////////////////////
|
||
boundary_temp->DeleteIfAllowed();
|
||
temp_reg->DeleteIfAllowed();
|
||
path->DeleteIfAllowed();
|
||
boundary->DeleteIfAllowed();
|
||
|
||
}
|
||
|
||
/*
|
||
calculate the shortest path between two points on a line.
|
||
the line is a cycle so there are two options
|
||
|
||
*/
|
||
void MaxRect::PathOnBorder(Line* boundary_temp, Point sp, Point cp_border,
|
||
Line* path2, int& edgeno)
|
||
{
|
||
SpacePartition* s_p = new SpacePartition();
|
||
//////////////////find the closest point to sp along the line///////////////
|
||
if(sp.Inside(*boundary_temp) == false){
|
||
vector<MyPoint> mp_list;
|
||
for(int j = 0;j < boundary_temp->Size();j++){
|
||
HalfSegment temp_hs;
|
||
boundary_temp->Get(j, temp_hs);
|
||
if(!temp_hs.IsLeftDomPoint())continue;
|
||
|
||
double d;
|
||
Point cp(true, 0, 0);
|
||
d = s_p->GetClosestPoint(temp_hs, sp, cp);
|
||
MyPoint mpe(cp, d);
|
||
mp_list.push_back(mpe);
|
||
}
|
||
|
||
sort(mp_list.begin(), mp_list.end());
|
||
Point sp_map = mp_list[0].loc;
|
||
|
||
HalfSegment hs(true, sp, sp_map);
|
||
hs.attr.edgeno = edgeno++;
|
||
*path2 += hs;
|
||
hs.SetLeftDomPoint(!hs.IsLeftDomPoint());
|
||
*path2 += hs;
|
||
|
||
sp = sp_map;
|
||
}
|
||
///////////////////////////////////////////////////////////////////////
|
||
////////////////connect sp and cp border along the line///////////////
|
||
///////////////as the boundary is a cycle, there are two paths///////
|
||
/////////////// select the shorter one ///////////////////////
|
||
//////////////////////////////////////////////////////////////////////
|
||
|
||
SimpleLine* sline = new SimpleLine(0);
|
||
sline->fromLine(*boundary_temp);
|
||
vector<MyHalfSegment> seq_halfseg;
|
||
s_p->ReorderLine(sline, seq_halfseg);
|
||
sline->DeleteIfAllowed();
|
||
|
||
int index1 = -1;
|
||
for(unsigned int i = 0;i < seq_halfseg.size();i++){
|
||
HalfSegment hs(true, seq_halfseg[i].from, seq_halfseg[i].to);
|
||
if(hs.Contains(sp)){
|
||
index1 = i;
|
||
break;
|
||
}
|
||
}
|
||
|
||
int index2 = -1;
|
||
for(unsigned int i = 0;i < seq_halfseg.size();i++){
|
||
HalfSegment hs(true, seq_halfseg[i].from, seq_halfseg[i].to);
|
||
if(hs.Contains(cp_border)){
|
||
index2 = i;
|
||
break;
|
||
}
|
||
}
|
||
assert(0 <= index1 && index1 < (int)seq_halfseg.size());
|
||
assert(0 <= index2 && index2 < (int)seq_halfseg.size());
|
||
|
||
// cout<<"index1 "<<index1<<" index2 "<<index2<<endl;
|
||
if(index1 == index2){
|
||
|
||
HalfSegment hs(true, sp, cp_border);
|
||
hs.attr.edgeno = edgeno++;
|
||
*path2 += hs;
|
||
hs.SetLeftDomPoint(!hs.IsLeftDomPoint());
|
||
*path2 += hs;
|
||
}else{
|
||
////////////////////////////////////////////////////////////////
|
||
///////////////////find one possible connection/////////////////
|
||
///////////////////////////////////////////////////////////////
|
||
Line* temp = new Line(0);
|
||
temp->StartBulkLoad();
|
||
int no = 0;
|
||
if(index1 < index2 ){
|
||
for(int i = index1;i <= index2;i++){
|
||
Point p1, p2;
|
||
if(i == index1){
|
||
p1 = sp;
|
||
p2 = seq_halfseg[i].to;
|
||
}else if(i == index2){
|
||
p1 = seq_halfseg[i].from;
|
||
p2 = cp_border;
|
||
}else{
|
||
p1 = seq_halfseg[i].from;
|
||
p2 = seq_halfseg[i].to;
|
||
}
|
||
if(!AlmostEqual(p1,p2)){
|
||
HalfSegment hs(true, p1, p2);
|
||
hs.attr.edgeno = no++;
|
||
*temp += hs;
|
||
hs.SetLeftDomPoint(!hs.IsLeftDomPoint());
|
||
*temp += hs;
|
||
}
|
||
}
|
||
}else{
|
||
for(int i = index2;i <= index1;i++){
|
||
Point p1, p2;
|
||
if(i == index2){
|
||
p1 = cp_border;
|
||
p2 = seq_halfseg[i].to;
|
||
}else if(i == index1){
|
||
p1 = seq_halfseg[i].from;
|
||
p2 = sp;
|
||
}else{
|
||
p1 = seq_halfseg[i].from;
|
||
p2 = seq_halfseg[i].to;
|
||
}
|
||
if(!AlmostEqual(p1,p2)){
|
||
HalfSegment hs(true, p1, p2);
|
||
hs.attr.edgeno = no++;
|
||
*temp += hs;
|
||
hs.SetLeftDomPoint(!hs.IsLeftDomPoint());
|
||
*temp += hs;
|
||
}
|
||
}
|
||
}
|
||
temp->EndBulkLoad();
|
||
///////////////////////////////////////////////////////////////////
|
||
double l1 = temp->Length();
|
||
double l2 = boundary_temp->Length() - l1;
|
||
// cout<<"l1 "<<l1<<" l2 "<<l2<<endl;
|
||
if(l1 < l2){/////////////select temp
|
||
for(int i = 0;i < temp->Size();i++){
|
||
HalfSegment hs1;
|
||
temp->Get(i, hs1);
|
||
if(!hs1.IsLeftDomPoint())continue;
|
||
HalfSegment hs2(true, hs1.GetLeftPoint(), hs1.GetRightPoint());
|
||
hs2.attr.edgeno = edgeno++;
|
||
*path2 += hs2;
|
||
hs2.SetLeftDomPoint(!hs2.IsLeftDomPoint());
|
||
*path2 += hs2;
|
||
}
|
||
}else{///////////////select the other one, use bounday minus temp
|
||
Line* res = new Line(0);
|
||
boundary_temp->Minus(*temp, *res);
|
||
for(int i = 0;i < res->Size();i++){
|
||
HalfSegment hs1;
|
||
res->Get(i, hs1);
|
||
if(!hs1.IsLeftDomPoint())continue;
|
||
HalfSegment hs2(true, hs1.GetLeftPoint(), hs1.GetRightPoint());
|
||
hs2.attr.edgeno = edgeno++;
|
||
*path2 += hs2;
|
||
hs2.SetLeftDomPoint(!hs2.IsLeftDomPoint());
|
||
*path2 += hs2;
|
||
}
|
||
res->DeleteIfAllowed();
|
||
}
|
||
temp->DeleteIfAllowed();
|
||
}
|
||
delete s_p;
|
||
}
|
||
|
||
|
||
/*
|
||
create a new region where r is outer cycle and the rectangles inside are holes
|
||
|
||
1. we have all points of all cycle so that we can call the function
|
||
buildRegion(). but very important: for each cycle,
|
||
the first and the last point should be the same.
|
||
|
||
2. we can directly use the outer region minus these rectangles which is much
|
||
simpler
|
||
|
||
*/
|
||
bool MaxRect::RegionWithHole(vector<Rectangle<2> >& hole_list, Region* reg)
|
||
{
|
||
|
||
/* for(unsigned int i = 0;i < hole_list.size();i++){
|
||
Region* temp = new Region(hole_list[i]);
|
||
// cout<<*temp<<endl;
|
||
Region* res = new Region(0);
|
||
reg->Minus(*temp, *res);
|
||
*reg = *res;
|
||
delete res;
|
||
delete temp;
|
||
}*/
|
||
|
||
|
||
//////////////////////////////////////////////////////////////////////////
|
||
Region* r = new Region(0);
|
||
|
||
for(unsigned int i = 0;i < hole_list.size();i++){
|
||
Region* temp = new Region(hole_list[i]);
|
||
Region* res = new Region(0);
|
||
temp->Union(*r, *res);
|
||
*r = *res;
|
||
res->DeleteIfAllowed();
|
||
temp->DeleteIfAllowed();
|
||
}
|
||
|
||
Region* res = new Region(0);
|
||
reg->Minus(*r, *res);
|
||
*reg = *res;
|
||
|
||
res->DeleteIfAllowed();
|
||
r->DeleteIfAllowed();
|
||
|
||
return true;
|
||
}
|
||
|
||
/*
|
||
for each rectangle, it sets which kind of building it is,
|
||
e.g., office or cinema
|
||
1 airport, 1-2 trainstations, 8 cinemas, 32 hotels, 48 shopping malls,
|
||
20 hospitals, 32 schooles, 4 libraries, 16 universities,
|
||
|
||
200 office 24,
|
||
|
||
houses and apartments: 1000
|
||
|
||
|
||
the left are of type none
|
||
|
||
*/
|
||
void MaxRect::SetBuildingType(R_Tree<2,TupleId>* rtree, Space* gl_sp)
|
||
{
|
||
Rectangle<2> bbox = rtree->BoundingBox();
|
||
Point center(true, (bbox.MinD(0) + bbox.MaxD(0))/2,
|
||
(bbox.MinD(1) + bbox.MaxD(1))/2);
|
||
|
||
vector<Build_Rect> build_rect_list;
|
||
|
||
for(int i = 1;i <= rel1->GetNoTuples();i++){
|
||
Tuple* tuple = rel1->GetTuple(i, false);
|
||
int reg_id = ((CcInt*)tuple->GetAttribute(REG_ID))->GetIntval();
|
||
Rectangle<2>* rect = (Rectangle<2>*)tuple->GetAttribute(GEODATA);
|
||
int poly_id = ((CcInt*)tuple->GetAttribute(POLY_ID))->GetIntval();
|
||
int reg_type = ((CcInt*)tuple->GetAttribute(REG_TYPE))->GetIntval();
|
||
|
||
Build_Rect br(reg_id, *rect, poly_id, reg_type);
|
||
Point p(true, (rect->MinD(0) + rect->MaxD(0))/2,
|
||
(rect->MinD(1) + rect->MaxD(1))/2);
|
||
if(p.GetX() > center.GetX()){
|
||
if(p.GetY() > center.GetY()) br.quadrant = 1;
|
||
else br.quadrant = 4;
|
||
}else{
|
||
if(p.GetY() > center.GetY()) br.quadrant = 2;
|
||
else br.quadrant = 3;
|
||
}
|
||
|
||
build_rect_list.push_back(br);
|
||
tuple->DeleteIfAllowed();
|
||
}
|
||
|
||
// cout<<build_rect_list.size()<<endl;
|
||
|
||
////////////////////////////////////////////////////////////////////
|
||
/////////////////set up building type//////////////////////////////
|
||
///////////////////////////////////////////////////////////////////
|
||
SetAirPort(build_rect_list, rtree);//1 airport
|
||
SetTrainStation(build_rect_list); // a trainstation
|
||
|
||
/////////////////these buildings can be close to each other//////////////
|
||
SetCinema(build_rect_list, 8, bbox);//maximum 8 cinemas
|
||
SetHotel(build_rect_list, 40, bbox);//maximum 40 hotels
|
||
SetShopMall(build_rect_list, 80, bbox);//maximum 80 shopping malls
|
||
|
||
SetOffice24(build_rect_list, 600);//maximum 500 office24
|
||
SetOffice38(build_rect_list, 600);//maximum 500 office38
|
||
|
||
////////////can not be close to the above three/////////////////////////
|
||
/////////////but may be close to school or houses, apartments//////////
|
||
// SetHospital(build_rect_list, 20);//maximum 20 hospitals
|
||
SetHospital(build_rect_list, 50);//maximum 50 hospitals
|
||
|
||
///////////////////////////////////////////////////////////////////////
|
||
//////////////////school library//////////////////////////////////
|
||
//////////////////////////////////////////////////////////////////
|
||
SetLibrary(build_rect_list, 4);//maximum 4 libraries
|
||
// SetSchool(build_rect_list, 32);//maximum 32 schools, no school yet
|
||
SetUniversity(build_rect_list, 20);//maximum 20 universities
|
||
|
||
/////////////////////////////////////////////////////////////////////
|
||
// SetHouse(build_rect_list, 3000);//maximum 3000 houses and apartments
|
||
SetHouse(build_rect_list, 5000);//maximum 5000 houses and apartments
|
||
|
||
///////////////////////////////////////////////////////////////////
|
||
int cur_max_ref_id = gl_sp->MaxRefId() + 1;
|
||
///////////////////////////////////////////////////////////////
|
||
///////////////max int 21474 83647//////////////////////////////
|
||
/////////////max int64_t 9223372036854775807///////////////////
|
||
////////////////////////////////////////////////////////////////
|
||
|
||
// cout<<"max int "<<numeric_limits<int>::max()<<endl;
|
||
// cout<<"max int64_t "<<numeric_limits<int64_t>::max()<<endl;
|
||
|
||
if(cur_max_ref_id == 0){
|
||
cout<<"!!! the space is empty !!!"<<endl;
|
||
return;
|
||
}
|
||
|
||
///////////////////////////////////////////////////////////////////
|
||
////////////////to check the minimum and maximum number///////////
|
||
///////////////have the same number of digits////////////////////
|
||
/////////////for example, min:12345 max: 34567///////////////////
|
||
////////////but min:12345 max 234567 are wrong!!!////////////////
|
||
//////////////////////////////////////////////////////////////////
|
||
int min_id = cur_max_ref_id;
|
||
int build_no = 0;
|
||
for(unsigned int i = 0;i < build_rect_list.size();i++){
|
||
if(build_rect_list[i].build_type > 0){
|
||
build_no++;
|
||
}
|
||
}
|
||
int max_id = min_id + build_no;
|
||
char buf1[64], buf2[64];
|
||
sprintf(buf1, "%d", min_id);
|
||
sprintf(buf2, "%d", max_id);
|
||
// cout<<"min_id "<<min_id<<" max_id "<<max_id<<endl;
|
||
if(strlen(buf1) < strlen(buf2)){////////perhaps + 1000000
|
||
cout<<"we need to reset the starting number for building id"<<endl;
|
||
// cur_max_ref_id += pow(10, strlen(buf2) + 1);
|
||
double base = 10;
|
||
double exponent = strlen(buf2) + 1;
|
||
cur_max_ref_id += pow(base, exponent);
|
||
assert(cur_max_ref_id + build_no < numeric_limits<int>::max());
|
||
assert(false);///////// can be deleted the above code should be correct
|
||
}
|
||
//////////////////////////////////////////////////////////////////
|
||
|
||
for(unsigned int i = 0;i < build_rect_list.size();i++){
|
||
if(build_rect_list[i].build_type > 0){
|
||
reg_id_list.push_back(build_rect_list[i].reg_id);
|
||
rect_list.push_back(build_rect_list[i].rect);
|
||
poly_id_list.push_back(build_rect_list[i].poly_id);
|
||
reg_type_list.push_back(build_rect_list[i].reg_type);
|
||
build_type_list.push_back(build_rect_list[i].build_type);
|
||
build_type2_list.push_back(GetBuildingStr(build_rect_list[i].build_type));
|
||
build_id_list.push_back(cur_max_ref_id);
|
||
cur_max_ref_id++;
|
||
}
|
||
}
|
||
|
||
if(cur_max_ref_id > numeric_limits<int>::max() - 1){
|
||
cout<<"!!!! building id number overflow !!!"<<endl;
|
||
assert(false);
|
||
}
|
||
|
||
}
|
||
|
||
/*
|
||
set the airport
|
||
|
||
*/
|
||
#define AIRPORT_AREA 9000.0
|
||
bool Build_Rect_COM1(const Build_Rect& br1, const Build_Rect& br2)
|
||
{
|
||
return br1.reg_type < br2.reg_type;
|
||
}
|
||
/*
|
||
an airport is an place far away from the city center and big enough, and
|
||
there are no other buildings nearby.
|
||
|
||
*/
|
||
void MaxRect::SetAirPort(vector<Build_Rect>& list, R_Tree<2,TupleId>* rtree)
|
||
{
|
||
sort(list.begin(), list.end(), Build_Rect_COM1);
|
||
/* for(unsigned int i = 0;i < list.size();i++)
|
||
list[i].Print();*/
|
||
for(int i = list.size() - 1;i >= 0;i--){
|
||
if(list[i].rect.Area() > AIRPORT_AREA && list[i].reg_type == 3 &&
|
||
list[i].init == false && NoNeighbor(list[i], rtree)){
|
||
// cout<<"find an airport site"<<endl;
|
||
list[i].build_type = BUILD_AIRPORT;
|
||
list[i].init = true;
|
||
return;
|
||
}
|
||
}
|
||
|
||
cout<<"no avaialbe place for an airport"<<endl;
|
||
}
|
||
|
||
|
||
/*
|
||
there are no rectangles whose distance to the input rect is smalelr than a
|
||
distance threshold
|
||
|
||
*/
|
||
bool MaxRect::NoNeighbor(Build_Rect& br, R_Tree<2,TupleId>* rtree)
|
||
{
|
||
|
||
vector<int> tid_list;
|
||
DFTraverse1(rtree, rtree->RootRecordId(), br.rect, tid_list);
|
||
// cout<<"reg id "<<br.reg_id<<" neighbor size "<<tid_list.size()<<endl;
|
||
// for(unsigned int i = 0;i < tid_list.size();i++){
|
||
// cout<<"neighbor "<<tid_list[i]<<" ";
|
||
// }
|
||
// cout<<endl;
|
||
|
||
if(tid_list.size() == 0) return true;
|
||
else return false;
|
||
}
|
||
|
||
void MaxRect::DFTraverse1(R_Tree<2,TupleId>* rtree, SmiRecordId adr,
|
||
Rectangle<2>& rect, vector<int>& tri_oid_list)
|
||
{
|
||
const double dist = 1000.0;
|
||
R_TreeNode<2,TupleId>* node = rtree->GetMyNode(adr,false,
|
||
rtree->MinEntries(0), rtree->MaxEntries(0));
|
||
for(int j = 0;j < node->EntryCount();j++){
|
||
if(node->IsLeaf()){
|
||
R_TreeLeafEntry<2,TupleId> e =
|
||
(R_TreeLeafEntry<2,TupleId>&)(*node)[j];
|
||
Tuple* dg_tuple = rel1->GetTuple(e.info, false);
|
||
Rectangle<2>* reg =
|
||
(Rectangle<2>*)dg_tuple->GetAttribute(GEODATA);
|
||
int reg_id =
|
||
((CcInt*)dg_tuple->GetAttribute(REG_ID))->GetIntval();
|
||
double d = rect.Distance(*reg);
|
||
if(d > 0.0 && d < dist){
|
||
tri_oid_list.push_back(reg_id);
|
||
}
|
||
dg_tuple->DeleteIfAllowed();
|
||
}else{
|
||
R_TreeInternalEntry<2> e =
|
||
(R_TreeInternalEntry<2>&)(*node)[j];
|
||
if(rect.Distance(e.box) < dist){
|
||
DFTraverse1(rtree, e.pointer, rect, tri_oid_list);
|
||
}
|
||
}
|
||
}
|
||
delete node;
|
||
}
|
||
|
||
|
||
/*
|
||
set the train station
|
||
|
||
*/
|
||
#define TRAINSTATION_AREA_MIN 800.0
|
||
#define TRAINSTATION_AREA_MAX 2000.0
|
||
|
||
void MaxRect::SetTrainStation(vector<Build_Rect>& list)
|
||
{
|
||
sort(list.begin(), list.end(), Build_Rect_COM1);
|
||
/* for(unsigned int i = 0;i < list.size();i++)
|
||
list[i].Print();*/
|
||
for(int i = list.size() - 1;i >= 0;i--){
|
||
if(list[i].rect.Area() > TRAINSTATION_AREA_MIN &&
|
||
list[i].rect.Area() < TRAINSTATION_AREA_MAX &&
|
||
list[i].reg_type == 1 &&
|
||
list[i].init == false){
|
||
// cout<<"find a train station site"<<endl;
|
||
list[i].build_type = BUILD_TRAINSTATION;
|
||
list[i].init = true;
|
||
return;
|
||
}
|
||
}
|
||
|
||
cout<<"no avaialbe place for a train station"<<endl;
|
||
}
|
||
|
||
|
||
/*
|
||
set the places for cinemas, uniformly distributed in each quadrant
|
||
|
||
*/
|
||
#define CINEMA_AREA_MIN 600.0
|
||
#define CINEMA_AREA_MAX 1200.0
|
||
|
||
void MaxRect::SetCinema(vector<Build_Rect>& list, unsigned int no,
|
||
Rectangle<2> bbox)
|
||
{
|
||
vector<Build_Rect> cand_list;
|
||
|
||
vector<unsigned int> quad_list;
|
||
quad_list.push_back(0);
|
||
quad_list.push_back(0);
|
||
quad_list.push_back(0);
|
||
quad_list.push_back(0);
|
||
|
||
for(int i = list.size() - 1;i >= 0;i--){
|
||
if(list[i].rect.Area() > CINEMA_AREA_MIN &&
|
||
list[i].rect.Area() < CINEMA_AREA_MAX &&
|
||
(list[i].reg_type == 1 || list[i].reg_type == 2) &&
|
||
list[i].init == false && NoNeighborCinema(cand_list, list[i], bbox)){
|
||
// cout<<"find a cinema site"<<endl;
|
||
if(quad_list[list[i].quadrant - 1] < no / 4){
|
||
list[i].build_type = BUILD_CINEMA;
|
||
list[i].init = true;
|
||
cand_list.push_back(list[i]);
|
||
quad_list[list[i].quadrant - 1]++;
|
||
if(cand_list.size() == no)return;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/*
|
||
cinemas should not be close to each other
|
||
|
||
*/
|
||
bool MaxRect::NoNeighborCinema(vector<Build_Rect>& list, Build_Rect br,
|
||
Rectangle<2> bbox)
|
||
{
|
||
const double min_dist = 5000.0;
|
||
// Point p1(true, bbox.MinD(0), bbox.MinD(1));
|
||
// Point p2(true, bbox.MaxD(0), bbox.MaxD(1));
|
||
//
|
||
// const double min_dist = p1.Distance(p2)/4;
|
||
|
||
if(list.size() == 0)return true;
|
||
for(unsigned int i = 0;i < list.size();i++)
|
||
if(list[i].rect.Distance(br.rect) < min_dist) return false;
|
||
|
||
return true;
|
||
}
|
||
|
||
|
||
/*
|
||
set the places for hotels, uniformly distributed in each quadrant
|
||
|
||
*/
|
||
#define HOTEL_AREA_MIN 800.0
|
||
#define HOTEL_AREA_MAX 1600.0
|
||
|
||
void MaxRect::SetHotel(vector<Build_Rect>& list, unsigned int no,
|
||
Rectangle<2> bbox)
|
||
{
|
||
vector<unsigned int> quad_list;
|
||
quad_list.push_back(0);
|
||
quad_list.push_back(0);
|
||
quad_list.push_back(0);
|
||
quad_list.push_back(0);
|
||
|
||
vector<Build_Rect> cand_list;
|
||
|
||
for(int i = list.size() - 1;i >= 0;i--){
|
||
if(list[i].rect.Area() > HOTEL_AREA_MIN &&
|
||
list[i].rect.Area() < HOTEL_AREA_MAX &&
|
||
list[i].init == false && NoNeighborHotel(cand_list, list[i], bbox)){
|
||
// cout<<"find a hotel site"<<endl;
|
||
if(quad_list[list[i].quadrant - 1] < no / 4){
|
||
list[i].build_type = BUILD_HOTEL;
|
||
list[i].init = true;
|
||
cand_list.push_back(list[i]);
|
||
quad_list[list[i].quadrant - 1]++;
|
||
if(cand_list.size() == no)return;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/*
|
||
hotels should not be close to each other
|
||
|
||
*/
|
||
bool MaxRect::NoNeighborHotel(vector<Build_Rect>& list, Build_Rect br,
|
||
Rectangle<2> bbox)
|
||
{
|
||
const double min_dist = 3000.0;
|
||
|
||
// Point p1(true, bbox.MinD(0), bbox.MinD(1));
|
||
// Point p2(true, bbox.MaxD(0), bbox.MaxD(1));
|
||
//
|
||
// const double min_dist = p1.Distance(p2)/8;
|
||
|
||
if(list.size() == 0)return true;
|
||
for(unsigned int i = 0;i < list.size();i++)
|
||
if(list[i].rect.Distance(br.rect) < min_dist) return false;
|
||
|
||
return true;
|
||
}
|
||
|
||
|
||
/*
|
||
set the places for shopping malls, uniformly distributed in each quadrant
|
||
|
||
*/
|
||
#define SHOPMALL_AREA_MIN 1000.0
|
||
#define SHOPMALL_AREA_MAX 2000.0
|
||
|
||
void MaxRect::SetShopMall(vector<Build_Rect>& list, unsigned int no,
|
||
Rectangle<2> bbox)
|
||
{
|
||
vector<unsigned int> quad_list;
|
||
quad_list.push_back(0);
|
||
quad_list.push_back(0);
|
||
quad_list.push_back(0);
|
||
quad_list.push_back(0);
|
||
|
||
vector<Build_Rect> cand_list;
|
||
|
||
for(int i = list.size() - 1;i >= 0;i--){
|
||
if(list[i].rect.Area() > SHOPMALL_AREA_MIN &&
|
||
list[i].rect.Area() < SHOPMALL_AREA_MAX &&
|
||
list[i].init == false && NoNeighborShopMall(cand_list, list[i], bbox)){
|
||
// cout<<"find a hotel site"<<endl;
|
||
if(quad_list[list[i].quadrant - 1] < no / 4){
|
||
list[i].build_type = BUILD_SHOPPINGMALL;
|
||
list[i].init = true;
|
||
cand_list.push_back(list[i]);
|
||
quad_list[list[i].quadrant - 1]++;
|
||
if(cand_list.size() == no)return;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/*
|
||
shopping malls should not be close to each other
|
||
|
||
*/
|
||
bool MaxRect::NoNeighborShopMall(vector<Build_Rect>& list, Build_Rect br,
|
||
Rectangle<2> bbox)
|
||
{
|
||
const double min_dist = 1500.0;
|
||
|
||
// Point p1(true, bbox.MinD(0), bbox.MinD(1));
|
||
// Point p2(true, bbox.MaxD(0), bbox.MaxD(1));
|
||
//
|
||
// const double min_dist = p1.Distance(p2)/8;
|
||
|
||
if(list.size() == 0)return true;
|
||
for(unsigned int i = 0;i < list.size();i++)
|
||
if(list[i].rect.Distance(br.rect) < min_dist) return false;
|
||
|
||
return true;
|
||
}
|
||
|
||
/*
|
||
set the places for office24, uniformly distributed in each quadrant
|
||
|
||
*/
|
||
#define OFFICE24_AREA_MIN 600.0
|
||
#define OFFICE24_AREA_MAX 2500.0
|
||
|
||
void MaxRect::SetOffice24(vector<Build_Rect>& list, unsigned int no)
|
||
{
|
||
vector<unsigned int> quad_list;
|
||
quad_list.push_back(0);
|
||
quad_list.push_back(0);
|
||
quad_list.push_back(0);
|
||
quad_list.push_back(0);
|
||
|
||
vector<Build_Rect> cand_list;
|
||
|
||
vector<unsigned int> reg_type_list;
|
||
reg_type_list.push_back(0);
|
||
reg_type_list.push_back(0);
|
||
reg_type_list.push_back(0);
|
||
|
||
|
||
for(int i = list.size() - 1;i >= 0;i--){
|
||
if(list[i].rect.Area() > OFFICE24_AREA_MIN &&
|
||
list[i].rect.Area() < OFFICE24_AREA_MAX &&
|
||
list[i].init == false){
|
||
// cout<<"find a office24 site"<<endl;
|
||
if(quad_list[list[i].quadrant - 1] < no / 4 &&
|
||
reg_type_list[list[i].reg_type - 1] < no /3){
|
||
list[i].build_type = BUILD_OFFICE24;
|
||
list[i].init = true;
|
||
cand_list.push_back(list[i]);
|
||
|
||
quad_list[list[i].quadrant - 1]++;
|
||
reg_type_list[list[i].reg_type - 1]++;
|
||
|
||
if(cand_list.size() == no)return;
|
||
}
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
/*
|
||
set the places for office38, uniformly distributed in each quadrant
|
||
|
||
*/
|
||
#define OFFICE38_AREA_MIN 1000.0
|
||
#define OFFICE38_AREA_MAX 3500.0
|
||
|
||
|
||
void MaxRect::SetOffice38(vector<Build_Rect>& list, unsigned int no)
|
||
{
|
||
vector<unsigned int> quad_list;
|
||
quad_list.push_back(0);
|
||
quad_list.push_back(0);
|
||
quad_list.push_back(0);
|
||
quad_list.push_back(0);
|
||
|
||
vector<Build_Rect> cand_list;
|
||
|
||
vector<unsigned int> reg_type_list;
|
||
reg_type_list.push_back(0);
|
||
reg_type_list.push_back(0);
|
||
reg_type_list.push_back(0);
|
||
|
||
|
||
for(int i = list.size() - 1;i >= 0;i--){
|
||
if(list[i].rect.Area() > OFFICE38_AREA_MIN &&
|
||
list[i].rect.Area() < OFFICE38_AREA_MAX &&
|
||
list[i].init == false){
|
||
// cout<<"find a office38 site"<<endl;
|
||
if(quad_list[list[i].quadrant - 1] < no / 4 &&
|
||
reg_type_list[list[i].reg_type - 1] < no /3){
|
||
list[i].build_type = BUILD_OFFICE38;
|
||
list[i].init = true;
|
||
cand_list.push_back(list[i]);
|
||
|
||
quad_list[list[i].quadrant - 1]++;
|
||
reg_type_list[list[i].reg_type - 1]++;
|
||
|
||
if(cand_list.size() == no)return;
|
||
}
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
|
||
/*
|
||
set the places for hospitals , uniformly distributed in each quadrant
|
||
|
||
*/
|
||
#define HOSPITAL_AREA_MIN 800.0
|
||
#define HOSPITAL_AREA_MAX 2000.0
|
||
|
||
void MaxRect::SetHospital(vector<Build_Rect>& list, unsigned int no)
|
||
{
|
||
vector<unsigned int> quad_list;
|
||
quad_list.push_back(0);
|
||
quad_list.push_back(0);
|
||
quad_list.push_back(0);
|
||
quad_list.push_back(0);
|
||
|
||
vector<Build_Rect> cand_list;
|
||
|
||
for(int i = list.size() - 1;i >= 0;i--){
|
||
if(list[i].rect.Area() > HOSPITAL_AREA_MIN &&
|
||
list[i].rect.Area() < HOSPITAL_AREA_MAX &&
|
||
list[i].init == false && NoNeighborHospital(cand_list, list[i]) &&
|
||
NoNearbyShopMallAndCinema(list, list[i])){
|
||
// cout<<"find a hotel site"<<endl;
|
||
if(quad_list[list[i].quadrant - 1] < no / 4){
|
||
list[i].build_type = BUILD_HOSPITAL;
|
||
list[i].init = true;
|
||
cand_list.push_back(list[i]);
|
||
quad_list[list[i].quadrant - 1]++;
|
||
if(cand_list.size() == no)return;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/*
|
||
hosptials should not be close to each other
|
||
|
||
*/
|
||
bool MaxRect::NoNeighborHospital(vector<Build_Rect>& list, Build_Rect br)
|
||
{
|
||
const double min_dist = 2000.0;
|
||
|
||
if(list.size() == 0)return true;
|
||
for(unsigned int i = 0;i < list.size();i++)
|
||
if(list[i].rect.Distance(br.rect) < min_dist) return false;
|
||
|
||
return true;
|
||
}
|
||
|
||
/*
|
||
a hospital should not have a shopping mall and cinema so close
|
||
it is also not too close to a train station
|
||
|
||
*/
|
||
bool MaxRect::NoNearbyShopMallAndCinema(vector<Build_Rect>& list, Build_Rect br)
|
||
{
|
||
const double min_dist1 = 1000.0;
|
||
const double min_dist2 = 500.0;
|
||
const double min_dist3 = 300.0;
|
||
|
||
if(list.size() == 0)return true;
|
||
for(unsigned int i = 0;i < list.size();i++){
|
||
if((list[i].build_type == BUILD_SHOPPINGMALL ||
|
||
list[i].build_type == BUILD_CINEMA) &&
|
||
list[i].rect.Distance(br.rect) < min_dist1) return false;
|
||
|
||
if(list[i].build_type == BUILD_HOTEL &&
|
||
list[i].rect.Distance(br.rect) < min_dist2) return false;
|
||
|
||
if(list[i].build_type == BUILD_TRAINSTATION &&
|
||
list[i].rect.Distance(br.rect) < min_dist3) return false;
|
||
}
|
||
return true;
|
||
}
|
||
|
||
/*
|
||
set the places for libraries , uniformly distributed in each quadrant
|
||
|
||
*/
|
||
#define LIBRARY_AREA_MIN 1000.0
|
||
#define LIBRARY_AREA_MAX 2000.0
|
||
|
||
void MaxRect::SetLibrary(vector<Build_Rect>& list, unsigned int no)
|
||
{
|
||
vector<unsigned int> quad_list;
|
||
quad_list.push_back(0);
|
||
quad_list.push_back(0);
|
||
quad_list.push_back(0);
|
||
quad_list.push_back(0);
|
||
|
||
vector<Build_Rect> cand_list;
|
||
|
||
for(int i = list.size() - 1;i >= 0;i--){
|
||
if(list[i].rect.Area() > LIBRARY_AREA_MIN &&
|
||
list[i].rect.Area() < LIBRARY_AREA_MAX &&
|
||
list[i].reg_type == 2 &&
|
||
list[i].init == false && NoNeighborLibrary(cand_list, list[i]) &&
|
||
NoNearbyCommercialBuilding(list, list[i])){
|
||
// cout<<"find a hotel site"<<endl;
|
||
if(quad_list[list[i].quadrant - 1] < no / 4){
|
||
list[i].build_type = BUILD_LIBRARY;
|
||
list[i].init = true;
|
||
cand_list.push_back(list[i]);
|
||
quad_list[list[i].quadrant - 1]++;
|
||
if(cand_list.size() == no)return;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/*
|
||
library should not be close to each other
|
||
|
||
*/
|
||
bool MaxRect::NoNeighborLibrary(vector<Build_Rect>& list, Build_Rect br)
|
||
{
|
||
const double min_dist = 3000.0;
|
||
|
||
if(list.size() == 0)return true;
|
||
for(unsigned int i = 0;i < list.size();i++)
|
||
if(list[i].rect.Distance(br.rect) < min_dist) return false;
|
||
|
||
return true;
|
||
}
|
||
|
||
/*
|
||
a library should not so close to cinemas, hotels, shopping malls
|
||
|
||
*/
|
||
bool MaxRect::NoNearbyCommercialBuilding(vector<Build_Rect>& list,
|
||
Build_Rect br)
|
||
{
|
||
const double min_dist1 = 1000.0;
|
||
const double min_dist2 = 500.0;
|
||
const double min_dist3 = 300.0;
|
||
|
||
if(list.size() == 0) return true;
|
||
for(unsigned int i = 0;i < list.size();i++){
|
||
if((list[i].build_type == BUILD_SHOPPINGMALL ||
|
||
list[i].build_type == BUILD_CINEMA) &&
|
||
list[i].rect.Distance(br.rect) < min_dist1) return false;
|
||
|
||
if((list[i].build_type == BUILD_HOTEL ||
|
||
list[i].build_type == BUILD_HOSPITAL )&&
|
||
list[i].rect.Distance(br.rect) < min_dist2) return false;
|
||
|
||
if(list[i].build_type == BUILD_TRAINSTATION &&
|
||
list[i].rect.Distance(br.rect) < min_dist3) return false;
|
||
|
||
}
|
||
return true;
|
||
}
|
||
|
||
|
||
/*
|
||
set the places for schools, uniformly distributed in each quadrant
|
||
|
||
*/
|
||
#define SCHOOL_AREA_MIN 2000.0
|
||
#define SCHOOL_AREA_MAX 3000.0
|
||
|
||
void MaxRect::SetSchool(vector<Build_Rect>& list, unsigned int no)
|
||
{
|
||
vector<unsigned int> quad_list;
|
||
quad_list.push_back(0);
|
||
quad_list.push_back(0);
|
||
quad_list.push_back(0);
|
||
quad_list.push_back(0);
|
||
|
||
vector<Build_Rect> cand_list;
|
||
|
||
for(int i = list.size() - 1;i >= 0;i--){
|
||
if(list[i].rect.Area() > SCHOOL_AREA_MIN &&
|
||
list[i].rect.Area() < SCHOOL_AREA_MAX &&
|
||
(list[i].reg_type == 1 || list[i].reg_type == 2)&&
|
||
list[i].init == false && NoNeighborSchool(cand_list, list[i]) &&
|
||
NoNearbyCommercialBuilding(list, list[i])){
|
||
// cout<<"find a school site"<<endl;
|
||
if(quad_list[list[i].quadrant - 1] < no / 4){
|
||
list[i].build_type = BUILD_SCHOOL;
|
||
list[i].init = true;
|
||
cand_list.push_back(list[i]);
|
||
quad_list[list[i].quadrant - 1]++;
|
||
if(cand_list.size() == no)return;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/*
|
||
schools should not be too close to each other
|
||
|
||
*/
|
||
bool MaxRect::NoNeighborSchool(vector<Build_Rect>& list, Build_Rect br)
|
||
{
|
||
const double min_dist = 600.0;
|
||
|
||
if(list.size() == 0)return true;
|
||
for(unsigned int i = 0;i < list.size();i++)
|
||
if(list[i].rect.Distance(br.rect) < min_dist) return false;
|
||
|
||
return true;
|
||
}
|
||
|
||
/*
|
||
set the places for universities, uniformly distributed in each quadrant
|
||
|
||
*/
|
||
#define UNIVERSITY_AREA_MIN 2000.0
|
||
#define UNIVERSITY_AREA_MAX 5000.0
|
||
|
||
void MaxRect::SetUniversity(vector<Build_Rect>& list, unsigned int no)
|
||
{
|
||
vector<unsigned int> quad_list;
|
||
quad_list.push_back(0);
|
||
quad_list.push_back(0);
|
||
quad_list.push_back(0);
|
||
quad_list.push_back(0);
|
||
|
||
vector<Build_Rect> cand_list;
|
||
|
||
for(int i = list.size() - 1;i >= 0;i--){
|
||
if(list[i].rect.Area() > UNIVERSITY_AREA_MIN &&
|
||
list[i].rect.Area() < UNIVERSITY_AREA_MAX &&
|
||
(list[i].reg_type == 2 || list[i].reg_type == 3)&&
|
||
list[i].init == false && NoNeighborUniversity(cand_list, list[i]) &&
|
||
NoNearbyCommercialBuilding(list, list[i])){
|
||
// cout<<"find a hotel site"<<endl;
|
||
if(quad_list[list[i].quadrant - 1] < no / 4){
|
||
list[i].build_type = BUILD_UNIVERSITY;
|
||
list[i].init = true;
|
||
cand_list.push_back(list[i]);
|
||
quad_list[list[i].quadrant - 1]++;
|
||
if(cand_list.size() == no)return;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/*
|
||
universities should not be too close to each other
|
||
|
||
*/
|
||
bool MaxRect::NoNeighborUniversity(vector<Build_Rect>& list, Build_Rect br)
|
||
{
|
||
const double min_dist = 500.0;
|
||
|
||
if(list.size() == 0)return true;
|
||
for(unsigned int i = 0;i < list.size();i++)
|
||
if(list[i].rect.Distance(br.rect) < min_dist) return false;
|
||
|
||
return true;
|
||
}
|
||
|
||
|
||
|
||
/*
|
||
set the places for houses, uniformly distributed in each quadrant
|
||
|
||
*/
|
||
#define HOUSE_AREA_MAX 1500.0
|
||
|
||
void MaxRect::SetHouse(vector<Build_Rect>& list, unsigned int no)
|
||
{
|
||
vector<unsigned int> quad_list;
|
||
quad_list.push_back(0);
|
||
quad_list.push_back(0);
|
||
quad_list.push_back(0);
|
||
quad_list.push_back(0);
|
||
|
||
vector<Build_Rect> cand_list;
|
||
|
||
for(int i = list.size() - 1;i >= 0;i--){
|
||
if( list[i].rect.Area() < HOUSE_AREA_MAX &&
|
||
|
||
list[i].init == false && NoNearbyNeighbors1(list, list[i])){
|
||
|
||
// if(quad_list[list[i].quadrant - 1] < no / 4){
|
||
list[i].build_type = BUILD_HOUSE;
|
||
list[i].init = true;
|
||
cand_list.push_back(list[i]);
|
||
quad_list[list[i].quadrant - 1]++;
|
||
if(cand_list.size() == no)return;
|
||
// }
|
||
}
|
||
}
|
||
}
|
||
|
||
/*
|
||
neighbor building limitations for personal houses and apartments
|
||
|
||
*/
|
||
bool MaxRect::NoNearbyNeighbors1(vector<Build_Rect>& list, Build_Rect br)
|
||
{
|
||
|
||
// const double min_dist1 = 800.0;/////////cinema, hotel
|
||
// const double min_dist2 = 400.0;//////shopping mall
|
||
// const double min_dist3 = 200.0;////////others
|
||
|
||
const double min_dist1 = 500.0;/////////cinema,
|
||
const double min_dist2 = 300.0;//////shopping mall, hotel
|
||
const double min_dist3 = 100.0;////////others
|
||
|
||
if(list.size() == 0){
|
||
return true;
|
||
}
|
||
|
||
for(unsigned int i = 0;i < list.size();i++){
|
||
if((list[i].build_type == BUILD_CINEMA) &&
|
||
list[i].rect.Distance(br.rect) < min_dist1) return false;
|
||
|
||
if((list[i].build_type == BUILD_SHOPPINGMALL ||
|
||
list[i].build_type == BUILD_HOTEL) &&
|
||
list[i].rect.Distance(br.rect) < min_dist2) return false;
|
||
|
||
if(( list[i].build_type == BUILD_SCHOOL ||
|
||
list[i].build_type == BUILD_HOSPITAL ||
|
||
list[i].build_type == BUILD_LIBRARY ||
|
||
list[i].build_type == BUILD_OFFICE24 ||
|
||
list[i].build_type == BUILD_UNIVERSITY ||
|
||
list[i].build_type == BUILD_TRAINSTATION ) &&
|
||
list[i].rect.Distance(br.rect) < min_dist3) return false;
|
||
}
|
||
return true;
|
||
}
|
||
|
||
///////////////////////////////////////////////////////////////////////////
|
||
///////////////Infrastructure Region Based Outdoor Pavement////////////////
|
||
///////////////////////////////////////////////////////////////////////////
|
||
ListExpr PavementProperty()
|
||
{
|
||
return (nl->TwoElemList(
|
||
nl->FourElemList(nl->StringAtom("Signature"),
|
||
nl->StringAtom("Example Type List"),
|
||
nl->StringAtom("List Rep"),
|
||
nl->StringAtom("Example List")),
|
||
nl->FourElemList(nl->StringAtom("-> DATA"),
|
||
nl->StringAtom("pavement"),
|
||
nl->StringAtom("((def, id))"),
|
||
nl->StringAtom("((TRUE 1))"))));
|
||
}
|
||
/*
|
||
output the pavement infrastructure
|
||
|
||
*/
|
||
ListExpr OutPavement( ListExpr typeInfo, Word value )
|
||
{
|
||
// cout<<"OutPavement"<<endl;
|
||
Pavement* pn = (Pavement*)(value.addr);
|
||
if(!pn->IsDefined()){
|
||
return nl->SymbolAtom("undef");
|
||
}
|
||
|
||
ListExpr list1 = nl->TwoElemList(
|
||
nl->StringAtom("Pavement Id:"),
|
||
nl->IntAtom(pn->GetId()));
|
||
|
||
ListExpr list2 = nl->TheEmptyList();
|
||
if(pn->IsDGInit()){
|
||
list2 = nl->TwoElemList(
|
||
nl->StringAtom("Dual Graph Id:"),
|
||
nl->IntAtom(pn->GetDGId()));
|
||
}else
|
||
list2 = nl->OneElemList( nl->StringAtom("Dual Graph undef"));
|
||
|
||
ListExpr list3 = nl->TheEmptyList();
|
||
if(pn->IsVGInit()){
|
||
list3 = nl->TwoElemList(
|
||
nl->StringAtom("Visbility Graph Id:"),
|
||
nl->IntAtom(pn->GetVGId()));
|
||
}else
|
||
list3 = nl->OneElemList( nl->StringAtom("Visibility Graph undef"));
|
||
|
||
|
||
ListExpr list4 = nl->TheEmptyList();
|
||
|
||
return nl->FourElemList(list1, list2, list3, list4);
|
||
}
|
||
|
||
/*
|
||
In function. there is not nested list expression here.
|
||
|
||
*/
|
||
Word InPavement( const ListExpr typeInfo, const ListExpr instance,
|
||
const int errorPos, ListExpr& errorInfo, bool& correct )
|
||
{
|
||
|
||
// cout<<"length "<<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<< "pavenetwork(): 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<< "pavenetwork(): pavement infrastructure id must be int type"<<endl;
|
||
correct = false;
|
||
return SetWord(Address(0));
|
||
}
|
||
unsigned int id = nl->IntValue(second);
|
||
|
||
Pavement* pn = new Pavement(d, id);
|
||
|
||
////////////////very important /////////////////////////////
|
||
correct = true;
|
||
///////////////////////////////////////////////////////////
|
||
return SetWord(pn);
|
||
}
|
||
|
||
correct = false;
|
||
return SetWord(Address(0));
|
||
}
|
||
|
||
bool SavePavement(SmiRecord& valueRecord, size_t& offset,
|
||
const ListExpr typeInfo, Word& value)
|
||
{
|
||
Pavement* pn = (Pavement*)value.addr;
|
||
return pn->Save(valueRecord, offset, typeInfo);
|
||
}
|
||
|
||
bool OpenPavement(SmiRecord& valueRecord, size_t& offset,
|
||
const ListExpr typeInfo, Word& value)
|
||
{
|
||
value.addr = Pavement::Open(valueRecord, offset, typeInfo);
|
||
return value.addr != NULL;
|
||
}
|
||
|
||
Word CreatePavement(const ListExpr typeInfo)
|
||
{
|
||
// cout<<"CreatePavement()"<<endl;
|
||
return SetWord (new Pavement());
|
||
}
|
||
|
||
|
||
void DeletePavement(const ListExpr typeInfo, Word& w)
|
||
{
|
||
// cout<<"DeletePavement()"<<endl;
|
||
Pavement* pn = (Pavement*)w.addr;
|
||
delete pn;
|
||
w.addr = NULL;
|
||
}
|
||
|
||
void ClosePavement( const ListExpr typeInfo, Word& w )
|
||
{
|
||
// cout<<"ClosePavement"<<endl;
|
||
delete static_cast<Pavement*>(w.addr);
|
||
w.addr = 0;
|
||
}
|
||
|
||
Word ClonePavement( const ListExpr typeInfo, const Word& w )
|
||
{
|
||
// cout<<"ClonePavement"<<endl;
|
||
return SetWord( new Address(0));
|
||
}
|
||
|
||
|
||
void* Pavement::Cast(void* addr)
|
||
{
|
||
return NULL;
|
||
}
|
||
|
||
int SizeOfPavement()
|
||
{
|
||
// cout<<"SizeOfPavement"<<endl;
|
||
return sizeof(Pavement);
|
||
}
|
||
|
||
bool CheckPavement( ListExpr type, ListExpr& errorInfo )
|
||
{
|
||
// cout<<"CheckPavement"<<endl;
|
||
return (nl->IsEqual( type, "pavenetwork" ));
|
||
}
|
||
|
||
|
||
Pavement::Pavement():def(false), pave_id(0), dg_init(false), dg_id(0),
|
||
vg_init(false), vg_id(0), pave_rel(NULL)
|
||
{
|
||
|
||
|
||
}
|
||
|
||
|
||
Pavement::Pavement(bool d, unsigned int i):def(d), pave_id(i),
|
||
dg_init(false), dg_id(0), vg_init(false), vg_id(0), pave_rel(NULL)
|
||
{
|
||
|
||
|
||
|
||
}
|
||
|
||
Pavement::Pavement(SmiRecord& valueRecord, size_t& offset,
|
||
const ListExpr typeInfo):def(false), pave_id(0),
|
||
dg_init(false), dg_id(0), vg_init(false), vg_id(0), pave_rel(NULL)
|
||
{
|
||
|
||
|
||
valueRecord.Read(&def, sizeof(bool), offset);
|
||
offset += sizeof(bool);
|
||
|
||
valueRecord.Read(&pave_id, sizeof(int), offset);
|
||
offset += sizeof(int);
|
||
|
||
valueRecord.Read(&dg_init, sizeof(bool), offset);
|
||
offset += sizeof(bool);
|
||
|
||
valueRecord.Read(&dg_id, sizeof(int), offset);
|
||
offset += sizeof(int);
|
||
|
||
valueRecord.Read(&vg_init, sizeof(bool), offset);
|
||
offset += sizeof(bool);
|
||
|
||
valueRecord.Read(&vg_id, sizeof(int), offset);
|
||
offset += sizeof(int);
|
||
|
||
ListExpr xType;
|
||
ListExpr xNumericType;
|
||
/***********************Open relation for triangles*********************/
|
||
// nl->ReadFromString(PaveTypeInfo,xType);
|
||
nl->ReadFromString(DualGraph::NodeTypeInfo,xType);
|
||
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
||
pave_rel = Relation::Open(valueRecord, offset, xNumericType);
|
||
if(!pave_rel) {
|
||
return;
|
||
}
|
||
|
||
}
|
||
|
||
Pavement::~Pavement()
|
||
{
|
||
if(pave_rel != NULL) pave_rel->Close();
|
||
|
||
}
|
||
|
||
/*
|
||
create the pavement infrastructure by a relation storing all triangles
|
||
|
||
*/
|
||
void Pavement::Load(unsigned int i, Relation* r)
|
||
{
|
||
if(i < 1){
|
||
cout<<"invalid id "<<i<<endl;
|
||
def = false;
|
||
return;
|
||
}
|
||
pave_id = i;
|
||
|
||
def = true;
|
||
|
||
|
||
|
||
ListExpr ptrList = listutils::getPtrList(r);
|
||
|
||
// string strQuery = "(consume(feed(" + PaveTypeInfo +
|
||
string strQuery = "(consume(feed(" + DualGraph::NodeTypeInfo +
|
||
"(ptr " + nl->ToString(ptrList) + "))))";
|
||
|
||
// cout<<strQuery<<endl;
|
||
|
||
Word xResult;
|
||
int QueryExecuted = QueryProcessor::ExecuteQuery(strQuery, xResult);
|
||
assert(QueryExecuted);
|
||
pave_rel = (Relation*)xResult.addr;
|
||
|
||
// cout<<pave_rel->GetNoTuples()<<endl;
|
||
|
||
}
|
||
|
||
bool Pavement::Save(SmiRecord& valueRecord, size_t& offset,
|
||
const ListExpr typeInfo)
|
||
{
|
||
|
||
// cout<<"Pavement::Save"<<endl;
|
||
|
||
valueRecord.Write(&def, sizeof(bool), offset);
|
||
offset += sizeof(bool);
|
||
|
||
valueRecord.Write(&pave_id, sizeof(int), offset);
|
||
offset += sizeof(int);
|
||
|
||
valueRecord.Write(&dg_init, sizeof(bool), offset);
|
||
offset += sizeof(bool);
|
||
|
||
valueRecord.Write(&dg_id, sizeof(int), offset);
|
||
offset += sizeof(int);
|
||
|
||
valueRecord.Write(&vg_init, sizeof(bool), offset);
|
||
offset += sizeof(bool);
|
||
|
||
valueRecord.Write(&vg_id, sizeof(int), offset);
|
||
offset += sizeof(int);
|
||
|
||
|
||
ListExpr xType;
|
||
ListExpr xNumericType;
|
||
|
||
////////////////////triangles relation/////////////////////////////
|
||
// nl->ReadFromString(PaveTypeInfo, xType);
|
||
nl->ReadFromString(DualGraph::NodeTypeInfo, xType);
|
||
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
||
if(!pave_rel->Save(valueRecord,offset,xNumericType))
|
||
return false;
|
||
|
||
return true;
|
||
}
|
||
|
||
/*
|
||
open a pavement object
|
||
|
||
*/
|
||
Pavement* Pavement::Open(SmiRecord& valueRecord, size_t& offset,
|
||
const ListExpr typeInfo)
|
||
{
|
||
return new Pavement(valueRecord, offset, typeInfo);
|
||
|
||
}
|
||
|
||
/*
|
||
set the dual graph id for the pavement
|
||
|
||
*/
|
||
void Pavement::SetDualGraphId(int id)
|
||
{
|
||
dg_id = id;
|
||
dg_init = true;
|
||
}
|
||
|
||
|
||
/*
|
||
set the visual graph id for the pavement
|
||
|
||
*/
|
||
void Pavement::SetVisualGraphId(int id)
|
||
{
|
||
vg_id = id;
|
||
vg_init = true;
|
||
}
|
||
|
||
/*
|
||
load dual graph if it is stored
|
||
|
||
*/
|
||
DualGraph* Pavement::GetDualGraph()
|
||
{
|
||
if(dg_init == false) return NULL;
|
||
|
||
ListExpr xObjectList = SecondoSystem::GetCatalog()->ListObjects();
|
||
xObjectList = nl->Rest(xObjectList);
|
||
while(!nl->IsEmpty(xObjectList))
|
||
{
|
||
// Next element in list
|
||
ListExpr xCurrent = nl->First(xObjectList);
|
||
xObjectList = nl->Rest(xObjectList);
|
||
|
||
// Type of object is at fourth position in list
|
||
ListExpr xObjectType = nl->First(nl->Fourth(xCurrent));
|
||
if(nl->IsAtom(xObjectType) &&
|
||
nl->SymbolValue(xObjectType) == "dualgraph"){
|
||
// Get name of the dual graph
|
||
ListExpr xObjectName = nl->Second(xCurrent);
|
||
string strObjectName = nl->SymbolValue(xObjectName);
|
||
|
||
// Load object to find out the id of the dual graph.
|
||
Word xValue;
|
||
bool bDefined;
|
||
bool bOk = SecondoSystem::GetCatalog()->GetObject(strObjectName,
|
||
xValue,
|
||
bDefined);
|
||
if(!bDefined || !bOk)
|
||
{
|
||
// Undefined
|
||
continue;
|
||
}
|
||
DualGraph* dg = (DualGraph*)xValue.addr;
|
||
if(dg->g_id == dg_id){
|
||
// This is the dual graph we have been looking for
|
||
return dg;
|
||
}
|
||
}
|
||
}
|
||
return NULL;
|
||
}
|
||
|
||
void Pavement::CloseDualGraph(DualGraph* dg)
|
||
{
|
||
if(dg == NULL) return;
|
||
Word xValue;
|
||
xValue.addr = dg;
|
||
SecondoSystem::GetCatalog()->CloseObject(nl->SymbolAtom( "dualgraph" ),
|
||
xValue);
|
||
}
|
||
|
||
/*
|
||
load visual graph if it is stored
|
||
|
||
*/
|
||
VisualGraph* Pavement::GetVisualGraph()
|
||
{
|
||
if(vg_init == false) return NULL;
|
||
|
||
ListExpr xObjectList = SecondoSystem::GetCatalog()->ListObjects();
|
||
xObjectList = nl->Rest(xObjectList);
|
||
while(!nl->IsEmpty(xObjectList))
|
||
{
|
||
// Next element in list
|
||
ListExpr xCurrent = nl->First(xObjectList);
|
||
xObjectList = nl->Rest(xObjectList);
|
||
|
||
// Type of object is at fourth position in list
|
||
ListExpr xObjectType = nl->First(nl->Fourth(xCurrent));
|
||
if(nl->IsAtom(xObjectType) &&
|
||
nl->SymbolValue(xObjectType) == "visualgraph"){
|
||
// Get name of the visual graph
|
||
ListExpr xObjectName = nl->Second(xCurrent);
|
||
string strObjectName = nl->SymbolValue(xObjectName);
|
||
|
||
// Load object to find out the id of the visual graph.
|
||
Word xValue;
|
||
bool bDefined;
|
||
bool bOk = SecondoSystem::GetCatalog()->GetObject(strObjectName,
|
||
xValue,
|
||
bDefined);
|
||
if(!bDefined || !bOk)
|
||
{
|
||
// Undefined
|
||
continue;
|
||
}
|
||
VisualGraph* vg = (VisualGraph*)xValue.addr;
|
||
if(vg->g_id == vg_id){
|
||
// This is the dual graph we have been looking for
|
||
return vg;
|
||
}
|
||
}
|
||
}
|
||
return NULL;
|
||
|
||
}
|
||
|
||
|
||
void Pavement::CloseVisualGraph(VisualGraph* vg)
|
||
{
|
||
if(vg == NULL) return;
|
||
Word xValue;
|
||
xValue.addr = vg;
|
||
SecondoSystem::GetCatalog()->CloseObject(nl->SymbolAtom( "visualgraph" ),
|
||
xValue);
|
||
}
|
||
|
||
Relation* Pavement::GetPaveRel()
|
||
{
|
||
if(IsDefined()) return pave_rel;
|
||
else return NULL;
|
||
}
|
||
|
||
/*
|
||
check the maximum distance between two lines, if the value is larger than d
|
||
return false
|
||
|
||
*/
|
||
|
||
bool SmallerD(Line* l1, Line* l2, float d)
|
||
{
|
||
if(l1->IsEmpty() || l2->IsEmpty()){
|
||
cout<<"line empty"<<endl;
|
||
return false;
|
||
}
|
||
|
||
assert( l1->IsOrdered() );
|
||
assert( l2->IsOrdered() );
|
||
HalfSegment hs1, hs2;
|
||
for( int i = 0; i < l1->Size(); ++i ){
|
||
l1->Get( i, hs1 );
|
||
Point lp1 = hs1.GetLeftPoint();
|
||
Point rp1 = hs1.GetRightPoint();
|
||
if(hs1.IsLeftDomPoint() == false) continue;
|
||
for( int j = 0; j < l2->Size(); ++j ) {
|
||
l2->Get( j, hs2 );
|
||
if(hs2.IsLeftDomPoint() == false) continue;
|
||
Point lp2 = hs2.GetLeftPoint();
|
||
Point rp2 = hs2.GetRightPoint();
|
||
if(lp1.Distance(lp2) > d) return false;
|
||
if(lp1.Distance(rp2) > d) return false;
|
||
if(rp1.Distance(lp2) > d) return false;
|
||
if(rp1.Distance(rp2) > d) return false;
|
||
}
|
||
}
|
||
|
||
return true;
|
||
}
|