14698 lines
444 KiB
C++
14698 lines
444 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
|
|
|
|
Dec, 2010 Jianqiu Xu
|
|
|
|
[TOC]
|
|
|
|
1 Overview
|
|
|
|
This source file essentially contains the necessary implementations for
|
|
indoor environment
|
|
|
|
*/
|
|
|
|
#include "Indoor.h"
|
|
#include "GeneralType.h"
|
|
#include "PaveGraph.h"
|
|
#include "SecParser.h"
|
|
|
|
using namespace std;
|
|
using namespace temporalalgebra;
|
|
using namespace datetime;
|
|
|
|
|
|
extern NestedList *nl;
|
|
extern QueryProcessor *qp;
|
|
extern AlgebraManager *am;
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/////////////////////////// Point3D ////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
Point3D::Point3D(SmiRecord& valueRecord, size_t& offset,
|
|
const ListExpr typeInfo)
|
|
{
|
|
valueRecord.Read(&x, sizeof(double), offset);
|
|
offset += sizeof(double);
|
|
valueRecord.Read(&y, sizeof(double), offset);
|
|
offset += sizeof(double);
|
|
valueRecord.Read(&z, sizeof(double), offset);
|
|
offset += sizeof(double);
|
|
SetDefined(true);
|
|
}
|
|
|
|
bool Point3D::Save(SmiRecord& valueRecord, size_t& offset,
|
|
const ListExpr typeInfo)
|
|
{
|
|
// cout<<"Point3D::Save()"<<endl;
|
|
valueRecord.Write(&x, sizeof(double),offset);
|
|
offset += sizeof(double);
|
|
valueRecord.Write(&y, sizeof(double),offset);
|
|
offset += sizeof(double);
|
|
valueRecord.Write(&z, sizeof(double), offset);
|
|
offset += sizeof(double);
|
|
// cout<<x<<" "<<y<<" "<<z<<endl;
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
output function for data type point3d
|
|
|
|
*/
|
|
ListExpr OutPoint3D(ListExpr typeInfo, Word value)
|
|
{
|
|
Point3D* p3d = (Point3D*)value.addr;
|
|
if(p3d->IsDefined()){
|
|
return nl->ThreeElemList(
|
|
nl->RealAtom(p3d->GetX()),
|
|
nl->RealAtom(p3d->GetY()),
|
|
nl->RealAtom(p3d->GetZ())
|
|
);
|
|
}else
|
|
return nl->SymbolAtom("undef");
|
|
}
|
|
|
|
/*
|
|
input function for data type point3d
|
|
|
|
*/
|
|
Word InPoint3D(const ListExpr typeInfo, const ListExpr instance,
|
|
const int errorPos, ListExpr& errorInfo, bool& correct)
|
|
{
|
|
correct = true;
|
|
if( nl->ListLength( instance ) == 3 ) {
|
|
ListExpr first = nl->First(instance);
|
|
ListExpr second = nl->Second(instance);
|
|
ListExpr third = nl->Third(instance);
|
|
|
|
correct = listutils::isNumeric(first) &&
|
|
listutils::isNumeric(second) && listutils::isNumeric(third);
|
|
if(!correct){
|
|
return SetWord( Address(0) );
|
|
} else {
|
|
return SetWord(new Point3D(true, listutils::getNumValue(first),
|
|
listutils::getNumValue(second),
|
|
listutils::getNumValue(third)));
|
|
}
|
|
} else if( listutils::isSymbol( instance, "undef" ) ){
|
|
return SetWord(new Point3D(false));
|
|
}
|
|
correct = false;
|
|
return SetWord( Address(0) );
|
|
}
|
|
|
|
|
|
/*
|
|
Creation of the type constructor instance for point3d
|
|
|
|
*/
|
|
|
|
ListExpr Point3DProperty()
|
|
{
|
|
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("point3d"),
|
|
nl->StringAtom("(x y z)"),
|
|
nl->StringAtom("(10 5 2)")));
|
|
}
|
|
|
|
|
|
Word CreatePoint3D(const ListExpr typeInfo)
|
|
{
|
|
return SetWord (new Point3D(false));
|
|
}
|
|
|
|
void DeletePoint3D(const ListExpr typeInfo, Word& w)
|
|
{
|
|
// ((Point3D*)w.addr)->DeleteIfAllowed();
|
|
Point3D* p3d = (Point3D*)w.addr;
|
|
delete p3d;
|
|
w.addr = NULL;
|
|
}
|
|
|
|
void ClosePoint3D(const ListExpr typeInfo, Word& w)
|
|
{
|
|
// ((Point3D*)w.addr)->DeleteIfAllowed();
|
|
Point3D* p3d = (Point3D*)w.addr;
|
|
delete p3d;
|
|
w.addr = NULL;
|
|
}
|
|
|
|
|
|
Word ClonePoint3D(const ListExpr typeInfo, const Word& w)
|
|
{
|
|
Point3D* p3d = new Point3D(*(Point3D*)w.addr);
|
|
return SetWord(p3d);
|
|
}
|
|
|
|
void* CastPoint3D(void* addr)
|
|
{
|
|
return new (addr)Point3D();
|
|
}
|
|
|
|
int SizeOfPoint3D()
|
|
{
|
|
return sizeof(Point3D);
|
|
}
|
|
|
|
bool CheckPoint3D(ListExpr type, ListExpr& errorInfo)
|
|
{
|
|
return nl->IsEqual(type, "point3d");
|
|
}
|
|
|
|
/*
|
|
save function for point3d
|
|
|
|
*/
|
|
bool SavePoint3D(SmiRecord& valueRecord, size_t& offset,
|
|
const ListExpr typeInfo, Word& value)
|
|
{
|
|
Point3D* p3d = (Point3D*)value.addr;
|
|
return p3d->Save(valueRecord, offset, typeInfo);
|
|
}
|
|
|
|
bool OpenPoint3D(SmiRecord& valueRecord, size_t& offset,
|
|
const ListExpr typeInfo, Word& value)
|
|
{
|
|
value.addr = new Point3D(valueRecord, offset, typeInfo);
|
|
return value.addr != NULL;
|
|
}
|
|
|
|
ostream& operator<<(ostream& o, const Point3D& loc)
|
|
{
|
|
if(loc.IsDefined()){
|
|
o<<"( "<<loc.GetX()<<" "<<loc.GetY()<<" "<<loc.GetZ()<<" )";
|
|
}else
|
|
o<<" undef";
|
|
return o;
|
|
|
|
}
|
|
///////////////////////////////////////////////////////////////////////////
|
|
/////////////////////// Line3D ////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////////////
|
|
Line3D::Line3D( const int initsize ) :
|
|
StandardSpatialAttribute<3>(true),
|
|
points( initsize )
|
|
{
|
|
// cout<<"constructor1 "<<endl;
|
|
// cout<<"initsize "<<initsize<<endl;
|
|
}
|
|
|
|
Line3D::Line3D( const Line3D& ps ) :
|
|
StandardSpatialAttribute<3>(ps.IsDefined()),
|
|
points( ps.Size() )
|
|
{
|
|
// cout<<"constructor2"<<endl;
|
|
if( IsDefined() ) {
|
|
assert( ps.IsOrdered() );
|
|
points.copyFrom(ps.points);
|
|
}
|
|
}
|
|
|
|
|
|
/*inline bool Line3D::Get( const int i, Point& p ) const
|
|
{
|
|
assert( IsDefined() );
|
|
return points.Get( i, &p );
|
|
}*/
|
|
|
|
inline bool Line3D::Get( const int i, Point3D& p ) const
|
|
{
|
|
assert( IsDefined() && 0 <= i && i < Size());
|
|
return points.Get( i, &p );
|
|
}
|
|
|
|
inline int Line3D::Size() const
|
|
{
|
|
return points.Size();
|
|
}
|
|
|
|
inline bool Line3D::IsEmpty() const
|
|
{
|
|
return !IsDefined() || (points.Size() == 0);
|
|
}
|
|
|
|
inline bool Line3D::IsOrdered() const
|
|
{
|
|
return true;
|
|
}
|
|
|
|
inline int Line3D::NumOfFLOBs() const
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
|
|
inline Flob *Line3D::GetFLOB(const int i)
|
|
{
|
|
assert( i >= 0 && i < NumOfFLOBs() );
|
|
return &points;
|
|
}
|
|
|
|
|
|
inline size_t Line3D::Sizeof() const
|
|
{
|
|
return sizeof( *this );
|
|
}
|
|
|
|
|
|
inline void Line3D::Resize(const int newSize){
|
|
if(newSize>Size()){
|
|
points.resize(newSize);
|
|
}
|
|
}
|
|
|
|
inline void Line3D::TrimToSize(){
|
|
points.TrimToSize();
|
|
}
|
|
|
|
void Line3D::RemoveDuplicates()
|
|
{
|
|
|
|
}
|
|
|
|
/*
|
|
sort 3d points in a line
|
|
|
|
*/
|
|
void Line3D::Sort(const bool exact /*= true*/)
|
|
{
|
|
|
|
}
|
|
|
|
void Line3D::Clear()
|
|
{
|
|
points.clean();
|
|
}
|
|
|
|
void Line3D::StartBulkLoad()
|
|
{
|
|
|
|
}
|
|
|
|
Line3D& Line3D::operator+=( const Point3D& p )
|
|
{
|
|
if(!IsDefined()){
|
|
return *this;
|
|
}
|
|
points.Append(p);
|
|
return *this;
|
|
}
|
|
|
|
bool Line3D::IsValid() const
|
|
{
|
|
return true;
|
|
}
|
|
|
|
size_t Line3D::HashValue() const
|
|
{
|
|
return (size_t)0.0;
|
|
}
|
|
|
|
void Line3D::CopyFrom( const Attribute* right )
|
|
{
|
|
// cout<<"Line3D CopyFrom"<<endl;
|
|
const Line3D *ps = (const Line3D*)right;
|
|
assert( ps->IsOrdered() );
|
|
*this = *ps;
|
|
}
|
|
|
|
/*
|
|
end bulkload for a line3d
|
|
|
|
*/
|
|
void Line3D::EndBulkLoad( bool sort, bool remDup, bool trim )
|
|
{
|
|
if( !IsDefined() ) {
|
|
Clear();
|
|
SetDefined( false );
|
|
}
|
|
|
|
if( sort ){
|
|
Sort();
|
|
}
|
|
|
|
if( remDup ){
|
|
RemoveDuplicates();
|
|
}
|
|
if(trim){
|
|
points.TrimToSize();
|
|
}
|
|
}
|
|
|
|
Line3D& Line3D::operator=( const Line3D& ps )
|
|
{
|
|
// cout<<"Line3D = "<<endl;
|
|
assert( ps.IsOrdered() );
|
|
// points.copyFrom(ps.points);
|
|
|
|
points.clean();
|
|
Line3D* l = const_cast<Line3D*>(&ps);
|
|
for(int i = 0;i < l->Size();i++){
|
|
Point3D p;
|
|
l->Get(i, p);
|
|
points.Append(p);
|
|
}
|
|
|
|
SetDefined(ps.IsDefined());
|
|
return *this;
|
|
}
|
|
|
|
bool Line3D::operator==( const Line3D& l) const
|
|
{
|
|
vector<Point3D> ps_list1;
|
|
vector<Point3D> ps_list2;
|
|
|
|
if(Size() != l.Size()) return false;
|
|
|
|
for(int i = 0;i < points.Size();i++){
|
|
Point3D p;
|
|
points.Get(i, p);
|
|
ps_list1.push_back(p);
|
|
}
|
|
|
|
for(int i = 0;i < l.Size();i++){
|
|
Point3D p;
|
|
l.Get(i, p);
|
|
ps_list2.push_back(p);
|
|
}
|
|
|
|
sort(ps_list1.begin(), ps_list1.end());
|
|
sort(ps_list2.begin(), ps_list2.end());
|
|
|
|
for(unsigned int i = 0;i < ps_list1.size();i++){
|
|
if(!(ps_list1[i] == ps_list2[i])) return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Line3D::Adjacent( const Attribute* arg ) const
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int Line3D::Compare( const Attribute* arg ) const
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int Line3D::CompareAlmost( const Attribute* arg ) const
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
|
|
double Line3D::Distance( const Rectangle<3>& r,const Geoid* geoid) const
|
|
{
|
|
return 0.0;
|
|
}
|
|
|
|
double Line3D::Length()
|
|
{
|
|
double length = 0.0;
|
|
for(int i = 0;i < points.Size() - 1;i++){
|
|
Point3D p1;
|
|
points.Get(i, p1);
|
|
Point3D p2;
|
|
points.Get(i + 1, p2);
|
|
length += p1.Distance(p2);
|
|
}
|
|
return length;
|
|
}
|
|
|
|
ostream& Line3D::Print(ostream& o) const
|
|
{
|
|
for(int i = 0;i < points.Size();i++){
|
|
Point3D p;
|
|
points.Get(i , p);
|
|
p.Print(o);
|
|
}
|
|
return o;
|
|
}
|
|
|
|
const Rectangle<3> Line3D::BoundingBox(const Geoid* geoid) const
|
|
{
|
|
// return new Rectangle<3>(true,0.0,0.0,0.0,0.0,0.0,0.0);
|
|
// cout<<"Rectangle<3> BoundingBox "<<endl;
|
|
double min[3];
|
|
double max[3];
|
|
for(int i = 0;i < 3;i++){
|
|
min[i] = numeric_limits<double>::max();
|
|
max[i] = numeric_limits<double>::min();
|
|
}
|
|
|
|
for(int i = 0;i < points.Size();i++){
|
|
Point3D p;
|
|
points.Get(i, p);
|
|
|
|
min[0] = MIN(p.GetX(), min[0]);
|
|
min[1] = MIN(p.GetY(), min[1]);
|
|
min[2] = MIN(p.GetZ(), min[2]);
|
|
|
|
max[0] = MAX(p.GetX(), max[0]);
|
|
max[1] = MAX(p.GetY(), max[1]);
|
|
max[2] = MAX(p.GetZ(), max[2]);
|
|
}
|
|
|
|
Rectangle<3> bbox3d(true, min, max);
|
|
return bbox3d;
|
|
}
|
|
|
|
|
|
/*
|
|
List Representation
|
|
|
|
The list representation of a point is
|
|
|
|
---- (x y)
|
|
----
|
|
|
|
~Out~-function
|
|
|
|
*/
|
|
ListExpr OutLine3D( ListExpr typeInfo, Word value )
|
|
{
|
|
Line3D* points = (Line3D*)(value.addr);
|
|
if(!points->IsDefined()){
|
|
return nl->SymbolAtom("undef");
|
|
}
|
|
|
|
if( points->IsEmpty() )
|
|
return nl->TheEmptyList();
|
|
|
|
// Point p;
|
|
Point3D p;
|
|
assert( points->Get( 0, p ) );
|
|
/* ListExpr result =
|
|
nl->OneElemList( OutPoint( nl->TheEmptyList(), SetWord( (void*)&p ) ) );*/
|
|
ListExpr result =
|
|
nl->OneElemList( OutPoint3D( nl->TheEmptyList(), SetWord( (void*)&p ) ) );
|
|
ListExpr last = result;
|
|
|
|
for( int i = 1; i < points->Size(); i++ )
|
|
{
|
|
assert( points->Get( i, p ) );
|
|
/* last = nl->Append( last,
|
|
OutPoint( nl->TheEmptyList(), SetWord( (void*)&p ) ) );*/
|
|
last = nl->Append( last,
|
|
OutPoint3D( nl->TheEmptyList(), SetWord( (void*)&p)));
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/*
|
|
In function
|
|
|
|
*/
|
|
Word InLine3D( const ListExpr typeInfo, const ListExpr instance,
|
|
const int errorPos, ListExpr& errorInfo, bool& correct )
|
|
{
|
|
if(nl->IsEqual(instance,"undef")) {
|
|
Points* points = new Points(0);
|
|
points->Clear();
|
|
points->SetDefined(false);
|
|
correct=true;
|
|
return SetWord( Address(points) );
|
|
}
|
|
Line3D* points = new Line3D( max(0,nl->ListLength( instance) ) );
|
|
points->SetDefined( true );
|
|
if(nl->AtomType(instance)!=NoAtom) {
|
|
points->DeleteIfAllowed();
|
|
correct = false;
|
|
cout << __PRETTY_FUNCTION__ << ": Unexpected Atom!" << endl;
|
|
return SetWord( Address(points) );
|
|
}
|
|
|
|
ListExpr rest = instance;
|
|
points->StartBulkLoad();
|
|
while( !nl->IsEmpty( rest ) ) {
|
|
ListExpr first = nl->First( rest );
|
|
rest = nl->Rest( rest );
|
|
|
|
/* Point *p = (Point*)InPoint( nl->TheEmptyList(),
|
|
first, 0, errorInfo, correct ).addr;*/
|
|
Point3D *p = (Point3D*)InPoint3D( nl->TheEmptyList(),
|
|
first, 0, errorInfo, correct ).addr;
|
|
|
|
if( correct && p->IsDefined() ) {
|
|
(*points) += (*p);
|
|
delete p;
|
|
} else {
|
|
if(p) {
|
|
delete p;
|
|
}
|
|
cout << __PRETTY_FUNCTION__ << ": Incorrect or undefined point!" << endl;
|
|
points->DeleteIfAllowed();
|
|
correct = false;
|
|
return SetWord( Address(0) );
|
|
}
|
|
|
|
}
|
|
points->EndBulkLoad();
|
|
|
|
if( points->IsValid() ) {
|
|
correct = true;
|
|
return SetWord( points );
|
|
}
|
|
points->DeleteIfAllowed();
|
|
correct = false;
|
|
cout << __PRETTY_FUNCTION__ << ": Invalid points value!" << endl;
|
|
return SetWord( Address(0) );
|
|
}
|
|
|
|
/*
|
|
Create function
|
|
|
|
*/
|
|
Word CreateLine3D( const ListExpr typeInfo )
|
|
{
|
|
// cout<<"CreateLine3D "<<endl;
|
|
return SetWord( new Line3D( 0 ) );
|
|
}
|
|
|
|
/*
|
|
Delete function
|
|
|
|
*/
|
|
void DeleteLine3D( const ListExpr typeInfo, Word& w )
|
|
{
|
|
// cout<<"DeleteLine3D "<<endl;
|
|
Line3D *ps = (Line3D *)w.addr;
|
|
ps->Destroy();
|
|
ps->DeleteIfAllowed(false);
|
|
w.addr = 0;
|
|
}
|
|
|
|
/*
|
|
Close function
|
|
|
|
*/
|
|
void CloseLine3D( const ListExpr typeInfo, Word& w )
|
|
{
|
|
// cout<<"CloseLine3D "<<endl;
|
|
((Line3D *)w.addr)->DeleteIfAllowed();
|
|
w.addr = 0;
|
|
}
|
|
|
|
/*
|
|
Clone function
|
|
|
|
*/
|
|
Word CloneLine3D( const ListExpr typeInfo, const Word& w )
|
|
{
|
|
return SetWord( new Line3D( *((Line3D *)w.addr) ) );
|
|
}
|
|
|
|
/*
|
|
Open function
|
|
|
|
*/
|
|
bool OpenLine3D( SmiRecord& valueRecord, size_t& offset,
|
|
const ListExpr typeInfo, Word& value )
|
|
{
|
|
Line3D *ps = (Line3D*)Attribute::Open( valueRecord, offset, typeInfo );
|
|
value = SetWord( ps );
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
Save function
|
|
|
|
*/
|
|
bool SaveLine3D( SmiRecord& valueRecord, size_t& offset,
|
|
const ListExpr typeInfo, Word& value )
|
|
{
|
|
Line3D *ps = (Line3D*)value.addr;
|
|
Attribute::Save( valueRecord, offset, typeInfo, ps );
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
SizeOf function
|
|
|
|
*/
|
|
int SizeOfLine3D()
|
|
{
|
|
return sizeof(Line3D);
|
|
}
|
|
|
|
|
|
ListExpr Line3DProperty()
|
|
{
|
|
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("line3d"),
|
|
nl->StringAtom("(<point3d>*) where point3d is (<x><y><z>)"),
|
|
nl->StringAtom("( (10 1 2)(4 5 3) )"))));
|
|
}
|
|
|
|
|
|
bool CheckLine3D( ListExpr type, ListExpr& errorInfo )
|
|
{
|
|
return (nl->IsEqual( type, "line3d" ));
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
////////////////////////// Floor3D /////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
/*
|
|
Constructor function for Floor3D
|
|
|
|
*/
|
|
Floor3D::Floor3D(SmiRecord& valueRecord, size_t& offset,
|
|
const ListExpr typeInfo):
|
|
StandardSpatialAttribute<2>(true),reg(0)
|
|
{
|
|
// cout<<"Floor3D(SmiRecord& , size_t& , const ListExpr) here"<<endl;
|
|
valueRecord.Read(&floor_height, sizeof(float), offset);
|
|
offset += sizeof(float);
|
|
ListExpr xType = nl->SymbolAtom("region");
|
|
ListExpr xNumericType =
|
|
SecondoSystem::GetCatalog()->NumericType(xType);
|
|
Region* r = (Region*)Attribute::Open(valueRecord,offset,xNumericType);
|
|
reg = *r;
|
|
// cout<<*r<<endl;
|
|
r->DeleteIfAllowed();
|
|
SetDefined(true);
|
|
}
|
|
|
|
bool Floor3D::Save(SmiRecord& valueRecord, size_t& offset,
|
|
const ListExpr typeInfo)
|
|
{
|
|
// cout<<"Save()"<<endl;
|
|
valueRecord.Write(&floor_height, sizeof(float),offset);
|
|
offset += sizeof(float);
|
|
ListExpr xType = nl->SymbolAtom("region");
|
|
ListExpr xNumericType =
|
|
SecondoSystem::GetCatalog()->NumericType(xType);
|
|
Attribute::Save(valueRecord, offset, xNumericType, ®);
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
Creation of the type constructor instance for floor3d
|
|
|
|
*/
|
|
ListExpr Floor3DProperty()
|
|
{
|
|
// cout<<"Floor3DProperty()"<<endl;
|
|
ListExpr examplelist = nl->TextAtom();
|
|
nl->AppendText(examplelist,"thefloor(floor_height, polygon)");
|
|
return nl->TwoElemList(
|
|
nl->TwoElemList(nl->StringAtom("Creation"),
|
|
nl->StringAtom("Example Creation")),
|
|
nl->TwoElemList(examplelist,
|
|
nl->StringAtom("(let room1=thefloor(0, r))"))
|
|
|
|
);
|
|
}
|
|
|
|
/*
|
|
OutPut function for floor3d
|
|
|
|
*/
|
|
ListExpr OutFloor3D(ListExpr typeInfo, Word value)
|
|
{
|
|
// cout<<"OutFloor3D()"<<endl;
|
|
Floor3D* fl = (Floor3D*)(value.addr);
|
|
|
|
if(!fl->IsDefined()){
|
|
return nl->SymbolAtom("undef");
|
|
}
|
|
|
|
if( fl->IsEmpty() ){
|
|
return (nl->TheEmptyList());
|
|
}
|
|
else{
|
|
Region* cr = const_cast<Region*>(fl->GetRegion());
|
|
ListExpr regionNL = OutRegion(nl->TheEmptyList(), SetWord(cr));
|
|
return nl->TwoElemList(nl->RealAtom(fl->GetHeight()), regionNL);
|
|
}
|
|
}
|
|
|
|
/*
|
|
input function for data type floor3d
|
|
a float value for ground height and a region for space covered
|
|
|
|
*/
|
|
Word InFloor3D(const ListExpr typeInfo, const ListExpr instance,
|
|
const int errorPos, ListExpr& errorInfo, bool& correct)
|
|
{
|
|
// cout<<"InFloor3D()"<<endl;
|
|
if(nl->ListLength(instance) != 2){
|
|
string strErrorMessage = "floor3d(): List length must be 2";
|
|
errorInfo = nl->Append(errorInfo,nl->StringAtom(strErrorMessage));
|
|
correct = false;
|
|
return SetWord(Address(0));
|
|
}
|
|
|
|
if (nl->IsAtom(instance)){
|
|
correct=false;
|
|
return SetWord( Address(0) );
|
|
}
|
|
|
|
if(nl->IsEqual(instance,"undef")){
|
|
correct=false;
|
|
return SetWord(Address(0));
|
|
}
|
|
|
|
ListExpr height_list = nl->First(instance);
|
|
if(!nl->IsAtom(height_list) || nl->AtomType(height_list) != RealType){
|
|
string strErrorMessage = "floor3d(): height must be float type";
|
|
errorInfo = nl->Append(errorInfo,nl->StringAtom(strErrorMessage));
|
|
correct = false;
|
|
return SetWord(Address(0));
|
|
}
|
|
float height = nl->RealValue(height_list);
|
|
// cout<<"height "<<height<<endl;
|
|
|
|
|
|
|
|
///// new implementation from Thomas
|
|
Word reg_addr= InRegion(typeInfo,nl->Second(instance),errorPos,
|
|
errorInfo,correct);
|
|
|
|
Region* cr = (Region*)reg_addr.addr;
|
|
Floor3D* fl = new Floor3D(height, *cr);
|
|
cr->DeleteIfAllowed();
|
|
return SetWord(fl);
|
|
|
|
}
|
|
|
|
|
|
void CloseFloor3D(const ListExpr typeInfo, Word& w)
|
|
{
|
|
// cout<<"CloseFloor3D()"<<endl;
|
|
// ((Floor3D*)w.addr)->DeleteIfAllowed();
|
|
delete static_cast<Floor3D*> (w.addr);
|
|
w.addr = NULL;
|
|
}
|
|
|
|
Word CloneFloor3D(const ListExpr typeInfo, const Word& w)
|
|
{
|
|
// cout<<"CloneFloor3D()"<<endl;
|
|
Floor3D* fl = new Floor3D(*(Floor3D*)w.addr);
|
|
return SetWord(fl);
|
|
}
|
|
|
|
Word CreateFloor3D(const ListExpr typeInfo)
|
|
{
|
|
// cout<<"CreateFloor3D()"<<endl;
|
|
return SetWord (new Floor3D(0.0));
|
|
}
|
|
|
|
void DeleteFloor3D(const ListExpr typeInfo, Word& w)
|
|
{
|
|
// cout<<"DeleteFloor3D()"<<endl;
|
|
Floor3D* fl = (Floor3D*)w.addr;
|
|
delete fl;
|
|
w.addr = NULL;
|
|
}
|
|
|
|
|
|
int SizeOfFloor3D()
|
|
{
|
|
// cout<<"SizeOfFloor3D()"<<endl;
|
|
return sizeof(Floor3D);
|
|
}
|
|
|
|
bool CheckFloor3D(ListExpr type, ListExpr& errorInfo)
|
|
{
|
|
// cout<<"CheckFloor3D()"<<endl;
|
|
return nl->IsEqual(type, "floor3d");
|
|
}
|
|
|
|
/*
|
|
open function for floor3d
|
|
|
|
*/
|
|
|
|
bool OpenFloor3D(SmiRecord& valueRecord, size_t& offset,
|
|
const ListExpr typeInfo, Word& value)
|
|
{
|
|
// cout<<"OpenFloor3D()"<<endl;
|
|
value.addr = new Floor3D(valueRecord, offset, typeInfo);
|
|
return value.addr != NULL;
|
|
}
|
|
|
|
/*
|
|
save function for floor3d
|
|
|
|
*/
|
|
bool SaveFloor3D(SmiRecord& valueRecord, size_t& offset,
|
|
const ListExpr typeInfo, Word& value)
|
|
{
|
|
// cout<<"SaveFloor3D()"<<endl;
|
|
Floor3D* fl = (Floor3D*)value.addr;
|
|
return fl->Save(valueRecord, offset, typeInfo);
|
|
}
|
|
///////////////////////////////////////////////////////////////////////////
|
|
///////////////////////////// Door3D /////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
/*
|
|
Constructor function for Door3D
|
|
|
|
*/
|
|
Door3D::Door3D(SmiRecord& valueRecord, size_t& offset,
|
|
const ListExpr typeInfo):StandardSpatialAttribute<2>(true),
|
|
door_pos1(0),door_pos2(0), tpstate(0)
|
|
{
|
|
|
|
valueRecord.Read(&oid1, sizeof(unsigned int), offset);
|
|
offset += sizeof(unsigned int);
|
|
ListExpr xType = nl->SymbolAtom("line");
|
|
ListExpr xNumericType =
|
|
SecondoSystem::GetCatalog()->NumericType(xType);
|
|
Line* l1 = (Line*)Attribute::Open(valueRecord,offset,xNumericType);
|
|
door_pos1 = *l1;
|
|
l1->DeleteIfAllowed();
|
|
|
|
valueRecord.Read(&oid2, sizeof(unsigned int), offset);
|
|
offset += sizeof(unsigned int);
|
|
Line* l2 = (Line*)Attribute::Open(valueRecord,offset,xNumericType);
|
|
door_pos2 = *l2;
|
|
l2->DeleteIfAllowed();
|
|
|
|
|
|
xType = nl->SymbolAtom("mbool");
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
MBool* mb = (MBool*)Attribute::Open(valueRecord,offset,xNumericType);
|
|
tpstate = *mb;
|
|
// cout<<tpstate<<endl;
|
|
|
|
|
|
valueRecord.Read(&lift_door, sizeof(bool), offset);
|
|
offset += sizeof(bool);
|
|
|
|
SetDefined(true);
|
|
}
|
|
|
|
bool Door3D::Save(SmiRecord& valueRecord, size_t& offset,
|
|
const ListExpr typeInfo)
|
|
{
|
|
// cout<<"Save()"<<endl;
|
|
|
|
valueRecord.Write(&oid1, sizeof(unsigned int),offset);
|
|
offset += sizeof(unsigned int);
|
|
ListExpr xType = nl->SymbolAtom("line");
|
|
ListExpr xNumericType =
|
|
SecondoSystem::GetCatalog()->NumericType(xType);
|
|
Attribute::Save(valueRecord, offset, xNumericType, &door_pos1);
|
|
|
|
valueRecord.Write(&oid2, sizeof(unsigned int),offset);
|
|
offset += sizeof(unsigned int);
|
|
Attribute::Save(valueRecord, offset, xNumericType, &door_pos2);
|
|
|
|
|
|
xType = nl->SymbolAtom("mbool");
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
Attribute::Save(valueRecord, offset, xNumericType, &tpstate);
|
|
|
|
valueRecord.Write(&lift_door, sizeof(bool), offset);
|
|
offset += sizeof(bool);
|
|
return true;
|
|
}
|
|
|
|
|
|
/*
|
|
Door3D Property function
|
|
|
|
*/
|
|
ListExpr Door3DProperty()
|
|
{
|
|
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("door3d"),
|
|
nl->StringAtom("(<door3d>) (int line int line mbool bool)"),
|
|
nl->StringAtom("(oid1 l1 oid2 l2 doorstat type)"))));
|
|
}
|
|
|
|
|
|
ListExpr OutDoor3D( ListExpr typeInfo, Word value )
|
|
{
|
|
// cout<<"OutDoor3D()"<<endl;
|
|
Door3D* dr = (Door3D*)(value.addr);
|
|
if(!dr->IsDefined()){
|
|
return nl->SymbolAtom("undef");
|
|
}
|
|
|
|
if( dr->IsEmpty() ){
|
|
return nl->TheEmptyList();
|
|
}
|
|
|
|
|
|
ListExpr l1 = OutLine(nl->TheEmptyList(), SetWord(dr->GetLoc(1)));
|
|
ListExpr l2 = OutLine(nl->TheEmptyList(), SetWord(dr->GetLoc(2)));
|
|
ListExpr tempstate = OutMapping<MBool,UBool,
|
|
OutConstTemporalUnit<CcBool,OutCcBool> >(nl->TheEmptyList(),
|
|
SetWord(dr->GetTState()));
|
|
|
|
ListExpr list1 = nl->TwoElemList(nl->IntAtom(dr->GetOid(1)), l1);
|
|
ListExpr list2 = nl->TwoElemList(nl->IntAtom(dr->GetOid(2)), l2);
|
|
return nl->FourElemList(list1, list2,
|
|
tempstate, nl->BoolAtom(dr->GetDoorType()));
|
|
|
|
}
|
|
|
|
/*
|
|
In function for door3d
|
|
|
|
*/
|
|
Word InDoor3D( const ListExpr typeInfo, const ListExpr instance,
|
|
const int errorPos, ListExpr& errorInfo, bool& correct )
|
|
{
|
|
if(nl->IsEqual(instance,"undef")) {
|
|
Door3D* dr = new Door3D();
|
|
dr->SetDefined(false);
|
|
correct=true;
|
|
return SetWord(Address(dr));
|
|
}
|
|
////////////////////////////////////////////////////////////////////////
|
|
/////////////////////// get the first genrange /////////////////////////
|
|
///////////////////////////////////////////////////////////////////////
|
|
ListExpr first_instance = nl->First(instance);
|
|
ListExpr oid_list1 = nl->First(first_instance);
|
|
|
|
if(!nl->IsAtom(oid_list1) || nl->AtomType(oid_list1) != IntType){
|
|
string strErrorMessage = "genrange(): obj id must be int type";
|
|
errorInfo = nl->Append(errorInfo,nl->StringAtom(strErrorMessage));
|
|
correct = false;
|
|
return SetWord(Address(0));
|
|
}
|
|
|
|
unsigned int oid1 = nl->IntValue(oid_list1);
|
|
ListExpr rest = nl->Second(first_instance);
|
|
Line* l1 = (Line*)(InLine(typeInfo,rest,errorPos,errorInfo,correct).addr);
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//////////////////////// get the second oid and line //////////////////////
|
|
///////////////////////////////////////////////////////////////////////////
|
|
ListExpr second_instance = nl->Second(instance);
|
|
ListExpr oid_list2 = nl->First(second_instance);
|
|
|
|
if(!nl->IsAtom(oid_list2) || nl->AtomType(oid_list2) != IntType){
|
|
string strErrorMessage = "genrange(): obj id must be int type";
|
|
errorInfo = nl->Append(errorInfo,nl->StringAtom(strErrorMessage));
|
|
correct = false;
|
|
return SetWord(Address(0));
|
|
}
|
|
|
|
unsigned int oid2 = nl->IntValue(oid_list2);
|
|
rest = nl->Second(second_instance);
|
|
Line* l2 = (Line*)(InLine(typeInfo,rest,errorPos,errorInfo,correct).addr);
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
///////////// time-dependent state mbool //////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////
|
|
ListExpr temporal_state = nl->Third(instance);
|
|
int numUnits = 0;
|
|
if(nl->AtomType(temporal_state)==NoAtom){
|
|
numUnits = nl->ListLength(temporal_state);
|
|
}
|
|
MBool* m = new MBool( numUnits );
|
|
correct = true;
|
|
int unitcounter = 0;
|
|
string errmsg;
|
|
|
|
m->StartBulkLoad();
|
|
|
|
rest = temporal_state;
|
|
if (nl->AtomType( rest ) != NoAtom)
|
|
{ if(nl->IsEqual(rest,"undef")){
|
|
m->EndBulkLoad();
|
|
m->SetDefined(false);
|
|
return SetWord( Address( m ) );
|
|
} else {
|
|
correct = false;
|
|
m->Destroy();
|
|
m->DeleteIfAllowed();
|
|
return SetWord( Address( 0 ) );
|
|
}
|
|
}
|
|
else while( !nl->IsEmpty( rest ) )
|
|
{
|
|
ListExpr first = nl->First( rest );
|
|
rest = nl->Rest( rest );
|
|
|
|
// UBool *unit = (UBool*)InUnit( nl->TheEmptyList(), first,
|
|
// errorPos, errorInfo, correct ).addr;
|
|
UBool *unit = (UBool*)InConstTemporalUnit<CcBool,InCcBool>(
|
|
nl->TheEmptyList(), first,
|
|
errorPos, errorInfo, correct ).addr;
|
|
|
|
if ( !correct )
|
|
{
|
|
errmsg = "InMapping(): Representation of Unit "
|
|
+ int2string(unitcounter) + " is wrong.";
|
|
errorInfo = nl->Append(errorInfo, nl->StringAtom(errmsg));
|
|
m->Destroy();
|
|
delete m;
|
|
return SetWord( Address(0) );
|
|
}
|
|
if( !unit->IsDefined() || !unit->IsValid() )
|
|
{
|
|
errmsg = "InMapping(): Unit " + int2string(unitcounter) + " is undef.";
|
|
errorInfo = nl->Append(errorInfo, nl->StringAtom(errmsg));
|
|
correct = false;
|
|
delete unit;
|
|
m->Destroy();
|
|
delete m;
|
|
return SetWord( Address(0) );
|
|
}
|
|
m->Add( *unit );
|
|
unitcounter++;
|
|
delete unit;
|
|
}
|
|
|
|
m->EndBulkLoad( true );
|
|
// cout<<*m<<endl;
|
|
////////////////////////////////////////////////////////////////////////
|
|
////////////// type of door: non-lift or lift////////////////////////////
|
|
/////////////////////////////////////////////////////////////////////////
|
|
ListExpr door_type = nl->Fourth(instance);
|
|
if(!nl->IsAtom(door_type) || nl->AtomType(door_type) != BoolType){
|
|
cout<< "door3d(): type must be bool type"<<endl;
|
|
correct = false;
|
|
return SetWord(Address(0));
|
|
}
|
|
|
|
bool dr_type = nl->BoolValue(door_type);
|
|
///////////////////////////////////////////////////////////////////////
|
|
Door3D* dr = new Door3D(oid1, oid2,*l1,*l2, *m, dr_type);
|
|
|
|
l1->DeleteIfAllowed();
|
|
l2->DeleteIfAllowed();
|
|
m->DeleteIfAllowed();
|
|
return SetWord(dr);
|
|
|
|
}
|
|
|
|
|
|
Word CreateDoor3D(const ListExpr typeInfo)
|
|
{
|
|
// cout<<"CreateDoor3D()"<<endl;
|
|
return SetWord (new Door3D(false));
|
|
}
|
|
|
|
|
|
void DeleteDoor3D(const ListExpr typeInfo, Word& w)
|
|
{
|
|
// cout<<"DeleteDoor3D()"<<endl;
|
|
Door3D* dr = (Door3D*)w.addr;
|
|
delete dr;
|
|
w.addr = NULL;
|
|
}
|
|
|
|
bool OpenDoor3D(SmiRecord& valueRecord, size_t& offset,
|
|
const ListExpr typeInfo, Word& value)
|
|
{
|
|
// cout<<"OpenDoor3D()"<<endl;
|
|
value.addr = new Door3D(valueRecord, offset, typeInfo);
|
|
return value.addr != NULL;
|
|
}
|
|
|
|
|
|
/*
|
|
save function for GenRange
|
|
|
|
*/
|
|
bool SaveDoor3D(SmiRecord& valueRecord, size_t& offset,
|
|
const ListExpr typeInfo, Word& value)
|
|
{
|
|
// cout<<"SaveDoor3D()"<<endl;
|
|
Door3D* dr = (Door3D*)value.addr;
|
|
return dr->Save(valueRecord, offset, typeInfo);
|
|
}
|
|
|
|
void CloseDoor3D( const ListExpr typeInfo, Word& w )
|
|
{
|
|
((Door3D*)w.addr)->DeleteIfAllowed();
|
|
w.addr = 0;
|
|
}
|
|
|
|
Word CloneDoor3D( const ListExpr typeInfo, const Word& w )
|
|
{
|
|
return SetWord( new Door3D( *((Door3D *)w.addr) ) );
|
|
}
|
|
|
|
void* CastDoor3D(void* addr)
|
|
{
|
|
return (new (addr) Door3D());
|
|
}
|
|
|
|
int SizeOfDoor3D()
|
|
{
|
|
return sizeof(Door3D);
|
|
}
|
|
|
|
bool CheckDoor3D( ListExpr type, ListExpr& errorInfo )
|
|
{
|
|
return (nl->IsEqual( type, "door3d" ));
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
///////////////////////////// GRoom //////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////////
|
|
/*
|
|
old version of region input
|
|
pointlist is to store the point in such a way that it is the same as for the
|
|
input.
|
|
1) Outercycle in a clock-wise and holes in a counter-clock wise
|
|
2) index list stores the start position of the first point for the outercycle
|
|
and the hole
|
|
|
|
*/
|
|
Word MyInRegion(const ListExpr typeInfo, const ListExpr instance,
|
|
const int errorPos, ListExpr& errorInfo, bool& correct,
|
|
int& cycno)
|
|
{
|
|
|
|
Region* cr = new Region( 0 );
|
|
cr->StartBulkLoad();
|
|
|
|
ListExpr RegionNL = instance;
|
|
ListExpr FaceNL, CycleNL;
|
|
int fcno = -1;
|
|
int ccno = -1;
|
|
int edno = -1;
|
|
int partnerno = 0;
|
|
if(nl->ListLength(RegionNL) > 1){
|
|
correct = false;
|
|
return SetWord(Address(0));
|
|
}
|
|
|
|
FaceNL = nl->First( RegionNL );
|
|
bool isCycle = true;
|
|
|
|
//A face is composed by 1 cycle, and can have holes.
|
|
//All the holes must be inside the face. (TO BE IMPLEMENTED0)
|
|
//Region *faceCycle;
|
|
|
|
fcno++;
|
|
ccno=-1;
|
|
edno=-1;
|
|
|
|
if (nl->IsAtom( FaceNL )){
|
|
correct=false;
|
|
return SetWord( Address(0) );
|
|
}
|
|
|
|
while (!nl->IsEmpty( FaceNL) ){ //several cycles (outer and hole)
|
|
CycleNL = nl->First( FaceNL );
|
|
FaceNL = nl->Rest( FaceNL );
|
|
|
|
|
|
ccno++;
|
|
edno=-1;
|
|
|
|
if (nl->IsAtom( CycleNL )){
|
|
correct=false;
|
|
return SetWord( Address(0) );
|
|
}
|
|
|
|
if (nl->ListLength( CycleNL) <3){
|
|
cerr << __PRETTY_FUNCTION__ << ": A cycle must have at least 3 edges!"
|
|
<< endl;
|
|
correct=false;
|
|
return SetWord( Address(0) );
|
|
}else{
|
|
ListExpr firstPoint = nl->First( CycleNL );
|
|
ListExpr prevPoint = nl->First( CycleNL );
|
|
ListExpr flagedSeg, currPoint;
|
|
CycleNL = nl->Rest( CycleNL );
|
|
|
|
//Starting to compute a new cycle
|
|
|
|
Points *cyclepoints= new Points( 8 ); // in memory
|
|
|
|
Point *currvertex,p1,p2,firstP;
|
|
|
|
//This function has the goal to store the half segments of
|
|
//the cycle that is been treated. When the cycle's computation
|
|
//is terminated the region rDir will be used to compute the
|
|
//insideAbove
|
|
//attribute of the half segments of this cycle.
|
|
Region *rDir = new Region(32);
|
|
rDir->StartBulkLoad();
|
|
|
|
|
|
currvertex = (Point*) InPoint ( nl->TheEmptyList(),
|
|
firstPoint, 0, errorInfo, correct ).addr;
|
|
if (!correct) {
|
|
// todo: delete temp objects
|
|
return SetWord( Address(0) );
|
|
}
|
|
|
|
cyclepoints->StartBulkLoad();
|
|
(*cyclepoints) += (*currvertex);
|
|
p1 = *currvertex;
|
|
firstP = p1;
|
|
cyclepoints->EndBulkLoad();
|
|
|
|
|
|
///////////////////////////////////////////////////////////////
|
|
////////////////////////one cycle /////////////////////////////
|
|
////////////////////////////////////////////////////////////////
|
|
delete currvertex;
|
|
cycno++;
|
|
while ( !nl->IsEmpty( CycleNL) ){
|
|
// cout<<"cycle "<<endl;
|
|
currPoint = nl->First( CycleNL );
|
|
CycleNL = nl->Rest( CycleNL );
|
|
|
|
currvertex = (Point*) InPoint( nl->TheEmptyList(),
|
|
currPoint, 0, errorInfo, correct ).addr;
|
|
|
|
|
|
// cout<<"curvertex "<<*currvertex<<endl;
|
|
if (!correct) return SetWord( Address(0) );
|
|
|
|
if (cyclepoints->Contains(*currvertex)){
|
|
cerr<< __PRETTY_FUNCTION__ << ": The same vertex: "
|
|
<<(*currvertex)
|
|
<<" appears repeatedly within the current cycle!"<<endl;
|
|
correct=false;
|
|
return SetWord( Address(0) );
|
|
}else{
|
|
p2 = *currvertex;
|
|
cyclepoints->StartBulkLoad();
|
|
(*cyclepoints) += (*currvertex);
|
|
cyclepoints->EndBulkLoad(true,false,false);
|
|
}
|
|
delete currvertex;
|
|
|
|
flagedSeg = nl->TwoElemList
|
|
(nl-> BoolAtom(true),
|
|
nl->TwoElemList(prevPoint, currPoint));
|
|
prevPoint=currPoint;
|
|
edno++;
|
|
//Create left dominating half segment
|
|
HalfSegment * hs = (HalfSegment*)InHalfSegment
|
|
( nl->TheEmptyList(), flagedSeg,
|
|
0, errorInfo, correct ).addr;
|
|
if(!correct){
|
|
if(hs){
|
|
cerr << __PRETTY_FUNCTION__ << ": Creation of left dominating "
|
|
<< "half segment (1) failed!" << endl;
|
|
delete hs;
|
|
}
|
|
cr->DeleteIfAllowed();
|
|
return SetWord( Address(0) );
|
|
}
|
|
hs->attr.faceno=fcno;
|
|
hs->attr.cycleno=ccno;
|
|
hs->attr.edgeno=edno;
|
|
hs->attr.partnerno=partnerno;
|
|
partnerno++;
|
|
hs->attr.insideAbove = (hs->GetLeftPoint() == p1);
|
|
//true (L-->R ),false (R--L)
|
|
p1 = p2;
|
|
|
|
if (( correct )&&( cr->InsertOk(*hs) )){
|
|
(*cr) += (*hs);
|
|
// cout<<"cr+1 "<<*hs<<endl;
|
|
if( hs->IsLeftDomPoint() ){
|
|
(*rDir) += (*hs);
|
|
// cout<<"rDr+1 "<<*hs<<endl;
|
|
hs->SetLeftDomPoint( false );
|
|
}else{
|
|
hs->SetLeftDomPoint( true );
|
|
// cout<<"rDr+2 "<<*hs<<endl;
|
|
(*rDir) += (*hs);
|
|
}
|
|
(*cr) += (*hs);
|
|
// cout<<"cr+2 "<<*hs<<endl;
|
|
delete hs;
|
|
}
|
|
else{
|
|
cerr<< __PRETTY_FUNCTION__ << ": Problematic HalfSegment: "
|
|
<< endl;
|
|
if(correct)
|
|
cerr << "\nhs = " << (*hs) << " cannot be inserted." << endl;
|
|
else
|
|
cerr << "\nInvalid half segment description." << endl;
|
|
correct=false;
|
|
return SetWord( Address(0) );
|
|
}
|
|
|
|
}
|
|
cyclepoints->DeleteIfAllowed();
|
|
|
|
|
|
edno++;
|
|
flagedSeg= nl->TwoElemList
|
|
(nl-> BoolAtom(true),
|
|
nl->TwoElemList(firstPoint, currPoint));
|
|
HalfSegment * hs = (HalfSegment*)InHalfSegment
|
|
( nl->TheEmptyList(), flagedSeg,
|
|
0, errorInfo, correct ).addr;
|
|
if(!correct){
|
|
if(hs){
|
|
cerr << __PRETTY_FUNCTION__ << ": Creation of "
|
|
<< "half segment (2) failed!" << endl;
|
|
delete hs;
|
|
}
|
|
cr->DeleteIfAllowed();
|
|
return SetWord( Address(0) );
|
|
}
|
|
hs->attr.faceno=fcno;
|
|
hs->attr.cycleno=ccno;
|
|
hs->attr.edgeno=edno;
|
|
hs->attr.partnerno=partnerno;
|
|
hs->attr.insideAbove = (hs->GetRightPoint() == firstP);
|
|
//true (L-->R ),false (R--L),
|
|
//the order of typing is last point than first point.
|
|
partnerno++;
|
|
|
|
//The last half segment of the region
|
|
if (( correct )&&( cr->InsertOk(*hs) )){
|
|
(*cr) += (*hs);
|
|
// cout<<"cr+3 "<<*hs<<endl;
|
|
if( hs->IsLeftDomPoint() ){
|
|
(*rDir) += (*hs);
|
|
// cout<<"rDr+3 "<<*hs<<endl;
|
|
hs->SetLeftDomPoint( false );
|
|
}else{
|
|
hs->SetLeftDomPoint( true );
|
|
// cout<<"rDr+4 "<<*hs<<endl;
|
|
(*rDir) += (*hs);
|
|
}
|
|
(*cr) += (*hs);
|
|
// cout<<"cr+4 "<<*hs<<endl;
|
|
delete hs;
|
|
rDir->EndBulkLoad(true, false, false, false);
|
|
|
|
|
|
//To calculate the inside above attribute
|
|
bool direction = rDir->GetCycleDirection();
|
|
|
|
int h = cr->Size() - ( rDir->Size() * 2 );
|
|
while ( h < cr->Size()){
|
|
//after each left half segment of the region is its
|
|
//correspondig right half segment
|
|
HalfSegment hsIA;
|
|
bool insideAbove;
|
|
cr->Get(h,hsIA);
|
|
|
|
if (direction == hsIA.attr.insideAbove)
|
|
insideAbove = false;
|
|
else
|
|
insideAbove = true;
|
|
if (!isCycle)
|
|
insideAbove = !insideAbove;
|
|
HalfSegment auxhsIA( hsIA );
|
|
auxhsIA.attr.insideAbove = insideAbove;
|
|
cr->UpdateAttr(h,auxhsIA.attr);
|
|
//Get right half segment
|
|
cr->Get(h+1,hsIA);
|
|
auxhsIA = hsIA;
|
|
auxhsIA.attr.insideAbove = insideAbove;
|
|
cr->UpdateAttr(h+1,auxhsIA.attr);
|
|
h+=2;
|
|
}
|
|
|
|
rDir->DeleteIfAllowed();
|
|
isCycle = false;
|
|
|
|
}
|
|
else{
|
|
correct=false;
|
|
return SetWord( Address(0) );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
cr->SetNoComponents( fcno+1 );
|
|
cr->EndBulkLoad( true, true, true, false );
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// cout<<"Area "<<cr->Area()<<endl;
|
|
correct = true;
|
|
return SetWord( cr );
|
|
}
|
|
|
|
/*
|
|
add one 3D region to the object
|
|
|
|
*/
|
|
void GRoom::Add(int id, float h,
|
|
vector<HalfSegment>& hs_list)
|
|
{
|
|
// cout<<"GRoom::Add()"<<endl;
|
|
|
|
int cur_points_size = seg_list.Size();
|
|
|
|
FloorElem felem;
|
|
felem.id = id;
|
|
// cout<<"start_pos "<<start_pos<<endl;
|
|
felem.start_pos = cur_points_size;
|
|
felem.num = hs_list.size();
|
|
felem.h = h;
|
|
|
|
// felem.Print();
|
|
elem_list.Append(felem);
|
|
for(unsigned int j = 0;j < hs_list.size();j++){
|
|
seg_list.Append(hs_list[j]);
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
get one 3D region with the height value
|
|
|
|
*/
|
|
void GRoom::Get(const int i, float& h, Region& r) const
|
|
{
|
|
if( 0 <= i && i < elem_list.Size()){
|
|
/////////colllect outer cycles and holes for the region //////////
|
|
vector<FloorElem> felem_list;
|
|
for(int j = 0;j < elem_list.Size();j++){
|
|
FloorElem elem;
|
|
elem_list.Get(j, elem);
|
|
if(elem.id == i){
|
|
felem_list.push_back(elem);
|
|
h = elem.h;
|
|
}
|
|
}
|
|
///////////////////////////////////////////////////////////////////
|
|
r.StartBulkLoad();
|
|
// cout<<"elem size "<<felem_list.size()<<endl;
|
|
for(unsigned int i = 0;i < felem_list.size();i++){
|
|
FloorElem felem = felem_list[i];
|
|
int start_pos = felem.start_pos;
|
|
int end_pos = felem.start_pos + felem.num;
|
|
// cout<<"start_pos "<<start_pos<<" end_pos "<<end_pos<<endl;
|
|
while(start_pos < end_pos){
|
|
HalfSegment hs;
|
|
seg_list.Get(start_pos, hs);
|
|
r += hs;
|
|
start_pos++;
|
|
}
|
|
}
|
|
r.SetNoComponents(1);
|
|
r.EndBulkLoad( true, true, true, false );
|
|
// cout<<r<<endl;
|
|
}else{
|
|
cout<<"not valid index in GRoom:Get()"<<endl;
|
|
assert(false);
|
|
}
|
|
}
|
|
|
|
/*
|
|
translate the 2D region of the groom
|
|
|
|
*/
|
|
void GRoom::Translate(const Coord& x, const Coord& y, GRoom& result)
|
|
{
|
|
result = *this;
|
|
for(int i = 0;i < result.SegSize();i++){
|
|
HalfSegment hs;
|
|
result.GetSeg(i, hs);
|
|
hs.Translate(x, y);
|
|
result.PutSeg(i, hs);
|
|
}
|
|
}
|
|
|
|
/*
|
|
get the 2D area covered by the region
|
|
|
|
*/
|
|
|
|
void GRoom::GetRegion(Region& r)
|
|
{
|
|
for( int i = 0; i < Size(); i++ ){
|
|
Region temp_reg(0);
|
|
float h;
|
|
Get( i, h, temp_reg);
|
|
Region* res = new Region(0);
|
|
r.Union(temp_reg, *res);
|
|
r = *res;
|
|
res->DeleteIfAllowed();
|
|
}
|
|
}
|
|
|
|
std::ostream& GRoom::Print(std::ostream& o) const
|
|
{
|
|
for( int i = 0; i < Size(); i++ ){
|
|
Region r(0);
|
|
float h;
|
|
Get( i, h, r);
|
|
o<<"elem "<<i<<" height "<<h<<endl;
|
|
o<<r<<endl;
|
|
}
|
|
return o;
|
|
}
|
|
|
|
/*
|
|
return the lowest height of a groom
|
|
|
|
*/
|
|
float GRoom::GetLowHeight()
|
|
{
|
|
float h = numeric_limits<float>::max();
|
|
for( int i = 0; i < elem_list.Size(); i++ ){
|
|
FloorElem felem;
|
|
elem_list.Get(i, felem);
|
|
if(felem.h < h)
|
|
h = felem.h;
|
|
}
|
|
return h;
|
|
}
|
|
|
|
/*
|
|
return the highest height of a groom
|
|
|
|
*/
|
|
float GRoom::GetHighHeight()
|
|
{
|
|
// float h = numeric_limits<float>::min(); //returns a positive value
|
|
float h = MIN_FLOOR_HEIGHT;
|
|
for( int i = 0; i < elem_list.Size(); i++ ){
|
|
FloorElem felem;
|
|
elem_list.Get(i, felem);
|
|
assert(felem.h > MIN_FLOOR_HEIGHT);
|
|
if(felem.h > h)
|
|
h = felem.h;
|
|
}
|
|
return h;
|
|
}
|
|
|
|
/*
|
|
get the 3D box of a groom
|
|
|
|
*/
|
|
const Rectangle<3> GRoom::BoundingBox3D() const
|
|
{
|
|
|
|
Rectangle<3> bbox;
|
|
for( int i = 0; i < Size(); i++ ){
|
|
Region r(0);
|
|
float h;
|
|
Get( i, h, r);
|
|
if( i == 0 ){
|
|
Rectangle<2> reg_box = r.BoundingBox();
|
|
double minMax[] = { reg_box.MinD(0), reg_box.MaxD(0),
|
|
reg_box.MinD(1), reg_box.MaxD(1),
|
|
h, h + ApplyFactor(h)};
|
|
bbox = Rectangle<3>(true,minMax);
|
|
}else{
|
|
Rectangle<2> reg_box = r.BoundingBox();
|
|
double minMax[] = {reg_box.MinD(0), reg_box.MaxD(0),
|
|
reg_box.MinD(1), reg_box.MaxD(1),
|
|
h, h + ApplyFactor(h)};
|
|
Rectangle<3> bbox1 =
|
|
Rectangle<3>(true,minMax );
|
|
bbox = bbox.Union(bbox1);
|
|
|
|
}
|
|
}
|
|
return bbox;
|
|
}
|
|
|
|
/*
|
|
Groom Property function
|
|
|
|
*/
|
|
ListExpr GRoomProperty()
|
|
{
|
|
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("groom"),
|
|
nl->StringAtom("(<floor3d>*) ((f1 floor3d)(f2 floor3d))"),
|
|
nl->StringAtom("((f1)(f2))"))));
|
|
}
|
|
|
|
/*
|
|
output the list expression for Staircase3D
|
|
|
|
*/
|
|
ListExpr OutGRoom( ListExpr typeInfo, Word value )
|
|
{
|
|
// cout<<"OutGRoom()"<<endl;
|
|
|
|
GRoom* gr = (GRoom*)(value.addr);
|
|
if(!gr->IsDefined()){
|
|
return nl->SymbolAtom("undef");
|
|
}
|
|
|
|
if( gr->IsEmpty() ){
|
|
return nl->TheEmptyList();
|
|
}
|
|
// cout<<"stair size "<<stair->Size()<<endl;
|
|
|
|
bool first = true;
|
|
ListExpr result = nl->TheEmptyList();
|
|
ListExpr last = result;
|
|
ListExpr sb_list;
|
|
for( int i = 0; i < gr->Size(); i++ ){
|
|
Region r(0);
|
|
float h;
|
|
gr->Get( i, h, r);
|
|
|
|
sb_list = nl->TwoElemList(nl->RealAtom(h),
|
|
OutRegion(nl->TheEmptyList(), SetWord(&r)));
|
|
|
|
if( first == true ){
|
|
result = nl->OneElemList( sb_list );
|
|
last = result;
|
|
first = false;
|
|
}else
|
|
last = nl->Append( last, sb_list);
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
In function
|
|
|
|
*/
|
|
Word InGRoom( const ListExpr typeInfo, const ListExpr instance,
|
|
const int errorPos, ListExpr& errorInfo, bool& correct )
|
|
{
|
|
if(nl->IsEqual(instance,"undef")) {
|
|
correct = false;
|
|
return SetWord(Address(0));
|
|
}
|
|
|
|
GRoom* gr = new GRoom(0);
|
|
// cout<<"length "<<nl->ListLength(instance)<<endl;
|
|
ListExpr floor_nl = instance;
|
|
int count = 0;
|
|
while(!nl->IsEmpty(floor_nl)){
|
|
ListExpr first = nl->First(floor_nl);
|
|
floor_nl = nl->Rest(floor_nl);
|
|
|
|
ListExpr height_nl = nl->First(first);
|
|
|
|
if(!(nl->IsAtom(height_nl) && nl->AtomType(height_nl) == RealType)){
|
|
cout<<"real value expected for height"<<endl;
|
|
correct = false;
|
|
return SetWord(Address(0));
|
|
}
|
|
float height = nl->RealValue(height_nl);
|
|
// cout<<"height "<<height<<endl;
|
|
///////////////////////////////////////////////////////////////////////
|
|
///////////////////////read the region ///////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////
|
|
int cycleno = 0;
|
|
Region* reg = (Region*)MyInRegion(typeInfo, nl->Second(first),
|
|
errorPos, errorInfo, correct, cycleno).addr;
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
///////////////temporally///////////////////////////////////////////
|
|
// Region* temp = new Region(0);
|
|
// reg->Translate(10.0, 0.0, *temp);
|
|
// *reg = *temp;
|
|
// delete temp;
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////
|
|
// cout<<"Area "<<reg->Area()<<endl;
|
|
// cout<<"point size "<<point_list.size()
|
|
// <<"index size "<<index_list.size()<<endl;
|
|
|
|
// for(unsigned int i = 0;i < point_list.size();i++)
|
|
// cout<<point_list[i];
|
|
|
|
// for(unsigned int i = 0;i < index_list.size();i++)
|
|
// cout<<"index "<<index_list[i]<<" num "<<num_list[i]<<endl;
|
|
///////////////////////////////////////////////////////////////
|
|
if(reg->NoComponents() != 1 || cycleno == 0){//only one face is allowed
|
|
cout<<"invalid region input "<<endl;
|
|
correct = false;
|
|
return SetWord(Address(0));
|
|
}
|
|
for(int i = 0;i < cycleno;i++){
|
|
vector<HalfSegment> hs_list;
|
|
for(int j = 0;j < reg->Size();j++){
|
|
HalfSegment hs;
|
|
reg->Get(j, hs);
|
|
if(hs.attr.cycleno == i){
|
|
hs_list.push_back(hs);
|
|
}
|
|
}
|
|
// cout<<i <<" seg list size "<<hs_list.size()<<endl;
|
|
if(i == 0)
|
|
gr->Add(count, height, hs_list);
|
|
else
|
|
gr->Add(count, height, hs_list);
|
|
|
|
}
|
|
|
|
count++;
|
|
}
|
|
////////////////very important ////////////////////////////////
|
|
correct = true;
|
|
////////////////////////////////////////////////////////
|
|
return SetWord(gr);
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
Open a GRoom object
|
|
|
|
*/
|
|
bool OpenGRoom(SmiRecord& valueRecord, size_t& offset,
|
|
const ListExpr typeInfo, Word& value)
|
|
{
|
|
// cout<<"OpenGRoom()"<<endl;
|
|
|
|
GRoom* gr = (GRoom*)Attribute::Open(valueRecord, offset, typeInfo);
|
|
value = SetWord(gr);
|
|
// cout<<gr->ElemSize()<<" "<<gr->SegSize()<<endl;
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
Save a GRoom object
|
|
|
|
*/
|
|
bool SaveGRoom(SmiRecord& valueRecord, size_t& offset,
|
|
const ListExpr typeInfo, Word& value)
|
|
{
|
|
// cout<<"SaveGRoom"<<endl;
|
|
GRoom* gr = (GRoom*)value.addr;
|
|
Attribute::Save(valueRecord, offset, typeInfo, gr);
|
|
// cout<<gr->ElemSize()<<" "<<gr->SegSize()<<endl;
|
|
return true;
|
|
}
|
|
|
|
|
|
/*
|
|
create function for GRoom
|
|
|
|
*/
|
|
|
|
Word CreateGRoom(const ListExpr typeInfo)
|
|
{
|
|
// cout<<"CreateGRoom()"<<endl;
|
|
return SetWord (new GRoom(0));
|
|
}
|
|
|
|
/*
|
|
Delete function for GRoom
|
|
|
|
*/
|
|
|
|
void DeleteGRoom(const ListExpr typeInfo, Word& w)
|
|
{
|
|
// cout<<"DeleteGRoom()"<<endl;
|
|
GRoom* gr = (GRoom*)w.addr;
|
|
delete gr;
|
|
w.addr = NULL;
|
|
}
|
|
|
|
|
|
void CloseGRoom( const ListExpr typeInfo, Word& w )
|
|
{
|
|
// cout<<"CloseGRoom"<<endl;
|
|
((GRoom*)w.addr)->DeleteIfAllowed();
|
|
w.addr = 0;
|
|
}
|
|
|
|
Word CloneGRoom( const ListExpr typeInfo, const Word& w )
|
|
{
|
|
// cout<<"CloneGRoom"<<endl;
|
|
return SetWord( new GRoom( *((GRoom *)w.addr) ) );
|
|
}
|
|
|
|
void* CastGRoomD(void* addr)
|
|
{
|
|
// cout<<"CastGRoomD"<<endl;
|
|
return (new (addr) GRoom());
|
|
}
|
|
|
|
int SizeOfGRoom()
|
|
{
|
|
// cout<<"SizeOfGroom"<<endl;
|
|
return sizeof(GRoom);
|
|
}
|
|
|
|
bool CheckGRoom( ListExpr type, ListExpr& errorInfo )
|
|
{
|
|
// cout<<"CheckGroom"<<endl;
|
|
return (nl->IsEqual( type, "groom" ));
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/////////////////////////////Indoor Navigation///////////////////////////////
|
|
////////////////////////////////////////////////////////////////////////////
|
|
string IndoorNav::Indoor_GRoom_Door =
|
|
"(rel(tuple((Oid int)(Name string)(Type string)(Room groom)(Door line))))";
|
|
|
|
/*
|
|
create a 3d line for the door. We use RTree to find doors that their
|
|
locations are the same in space.
|
|
Because for the data type door3d, we have to know the relative position in
|
|
each room.
|
|
|
|
*/
|
|
void IndoorNav::CreateDoor3D()
|
|
{
|
|
// cout<<"CreateDoor3D()"<<endl;
|
|
|
|
vector<float> floor_height;
|
|
for(int i = 1;i <= rel1->GetNoTuples();i++){
|
|
Tuple* indoor_tuple = rel1->GetTuple(i, false);
|
|
string s = ((CcString*)indoor_tuple->GetAttribute(I_Type))->GetValue();
|
|
if(GetRoomEnum(s) == EL){
|
|
GRoom* groom = (GRoom*)indoor_tuple->GetAttribute(I_Room);
|
|
float h = groom->GetLowHeight();
|
|
if(floor_height.size() == 0)
|
|
floor_height.push_back(h);
|
|
else{
|
|
unsigned int j = 0;
|
|
for(;j < floor_height.size();j++){
|
|
if(AlmostEqual(floor_height[j], h))break;
|
|
}
|
|
if(j == floor_height.size())
|
|
floor_height.push_back(h);
|
|
}
|
|
}
|
|
indoor_tuple->DeleteIfAllowed();
|
|
}
|
|
sort(floor_height.begin(), floor_height.end());
|
|
|
|
// cout<<"rel1 no "<<rel1->GetNoTuples()<<endl;
|
|
for(int i = 1;i <= rel1->GetNoTuples();i++){
|
|
Tuple* indoor_tuple = rel1->GetTuple(i, false);
|
|
GRoom* groom = (GRoom*)indoor_tuple->GetAttribute(I_Room);
|
|
Line* l = (Line*)indoor_tuple->GetAttribute(I_Door);
|
|
int oid = ((CcInt*)indoor_tuple->GetAttribute(I_OID))->GetIntval();
|
|
|
|
string s = ((CcString*)indoor_tuple->GetAttribute(I_Type))->GetValue();
|
|
|
|
// groom->Print();
|
|
// cout<<*l<<endl;
|
|
// cout<<"type "<<s<<endl;
|
|
float h = groom->GetLowHeight();
|
|
CreateLine3D(oid, l, h);
|
|
|
|
/////////////////3D box x,y,z ////////////////////////
|
|
if(GetRoomEnum(s) == ST){//Staircase
|
|
// cout<<"one more box needed"<<endl;
|
|
h = groom->GetHighHeight();
|
|
CreateLine3D(oid, l, h);
|
|
}
|
|
|
|
if(GetRoomEnum(s) == EL){//Elevator
|
|
// cout<<"one more box needed"<<endl;
|
|
bool flag_h = false;
|
|
h = NextFloorHeight(h, floor_height, flag_h);
|
|
// if(h > 0.0){
|
|
if(flag_h){
|
|
CreateLine3D(oid, l, h);
|
|
}
|
|
}
|
|
|
|
indoor_tuple->DeleteIfAllowed();
|
|
}
|
|
}
|
|
|
|
/*
|
|
create a 3d line
|
|
|
|
*/
|
|
void IndoorNav::CreateLine3D(int oid, Line* l, float h)
|
|
{
|
|
// cout<<"oid "<<oid<<" line "<<*l<<" h "<<h<<endl;
|
|
for(int i = 0;i < l->Size();i++){
|
|
HalfSegment hs;
|
|
l->Get(i, hs);
|
|
if(hs.IsLeftDomPoint() == false) continue;
|
|
Point lp = hs.GetLeftPoint();
|
|
Point rp = hs.GetRightPoint();
|
|
Line3D* l3d = new Line3D(0);
|
|
l3d->StartBulkLoad();
|
|
Point3D q1(true, lp.GetX(), lp.GetY(), h);
|
|
*l3d += q1;
|
|
Point3D q2(true, rp.GetX(), rp.GetY(), h);
|
|
*l3d += q2;
|
|
l3d->EndBulkLoad();
|
|
|
|
groom_oid_list.push_back(oid);
|
|
path_list.push_back(*l3d);
|
|
l3d->DeleteIfAllowed();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
create a 3D box for each door. return (oid, tid, box3d)
|
|
for staircase and elevator. In the original data, it only stores the door for
|
|
each floor, but in fact the staircase and elevator builds the connection
|
|
between two floors. so, we create one more door for staircase and elevator
|
|
|
|
If a groom has several 3D regions, the door normally is located at the lowest
|
|
level
|
|
|
|
The result is: for each groom, we create its doors. so usually, the door
|
|
(spatial locatin in space) will be represented twice because it connects two
|
|
rooms.
|
|
|
|
*/
|
|
void IndoorNav::CreateDoorBox()
|
|
{
|
|
/////////////// collect the height value for each floor///////////////////
|
|
//////////////// for staircase and elevator //////////////////////////////
|
|
vector<float> floor_height;
|
|
for(int i = 1;i <= rel1->GetNoTuples();i++){
|
|
Tuple* indoor_tuple = rel1->GetTuple(i, false);
|
|
string s = ((CcString*)indoor_tuple->GetAttribute(I_Type))->GetValue();
|
|
if(GetRoomEnum(s) == EL){
|
|
GRoom* groom = (GRoom*)indoor_tuple->GetAttribute(I_Room);
|
|
float h = groom->GetLowHeight();
|
|
if(floor_height.size() == 0)
|
|
floor_height.push_back(h);
|
|
else{
|
|
unsigned int j = 0;
|
|
for(;j < floor_height.size();j++){
|
|
if(AlmostEqual(floor_height[j], h))break;
|
|
}
|
|
if(j == floor_height.size())
|
|
floor_height.push_back(h);
|
|
}
|
|
}
|
|
indoor_tuple->DeleteIfAllowed();
|
|
}
|
|
sort(floor_height.begin(), floor_height.end());
|
|
|
|
// for(unsigned int i = 0;i < floor_height.size();i++)
|
|
// cout<<"floor "<<i<<" height "<<floor_height[i]<<endl;
|
|
|
|
|
|
// cout<<"rel1 no "<<rel1->GetNoTuples()<<endl;
|
|
|
|
for(int i = 1;i <= rel1->GetNoTuples();i++){
|
|
Tuple* indoor_tuple = rel1->GetTuple(i, false);
|
|
GRoom* groom = (GRoom*)indoor_tuple->GetAttribute(I_Room);
|
|
Line* l = (Line*)indoor_tuple->GetAttribute(I_Door);
|
|
int oid = ((CcInt*)indoor_tuple->GetAttribute(I_OID))->GetIntval();
|
|
int tid = indoor_tuple->GetTupleId();
|
|
string s = ((CcString*)indoor_tuple->GetAttribute(I_Type))->GetValue();
|
|
// groom->Print();
|
|
// cout<<*l<<endl;
|
|
// cout<<"type "<<s<<endl;
|
|
float h = groom->GetLowHeight();
|
|
CreateBox3D(oid, tid, l, h);
|
|
|
|
/////////////////3D box x,y,z ////////////////////////
|
|
|
|
if(GetRoomEnum(s) == ST){//Staircase
|
|
// cout<<"one more box needed"<<endl;
|
|
h = groom->GetHighHeight();
|
|
CreateBox3D(oid, tid, l, h);
|
|
}
|
|
|
|
if(GetRoomEnum(s) == EL){// Elevator
|
|
// cout<<"one more box needed"<<endl;
|
|
bool flag_h = false;
|
|
h = NextFloorHeight(h, floor_height, flag_h);
|
|
// if(h > 0.0){
|
|
if(flag_h){
|
|
CreateBox3D(oid, tid, l, h);
|
|
}
|
|
}
|
|
|
|
indoor_tuple->DeleteIfAllowed();
|
|
}
|
|
}
|
|
|
|
/*
|
|
get the floor height in the next higher level
|
|
|
|
*/
|
|
float IndoorNav::NextFloorHeight(float h,
|
|
vector<float>& floor_height, bool& flag_h)
|
|
{
|
|
for(unsigned int i = 0;i < floor_height.size();i++){
|
|
if(AlmostEqual(h, floor_height[i])){
|
|
if(i != floor_height.size() - 1){
|
|
flag_h = true;
|
|
return floor_height[ i + 1];
|
|
}
|
|
else{
|
|
flag_h = false;
|
|
return -1.0;
|
|
}
|
|
}
|
|
}
|
|
assert(false);
|
|
// return -1.0;
|
|
}
|
|
|
|
void IndoorNav::CreateBox3D(int oid, int tid, Line* l, float h)
|
|
{
|
|
// const double delta_h = 0.01;
|
|
// cout<<"oid "<<oid<<" tid "<<tid<<" height "<<h<<endl;
|
|
// cout<<"line "<<*l<<endl;
|
|
const double delta = 0.001;
|
|
if(fabs(h) < delta) h = 0.0;
|
|
|
|
for(int i = 0;i < l->Size();i++){
|
|
HalfSegment hs;
|
|
l->Get(i, hs);
|
|
if(hs.IsLeftDomPoint() == false) continue;
|
|
double min[3];
|
|
double max[3];
|
|
Point lp = hs.GetLeftPoint();
|
|
Point rp = hs.GetRightPoint();
|
|
min[0] = MIN(lp.GetX(), rp.GetX());
|
|
min[1] = MIN(lp.GetY(), rp.GetY());
|
|
min[2] = h;
|
|
|
|
max[0] = MAX(lp.GetX(), rp.GetX());
|
|
max[1] = MAX(lp.GetY(), rp.GetY());
|
|
// max[2] = h + delta_h;
|
|
max[2] = h + ApplyFactor(h);
|
|
|
|
Rectangle<3> bbox3d(true, min, max);
|
|
oid_list.push_back(oid);
|
|
tid_list.push_back(tid);
|
|
box_list.push_back(bbox3d);
|
|
// cout<<"i "<<i<<bbox3d<<endl;
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
create a relation storing the doors of a building
|
|
|
|
*/
|
|
void IndoorNav::CreateDoor1(R_Tree<3, TupleId>* rtree,
|
|
int attr1, int attr2, int attr3)
|
|
{
|
|
///////////// minimum and maximum height of the building////////////////
|
|
vector<float> height_list;
|
|
for(int i = 1;i <= rel1->GetNoTuples();i++){
|
|
Tuple* groom_tuple = rel1->GetTuple(i, false);
|
|
GRoom* groom = (GRoom*)groom_tuple->GetAttribute(I_Room);
|
|
height_list.push_back(groom->GetLowHeight());
|
|
groom_tuple->DeleteIfAllowed();
|
|
}
|
|
sort(height_list.begin(), height_list.end());
|
|
///////////////////////////////////////////////////////////////////////
|
|
float max_height = height_list[ height_list.size() - 1];
|
|
// cout<<"max_height "<<max_height<<endl;
|
|
|
|
// cout<<"CreateDoor()"<<endl;
|
|
// cout<<"attr1 "<<attr1<<" attr2 "<<attr2<<" attr3 "<<attr3<<endl;
|
|
SmiRecordId adr = rtree->RootRecordId();
|
|
|
|
for(int i = 1;i <= rel2->GetNoTuples();i++){
|
|
|
|
Tuple* door_tuple = rel2->GetTuple(i, false);
|
|
int oid = ((CcInt*)door_tuple->GetAttribute(attr1))->GetIntval();
|
|
int tid = ((CcInt*)door_tuple->GetAttribute(attr2))->GetIntval();
|
|
Rectangle<3>* bbox3d = (Rectangle<3>*)door_tuple->GetAttribute(attr3);
|
|
|
|
unsigned int id = door_tuple->GetTupleId();
|
|
|
|
/* if(oid != 81){
|
|
door_tuple->DeleteIfAllowed();
|
|
continue;
|
|
}*/
|
|
|
|
vector<TupleId> id_list;
|
|
// cout<<"oid "<<oid<<" tid "<<tid<<endl;
|
|
// cout<<"bbox3d -- line "<<*bbox3d<<endl;
|
|
DFTraverse(rtree, adr, id, bbox3d, attr1, attr2, attr3, id_list);
|
|
|
|
// cout<<"neighbor size "<<id_list.size()<<endl;
|
|
|
|
// for(unsigned int j = 0;j < id_list.size();j++)
|
|
// cout<<"neighbor tuple id "<<id_list[j]<<endl;
|
|
// cout<<endl;
|
|
|
|
//for staircase and elevator, size = 2
|
|
//the floor at i and i+1 are both represented
|
|
// the size can be 0 at some special places after translating
|
|
assert(id_list.size() <= 2);
|
|
///////////// create the result ///////////////////////////////
|
|
////////// use tid to get the tuple /////////////////////////
|
|
/////////// use the tuple to get oid and line ////////////////
|
|
// if(id_list.size() == 1)
|
|
CreateResDoor(id, oid, tid, id_list, attr1, attr2, attr3);
|
|
|
|
//////////////special door for the building entrance ///////////////
|
|
if(id_list.size() == 0 && IsGRoom(tid, rel1)){
|
|
if(AlmostEqual(max_height, bbox3d->MinD(2))){
|
|
// cout<<"find "<<endl;
|
|
// cout<<"oid "<<oid<<"tid "<<tid<<" rect "<<*bbox3d<<endl;
|
|
/////////////create entrance door for the building//////////////
|
|
CreateEntranceDoor(id, oid, tid, attr1, attr2, attr3);
|
|
}else if(AlmostEqual(bbox3d->MinD(2), 0.0)){//height 0 = underground level
|
|
/////////////////////////////////////////////////////////////////
|
|
////////////////////we define 0.0 for the first level////////////
|
|
/////////////////where the building entrance is located//////////
|
|
////////////////this is for buildings have underground level/////
|
|
//////////////////////trainstation, hospital/////////////////////
|
|
///////////////////// mall /////////////////////////////////////
|
|
/////////////////////////////////////////////////////////////////
|
|
// cout<<"underground here"<<endl;
|
|
// cout<<"oid "<<oid<<"tid "<<tid<<" rect "<<*bbox3d<<endl;
|
|
CreateEntranceDoor(id, oid, tid, attr1, attr2, attr3);
|
|
}
|
|
|
|
}
|
|
|
|
door_tuple->DeleteIfAllowed();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
check whether the room is OR or CO. excludes BR, ST, EL
|
|
|
|
*/
|
|
bool IndoorNav::IsGRoom(int tid, Relation* rel)
|
|
{
|
|
assert(1 <= tid && tid <= rel->GetNoTuples());
|
|
Tuple* groom_tuple = rel->GetTuple(tid, false);
|
|
string type = ((CcString*)groom_tuple->GetAttribute(I_Type))->GetValue();
|
|
groom_tuple->DeleteIfAllowed();
|
|
if(GetRoomEnum(type) == OR || GetRoomEnum(type) == CO)
|
|
return true;
|
|
else
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
create the result for door relation: door3d line groomid1 groomid2
|
|
for data type line, region, mbool, the function operator=() is not
|
|
correctly impelmented. it should copy the value from the dbarray instead of
|
|
calling copyfrom.
|
|
|
|
It is no problem in memory, but has problems in disk for storage
|
|
|
|
*/
|
|
void IndoorNav::CreateResDoor(int id, int oid, int tid, vector<TupleId> id_list,
|
|
int attr1, int attr2, int attr3)
|
|
{
|
|
|
|
for(unsigned int i = 0;i < id_list.size();i++){
|
|
|
|
/////////////// first door in one groom ////////////////////
|
|
Tuple* indoor_tuple1 = rel1->GetTuple(tid, false);
|
|
int oid1 = ((CcInt*)indoor_tuple1->GetAttribute(I_OID))->GetIntval();
|
|
assert(oid1 == oid);
|
|
string type1 = ((CcString*)indoor_tuple1->GetAttribute(I_Type))->GetValue();
|
|
GRoom* groom1 = (GRoom*)indoor_tuple1->GetAttribute(I_Room);
|
|
Tuple* box_tuple1 = rel2->GetTuple(id, false);
|
|
Rectangle<3>* bbox3d_1 = (Rectangle<3>*)box_tuple1->GetAttribute(attr3);
|
|
// cout<<"bbox3d 1 "<<*bbox3d_1<<endl;
|
|
Rectangle<2> groom_box1 = groom1->BoundingBox();
|
|
|
|
/////////////// second door in one groom ////////////////////
|
|
Tuple* box_tuple2 = rel2->GetTuple(id_list[i], false);
|
|
int oid2 = ((CcInt*)box_tuple2->GetAttribute(attr1))->GetIntval();
|
|
int groom_tid = ((CcInt*)box_tuple2->GetAttribute(attr2))->GetIntval();
|
|
/* if(oid2 != 385){
|
|
indoor_tuple1->DeleteIfAllowed();
|
|
box_tuple1->DeleteIfAllowed();
|
|
box_tuple2->DeleteIfAllowed();
|
|
continue;
|
|
}*/
|
|
|
|
|
|
assert(1 <= groom_tid && groom_tid <= rel1->GetNoTuples());
|
|
|
|
Tuple* indoor_tuple2 = rel1->GetTuple(groom_tid, false);
|
|
|
|
string type2 = ((CcString*)indoor_tuple2->GetAttribute(I_Type))->GetValue();
|
|
GRoom* groom2 = (GRoom*)indoor_tuple2->GetAttribute(I_Room);
|
|
|
|
Rectangle<3>* bbox3d_2 = (Rectangle<3>*)box_tuple2->GetAttribute(attr3);
|
|
Rectangle<2> groom_box2 = groom2->BoundingBox();
|
|
// cout<<"bbox3d 2 "<<*bbox3d_2<<endl;
|
|
///////////////////////////////////////////////////////////////////
|
|
///////////////create moving bool/////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////
|
|
MBool* mb1 = new MBool(0);
|
|
CreateDoorState(mb1);
|
|
|
|
|
|
bool lift_door = false;
|
|
if(GetRoomEnum(type1) == EL || GetRoomEnum(type2) == EL)
|
|
lift_door = true;
|
|
//////////////////////////////////////////////////////////////////
|
|
///////////////// the position of the door in space /////////////
|
|
//////////////////////////////////////////////////////////////////
|
|
|
|
// cout<<"line1 "<<*l1<<" line2 "<<*l2<<endl;
|
|
////////////////////////////////////////////////////////////////
|
|
/////////////////////create line //////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
Line* l1 = new Line(0);
|
|
Line* l2 = new Line(0);
|
|
Line* l3 = new Line(0);
|
|
Line3D* l3d_1 = new Line3D(0);
|
|
GRoomDoorLine(bbox3d_1, bbox3d_2, l1, l2, l3, &groom_box1,
|
|
&groom_box2, l3d_1, bbox3d_1->MinD(2));
|
|
|
|
///////////////////// create the door //////////////////////////////
|
|
Door3D* door_obj1 = new Door3D(oid1, oid2, *l1, *l2, *mb1, lift_door);
|
|
////////////////////// result ///////////////////////////////
|
|
door_list.push_back(*door_obj1);
|
|
line_list.push_back(*l3);
|
|
groom_id_list1.push_back(oid1);
|
|
groom_id_list2.push_back(oid2);
|
|
path_list.push_back(*l3d_1);
|
|
door_heights.push_back(bbox3d_1->MinD(2));
|
|
|
|
|
|
l1->DeleteIfAllowed();
|
|
l2->DeleteIfAllowed();
|
|
l3->DeleteIfAllowed();
|
|
delete door_obj1;
|
|
l3d_1->DeleteIfAllowed();
|
|
mb1->DeleteIfAllowed();
|
|
|
|
/////////////////////////////////////////////////////////////
|
|
box_tuple1->DeleteIfAllowed();
|
|
box_tuple2->DeleteIfAllowed();
|
|
indoor_tuple2->DeleteIfAllowed();
|
|
indoor_tuple1->DeleteIfAllowed();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
create the time-dependent state for the door
|
|
|
|
*/
|
|
void IndoorNav::CreateDoorState(MBool* mb)
|
|
{
|
|
Instant start_time(instanttype);
|
|
start_time.ReadFrom("2010-12-5-0:0:0");
|
|
Instant end_time(instanttype);
|
|
end_time.ReadFrom("2010-12-6-0:0:0");
|
|
|
|
Instant begin_time(instanttype);
|
|
begin_time.ReadFrom("begin of time");
|
|
Instant finish_time(instanttype);
|
|
finish_time.ReadFrom("end of time");
|
|
|
|
mb->StartBulkLoad();
|
|
UBool ub1;
|
|
ub1.timeInterval.start = begin_time;
|
|
ub1.timeInterval.end = start_time;
|
|
|
|
ub1.timeInterval.lc = true;
|
|
ub1.timeInterval.rc = false;
|
|
ub1.constValue.Set(true, true);
|
|
ub1.SetDefined(true);
|
|
|
|
|
|
UBool ub2;
|
|
ub2.timeInterval.start = start_time;
|
|
ub2.timeInterval.end = end_time;
|
|
|
|
ub2.timeInterval.lc = true;
|
|
ub2.timeInterval.rc = false;
|
|
ub2.constValue.Set(true, true);
|
|
ub2.SetDefined(true);
|
|
|
|
UBool ub3;
|
|
ub3.timeInterval.start = end_time;
|
|
ub3.timeInterval.end = finish_time;
|
|
|
|
ub3.timeInterval.lc = true;
|
|
ub3.timeInterval.rc = false;
|
|
ub3.constValue.Set(true, true);
|
|
ub3.SetDefined(true);
|
|
|
|
// ub1.Print(cout);
|
|
// ub2.Print(cout);
|
|
// ub3.Print(cout);
|
|
|
|
mb->Add(ub1);
|
|
mb->Add(ub2);
|
|
mb->Add(ub3);
|
|
mb->EndBulkLoad();
|
|
}
|
|
|
|
/*
|
|
depth-first traverse the Rtree to find the element (line3d) intersects the
|
|
bbox3d
|
|
|
|
*/
|
|
void IndoorNav::DFTraverse(R_Tree<3,TupleId>* rtree, SmiRecordId adr,
|
|
unsigned int id,
|
|
Rectangle<3>* bbox3d,
|
|
int attr1, int attr2, int attr3,
|
|
vector<TupleId>& id_list)
|
|
{
|
|
R_TreeNode<3,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<3,TupleId> e =
|
|
(R_TreeLeafEntry<3,TupleId>&)(*node)[j];
|
|
Tuple* box_tuple = rel2->GetTuple(e.info,false);
|
|
Rectangle<3>* b =
|
|
(Rectangle<3>*)box_tuple->GetAttribute(attr3);
|
|
if(b->Intersects(*bbox3d) && id != e.info){
|
|
Tuple* box_tuple = rel2->GetTuple(e.info, false);
|
|
Rectangle<3>* bbox_3d =
|
|
(Rectangle<3>*)box_tuple->GetAttribute(attr3);
|
|
|
|
if(BBox3DEqual(bbox3d, bbox_3d))
|
|
id_list.push_back(e.info);
|
|
box_tuple->DeleteIfAllowed();
|
|
}
|
|
box_tuple->DeleteIfAllowed();
|
|
}else{
|
|
R_TreeInternalEntry<3> e =
|
|
(R_TreeInternalEntry<3>&)(*node)[j];
|
|
if(bbox3d->Intersects(e.box)){
|
|
DFTraverse(rtree, e.pointer, id, bbox3d,
|
|
attr1, attr2, attr3, id_list);
|
|
}
|
|
}
|
|
}
|
|
delete node;
|
|
|
|
}
|
|
|
|
/*
|
|
create entrance door of the building
|
|
if it is the entrance of the building, we set groom oid1: oid1, groom oid2:-1
|
|
|
|
*/
|
|
void IndoorNav::CreateEntranceDoor(int id, int oid, int tid,
|
|
int attr1, int attr2, int attr3)
|
|
{
|
|
|
|
/////////////// first door in one groom ////////////////////
|
|
Tuple* indoor_tuple1 = rel1->GetTuple(tid, false);
|
|
int oid1 = ((CcInt*)indoor_tuple1->GetAttribute(I_OID))->GetIntval();
|
|
assert(oid1 == oid);
|
|
string type1 = ((CcString*)indoor_tuple1->GetAttribute(I_Type))->GetValue();
|
|
GRoom* groom1 = (GRoom*)indoor_tuple1->GetAttribute(I_Room);
|
|
Tuple* box_tuple1 = rel2->GetTuple(id, false);
|
|
Rectangle<3>* bbox3d_1 = (Rectangle<3>*)box_tuple1->GetAttribute(attr3);
|
|
// cout<<"bbox3d 1 "<<*bbox3d_1<<endl;
|
|
Rectangle<2> groom_box1 = groom1->BoundingBox();
|
|
|
|
/////////////// second door in one groom ////////////////////
|
|
Tuple* box_tuple2 = rel2->GetTuple(tid, false);
|
|
int oid2 = ((CcInt*)box_tuple2->GetAttribute(attr1))->GetIntval();
|
|
int groom_tid = ((CcInt*)box_tuple2->GetAttribute(attr2))->GetIntval();
|
|
|
|
assert(1 <= groom_tid && groom_tid <= rel1->GetNoTuples());
|
|
|
|
Tuple* indoor_tuple2 = rel1->GetTuple(groom_tid, false);
|
|
|
|
string type2 = ((CcString*)indoor_tuple2->GetAttribute(I_Type))->GetValue();
|
|
GRoom* groom2 = (GRoom*)indoor_tuple2->GetAttribute(I_Room);
|
|
|
|
Rectangle<3>* bbox3d_2 = (Rectangle<3>*)box_tuple2->GetAttribute(attr3);
|
|
Rectangle<2> groom_box2 = groom2->BoundingBox();
|
|
// cout<<"bbox3d 2 "<<*bbox3d_2<<endl;
|
|
///////////////////////////////////////////////////////////////////
|
|
///////////////create moving bool/////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////
|
|
MBool* mb1 = new MBool(0);
|
|
CreateDoorState(mb1);
|
|
|
|
bool lift_door = false;
|
|
|
|
////////////////////////////////////////////////////////////////
|
|
/////////////////////create line //////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
Line* l1 = new Line(0);
|
|
Line* l2 = new Line(0);
|
|
Line* l3 = new Line(0);
|
|
Line3D* l3d_1 = new Line3D(0);
|
|
GRoomDoorLine(bbox3d_1, bbox3d_2, l1, l2, l3, &groom_box1,
|
|
&groom_box2, l3d_1, bbox3d_1->MinD(2));
|
|
|
|
///////////////////// create the door //////////////////////////////
|
|
Door3D* door_obj1 = new Door3D(oid1, oid2, *l1, *l2, *mb1, lift_door);
|
|
////////////////////// result ///////////////////////////////////
|
|
door_list.push_back(*door_obj1);
|
|
line_list.push_back(*l3);
|
|
groom_id_list1.push_back(oid1);//the room oid
|
|
// groom_id_list2.push_back(-1);//-1 for entrance door
|
|
groom_id_list2.push_back((int)UNDEFVAL);//UNDEFVAL for entrance door
|
|
path_list.push_back(*l3d_1);
|
|
door_heights.push_back(bbox3d_1->MinD(2));
|
|
|
|
|
|
l1->DeleteIfAllowed();
|
|
l2->DeleteIfAllowed();
|
|
l3->DeleteIfAllowed();
|
|
delete door_obj1;
|
|
l3d_1->DeleteIfAllowed();
|
|
mb1->DeleteIfAllowed();
|
|
|
|
/////////////////////////////////////////////////////////////
|
|
box_tuple1->DeleteIfAllowed();
|
|
box_tuple2->DeleteIfAllowed();
|
|
indoor_tuple2->DeleteIfAllowed();
|
|
indoor_tuple1->DeleteIfAllowed();
|
|
|
|
}
|
|
|
|
/*
|
|
Compare two 3D box
|
|
|
|
*/
|
|
bool IndoorNav::BBox3DEqual(Rectangle<3>* bbox3d, Rectangle<3>* bbox_3d)
|
|
{
|
|
for(unsigned int i = 0;i < 3;i ++){
|
|
if(!AlmostEqual(bbox3d->MinD(i), bbox_3d->MinD(i)))return false;
|
|
if(!AlmostEqual(bbox3d->MaxD(i), bbox_3d->MaxD(i)))return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
/*
|
|
create virtual doors for the staircase. The position is the place of the
|
|
first footstep (higher than the ground level) which is the place for entering
|
|
the staircase
|
|
|
|
*/
|
|
void IndoorNav::CreateDoor2()
|
|
{
|
|
for(int i = 1;i <= rel1->GetNoTuples();i++){
|
|
Tuple* groom_tuple = rel1->GetTuple(i, false);
|
|
string type = ((CcString*)groom_tuple->GetAttribute(I_Type))->GetValue();
|
|
if(!(GetRoomEnum(type) == ST)){
|
|
groom_tuple->DeleteIfAllowed();
|
|
continue;
|
|
}
|
|
int oid = ((CcInt*)groom_tuple->GetAttribute(I_OID))->GetIntval();
|
|
GRoom* groom = (GRoom*)groom_tuple->GetAttribute(I_Room);
|
|
Rectangle<2> groom_box = groom->BoundingBox();
|
|
Line* l1 = new Line(0);
|
|
Line* l2 = new Line(0);
|
|
Line* l3 = new Line(0);
|
|
Line* l4 = new Line(0);
|
|
|
|
Line3D* l3d1 = new Line3D(0);
|
|
Line3D* l3d2 = new Line3D(0);
|
|
|
|
|
|
float h1 = GetVirtualDoor1(groom, l1, l2, l3d1);
|
|
float h2 = GetVirtualDoor2(groom, l3, l4, l3d2);
|
|
|
|
|
|
MBool* mb1 = new MBool(0);
|
|
CreateDoorState(mb1);
|
|
|
|
MBool* mb2 = new MBool(0);
|
|
CreateDoorState(mb2);
|
|
|
|
|
|
Door3D* door_obj1 = new Door3D(oid, oid, *l1, *l1, *mb1, false);
|
|
Door3D* door_obj2 = new Door3D(oid, oid, *l3, *l3, *mb2, false);
|
|
|
|
door_list.push_back(*door_obj1);
|
|
line_list.push_back(*l2);
|
|
groom_id_list1.push_back(oid);
|
|
groom_id_list2.push_back(oid);
|
|
path_list.push_back(*l3d1);
|
|
door_heights.push_back(h1);
|
|
|
|
|
|
door_list.push_back(*door_obj2);
|
|
line_list.push_back(*l4);
|
|
groom_id_list1.push_back(oid);
|
|
groom_id_list2.push_back(oid);
|
|
path_list.push_back(*l3d2);
|
|
door_heights.push_back(h2);
|
|
|
|
|
|
l1->DeleteIfAllowed();
|
|
l2->DeleteIfAllowed();
|
|
l3->DeleteIfAllowed();
|
|
l4->DeleteIfAllowed();
|
|
l3d1->DeleteIfAllowed();
|
|
l3d2->DeleteIfAllowed();
|
|
mb1->DeleteIfAllowed();
|
|
mb2->DeleteIfAllowed();
|
|
delete door_obj1;
|
|
delete door_obj2;
|
|
groom_tuple->DeleteIfAllowed();
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
constuct a middle path in the staircase
|
|
the middle path does not include the lowest and highest level
|
|
|
|
*/
|
|
bool Floor3DCompare1(const Floor3D& f1, const Floor3D& f2)
|
|
{
|
|
return f1.GetHeight() < f2.GetHeight();
|
|
}
|
|
|
|
|
|
bool Floor3DCompare2(const Floor3D& f1, const Floor3D& f2)
|
|
{
|
|
return f1.GetHeight() > f2.GetHeight();
|
|
}
|
|
|
|
/*
|
|
Create a virtual door, relative position in a groom, absolute position 2D,
|
|
absolute position 3D. low level height.
|
|
Note: the height for the foorsteps in the input data is set in the reverse way
|
|
|
|
*/
|
|
|
|
float IndoorNav::GetVirtualDoor1(GRoom* groom, Line* l1, Line* l2, Line3D* l3d)
|
|
{
|
|
|
|
vector<Floor3D> floors;
|
|
for(int i = 0;i < groom->Size();i++){
|
|
float h;
|
|
Region r(0);
|
|
groom->Get(i, h, r);
|
|
Floor3D floor(h, r);
|
|
floors.push_back(floor);
|
|
}
|
|
|
|
sort(floors.begin(), floors.end(), Floor3DCompare2);
|
|
|
|
Region* r1 = const_cast<Region*>(floors[0].GetRegion());
|
|
Region* r2 = const_cast<Region*>(floors[1].GetRegion());
|
|
|
|
Line* boundary = new Line(0);
|
|
r1->Boundary(boundary);
|
|
r2->Intersection(*boundary, *l2);
|
|
|
|
assert(l2->Size() == 2);
|
|
|
|
HalfSegment hs;
|
|
l2->Get(0, hs);
|
|
|
|
|
|
boundary->DeleteIfAllowed();
|
|
|
|
|
|
Rectangle<2> groom_box = groom->BoundingBox();
|
|
|
|
double x1 = hs.GetLeftPoint().GetX() - groom_box.MinD(0);
|
|
double y1 = hs.GetLeftPoint().GetY() - groom_box.MinD(1);
|
|
Point p1(true, x1, y1);
|
|
|
|
double x2 = hs.GetRightPoint().GetX() - groom_box.MinD(0);
|
|
double y2 = hs.GetRightPoint().GetY() - groom_box.MinD(1);
|
|
Point p2(true, x2, y2);
|
|
|
|
//////////////////relative position in the groom////////////////////////
|
|
l1->StartBulkLoad();
|
|
int edgeno = 0;
|
|
HalfSegment temp_hs(true, p1, p2);
|
|
temp_hs.attr.edgeno = edgeno++;
|
|
*l1 += temp_hs;
|
|
temp_hs.SetLeftDomPoint(!temp_hs.IsLeftDomPoint());
|
|
*l1 += temp_hs;
|
|
l1->EndBulkLoad();
|
|
//////////////////////////////////////////////////////////////////////////
|
|
////////////////absolute position in 3D space/////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////////
|
|
float h = floors[0].GetHeight();
|
|
|
|
l3d->StartBulkLoad();
|
|
Point3D q1(true, hs.GetLeftPoint().GetX(), hs.GetLeftPoint().GetY(), h);
|
|
Point3D q2(true, hs.GetRightPoint().GetX(), hs.GetRightPoint().GetY(), h);
|
|
*l3d += q1;
|
|
*l3d += q2;
|
|
l3d->EndBulkLoad();
|
|
|
|
return h;
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
}
|
|
|
|
/*
|
|
Create a virtual door, relative position in a groom, absolute position 2D,
|
|
absolute position 3D. high level height
|
|
Note: the height for the foorsteps in the input data is set in the reverse way
|
|
|
|
*/
|
|
|
|
float IndoorNav::GetVirtualDoor2(GRoom* groom, Line* l1, Line* l2, Line3D* l3d)
|
|
{
|
|
vector<Floor3D> floors;
|
|
for(int i = 0;i < groom->Size();i++){
|
|
float h;
|
|
Region r(0);
|
|
groom->Get(i, h, r);
|
|
Floor3D floor(h, r);
|
|
floors.push_back(floor);
|
|
}
|
|
|
|
sort(floors.begin(), floors.end(), Floor3DCompare2);
|
|
|
|
Region* r1 = const_cast<Region*>(floors[0].GetRegion());
|
|
Region* r2 = const_cast<Region*>(floors[1].GetRegion());
|
|
|
|
Line* boundary = new Line(0);
|
|
r1->Boundary(boundary);
|
|
r2->Intersection(*boundary, *l2);
|
|
|
|
assert(l2->Size() == 2);
|
|
|
|
HalfSegment hs;
|
|
l2->Get(0, hs);
|
|
|
|
|
|
boundary->DeleteIfAllowed();
|
|
|
|
|
|
Rectangle<2> groom_box = groom->BoundingBox();
|
|
|
|
double x1 = hs.GetLeftPoint().GetX() - groom_box.MinD(0);
|
|
double y1 = hs.GetLeftPoint().GetY() - groom_box.MinD(1);
|
|
Point p1(true, x1, y1);
|
|
|
|
double x2 = hs.GetRightPoint().GetX() - groom_box.MinD(0);
|
|
double y2 = hs.GetRightPoint().GetY() - groom_box.MinD(1);
|
|
Point p2(true, x2, y2);
|
|
|
|
//////////////////relative position in the groom////////////////////////
|
|
l1->StartBulkLoad();
|
|
int edgeno = 0;
|
|
HalfSegment temp_hs(true, p1, p2);
|
|
temp_hs.attr.edgeno = edgeno++;
|
|
*l1 += temp_hs;
|
|
temp_hs.SetLeftDomPoint(!temp_hs.IsLeftDomPoint());
|
|
*l1 += temp_hs;
|
|
l1->EndBulkLoad();
|
|
//////////////////////////////////////////////////////////////////////////
|
|
////////////////absolute position in 3D space/////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////////
|
|
float h = floors[floors.size() - 1].GetHeight();
|
|
|
|
l3d->StartBulkLoad();
|
|
Point3D q1(true, hs.GetLeftPoint().GetX(), hs.GetLeftPoint().GetY(), h);
|
|
Point3D q2(true, hs.GetRightPoint().GetX(), hs.GetRightPoint().GetY(), h);
|
|
*l3d += q1;
|
|
*l3d += q2;
|
|
l3d->EndBulkLoad();
|
|
|
|
return h;
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
}
|
|
|
|
/*
|
|
create a line denoting the positio of a door. we record the relative position
|
|
according to the groom
|
|
|
|
*/
|
|
|
|
void IndoorNav::GRoomDoorLine(Rectangle<3>* bbox3d_1, Rectangle<3>* bbox3d_2,
|
|
Line* l1, Line* l2, Line* l3,
|
|
const Rectangle<2>* groom_box1,
|
|
const Rectangle<2>* groom_box2,
|
|
Line3D* l3d, float h)
|
|
{
|
|
// cout<<"door box1 "<<*bbox3d_1<<endl;
|
|
// cout<<"GRoom box1 "<<*groom_box1<<endl;
|
|
// cout<<"door box2 "<<*bbox3d_2<<endl;
|
|
// cout<<"GRoom box2 "<<*groom_box2<<endl;
|
|
|
|
double min_x1 = bbox3d_1->MinD(0) - groom_box1->MinD(0);
|
|
double min_y1 = bbox3d_1->MinD(1) - groom_box1->MinD(1);
|
|
double max_x1 = bbox3d_1->MaxD(0) - groom_box1->MinD(0);
|
|
double max_y1 = bbox3d_1->MaxD(1) - groom_box1->MinD(1);
|
|
|
|
|
|
double min_x2 = bbox3d_2->MinD(0) - groom_box2->MinD(0);
|
|
double min_y2 = bbox3d_2->MinD(1) - groom_box2->MinD(1);
|
|
double max_x2 = bbox3d_2->MaxD(0) - groom_box2->MinD(0);
|
|
double max_y2 = bbox3d_2->MaxD(1) - groom_box2->MinD(1);
|
|
|
|
// cout<<" x1 "<<min_x1<<" y1 "<<min_y1<<" x2 "<<max_x1<<" y2 "<<max_y1<<endl;
|
|
// cout<<" x1 "<<min_x2<<" y1 "<<min_y2<<" x2 "<<max_x2<<" y2 "<<max_y2<<endl;
|
|
|
|
l1->StartBulkLoad();
|
|
Point lp1(true, min_x1, min_y1);
|
|
Point rp1(true, max_x1, max_y1);
|
|
HalfSegment hs1(true, lp1, rp1);
|
|
int edgeno1 = 0;
|
|
hs1.attr.edgeno = edgeno1++;
|
|
*l1 += hs1;
|
|
hs1.SetLeftDomPoint(!hs1.IsLeftDomPoint());
|
|
*l1 += hs1;
|
|
l1->EndBulkLoad();
|
|
|
|
|
|
l2->StartBulkLoad();
|
|
Point lp2(true, min_x2, min_y2);
|
|
Point rp2(true, max_x2, max_y2);
|
|
HalfSegment hs2(true, lp2, rp2);
|
|
int edgeno2 = 0;
|
|
hs2.attr.edgeno = edgeno2++;
|
|
*l2 += hs2;
|
|
hs2.SetLeftDomPoint(!hs2.IsLeftDomPoint());
|
|
*l2 += hs2;
|
|
l2->EndBulkLoad();
|
|
|
|
|
|
l3->StartBulkLoad();
|
|
Point lp3(true, bbox3d_1->MinD(0), bbox3d_1->MinD(1));
|
|
Point rp3(true, bbox3d_1->MaxD(0), bbox3d_1->MaxD(1));
|
|
HalfSegment hs3(true, lp3, rp3);
|
|
int edgeno3 = 0;
|
|
hs3.attr.edgeno = edgeno3++;
|
|
*l3 += hs3;
|
|
hs3.SetLeftDomPoint(!hs3.IsLeftDomPoint());
|
|
*l3 += hs3;
|
|
l3->EndBulkLoad();
|
|
|
|
|
|
|
|
l3d->StartBulkLoad();
|
|
Point3D lq(true, bbox3d_1->MinD(0), bbox3d_1->MinD(1), h);
|
|
Point3D rq(true, bbox3d_1->MaxD(0), bbox3d_1->MaxD(1), h);
|
|
*l3d += lq;
|
|
*l3d += rq;
|
|
|
|
l3d->EndBulkLoad();
|
|
}
|
|
|
|
/*
|
|
create the edges connecting two doors inside one room
|
|
|
|
*/
|
|
|
|
void IndoorNav::CreateAdjDoor1(BTree* btree,int attr1, int attr2,
|
|
int attr3, int attr4)
|
|
{
|
|
// cout<<"CreateAdjDoor() "<<endl;
|
|
// cout<<"attr1 "<<attr1<<" attr2 "<<attr2<<" attr3 "<<attr3
|
|
// <<" attr4 "<<attr4<<endl;
|
|
|
|
for(int i = 1;i <= rel1->GetNoTuples();i++){
|
|
Tuple* groom_tuple = rel1->GetTuple(i, false);
|
|
int groom_oid = ((CcInt*)groom_tuple->GetAttribute(I_OID))->GetIntval();
|
|
//////////////////////////////////////////////////////////////////////////
|
|
/////////////find all doors belong to this groom/////////////////////////
|
|
/////////////////////////////////////////////////////////////////////////
|
|
|
|
CcInt* search_id = new CcInt(true, groom_oid);
|
|
BTreeIterator* btree_iter = btree->ExactMatch(search_id);
|
|
vector<int> tid_list;
|
|
while(btree_iter->Next()){
|
|
Tuple* tuple = rel2->GetTuple(btree_iter->GetId(), false);
|
|
tid_list.push_back(tuple->GetTupleId());
|
|
tuple->DeleteIfAllowed();
|
|
}
|
|
delete btree_iter;
|
|
delete search_id;
|
|
|
|
// cout<<"groom_oid "<<groom_oid<<" door num "<<tid_list.size()<<endl;
|
|
/* for(unsigned int j = 0;j < tid_list.size();j++)
|
|
cout<<"door tid "<<tid_list[j] <<endl;
|
|
cout<<endl; */
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
/////////////compute shortest path between each pair of doors/////////
|
|
/////////////the doors should not be equal to each other////////////
|
|
////////////////////////////////////////////////////////////////////
|
|
if(tid_list.size() > 1){
|
|
GRoom* groom = (GRoom*)groom_tuple->GetAttribute(I_Room);
|
|
string groom_type =
|
|
((CcString*)groom_tuple->GetAttribute(I_Type))->GetValue();
|
|
// cout<<"groom type"<<groom_type<<endl;
|
|
///OR, CO,
|
|
/////////////////////////////////////////////////////////
|
|
////// the path inside a elevator: EL //////////////////////
|
|
///////////////////////////////////////////////////////////
|
|
if(GetRoomEnum(groom_type) == EL){
|
|
BuildPathEL(groom_oid, groom, tid_list, attr1, attr2, attr3, attr4);
|
|
}
|
|
/////////////////////////////////////////////////////////
|
|
////// the path inside a elevator: ST //////////////////////
|
|
///////////////////////////////////////////////////////////
|
|
if(GetRoomEnum(groom_type) == ST){
|
|
BuildPathST(groom_oid, groom, tid_list, attr1, attr2, attr3, attr4);
|
|
|
|
}
|
|
/////////////////////////////////////////////////////////////
|
|
////// the path inside an office room : OR ///
|
|
//////////////////////////////////////////////////////////////
|
|
if(GetRoomEnum(groom_type) == OR){
|
|
BuildPathOR(groom_oid, groom, tid_list, attr1, attr2, attr3, attr4);
|
|
}
|
|
/////////////////////////////////////////////////////////////
|
|
////// the path inside a corridor: CO///
|
|
//////////////////////////////////////////////////////////////
|
|
if(GetRoomEnum(groom_type) == CO){
|
|
bool b =
|
|
BuildPathCO(groom_oid, groom, tid_list, attr1, attr2, attr3, attr4);
|
|
if(b == false){
|
|
cout<<"build path in corridor error"<<endl;
|
|
groom_tuple->DeleteIfAllowed();
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
groom_tuple->DeleteIfAllowed();
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//////////// compute the path for each pair of doors inside one room //////
|
|
//////////// The rooms needs to be considered: OR, CO, ST, EL /////////////
|
|
//////////////// BR (bath room) is excluded //////////////////////////////
|
|
|
|
/*
|
|
the path for an elevator, a straight line connecting two floors
|
|
|
|
*/
|
|
void IndoorNav::BuildPathEL(int groom_oid, GRoom* groom, vector<int> tid_list,
|
|
int attr1, int attr2,
|
|
int attr3, int attr4)
|
|
{
|
|
|
|
// cout<<"BuildPathEL() tid_lise size "<<tid_list.size()<<endl;
|
|
// cout<<"low height "<<groom->GetLowHeight()<<endl;
|
|
////////////////////use tid id to collect the door tuple/////////////
|
|
|
|
// cout<<"tid list size "<<tid_list.size()<<endl;
|
|
// assert(tid_list.size() == 2);
|
|
for(unsigned int i = 0;i < tid_list.size(); i++){
|
|
Tuple* door_tuple1 = rel2->GetTuple(tid_list[i], false);
|
|
float h1 = ((CcReal*)door_tuple1->GetAttribute(attr4))->GetRealval();
|
|
|
|
for(unsigned int j = 0;j < tid_list.size();j++){
|
|
if(tid_list[i] == tid_list[j])continue;
|
|
Tuple* door_tuple2 = rel2->GetTuple(tid_list[j], false);
|
|
float h2 = ((CcReal*)door_tuple2->GetAttribute(attr4))->GetRealval();
|
|
if(AlmostEqual(h1, h2)) {
|
|
door_tuple2->DeleteIfAllowed();
|
|
continue; //ignore the doors on the same level
|
|
}
|
|
|
|
Line* l = (Line*)door_tuple1->GetAttribute(attr2);
|
|
assert(l->Size() == 2);
|
|
HalfSegment hs;
|
|
l->Get(0, hs);
|
|
|
|
double x = (hs.GetLeftPoint().GetX() + hs.GetRightPoint().GetX())/2;
|
|
double y = (hs.GetLeftPoint().GetY() + hs.GetRightPoint().GetY())/2;
|
|
Point3D p1(true, x, y, h1);
|
|
Point3D p2(true, x, y, h2);
|
|
|
|
Line3D* l3d = new Line3D(0);
|
|
l3d->StartBulkLoad();
|
|
*l3d += p1;
|
|
*l3d += p2;
|
|
l3d->EndBulkLoad();
|
|
|
|
////////////////////// result ////////////////////////////////////////
|
|
groom_oid_list.push_back(groom_oid);
|
|
door_tid_list1.push_back(tid_list[i]);
|
|
door_tid_list2.push_back(tid_list[j]);
|
|
path_list.push_back(*l3d);
|
|
l3d->DeleteIfAllowed();
|
|
|
|
// cout<<"groom_oid "<<groom_oid<<"tid1 "<<tid_list[i]
|
|
// <<" tid2 "<<tid_list[j]<<endl;
|
|
|
|
door_tuple2->DeleteIfAllowed();
|
|
}
|
|
|
|
door_tuple1->DeleteIfAllowed();
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
the path for the staircase
|
|
|
|
*/
|
|
void IndoorNav::BuildPathST(int groom_oid, GRoom* groom, vector<int> tid_list,
|
|
int attr1, int attr2,
|
|
int attr3, int attr4)
|
|
{
|
|
const double dist_delta = 0.001;
|
|
// cout<<"BuildPathST()"<<endl;
|
|
// cout<<"groom_oid "<<groom_oid<<" door num "<<tid_list.size()<<endl;
|
|
|
|
//////////////construct a standard path for the staircase///////////////////
|
|
vector<MySegHeight> middle_path;
|
|
ConstructMiddlePath(groom, middle_path);
|
|
|
|
// cout<<"low height "<<groom->GetLowHeight()<<endl;
|
|
////////////////////use tid id to collect the door tuple/////////////
|
|
for(unsigned int i = 0;i < tid_list.size();i++){
|
|
// cout<<"door tid "<<tid_list[i]<<endl;
|
|
Tuple* door_tuple1 = rel2->GetTuple(tid_list[i], false);
|
|
float h1 = ((CcReal*)door_tuple1->GetAttribute(attr4))->GetRealval();
|
|
Line* l1 = (Line*)door_tuple1->GetAttribute(attr2);
|
|
|
|
for(unsigned int j = 0;j < tid_list.size();j++){
|
|
if(tid_list[j] == tid_list[i]) continue;
|
|
Tuple* door_tuple2 = rel2->GetTuple(tid_list[j], false);
|
|
float h2 = ((CcReal*)door_tuple2->GetAttribute(attr4))->GetRealval();
|
|
Line* l2 = (Line*)door_tuple2->GetAttribute(attr2);
|
|
if(fabs(h1-h2) < dist_delta){ // on the same floor
|
|
ST_ConnectOneFloor(groom_oid, groom, l1, l2,
|
|
tid_list[i], tid_list[j], h1);
|
|
|
|
}else{ //not on the same floor
|
|
|
|
ST_ConnectFloors(groom_oid, groom, l1, l2,
|
|
tid_list[i], tid_list[j], h1, h2, middle_path);
|
|
|
|
// return;
|
|
}
|
|
door_tuple2->DeleteIfAllowed();
|
|
}
|
|
|
|
door_tuple1->DeleteIfAllowed();
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
build the connection for two doors of a staircase at the same level
|
|
|
|
*/
|
|
void IndoorNav::ST_ConnectOneFloor(int groom_oid, GRoom* groom, Line* l1,
|
|
Line* l2, int tid1, int tid2, float h)
|
|
{
|
|
// cout<<" ST_ConnectOneFloor "<<endl;
|
|
// <<"groom oid "<<groom_oid<<" id1 "<<tid1<<" id2 "<<tid2<<endl;
|
|
|
|
const double dist_delta = 0.001;
|
|
HalfSegment hs1;
|
|
assert(l1->Size() == 2);
|
|
l1->Get(0, hs1);
|
|
|
|
HalfSegment hs2;
|
|
assert(l2->Size() == 2);
|
|
l2->Get(0, hs2);
|
|
|
|
double x1 = (hs1.GetLeftPoint().GetX() + hs1.GetRightPoint().GetX())/2;
|
|
double y1 = (hs1.GetLeftPoint().GetY() + hs1.GetRightPoint().GetY())/2;
|
|
Point p1(true, x1, y1);
|
|
|
|
double x2 = (hs2.GetLeftPoint().GetX() + hs2.GetRightPoint().GetX())/2;
|
|
double y2 = (hs2.GetLeftPoint().GetY() + hs2.GetRightPoint().GetY())/2;
|
|
Point p2(true, x2, y2);
|
|
|
|
if(p1.Distance(p2) < dist_delta) return;
|
|
|
|
|
|
vector<MyHalfSegment> mhs;
|
|
|
|
FindPathInRegion(groom, h, mhs, &p1, &p2);
|
|
///////////////// conver to 3D line //////////////////////////////
|
|
Line3D* l3d = new Line3D(0);
|
|
l3d->StartBulkLoad();
|
|
|
|
for(unsigned int i = 0;i < mhs.size();i++){
|
|
Point p = mhs[i].from;
|
|
Point3D q(true, p.GetX(), p.GetY(), h);
|
|
*l3d += q;
|
|
if(i == mhs.size() - 1){
|
|
Point p1 = mhs[i].to;
|
|
Point3D q1(true, p1.GetX(), p1.GetY(), h);
|
|
*l3d += q1;
|
|
}
|
|
}
|
|
l3d->EndBulkLoad();
|
|
|
|
groom_oid_list.push_back(groom_oid);
|
|
door_tid_list1.push_back(tid1);
|
|
door_tid_list2.push_back(tid2);
|
|
path_list.push_back(*l3d);
|
|
|
|
l3d->DeleteIfAllowed();
|
|
}
|
|
|
|
/*
|
|
find the path in one floor
|
|
|
|
vector MyHalfSegment store the result
|
|
|
|
*/
|
|
void IndoorNav::FindPathInRegion(GRoom* groom, float h,
|
|
vector<MyHalfSegment>& mhs,
|
|
Point* p1, Point* p2)
|
|
{
|
|
const double dist_delta = 0.001;
|
|
Region* r = new Region(0);
|
|
|
|
int i = 0;
|
|
for(;i < groom->Size();i++){
|
|
float temp_h;
|
|
groom->Get(i, temp_h, *r);
|
|
if(fabs(h - temp_h) < dist_delta){
|
|
break;
|
|
}
|
|
r->Clear();
|
|
}
|
|
if(i == groom->Size()){
|
|
cout<<" such height " <<h <<"does not exist in the GRoom"<<endl;
|
|
assert(false);
|
|
}
|
|
|
|
Line* l = new Line(0);
|
|
|
|
// cout<<*r<<endl;
|
|
// cout<<" p1 "<<*p1<<" p2 "<<*p2<<endl;
|
|
ShortestPath_InRegion(r, p1, p2, l);
|
|
// cout<<"l "<<*l<<endl;
|
|
|
|
if(l->Size() == 0) {
|
|
r->DeleteIfAllowed();
|
|
l->DeleteIfAllowed();
|
|
return;
|
|
}
|
|
|
|
SimpleLine* sl = new SimpleLine(0);
|
|
sl->fromLine(*l);
|
|
l->DeleteIfAllowed();
|
|
SpacePartition* sp = new SpacePartition();
|
|
|
|
sp->ReorderLine(sl, mhs);
|
|
delete sp;
|
|
sl->DeleteIfAllowed();
|
|
r->DeleteIfAllowed();
|
|
|
|
|
|
|
|
if(mhs[0].from.Distance(*p1) < dist_delta &&
|
|
mhs[mhs.size() - 1].to.Distance(*p2) < dist_delta) return;
|
|
|
|
|
|
assert(mhs[mhs.size() - 1].to.Distance(*p1) < dist_delta &&
|
|
mhs[0].from.Distance(*p2) < dist_delta);
|
|
vector<MyHalfSegment> temp_mhs;
|
|
for(int i = mhs.size() - 1;i >= 0;i--){
|
|
MyHalfSegment seg = mhs[i];
|
|
Point p = seg.from;
|
|
seg.from = seg.to;
|
|
seg.to = p;
|
|
temp_mhs.push_back(seg);
|
|
}
|
|
mhs.clear();
|
|
for(unsigned int i = 0;i < temp_mhs.size();i++)
|
|
mhs.push_back(temp_mhs[i]);
|
|
|
|
if(mhs[0].from.Distance(*p1) < dist_delta &&
|
|
mhs[mhs.size() - 1].to.Distance(*p2) < dist_delta) return;
|
|
|
|
assert(false);
|
|
}
|
|
|
|
/*
|
|
build a path inside a staircase and it connects from the second footstep to
|
|
the last second footstep.
|
|
|
|
*/
|
|
void IndoorNav::ConstructMiddlePath(GRoom* groom,
|
|
vector<MySegHeight>& middle_path)
|
|
{
|
|
vector<Floor3D> floors;
|
|
for(int i = 0;i < groom->Size();i++){
|
|
float h;
|
|
Region r(0);
|
|
groom->Get(i, h, r);
|
|
Floor3D floor(h, r);
|
|
floors.push_back(floor);
|
|
}
|
|
|
|
sort(floors.begin(), floors.end(), Floor3DCompare1);
|
|
|
|
///////// from low height to high height ////////////////////
|
|
for(unsigned int i = 0; i < floors.size();i++){
|
|
// cout<<"height "<<floors[i].GetHeight()<<endl;
|
|
///////////////////////////////////////////////////////////
|
|
if(i == floors.size() - 1 || i == 0) continue;
|
|
////////////////////////////////////////////////////////////
|
|
|
|
Region* cur_r = const_cast<Region*>(floors[i].GetRegion());
|
|
Region* r1 = const_cast<Region*>(floors[i - 1].GetRegion());
|
|
Region* r2 = const_cast<Region*>(floors[i + 1].GetRegion());
|
|
|
|
// cout<<"cur "<<*cur_r<<" r1 "<<*r1<<" r2 "<<*r2<<endl;
|
|
|
|
Line* l1 = new Line(0);
|
|
r1->Boundary(l1);
|
|
Line* l2 = new Line(0);
|
|
r2->Boundary(l2);
|
|
|
|
Line* il1 = new Line(0);
|
|
Line* il2 = new Line(0);
|
|
cur_r->Intersection(*l1, *il1);
|
|
cur_r->Intersection(*l2, *il2);
|
|
assert(il1->Size() == 2 && il2->Size() == 2);
|
|
|
|
HalfSegment hs1;
|
|
HalfSegment hs2;
|
|
il1->Get(0, hs1);
|
|
il2->Get(0, hs2);
|
|
|
|
il1->DeleteIfAllowed();
|
|
il2->DeleteIfAllowed();
|
|
l1->DeleteIfAllowed();
|
|
l2->DeleteIfAllowed();
|
|
|
|
|
|
double x1 = (hs1.GetLeftPoint().GetX() + hs1.GetRightPoint().GetX())/2;
|
|
double y1 = (hs1.GetLeftPoint().GetY() + hs1.GetRightPoint().GetY())/2;
|
|
Point p1(true, x1, y1);
|
|
|
|
double x2 = (hs2.GetLeftPoint().GetX() + hs2.GetRightPoint().GetX())/2;
|
|
double y2 = (hs2.GetLeftPoint().GetY() + hs2.GetRightPoint().GetY())/2;
|
|
Point p2(true, x2, y2);
|
|
|
|
MySegHeight mysegh(true, p1, p2, floors[i].GetHeight());
|
|
middle_path.push_back(mysegh);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
///////////////////for debuging///////////////////////////////////////
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
/* float low_h = floors[0].GetHeight();
|
|
float high_h = floors[floors.size() - 1].GetHeight();
|
|
|
|
Line3D* l3d = new Line3D(0);
|
|
l3d->StartBulkLoad();
|
|
for(unsigned int i = 0 ;i < middle_path.size();i++){
|
|
if(i == 0){
|
|
Point3D p(true, middle_path[i].from.GetX(),
|
|
middle_path[i].from.GetY(), low_h);
|
|
*l3d += p;
|
|
}
|
|
|
|
Point3D p1(true, middle_path[i].from.GetX(),
|
|
middle_path[i].from.GetY(), middle_path[i].h);
|
|
Point3D p2(true, middle_path[i].to.GetX(),
|
|
middle_path[i].to.GetY(), middle_path[i].h);
|
|
*l3d += p1;
|
|
*l3d += p2;
|
|
|
|
if(i == middle_path.size() - 1){
|
|
Point3D p(true, middle_path[i].to.GetX(),
|
|
middle_path[i].to.GetY(), high_h);
|
|
*l3d += p;
|
|
}
|
|
|
|
}
|
|
|
|
l3d->EndBulkLoad();
|
|
|
|
groom_oid_list.push_back(1);
|
|
door_tid_list1.push_back(1);
|
|
door_tid_list2.push_back(1);
|
|
path_list.push_back(*l3d);
|
|
|
|
delete l3d; */
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
build a path inside a staircase and it connects from height h1 to height h2
|
|
|
|
*/
|
|
void IndoorNav::ConstructMiddlePath2(GRoom* groom,
|
|
vector<Point3D>& middle_path,
|
|
float h1, float h2)
|
|
{
|
|
assert(h1 < h2);
|
|
const double delta_dist = 0.001;
|
|
vector<Floor3D> floors;
|
|
for(int i = 0;i < groom->Size();i++){
|
|
float h;
|
|
Region r(0);
|
|
groom->Get(i, h, r);
|
|
if(fabs(h - h1) < delta_dist || fabs(h - h2) < delta_dist){
|
|
Floor3D floor(h, r);
|
|
floors.push_back(floor);
|
|
}else if(h1 < h && h < h2){
|
|
Floor3D floor(h, r);
|
|
floors.push_back(floor);
|
|
}
|
|
}
|
|
|
|
sort(floors.begin(), floors.end(), Floor3DCompare1);
|
|
|
|
|
|
///////// from low height to high height ////////////////////
|
|
for(unsigned int i = 0; i < floors.size();i++){
|
|
// cout<<"height "<<floors[i].GetHeight()<<endl;
|
|
///////////////////////////////////////////////////////////
|
|
if(i == 0) continue;
|
|
////////////////////////////////////////////////////////////
|
|
|
|
Region* cur_r = const_cast<Region*>(floors[i].GetRegion());
|
|
Region* r1 = const_cast<Region*>(floors[i - 1].GetRegion());
|
|
|
|
|
|
// cout<<"cur "<<*cur_r<<" r1 "<<*r1<<" r2 "<<*r2<<endl;
|
|
|
|
Line* l1 = new Line(0);
|
|
r1->Boundary(l1);
|
|
|
|
Line* il1 = new Line(0);
|
|
cur_r->Intersection(*l1, *il1);
|
|
assert(il1->Size() == 2);
|
|
HalfSegment hs1;
|
|
il1->Get(0, hs1);
|
|
il1->DeleteIfAllowed();
|
|
l1->DeleteIfAllowed();
|
|
|
|
double x = (hs1.GetLeftPoint().GetX() + hs1.GetRightPoint().GetX())/2;
|
|
double y = (hs1.GetLeftPoint().GetY() + hs1.GetRightPoint().GetY())/2;
|
|
|
|
Point3D q1(true, x, y, floors[i - 1].GetHeight());
|
|
Point3D q2(true, x, y, floors[i].GetHeight());
|
|
|
|
middle_path.push_back(q1);
|
|
middle_path.push_back(q2);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
build the connection for two doors of a staircase at different levels
|
|
middle path from low height to heigh height
|
|
|
|
*/
|
|
void IndoorNav::ST_ConnectFloors(int groom_oid, GRoom* groom, Line* l1,
|
|
Line* l2, int tid1, int tid2,
|
|
float h1, float h2,
|
|
vector<MySegHeight>& middle_path)
|
|
{
|
|
// cout<<" ST_ConnectFloorS "<<endl;
|
|
|
|
HalfSegment hs1;
|
|
assert(l1->Size() == 2);
|
|
l1->Get(0, hs1);
|
|
|
|
HalfSegment hs2;
|
|
assert(l2->Size() == 2);
|
|
l2->Get(0, hs2);
|
|
|
|
double x1 = (hs1.GetLeftPoint().GetX() + hs1.GetRightPoint().GetX())/2;
|
|
double y1 = (hs1.GetLeftPoint().GetY() + hs1.GetRightPoint().GetY())/2;
|
|
Point p1(true, x1, y1);
|
|
|
|
double x2 = (hs2.GetLeftPoint().GetX() + hs2.GetRightPoint().GetX())/2;
|
|
double y2 = (hs2.GetLeftPoint().GetY() + hs2.GetRightPoint().GetY())/2;
|
|
Point p2(true, x2, y2);
|
|
|
|
// cout<<"p1 "<<p1<<"h1 "<<h1<<endl;
|
|
// cout<<"p2 "<<p2<<"h2 "<<h2<<endl;
|
|
|
|
vector<Floor3D> floors;
|
|
for(int i = 0;i < groom->Size();i++){
|
|
float h;
|
|
Region r(0);
|
|
groom->Get(i, h, r);
|
|
Floor3D floor(h, r);
|
|
floors.push_back(floor);
|
|
}
|
|
sort(floors.begin(), floors.end(), Floor3DCompare1);
|
|
|
|
|
|
if(h1 < h2){
|
|
Point q1 = middle_path[0].from;
|
|
Point q2 = middle_path[middle_path.size() - 1].to;
|
|
|
|
vector<MyHalfSegment> mhs1;
|
|
FindPathInRegion(groom, h1, mhs1, &p1, &q1);
|
|
vector<MyHalfSegment> mhs2;
|
|
FindPathInRegion(groom, h2, mhs2, &q2, &p2);
|
|
|
|
Line3D* l3d = new Line3D(0);
|
|
l3d->StartBulkLoad();
|
|
|
|
for(unsigned int i = 0 ;i < mhs1.size();i++){
|
|
Point p = mhs1[i].from;
|
|
Point3D q(true, p.GetX(), p.GetY(), h1);
|
|
*l3d += q;
|
|
}
|
|
|
|
for(unsigned int i = 0 ;i < middle_path.size();i++){
|
|
Point p = middle_path[i].from;
|
|
if(i == 0){
|
|
Point3D q(true, p.GetX(), p.GetY(), h1);
|
|
*l3d += q;
|
|
}
|
|
Point3D q1(true, p.GetX(), p.GetY(), middle_path[i].h);
|
|
*l3d += q1;
|
|
|
|
p = middle_path[i].to;
|
|
Point3D q2(true, p.GetX(), p.GetY(), middle_path[i].h);
|
|
*l3d += q2;
|
|
}
|
|
// cout<<"mhs2 size "<<mhs2.size()<<endl;
|
|
for(unsigned int i = 0 ;i < mhs2.size();i++){
|
|
Point p = mhs2[i].from;
|
|
Point3D q(true, p.GetX(), p.GetY(), h2);
|
|
*l3d += q;
|
|
if(i == mhs2.size() - 1){
|
|
Point p = mhs2[i].to;
|
|
Point3D q(true, p.GetX(), p.GetY(), h2);
|
|
*l3d += q;
|
|
}
|
|
}
|
|
|
|
l3d->EndBulkLoad();
|
|
|
|
groom_oid_list.push_back(groom_oid);
|
|
door_tid_list1.push_back(tid1);
|
|
door_tid_list2.push_back(tid2);
|
|
path_list.push_back(*l3d);
|
|
|
|
}else{ //h1 > h2
|
|
|
|
Point q1 = middle_path[middle_path.size() - 1].to;
|
|
Point q2 = middle_path[0].from;
|
|
|
|
vector<MyHalfSegment> mhs1;
|
|
FindPathInRegion(groom, h1, mhs1, &p1, &q1);
|
|
vector<MyHalfSegment> mhs2;
|
|
FindPathInRegion(groom, h2, mhs2, &q2, &p2);
|
|
|
|
Line3D* l3d = new Line3D(0);
|
|
l3d->StartBulkLoad();
|
|
|
|
for(unsigned int i = 0 ;i < mhs1.size();i++){
|
|
Point p = mhs1[i].from;
|
|
Point3D q(true, p.GetX(), p.GetY(), h1);
|
|
*l3d += q;
|
|
}
|
|
|
|
for(int i = middle_path.size() - 1;i >= 0; i--){
|
|
Point p = middle_path[i].to;
|
|
if(i == (int)(middle_path.size() - 1)){
|
|
Point3D q(true, p.GetX(), p.GetY(), h1);
|
|
*l3d += q;
|
|
}
|
|
Point3D q1(true, p.GetX(), p.GetY(), middle_path[i].h);
|
|
*l3d += q1;
|
|
|
|
p = middle_path[i].from;
|
|
Point3D q2(true, p.GetX(), p.GetY(), middle_path[i].h);
|
|
*l3d += q2;
|
|
}
|
|
|
|
for(unsigned int i = 0 ;i < mhs2.size();i++){
|
|
Point p = mhs2[i].from;
|
|
Point3D q(true, p.GetX(), p.GetY(), h2);
|
|
*l3d += q;
|
|
if(i == mhs2.size() - 1){
|
|
Point p = mhs2[i].to;
|
|
Point3D q(true, p.GetX(), p.GetY(), h2);
|
|
*l3d += q;
|
|
}
|
|
}
|
|
|
|
l3d->EndBulkLoad();
|
|
|
|
groom_oid_list.push_back(groom_oid);
|
|
door_tid_list1.push_back(tid1);
|
|
door_tid_list2.push_back(tid2);
|
|
path_list.push_back(*l3d);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
compute the path for each pair of doors inside one room
|
|
The rooms needs to be considered: OR, CO
|
|
BR (bath room) is excluded
|
|
Note: in the original data.
|
|
!!! the position of the door should be covered by the room !!!
|
|
otherwise, it can not find the shorest path connecting two doors inside one
|
|
room
|
|
|
|
*/
|
|
|
|
void IndoorNav::BuildPathOR(int groom_oid,
|
|
GRoom* groom, vector<int> tid_list,
|
|
int attr1, int attr2,
|
|
int attr3, int attr4)
|
|
{
|
|
if(groom->Size() > 1){
|
|
cout<<"groom has several levels"<<endl;
|
|
cout<<"not implemented yet"<<endl;
|
|
assert(false);
|
|
}
|
|
// cout<<"size "<<tid_list.size()<<endl;
|
|
const double dist_delta = 0.001;
|
|
for(unsigned int i = 0;i < tid_list.size();i++){
|
|
Tuple* door_tuple1 = rel2->GetTuple(tid_list[i], false);
|
|
float h1 = ((CcReal*)door_tuple1->GetAttribute(attr4))->GetRealval();
|
|
Line* l1 = (Line*)door_tuple1->GetAttribute(attr2);
|
|
// cout<<"i "<<i<<endl;
|
|
for(unsigned int j = 0;j < tid_list.size();j++){
|
|
if(tid_list[j] == tid_list[i]) continue;
|
|
Tuple* door_tuple2 = rel2->GetTuple(tid_list[j], false);
|
|
float h2 = ((CcReal*)door_tuple2->GetAttribute(attr4))->GetRealval();
|
|
Line* l2 = (Line*)door_tuple2->GetAttribute(attr2);
|
|
// cout<<"j "<<j<<endl;
|
|
if(fabs(h1-h2) < dist_delta){ // on the same floor
|
|
ST_ConnectOneFloor(groom_oid, groom, l1, l2,
|
|
tid_list[i], tid_list[j], h1);
|
|
}else
|
|
assert(false);
|
|
door_tuple2->DeleteIfAllowed();
|
|
}
|
|
|
|
door_tuple1->DeleteIfAllowed();
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
compute the path for each pair of doors inside one room
|
|
The rooms needs to be considered: CO
|
|
BR (bath room) is excluded
|
|
Note: in the original data.
|
|
!!! the position of the door should be covered by the room !!!
|
|
otherwise, it can not find the shorest path connecting two doors inside one
|
|
room.
|
|
The function is different from the function for OR.
|
|
|
|
if the corridor is complex which has many vertices and holes inside, the
|
|
simple method needs too much time to compute the shortest path between
|
|
each pair of doors. So, we use the method for trip planning for pedestrian.
|
|
it builds dual graph and visual graph.
|
|
|
|
*/
|
|
|
|
bool IndoorNav::BuildPathCO(int groom_oid,
|
|
GRoom* groom, vector<int> tid_list,
|
|
int attr1, int attr2,
|
|
int attr3, int attr4)
|
|
{
|
|
if(groom->Size() > 1){
|
|
cout<<"groom has several levels"<<endl;
|
|
cout<<"not implemented yet"<<endl;
|
|
assert(false);
|
|
}
|
|
|
|
const double dist_delta = 0.001;
|
|
/////////////////////////////////////////////////////////////////////////
|
|
////////////////1. get 2D area of the groom/////////////////////////////////
|
|
/////////////////////////////////////////////////////////////////////////
|
|
float h = groom->GetLowHeight();
|
|
// cout<<"low h "<<h<<endl;
|
|
Region* groom_reg = new Region(0);
|
|
int index = 0;
|
|
for(;index < groom->Size();index++){
|
|
float temp_h;
|
|
groom->Get(index, temp_h, *groom_reg);
|
|
if(fabs(h - temp_h) < dist_delta){
|
|
break;
|
|
}
|
|
groom_reg->Clear();
|
|
}
|
|
if(index == groom->Size()){
|
|
cout<<" such height " <<h <<"does not exist in the GRoom"<<endl;
|
|
delete groom_reg;
|
|
assert(false);
|
|
}
|
|
|
|
// cout<<"area "<<groom_reg->Area()<<endl;
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
////////////2. check whether the region is complex or not ///////
|
|
//////////////////////////////////////////////////////////////////
|
|
CompTriangle* ct = new CompTriangle(groom_reg);
|
|
int complex_reg = ct->ComplexRegion();
|
|
delete ct;
|
|
assert(complex_reg >= 0);
|
|
vector<string> obj_name;
|
|
DualGraph* dg = NULL;
|
|
VisualGraph* vg = NULL;
|
|
Relation* tri_rel = NULL;
|
|
|
|
|
|
if(complex_reg == 1){ ///complex region, we build dual graph and visual graph
|
|
|
|
// cout<<"complex corridor "<<endl;
|
|
|
|
GetSecondoObj(groom_reg, obj_name);
|
|
assert(obj_name.size() == 3);
|
|
SecondoCatalog* ctlg = SecondoSystem::GetCatalog();
|
|
bool dg_def, vg_def, rel_def;
|
|
Word dg_addr, vg_addr, rel_addr;
|
|
ctlg->GetObject(obj_name[0], dg_addr, dg_def);
|
|
ctlg->GetObject(obj_name[1], vg_addr, vg_def);
|
|
ctlg->GetObject(obj_name[2], rel_addr, rel_def);
|
|
|
|
if(dg_def && vg_def && rel_def){
|
|
dg = (DualGraph*)dg_addr.addr;
|
|
vg = (VisualGraph*)vg_addr.addr;
|
|
tri_rel = (Relation*)rel_addr.addr;
|
|
assert(dg != NULL);
|
|
assert(vg != NULL);
|
|
assert(tri_rel != NULL);
|
|
}else{
|
|
cout<<"open dual graph or visual graph error"<<endl;
|
|
delete groom_reg;
|
|
DeleteSecondoObj(obj_name);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
for(unsigned int i = 0;i < tid_list.size();i++){
|
|
Tuple* door_tuple1 = rel2->GetTuple(tid_list[i], false);
|
|
float h1 = ((CcReal*)door_tuple1->GetAttribute(attr4))->GetRealval();
|
|
Line* l1 = (Line*)door_tuple1->GetAttribute(attr2);
|
|
|
|
for(unsigned int j = 0;j < tid_list.size();j++){
|
|
if(tid_list[j] == tid_list[i]) continue;
|
|
Tuple* door_tuple2 = rel2->GetTuple(tid_list[j], false);
|
|
float h2 = ((CcReal*)door_tuple2->GetAttribute(attr4))->GetRealval();
|
|
Line* l2 = (Line*)door_tuple2->GetAttribute(attr2);
|
|
|
|
if(fabs(h1-h2) < dist_delta){ // on the same floor
|
|
if(complex_reg == 0){//////////simple region
|
|
ST_ConnectOneFloor(groom_oid, groom, l1, l2,
|
|
tid_list[i], tid_list[j], h1);
|
|
}else if(complex_reg == 1){//////complex region
|
|
|
|
ConnectComplexRegion(groom_oid, l1, l2,
|
|
tid_list[i], tid_list[j], h1,
|
|
dg, vg, tri_rel, groom_reg);
|
|
}else assert(false);
|
|
|
|
}else
|
|
assert(false);
|
|
door_tuple2->DeleteIfAllowed();
|
|
}
|
|
|
|
door_tuple1->DeleteIfAllowed();
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
delete groom_reg;
|
|
if(complex_reg == 1)DeleteSecondoObj(obj_name);
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
build the connection of two doors in a complex corrdior region
|
|
it uses dual graph, visual graph.
|
|
|
|
*/
|
|
void IndoorNav::ConnectComplexRegion(int groom_oid, Line* l1, Line* l2,
|
|
int tid1, int tid2, float h,
|
|
DualGraph* dg, VisualGraph* vg,
|
|
Relation* tri_rel, Region* groom_reg)
|
|
{
|
|
// if(tid1 != 135 ) return;
|
|
|
|
assert(dg != NULL);
|
|
assert(vg != NULL);
|
|
assert(tri_rel != NULL);
|
|
|
|
const double dist_delta = 0.001;
|
|
/////////////////////////////////////////////////////////////////////////
|
|
//////////////////get the position of two doors//////////////////////////
|
|
/////////////////////////////////////////////////////////////////////////
|
|
HalfSegment hs1;
|
|
assert(l1->Size() == 2);
|
|
l1->Get(0, hs1);
|
|
|
|
HalfSegment hs2;
|
|
assert(l2->Size() == 2);
|
|
l2->Get(0, hs2);
|
|
|
|
double x1 = (hs1.GetLeftPoint().GetX() + hs1.GetRightPoint().GetX())/2;
|
|
double y1 = (hs1.GetLeftPoint().GetY() + hs1.GetRightPoint().GetY())/2;
|
|
Point p1(true, x1, y1);
|
|
|
|
double x2 = (hs2.GetLeftPoint().GetX() + hs2.GetRightPoint().GetX())/2;
|
|
double y2 = (hs2.GetLeftPoint().GetY() + hs2.GetRightPoint().GetY())/2;
|
|
Point p2(true, x2, y2);
|
|
|
|
if(p1.Distance(p2) < dist_delta) return;
|
|
/////////////////////////////////////////////////////////////////////////
|
|
///////////////////compute the shortest path/////////////////////////////
|
|
/////////////////////////////////////////////////////////////////////////
|
|
int oid1 = 0;
|
|
int oid2 = 0;
|
|
// cout<<"tri no "<<dg->node_rel->GetNoTuples()<<endl;
|
|
FindPointInDG1(dg, &p1, oid1);
|
|
assert(1 <= oid1 && oid1 <= dg->node_rel->GetNoTuples());
|
|
FindPointInDG1(dg, &p2, oid2);
|
|
assert(1 <= oid2 && oid2 <= dg->node_rel->GetNoTuples());
|
|
|
|
Walk_SP* wsp = new Walk_SP(dg, vg, NULL, NULL);
|
|
wsp->rel3 = tri_rel;
|
|
Line* sp_path = new Line(0);
|
|
if(EuclideanConnection(groom_reg, &p1, &p2, sp_path)){
|
|
|
|
}else{
|
|
// cout<<"p1 "<<p1<<" p2 "<<p2<<endl;
|
|
// cout<<"oid1 "<<oid1<<" oid2 "<<oid2<<endl;
|
|
wsp->WalkShortestPath2(oid1, oid2, p1, p2, sp_path);
|
|
}
|
|
|
|
delete wsp;
|
|
|
|
|
|
if(sp_path->Size() == 0){
|
|
sp_path->DeleteIfAllowed();
|
|
return;
|
|
}
|
|
|
|
vector<MyHalfSegment> mhs;
|
|
|
|
SimpleLine* sl = new SimpleLine(0);
|
|
sl->fromLine(*sp_path);
|
|
SpacePartition* sp = new SpacePartition();
|
|
sp->ReorderLine(sl, mhs);
|
|
delete sp;
|
|
sl->DeleteIfAllowed();
|
|
sp_path->DeleteIfAllowed();
|
|
|
|
if(mhs[0].from.Distance(p1) < dist_delta &&
|
|
mhs[mhs.size() - 1].to.Distance(p2) < dist_delta){
|
|
|
|
}else{
|
|
assert(mhs[mhs.size() - 1].to.Distance(p1) < dist_delta &&
|
|
mhs[0].from.Distance(p2) < dist_delta);
|
|
|
|
vector<MyHalfSegment> temp_mhs;
|
|
for(int i = mhs.size() - 1;i >= 0;i--){
|
|
MyHalfSegment seg = mhs[i];
|
|
Point p = seg.from;
|
|
seg.from = seg.to;
|
|
seg.to = p;
|
|
temp_mhs.push_back(seg);
|
|
}
|
|
mhs.clear();
|
|
for(unsigned int i = 0;i < temp_mhs.size();i++)
|
|
mhs.push_back(temp_mhs[i]);
|
|
assert(mhs[0].from.Distance(p1) < dist_delta &&
|
|
mhs[mhs.size() - 1].to.Distance(p2) < dist_delta);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
///////////////// conver to 3D line //////////////////////////////
|
|
///////////////////////////////////////////////////////////////////
|
|
Line3D* l3d = new Line3D(0);
|
|
l3d->StartBulkLoad();
|
|
|
|
for(unsigned int i = 0;i < mhs.size();i++){
|
|
Point p = mhs[i].from;
|
|
Point3D q(true, p.GetX(), p.GetY(), h);
|
|
*l3d += q;
|
|
if(i == mhs.size() - 1){
|
|
Point p1 = mhs[i].to;
|
|
Point3D q1(true, p1.GetX(), p1.GetY(), h);
|
|
*l3d += q1;
|
|
}
|
|
}
|
|
l3d->EndBulkLoad();
|
|
|
|
groom_oid_list.push_back(groom_oid);
|
|
door_tid_list1.push_back(tid1);
|
|
door_tid_list2.push_back(tid2);
|
|
path_list.push_back(*l3d);
|
|
|
|
l3d->DeleteIfAllowed();
|
|
|
|
}
|
|
/*
|
|
create the edges connecting the same door but belong to two rooms
|
|
|
|
*/
|
|
|
|
void IndoorNav::CreateAdjDoor2(R_Tree<3,TupleId>* rtree)
|
|
{
|
|
SmiRecordId adr = rtree->RootRecordId();
|
|
|
|
for(int i = 1;i <= rel1->GetNoTuples();i++){
|
|
|
|
Tuple* door_tuple = rel1->GetTuple(i, false);
|
|
int groom_oid =
|
|
((CcInt*)door_tuple->GetAttribute(IndoorGraph::I_GROOM_OID1))->GetIntval();
|
|
Line3D* l = (Line3D*)door_tuple->GetAttribute(IndoorGraph::I_DOOR_LOC_3D);
|
|
vector<TupleId> id_list;
|
|
// l->Print();
|
|
////// the number of neighbor should be 2 or 3 //////////////////
|
|
DFTraverse(rtree, adr, i, l, id_list, groom_oid);
|
|
|
|
// assert(id_list.size() > 0);
|
|
|
|
|
|
// cout<<"door tid "<<i<<endl;
|
|
// cout<<"neighbor size "<<id_list.size()<<endl;
|
|
|
|
for(unsigned int j = 0;j < id_list.size();j++){
|
|
// cout<<"neighbor "<<id_list[j]<<endl;
|
|
|
|
// groom_oid_list.push_back(groom_oid);
|
|
groom_oid_list.push_back(0);/////////////no physical connection room
|
|
door_tid_list1.push_back(i);
|
|
door_tid_list2.push_back(id_list[j]);
|
|
Line3D* l3d = new Line3D(0);
|
|
path_list.push_back(*l3d);
|
|
l3d->DeleteIfAllowed();
|
|
}
|
|
|
|
|
|
door_tuple->DeleteIfAllowed();
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
traverse the RTree to find the same door but belongs to two rooms
|
|
|
|
*/
|
|
void IndoorNav::DFTraverse(R_Tree<3,TupleId>* rtree, SmiRecordId adr,
|
|
unsigned int id, Line3D* l,
|
|
vector<TupleId>& id_list, int groom_oid)
|
|
{
|
|
|
|
R_TreeNode<3,TupleId>* node = rtree->GetMyNode(adr,false,
|
|
rtree->MinEntries(0), rtree->MaxEntries(0));
|
|
Rectangle<3> bbox3d_1 = l->BoundingBox();
|
|
|
|
for(int j = 0;j < node->EntryCount();j++){
|
|
if(node->IsLeaf()){
|
|
R_TreeLeafEntry<3,TupleId> e =
|
|
(R_TreeLeafEntry<3,TupleId>&)(*node)[j];
|
|
Tuple* door_tuple = rel1->GetTuple(e.info,false);
|
|
Line3D* l3d =
|
|
(Line3D*)door_tuple->GetAttribute(IndoorGraph::I_DOOR_LOC_3D);
|
|
|
|
if(l3d->BoundingBox().Intersects(bbox3d_1) && id != e.info){
|
|
if(*l == *l3d)id_list.push_back(e.info);
|
|
}
|
|
|
|
|
|
/* if(l3d->BoundingBox().Intersects(bbox3d_1)){
|
|
cout<<"l2 ";
|
|
l3d->Print();
|
|
if(*l == *l3d)id_list.push_back(e.info);
|
|
}*/
|
|
|
|
door_tuple->DeleteIfAllowed();
|
|
}else{
|
|
R_TreeInternalEntry<3> e = (R_TreeInternalEntry<3>&)(*node)[j];
|
|
if(l->BoundingBox().Intersects(e.box)){
|
|
DFTraverse(rtree, e.pointer, id, l, id_list, groom_oid);
|
|
}
|
|
}
|
|
}
|
|
delete node;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
////////// shortest path inside a polygon (convex, concave, holes) /////////
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
string PointsTypeInfo =
|
|
"(rel(tuple((v point)(neighbor1 point)(neighbor2 point)(regid int))))";
|
|
|
|
|
|
void ShortestPath_InRegion(Region* reg, Point* s, Point* d, Line* pResult)
|
|
{
|
|
const double dist_delta = 0.001;
|
|
if(reg->Contains(*s) == false){
|
|
cout<<"region "<<*reg<<"start point "<<*s<<" end point "<<*d<<endl;
|
|
cout<<"start point should be inside the region"<<endl;
|
|
return;
|
|
}
|
|
if(reg->Contains(*d) == false){
|
|
cout<<"region "<<*reg<<"start point "<<*s<<" end point "<<*d<<endl;
|
|
cout<<"end point should be inside the region"<<endl;
|
|
return;
|
|
}
|
|
|
|
if(reg->NoComponents() > 1){
|
|
cout<<"only one face is allowed"<<endl;
|
|
return;
|
|
}
|
|
if(s->Distance(*d) < dist_delta){
|
|
// cout<<"start location equals to the end locaton"<<endl;
|
|
return;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
////////////// naive method to compute shortest path in a polygon////
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
/////////////////////// collect all points//////////////////////////////
|
|
vector<PointAndID> ps_list;
|
|
Points* ps = new Points(0);
|
|
reg->Vertices(ps);
|
|
vector<bool> visit_flag;
|
|
for(int i = 0;i < ps->Size();i++){
|
|
Point p;
|
|
ps->Get(i, p);
|
|
PointAndID* paid = new PointAndID(i + 1, p);
|
|
ps_list.push_back(*paid);
|
|
// paid->Print();
|
|
delete paid;
|
|
visit_flag.push_back(true);
|
|
}
|
|
ps->DeleteIfAllowed();
|
|
////////////////////collec all segments////////////////////////////////////
|
|
vector<HalfSegment> seg_list;
|
|
for(int i = 0;i < reg->Size();i++){
|
|
HalfSegment hs;
|
|
reg->Get(i, hs);
|
|
if(!hs.IsLeftDomPoint())continue;
|
|
seg_list.push_back(hs);
|
|
}
|
|
//////////////////create start and end point /////////////////////////////
|
|
PointAndID start_loc;
|
|
PointAndID end_loc;
|
|
bool start = false;
|
|
bool end = false;
|
|
|
|
for(unsigned int i = 0;i < ps_list.size();i++){
|
|
Point loc = ps_list[i].loc;
|
|
if(s->Distance(loc) < dist_delta){
|
|
start_loc = ps_list[i];
|
|
start = true;
|
|
}
|
|
if(d->Distance(loc) < dist_delta){
|
|
end_loc = ps_list[i];
|
|
end = true;
|
|
}
|
|
if(start && end) break;
|
|
}
|
|
if(start == false){
|
|
start_loc.pid = 0;
|
|
start_loc.loc = *s;
|
|
}else
|
|
visit_flag[start_loc.pid - 1] = false;
|
|
|
|
|
|
if(end == false){
|
|
end_loc.pid = ps_list.size() + 1;
|
|
end_loc.loc = *d;
|
|
ps_list.push_back(end_loc);
|
|
visit_flag.push_back(true);
|
|
}
|
|
/////////////////////////////////////////////////////////////////////////
|
|
////////////first check whether Euclidean distance between s and d//////
|
|
HalfSegment temp_hs(true, start_loc.loc, end_loc.loc);
|
|
|
|
|
|
|
|
if(SegAvailable(temp_hs, seg_list) && RegContainHS(reg, temp_hs)){
|
|
// cout<<"find the path"<<endl;
|
|
pResult->StartBulkLoad();
|
|
int edgeno = 0;
|
|
HalfSegment hs(true, start_loc.loc, end_loc.loc);
|
|
hs.attr.edgeno = edgeno++;
|
|
*pResult += hs;
|
|
hs.SetLeftDomPoint(!hs.IsLeftDomPoint());
|
|
*pResult += hs;
|
|
pResult->EndBulkLoad();
|
|
return;
|
|
}
|
|
//////////////searching inside the region//////////////////////////////
|
|
// for(unsigned int i = 0;i < pslist.size();i++)
|
|
// pslist[i].Print();
|
|
|
|
|
|
priority_queue<RPath_elem> path_queue;
|
|
vector<RPath_elem> expand_path;
|
|
|
|
InitializeQueue(reg, path_queue, expand_path, start_loc, end_loc,
|
|
ps_list, seg_list);
|
|
// cout<<" initialize size "<<pathqueue.size()<<endl;
|
|
// cout<<" expand size "<<expandpath.size()<<endl;
|
|
bool find = false;
|
|
RPath_elem dest;
|
|
while(path_queue.empty() == false){
|
|
RPath_elem top = path_queue.top();
|
|
path_queue.pop();
|
|
// top.Print();
|
|
PointAndID cur_loc = ps_list[top.tri_index - 1];
|
|
|
|
if(top.tri_index == end_loc.pid){
|
|
// cout<<"find the path"<<endl;
|
|
find = true;
|
|
dest = top;
|
|
break;
|
|
}
|
|
|
|
vector<int> adj_list;
|
|
FindAdj(reg, cur_loc, visit_flag, adj_list, ps_list, seg_list);
|
|
int pos_expand_path = top.cur_index;
|
|
for(unsigned int i = 0;i < adj_list.size();i++){
|
|
// cout<<" neighbor ";
|
|
|
|
int expand_path_size = expand_path.size();
|
|
double w = cur_loc.loc.Distance(ps_list[adj_list[i] - 1].loc);
|
|
double hw = ps_list[adj_list[i] - 1].loc.Distance(end_loc.loc);
|
|
|
|
path_queue.push(RPath_elem(pos_expand_path, expand_path_size,
|
|
adj_list[i], top.real_w + w + hw,
|
|
top.real_w + w));
|
|
expand_path.push_back(RPath_elem(pos_expand_path, expand_path_size,
|
|
adj_list[i], top.real_w + w + hw,
|
|
top.real_w + w));
|
|
}
|
|
|
|
visit_flag[top.tri_index - 1] = false;
|
|
|
|
// cout<<endl;
|
|
}
|
|
if(find){
|
|
vector<Point> points;
|
|
while(dest.prev_index != -1){
|
|
points.push_back(ps_list[dest.tri_index - 1].loc);
|
|
dest = expand_path[dest.prev_index];
|
|
}
|
|
points.push_back(ps_list[dest.tri_index - 1].loc);
|
|
points.push_back(start_loc.loc);
|
|
|
|
pResult->StartBulkLoad();
|
|
int edgeno = 0;
|
|
|
|
for(unsigned int i = 0;i < points.size() - 1;i++){
|
|
|
|
HalfSegment hs(true, points[i], points[i + 1]);
|
|
hs.attr.edgeno = edgeno++;
|
|
*pResult += hs;
|
|
hs.SetLeftDomPoint(!hs.IsLeftDomPoint());
|
|
*pResult += hs;
|
|
}
|
|
pResult->EndBulkLoad();
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
Initialize the queue for searching, put all points which are reachable to the
|
|
start point
|
|
|
|
*/
|
|
void InitializeQueue(Region* reg, priority_queue<RPath_elem>& path_queue,
|
|
vector<RPath_elem>& expand_queue,
|
|
PointAndID start_loc, PointAndID end_loc,
|
|
vector<PointAndID>& ps_list,
|
|
vector<HalfSegment>& seg_list)
|
|
{
|
|
// cout<<"Initialize Queue "<<endl;
|
|
|
|
vector<int> candidate;
|
|
for(unsigned int i = 0;i < ps_list.size();i++){
|
|
if(start_loc.pid != ps_list[i].pid){
|
|
HalfSegment hs(true, start_loc.loc, ps_list[i].loc);
|
|
if(SegAvailable(hs, seg_list)){
|
|
candidate.push_back(i);
|
|
}
|
|
}
|
|
}
|
|
for(unsigned int i = 0;i < candidate.size();i++){
|
|
unsigned int j = candidate[i];
|
|
HalfSegment hs(true, start_loc.loc, ps_list[j].loc);
|
|
if(RegContainHS(reg, hs)){
|
|
int cur_size = expand_queue.size();
|
|
double w = start_loc.loc.Distance(ps_list[j].loc);
|
|
double hw = ps_list[j].loc.Distance(end_loc.loc);
|
|
RPath_elem elem(-1, cur_size, ps_list[j].pid, w + hw, w);
|
|
path_queue.push(elem);
|
|
expand_queue.push_back(elem);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
find points which are available
|
|
|
|
*/
|
|
void FindAdj(Region* reg, PointAndID top, vector<bool>& visit_flag,
|
|
vector<int>& adj_list, vector<PointAndID>& ps_list,
|
|
vector<HalfSegment>& seg_list)
|
|
{
|
|
|
|
vector<int> candidate;
|
|
for(unsigned int i = 0;i < ps_list.size();i++){
|
|
if(top.pid != ps_list[i].pid && visit_flag[i]){
|
|
HalfSegment hs(true, top.loc, ps_list[i].loc);
|
|
if(SegAvailable(hs, seg_list)){
|
|
candidate.push_back(i);
|
|
}
|
|
}
|
|
}
|
|
|
|
for(unsigned int i = 0;i < candidate.size();i++){
|
|
unsigned int j = candidate[i];
|
|
HalfSegment hs(true, top.loc, ps_list[j].loc);
|
|
if(RegContainHS(reg, hs))
|
|
adj_list.push_back(ps_list[j].pid);
|
|
}
|
|
}
|
|
|
|
/*
|
|
check whether the segment middle intersects another one
|
|
|
|
*/
|
|
bool SegAvailable(HalfSegment hs, vector<HalfSegment>& seg_list)
|
|
{
|
|
const double dist_delta = 0.001;
|
|
for(unsigned int i = 0;i < seg_list.size();i++){
|
|
HalfSegment seg = seg_list[i];
|
|
|
|
if( (hs.GetLeftPoint().Distance(seg.GetLeftPoint()) < dist_delta &&
|
|
hs.GetRightPoint().Distance(seg.GetRightPoint()) < dist_delta )||
|
|
(hs.GetLeftPoint().Distance(seg.GetRightPoint()) < dist_delta &&
|
|
hs.GetRightPoint().Distance(seg.GetLeftPoint()) < dist_delta ))
|
|
return true;
|
|
|
|
HalfSegment iseg;
|
|
if(hs.Intersection(seg, iseg) && iseg.Length() > dist_delta){
|
|
if(fabs(iseg.Length() - hs.Length()) < dist_delta) return true;
|
|
return false;
|
|
}
|
|
|
|
Point ip;
|
|
if(hs.Intersection(seg, ip)){
|
|
if( hs.GetLeftPoint().Distance(ip) < dist_delta ||
|
|
hs.GetRightPoint().Distance(ip) < dist_delta)
|
|
continue;
|
|
else
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
collect the boundary points of a region cycle
|
|
|
|
*/
|
|
|
|
void GetBoundaryPoints(Region* reg, vector<Point>& ps, unsigned int i)
|
|
{
|
|
SimpleLine* sl = new SimpleLine(0);
|
|
sl->StartBulkLoad();
|
|
int edgeno = 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 = edgeno++;
|
|
*sl += hs2;
|
|
hs2.SetLeftDomPoint(!hs2.IsLeftDomPoint());
|
|
*sl += hs2;
|
|
}
|
|
sl->EndBulkLoad();
|
|
|
|
SpacePartition* sp = new SpacePartition();
|
|
vector<MyHalfSegment> mhs;
|
|
sp->ReorderLine(sl, mhs);
|
|
for(unsigned int j = 0;j < mhs.size();j++)
|
|
ps.push_back(mhs[j].from);
|
|
delete sp;
|
|
sl->DeleteIfAllowed();
|
|
|
|
|
|
CompTriangle* ct = new CompTriangle();
|
|
bool clock;
|
|
if(0.0f < ct->Area(ps)){//points counter-clockwise order
|
|
clock = false;
|
|
}else{// points clockwise
|
|
clock = true;
|
|
}
|
|
|
|
vector<Point> temp_ps1; //clockwise
|
|
vector<Point> temp_ps2; //counter-clockwise
|
|
if(clock){
|
|
for(unsigned int i = 0;i < ps.size();i++){
|
|
temp_ps1.push_back(ps[i]);
|
|
temp_ps2.push_back(ps[ps.size() - 1 - i]);
|
|
}
|
|
}else{
|
|
for(unsigned int i = 0;i < ps.size();i++){
|
|
temp_ps2.push_back(ps[i]);
|
|
temp_ps1.push_back(ps[ps.size() - 1 - i]);
|
|
}
|
|
}
|
|
if(i == 0){
|
|
ps.clear();
|
|
for(unsigned int i = 0;i < temp_ps1.size();i++)
|
|
ps.push_back(temp_ps1[i]);
|
|
}else{
|
|
ps.clear();
|
|
for(unsigned int i = 0;i < temp_ps2.size();i++)
|
|
ps.push_back(temp_ps2[i]);
|
|
}
|
|
|
|
delete ct;
|
|
}
|
|
|
|
/*
|
|
create the dual graph and visual graph for finding the shortest path between
|
|
two points inside a region. not use the simple method for complex region
|
|
|
|
*/
|
|
void ShortestPath_InRegionNew(Region* reg, Point* s, Point* d, Line* pResult)
|
|
{
|
|
const double dist_delta = 0.001;
|
|
if(reg->Contains(*s) == false){
|
|
cout<<"region "<<*reg<<"start point "<<*s<<" end point "<<*d<<endl;
|
|
cout<<"start point should be inside the region"<<endl;
|
|
return;
|
|
}
|
|
if(reg->Contains(*d) == false){
|
|
cout<<"region "<<*reg<<"start point "<<*s<<" end point "<<*d<<endl;
|
|
cout<<"end point should be inside the region"<<endl;
|
|
return;
|
|
}
|
|
|
|
if(reg->NoComponents() > 1){
|
|
cout<<"only one face is allowed"<<endl;
|
|
return;
|
|
}
|
|
if(s->Distance(*d) < dist_delta){
|
|
cout<<"start location equals to the end locaton"<<endl;
|
|
return;
|
|
}
|
|
//////////////Euclidean connection is avaialble////////////////////////////
|
|
if(EuclideanConnection(reg, s, d, pResult))return;
|
|
/////////////////////////////////////////////////////////////////////////
|
|
vector<string> obj_name;
|
|
GetSecondoObj(reg, obj_name);
|
|
assert(obj_name.size() == 3);
|
|
///////////////////////////////////////////////////////
|
|
SecondoCatalog* ctlg = SecondoSystem::GetCatalog();
|
|
bool dg_def, vg_def, rel_def;
|
|
Word dg_addr, vg_addr, rel_addr;
|
|
ctlg->GetObject(obj_name[0], dg_addr, dg_def);
|
|
ctlg->GetObject(obj_name[1], vg_addr, vg_def);
|
|
ctlg->GetObject(obj_name[2], rel_addr, rel_def);
|
|
|
|
if(dg_def && vg_def && rel_def){
|
|
DualGraph* dg = (DualGraph*)dg_addr.addr;
|
|
VisualGraph* vg = (VisualGraph*)vg_addr.addr;
|
|
Relation* rel = (Relation*)rel_addr.addr;
|
|
assert(dg != NULL);
|
|
assert(vg != NULL);
|
|
assert(rel != NULL);
|
|
|
|
Walk_SP* wsp = new Walk_SP(dg, vg, NULL, NULL);
|
|
wsp->rel3 = rel;
|
|
int oid1 = 0;
|
|
int oid2 = 0;
|
|
FindPointInDG(dg, s, d, oid1, oid2);
|
|
|
|
assert(1 <= oid1 && oid1 <= dg->node_rel->GetNoTuples());
|
|
assert(1 <= oid2 && oid2 <= dg->node_rel->GetNoTuples());
|
|
|
|
wsp->WalkShortestPath2(oid1, oid2, *s, *d, pResult);
|
|
|
|
delete wsp;
|
|
|
|
}else{
|
|
cout<<"open dual graph or visual graph error"<<endl;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////
|
|
DeleteSecondoObj(obj_name);
|
|
|
|
}
|
|
|
|
/*
|
|
direct connection between start and end location
|
|
|
|
*/
|
|
bool EuclideanConnection(Region* reg, Point*s, Point* d, Line* pResult)
|
|
{
|
|
// cout<<"reg "<<*reg<<endl;
|
|
|
|
vector<HalfSegment> seg_list;
|
|
for(int i = 0;i < reg->Size();i++){
|
|
HalfSegment hs;
|
|
reg->Get(i, hs);
|
|
if(!hs.IsLeftDomPoint())continue;
|
|
seg_list.push_back(hs);
|
|
}
|
|
HalfSegment temp_hs(true, *s, *d);
|
|
if(SegAvailable(temp_hs, seg_list) && RegContainHS(reg, temp_hs)){
|
|
pResult->StartBulkLoad();
|
|
HalfSegment hs(true, *s, *d);
|
|
hs.attr.edgeno = 0;
|
|
*pResult += hs;
|
|
hs.SetLeftDomPoint(!hs.IsLeftDomPoint());
|
|
*pResult += hs;
|
|
pResult->EndBulkLoad();
|
|
return true;
|
|
}
|
|
return false;
|
|
|
|
}
|
|
|
|
/*
|
|
find which triangle the point is located inside
|
|
|
|
*/
|
|
void FindPointInDG(DualGraph* dg, Point* loc1, Point* loc2, int& id1, int& id2)
|
|
{
|
|
|
|
for(int i = 1;i <= dg->node_rel->GetNoTuples();i++){
|
|
Tuple* dg_tuple = dg->node_rel->GetTuple(i, false);
|
|
Region* reg = (Region*)dg_tuple->GetAttribute(DualGraph::PAVEMENT);
|
|
if(loc1->Inside(*reg))id1 = i;
|
|
if(loc2->Inside(*reg))id2 = i;
|
|
dg_tuple->DeleteIfAllowed();
|
|
}
|
|
// cout<<"oid1 "<<id1<<" oid2 "<<id2<<endl;
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
find which triangle the point is located inside
|
|
|
|
*/
|
|
void FindPointInDG1(DualGraph* dg, Point* loc1, int& id1)
|
|
{
|
|
|
|
for(int i = 1;i <= dg->node_rel->GetNoTuples();i++){
|
|
Tuple* dg_tuple = dg->node_rel->GetTuple(i, false);
|
|
Region* reg = (Region*)dg_tuple->GetAttribute(DualGraph::PAVEMENT);
|
|
if(loc1->Inside(*reg))id1 = i;
|
|
dg_tuple->DeleteIfAllowed();
|
|
}
|
|
// cout<<"oid1 "<<id1<<endl;
|
|
|
|
}
|
|
|
|
/*
|
|
create second object : dual graph, visual graph and delete them
|
|
|
|
*/
|
|
void GetSecondoObj(Region* reg, vector<string>& obj_name)
|
|
{
|
|
|
|
////////1. create a second object from the memory region//////////////
|
|
string ObjName_Reg = "xu_region";
|
|
SecondoCatalog* ctlg = SecondoSystem::GetCatalog();
|
|
|
|
if ( ctlg->IsSystemObject(ObjName_Reg) ) {
|
|
cout<< "ERROR: Object name identifier is a reseverved identifier.";
|
|
return;
|
|
} else if (ctlg->IsObjectName(ObjName_Reg) ) {
|
|
cout<< "ERROR: Object name identifier "
|
|
+ ObjName_Reg + " is already used.";
|
|
return;
|
|
}
|
|
ListExpr resultType1 = nl->SymbolAtom("region");
|
|
ctlg->CreateObject(ObjName_Reg, "", resultType1, 0);
|
|
ctlg->CloneObject( ObjName_Reg, SetWord( reg ) );
|
|
////////////////////////////////////////////////////////////////////
|
|
/////////////////////2. dual graph/////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
///////////////// 1) dual graph nodes //////////////////////////////
|
|
|
|
string ObjName_DG_Node = "xu_dg_node";
|
|
string command1 = "triangulation(" + ObjName_Reg + ") transformstream \
|
|
addcounter[Oid, 1] extend[Rid:.Oid] extend[Pavement:.Elem] \
|
|
project[Oid,Rid,Pavement] consume";
|
|
string querystringParsed = "";
|
|
ListExpr parsedCommand1;
|
|
if(CheckCommand(command1, querystringParsed, parsedCommand1) == false)return;
|
|
|
|
// cout<<querystringParsed<<endl;
|
|
RunCommand(ctlg, parsedCommand1, ObjName_DG_Node); ////create dual graph node
|
|
|
|
|
|
///////////////// 2) dual graph edges //////////////////////////////
|
|
|
|
string ObjName_REGNODES = "xu_regnodes";
|
|
string command2 = "regvertex(" + ObjName_Reg + ") consume";
|
|
querystringParsed = "";
|
|
ListExpr parsedCommand2;
|
|
if(CheckCommand(command2, querystringParsed, parsedCommand2) == false)return;
|
|
|
|
RunCommand(ctlg, parsedCommand2, ObjName_REGNODES);
|
|
|
|
|
|
string ObjName_TRIREG = "xu_tri_reg";
|
|
string command3 = "triangulation_new(" + ObjName_Reg + ") consume";
|
|
querystringParsed = "";
|
|
ListExpr parsedCommand3;
|
|
if(CheckCommand(command3, querystringParsed, parsedCommand3) == false)return;
|
|
|
|
RunCommand(ctlg, parsedCommand3, ObjName_TRIREG); ///////we need this later
|
|
|
|
|
|
string ObjName_TRIREGSORT = "xu_tri_reg_sort";
|
|
string command4 = ObjName_TRIREG + " feed addcounter[Oid, 1]\
|
|
extend[Zvalue:zval(.Centroid)] sortby[Zvalue asc] remove[Zvalue] consume";
|
|
querystringParsed = "";
|
|
ListExpr parsedCommand4;
|
|
if(CheckCommand(command4, querystringParsed, parsedCommand4) == false)return;
|
|
|
|
RunCommand(ctlg, parsedCommand4, ObjName_TRIREGSORT);
|
|
|
|
|
|
string ObjName_DG_Edge = "xu_dg_edge";
|
|
string command5 = "get_dg_edge(" + ObjName_TRIREGSORT + ", " +
|
|
ObjName_REGNODES + ") consume";
|
|
|
|
querystringParsed = "";
|
|
ListExpr parsedCommand5;
|
|
if(CheckCommand(command5, querystringParsed, parsedCommand5) == false)return;
|
|
|
|
RunCommand(ctlg, parsedCommand5, ObjName_DG_Edge);
|
|
|
|
|
|
////////////////// 3) graph /////////////////////////////////////////
|
|
string ObjName_DG = "xu_dg";
|
|
string command6 = "createdualgraph( 1000," + ObjName_DG_Node + ", " +
|
|
ObjName_DG_Edge + ")";
|
|
|
|
querystringParsed = "";
|
|
ListExpr parsedCommand6;
|
|
if(CheckCommand(command6, querystringParsed, parsedCommand6) == false)return;
|
|
|
|
RunCommand(ctlg, parsedCommand6, ObjName_DG); ////////we need this later
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
/////////////////////3 visual graph/////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////// 1) nodes /////////////////////////////////////////
|
|
|
|
string ObjName_VG_Node = "xu_vg_node";
|
|
string command7 = "regvertex(" + ObjName_Reg + ") addcounter[Oid,1] \
|
|
extend[Loc:.Vertex] project[Oid,Loc] consume";
|
|
querystringParsed = "";
|
|
ListExpr parsedCommand7;
|
|
if(CheckCommand(command7, querystringParsed, parsedCommand7) == false)return;
|
|
|
|
RunCommand(ctlg, parsedCommand7, ObjName_VG_Node);//create visual graph node
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
string ObjName_VG_TRI = "xu_vertex_tri";
|
|
string command8 = "decomposetri(" + ObjName_TRIREGSORT + ") consume";
|
|
querystringParsed = "";
|
|
ListExpr parsedCommand8;
|
|
if(CheckCommand(command8, querystringParsed, parsedCommand8) == false){
|
|
|
|
assert( ctlg->DeleteObject(ObjName_Reg));
|
|
assert( ctlg->DeleteObject(ObjName_DG_Node));
|
|
assert( ctlg->DeleteObject(ObjName_REGNODES));
|
|
assert( ctlg->DeleteObject(ObjName_TRIREG));
|
|
assert( ctlg->DeleteObject(ObjName_TRIREGSORT));
|
|
assert( ctlg->DeleteObject(ObjName_DG_Edge));
|
|
assert( ctlg->DeleteObject(ObjName_DG));
|
|
assert( ctlg->DeleteObject(ObjName_VG_Node));
|
|
return;
|
|
}
|
|
|
|
RunCommand(ctlg, parsedCommand8, ObjName_VG_TRI);
|
|
|
|
|
|
string ObjName_VG_TRI_BTREE = "xu_btr_vid";
|
|
string command9 = ObjName_VG_TRI + " createbtree[Vid]";
|
|
querystringParsed = "";
|
|
ListExpr parsedCommand9;
|
|
|
|
if(CheckCommand(command9, querystringParsed, parsedCommand9) == false){
|
|
|
|
assert( ctlg->DeleteObject(ObjName_Reg));
|
|
assert( ctlg->DeleteObject(ObjName_DG_Node));
|
|
assert( ctlg->DeleteObject(ObjName_REGNODES));
|
|
assert( ctlg->DeleteObject(ObjName_TRIREG));
|
|
assert( ctlg->DeleteObject(ObjName_TRIREGSORT));
|
|
assert( ctlg->DeleteObject(ObjName_DG_Edge));
|
|
assert( ctlg->DeleteObject(ObjName_DG));
|
|
assert( ctlg->DeleteObject(ObjName_VG_Node));
|
|
assert( ctlg->DeleteObject(ObjName_VG_TRI));
|
|
return;
|
|
}
|
|
RunCommand(ctlg, parsedCommand9, ObjName_VG_TRI_BTREE);
|
|
|
|
|
|
////////////////// 2) edges /////////////////////////////////////////
|
|
|
|
string ObjName_VG_Edge = "xu_vg_edge";
|
|
string command10 = "getvgedge(" + ObjName_DG + "," + ObjName_VG_Node + ","
|
|
+ ObjName_TRIREG + ", " + ObjName_VG_TRI + ", "
|
|
+ ObjName_VG_TRI_BTREE + ") consume";
|
|
querystringParsed = "";
|
|
ListExpr parsedCommand10;
|
|
if(CheckCommand(command10, querystringParsed, parsedCommand10) == false){
|
|
|
|
return;
|
|
}
|
|
RunCommand(ctlg, parsedCommand10, ObjName_VG_Edge);
|
|
//////////////////////3) graph //////////////////////////////////
|
|
string ObjName_VG = "xu_vg";
|
|
string command11 = "createvgraph( 1000, " + ObjName_VG_Node + ","
|
|
+ ObjName_VG_Edge + ")";
|
|
|
|
querystringParsed = "";
|
|
ListExpr parsedCommand11;
|
|
if(CheckCommand(command11, querystringParsed, parsedCommand11) == false){
|
|
return;
|
|
}
|
|
RunCommand(ctlg, parsedCommand11, ObjName_VG);
|
|
/////////////////////////////////////////////////////////////////////////
|
|
///////////////delete all objects/////////////////////////////////
|
|
|
|
assert( ctlg->DeleteObject(ObjName_Reg));
|
|
assert( ctlg->DeleteObject(ObjName_DG_Node));
|
|
assert( ctlg->DeleteObject(ObjName_REGNODES));
|
|
// assert( ctlg->DeleteObject(ObjName_TRIREG)); //we need this
|
|
assert( ctlg->DeleteObject(ObjName_TRIREGSORT));
|
|
assert( ctlg->DeleteObject(ObjName_DG_Edge));
|
|
// assert( ctlg->DeleteObject(ObjName_DG)); //we need dual graph
|
|
assert( ctlg->DeleteObject(ObjName_VG_Node));
|
|
assert( ctlg->DeleteObject(ObjName_VG_TRI));
|
|
assert( ctlg->DeleteObject(ObjName_VG_TRI_BTREE));
|
|
assert( ctlg->DeleteObject(ObjName_VG_Edge));
|
|
// assert( ctlg->DeleteObject(ObjName_VG)); //we need visual graph
|
|
|
|
obj_name.push_back(ObjName_DG);
|
|
obj_name.push_back(ObjName_VG);
|
|
obj_name.push_back(ObjName_TRIREG);
|
|
}
|
|
|
|
bool CheckCommand(string& str1, string& str2, ListExpr& parsedCommand)
|
|
{
|
|
SecParser mySecParser;
|
|
if(mySecParser.Text2List( "query " + str1, str2 ) != 0){
|
|
cout<< "ERROR: Value text does not contain a \
|
|
parsable value expression.";
|
|
return false;
|
|
}
|
|
|
|
|
|
if (!nl->ReadFromString(str2, parsedCommand) ) {
|
|
cout<< "ERROR: Value text does not produce a \
|
|
valid nested list expression.";
|
|
return false;
|
|
}
|
|
|
|
if ( (nl->ListLength(parsedCommand) == 2) ){
|
|
parsedCommand = nl->Second(parsedCommand);
|
|
} else {
|
|
cout<< "ERROR: Value text does not produce a \
|
|
valid nested list expression.";
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
run the commond to create second object
|
|
|
|
*/
|
|
bool RunCommand(SecondoCatalog* ctlg, ListExpr parsedCommand,
|
|
string ObjNameString)
|
|
{
|
|
// cout<<"object name "<<ObjNameString <<endl;
|
|
OpTree tree = 0;
|
|
ListExpr resultType;
|
|
QueryProcessor *qpp = new QueryProcessor( nl, am );
|
|
bool correct = false;
|
|
bool evaluable = false;
|
|
bool defined = false;
|
|
bool isFunction = false;
|
|
Word qresult;
|
|
|
|
|
|
qpp->Construct( parsedCommand, correct, evaluable, defined, isFunction,
|
|
tree, resultType );
|
|
if ( !correct ){
|
|
cout<<"ERROR: Value text yields a TYPEERROR.";
|
|
// Do not need to destroy tree here!
|
|
delete qpp;
|
|
return false;
|
|
}
|
|
|
|
string typestring = nl->ToString(resultType);
|
|
|
|
if ( evaluable){
|
|
string typeName = "";
|
|
ctlg->CreateObject(ObjNameString, typeName, resultType, 0);
|
|
}
|
|
|
|
if ( evaluable ){
|
|
qpp->EvalS( tree, qresult, 1 );
|
|
if( IsRootObject( tree ) && !IsConstantObject( tree ) ){
|
|
// ctlg->CloneObject( ObjNameString, qresult );
|
|
// qpp->Destroy( tree, true );
|
|
} else {
|
|
ctlg->UpdateObject( ObjNameString, qresult );
|
|
// qpp->Destroy( tree, false);
|
|
}
|
|
}
|
|
delete qpp;
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
delete the dual graph, visual graph and the relation
|
|
|
|
*/
|
|
void DeleteSecondoObj(vector<string> obj_name)
|
|
{
|
|
SecondoCatalog* ctlg = SecondoSystem::GetCatalog();
|
|
for(unsigned int i = 0;i < obj_name.size();i++){
|
|
assert( ctlg->DeleteObject(obj_name[i]));
|
|
}
|
|
|
|
}
|
|
//////////////////////////////////////////////////////////////////////////
|
|
///////////////////Indoor Graph for Navigation//////////////////////////
|
|
/////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
string IndoorGraph::NodeTypeInfo =
|
|
"(rel (tuple ((Door door3d) (Door_loc line) (Groom_oid1 int) (Groom_oid2 int)\
|
|
(Door_loc3d line3d) (Doorheight real))))";
|
|
|
|
string IndoorGraph::EdgeTypeInfo =
|
|
"(rel (tuple ((Groom_oid int) (Door_tid1 int) (Door_tid2 int) (Path line3d))))";
|
|
|
|
string IndoorGraph::NodeBTreeTypeInfo =
|
|
"(btree (tuple ((Door door3d) (Door_loc line) (Groom_oid1 int) (Groom_oid2 int)\
|
|
(Door_loc3d line3d) (Doorheight real))) int)";
|
|
|
|
string IndoorGraph::EntranceTidTypeInfo =
|
|
"(rel (tuple ((Entrance int))))";
|
|
|
|
|
|
IndoorGraph::~IndoorGraph()
|
|
{
|
|
// cout<<"~IndoorGraph()"<<endl;
|
|
if(btree_node) delete btree_node;
|
|
if(entrance_list != NULL) entrance_list->Close();
|
|
}
|
|
|
|
IndoorGraph::IndoorGraph():btree_node(NULL), entrance_list(NULL), graph_type(0)
|
|
{
|
|
// cout<<"IndoorGraph::IndoorGraph()"<<endl;
|
|
}
|
|
|
|
IndoorGraph::IndoorGraph(ListExpr in_xValue,int in_iErrorPos,
|
|
ListExpr& inout_xErrorInfo,
|
|
bool& inout_bCorrect):btree_node(NULL),
|
|
entrance_list(NULL), graph_type(0)
|
|
{
|
|
// cout<<"IndoorGraph::IndoorGraph(ListExpr)"<<endl;
|
|
}
|
|
|
|
bool IndoorGraph::CheckIndoorGraph(ListExpr type, ListExpr& errorInfo)
|
|
{
|
|
// cout<<"CheckIndoorGraph()"<<endl;
|
|
return nl->IsEqual(type, "indoorgraph");
|
|
}
|
|
|
|
void IndoorGraph::CloseIndoorGraph(const ListExpr typeInfo, Word& w)
|
|
{
|
|
// cout<<"CloseIndoorGraph()"<<endl;
|
|
delete static_cast<IndoorGraph*> (w.addr);
|
|
w.addr = NULL;
|
|
}
|
|
|
|
void IndoorGraph::DeleteIndoorGraph(const ListExpr typeInfo, Word& w)
|
|
{
|
|
// cout<<"DeleteIndoorGraph()"<<endl;
|
|
IndoorGraph* ig = (IndoorGraph*)w.addr;
|
|
delete ig;
|
|
w.addr = NULL;
|
|
}
|
|
|
|
Word IndoorGraph::CreateIndoorGraph(const ListExpr typeInfo)
|
|
{
|
|
// cout<<"CreateIndoorGraph()"<<endl;
|
|
return SetWord(new IndoorGraph());
|
|
}
|
|
|
|
/*
|
|
Input a indoor graph
|
|
|
|
*/
|
|
|
|
Word IndoorGraph::InIndoorGraph(ListExpr in_xTypeInfo,
|
|
ListExpr in_xValue,
|
|
int in_iErrorPos, ListExpr& inout_xErrorInfo,
|
|
bool& inout_bCorrect)
|
|
{
|
|
// cout<<"InIndoorGraph()"<<endl;
|
|
IndoorGraph* ig = new IndoorGraph(in_xValue, in_iErrorPos, inout_xErrorInfo,
|
|
inout_bCorrect);
|
|
if(inout_bCorrect) return SetWord(ig);
|
|
else{
|
|
delete ig;
|
|
return SetWord(Address(0));
|
|
}
|
|
}
|
|
|
|
|
|
ListExpr IndoorGraph::OutIndoorGraph(ListExpr typeInfo, Word value)
|
|
{
|
|
// cout<<"OutIndoorGraph()"<<endl;
|
|
IndoorGraph* ig = (IndoorGraph*)value.addr;
|
|
return ig->Out(typeInfo);
|
|
}
|
|
/*
|
|
Output the indoor graph
|
|
|
|
*/
|
|
ListExpr IndoorGraph::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* groom_oid = (CcInt*)edge_tuple->GetAttribute(I_GROOM_OID);
|
|
CcInt* oid1 = (CcInt*)edge_tuple->GetAttribute(I_DOOR_TID1);
|
|
CcInt* oid2 = (CcInt*)edge_tuple->GetAttribute(I_DOOR_TID2);
|
|
Line* connection = (Line*)edge_tuple->GetAttribute(I_PATH);
|
|
|
|
ListExpr xline = OutLine3D(nl->TheEmptyList(),SetWord(connection));
|
|
xNext = nl->FourElemList(nl->IntAtom(groom_oid->GetIntval()),
|
|
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();
|
|
}
|
|
|
|
ListExpr xtype = nl->TwoElemList(
|
|
nl->StringAtom("Graph Type: "),
|
|
nl->StringAtom(GetBuildingStr(graph_type)));
|
|
|
|
// return nl->TwoElemList(nl->IntAtom(g_id),xNode);
|
|
return nl->ThreeElemList(nl->IntAtom(g_id), xtype, xNode);
|
|
|
|
}
|
|
|
|
IndoorGraph::IndoorGraph(SmiRecord& in_xValueRecord, size_t& inout_iOffset,
|
|
const ListExpr in_xTypeInfo)
|
|
{
|
|
// cout<<"IndoorGraph::IndoorGraph(SmiRecord)"<<endl;
|
|
/***********************Read graph id********************************/
|
|
in_xValueRecord.Read(&g_id,sizeof(int),inout_iOffset);
|
|
inout_iOffset += sizeof(int);
|
|
|
|
//////////////////////graph type/////////////////////////////////////
|
|
in_xValueRecord.Read(&graph_type, 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);
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
/////////////////btree on node/////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
nl->ReadFromString(NodeBTreeTypeInfo,xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
btree_node = BTree::Open(in_xValueRecord, inout_iOffset, xNumericType);
|
|
if(!btree_node) {
|
|
node_rel->Delete();
|
|
edge_rel->Delete();
|
|
return;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////
|
|
////////////relation for door tid for entrance////////////////
|
|
//////////////////////////////////////////////////////////////
|
|
nl->ReadFromString(EntranceTidTypeInfo, xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
entrance_list = Relation::Open(in_xValueRecord, inout_iOffset, xNumericType);
|
|
if(!entrance_list) {
|
|
node_rel->Delete();
|
|
edge_rel->Delete();
|
|
delete btree_node;
|
|
return;
|
|
}
|
|
|
|
}
|
|
|
|
IndoorGraph* IndoorGraph::Open(SmiRecord& valueRecord,size_t& offset,
|
|
const ListExpr typeInfo)
|
|
{
|
|
|
|
return new IndoorGraph(valueRecord,offset,typeInfo);
|
|
}
|
|
|
|
|
|
bool IndoorGraph::OpenIndoorGraph(SmiRecord& valueRecord, size_t& offset,
|
|
const ListExpr typeInfo, Word& value)
|
|
{
|
|
// cout<<"OpenIndoorGraph()"<<endl;
|
|
value.addr = IndoorGraph::Open(valueRecord, offset, typeInfo);
|
|
bool result = (value.addr != NULL);
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
bool IndoorGraph::SaveIndoorGraph(SmiRecord& valueRecord, size_t& offset,
|
|
const ListExpr typeInfo, Word& value)
|
|
{
|
|
// cout<<"SaveIndoorGraph()"<<endl;
|
|
IndoorGraph* ig = (IndoorGraph*)value.addr;
|
|
bool result = ig->Save(valueRecord, offset, typeInfo);
|
|
|
|
return result;
|
|
}
|
|
|
|
/*
|
|
Save an indoor graph
|
|
|
|
*/
|
|
|
|
bool IndoorGraph::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);
|
|
|
|
/////////////////////////graph type//////////////////////////
|
|
in_xValueRecord.Write(&graph_type,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;
|
|
|
|
/////////////////////////////save btree on node ////////////////////
|
|
nl->ReadFromString(NodeBTreeTypeInfo, xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
if(!btree_node->Save(in_xValueRecord, inout_iOffset, xNumericType))
|
|
return false;
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
/**************door tid for building entrance*************************/
|
|
nl->ReadFromString(EntranceTidTypeInfo, xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
if(!entrance_list->Save(in_xValueRecord,inout_iOffset,xNumericType))
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
Load the Indoor graph
|
|
|
|
*/
|
|
|
|
void IndoorGraph::Load(int id, Relation* r1, Relation* r2, int type)
|
|
{
|
|
// cout<<"IndoorGraph::Load()"<<endl;
|
|
g_id = id;
|
|
//////////////////node relation////////////////////
|
|
|
|
ListExpr ptrList1 = listutils::getPtrList(r1);
|
|
|
|
string strQuery = "(consume(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) + "))" + "Door_tid1)";
|
|
|
|
QueryExecuted = QueryProcessor::ExecuteQuery(strQuery,xResult);
|
|
assert(QueryExecuted);
|
|
BTree* btree_node_oid1 = (BTree*)xResult.addr;
|
|
|
|
|
|
// cout<<"b-tree on edge is finished....."<<endl;
|
|
/////////////////////////////////////////////////////////////////////////
|
|
/////////the adjacent list here is different from dual graph and
|
|
///////// visibility graph. before we store the node id
|
|
/////////now we store the edge id because the weight, path is stored
|
|
////////in the edge relation ////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
for(int i = 1;i <= node_rel->GetNoTuples();i++){
|
|
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 tid2 = ((CcInt*)edge_tuple->GetAttribute(I_DOOR_TID2))->GetIntval();
|
|
|
|
adj_list.Append(edge_tuple->GetTupleId());//get the edge tuple id
|
|
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;
|
|
//////////////////////////////////////////////////////////////////////
|
|
/////////////////////////build a btree on node rel////////////////////
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
ListExpr ptrList4 = listutils::getPtrList(node_rel);
|
|
|
|
strQuery = "(createbtree (" + NodeTypeInfo +
|
|
"(ptr " + nl->ToString(ptrList4) + "))" + "Groom_oid1)";
|
|
|
|
// cout<<strQuery<<endl;
|
|
QueryExecuted = QueryProcessor::ExecuteQuery(strQuery, xResult);
|
|
assert(QueryExecuted);
|
|
btree_node = (BTree*)xResult.addr;
|
|
/////////////////////////////////////////////////////////////////////////
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
///////////////////calculate the number of grooms////////////////////
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
/* vector<int> groom_id_list;
|
|
for(int i = 1;i <= r2->GetNoTuples();i++){
|
|
Tuple* groom_tuple = r2->GetTuple(i, false);
|
|
int gid =
|
|
((CcInt*)groom_tuple->GetAttribute(IndoorGraph::I_GROOM_OID))->GetIntval();
|
|
groom_id_list.push_back(gid);
|
|
groom_tuple->DeleteIfAllowed();
|
|
}
|
|
sort(groom_id_list.begin(), groom_id_list.end());
|
|
vector<int>::iterator last;
|
|
last = unique(groom_id_list.begin(), groom_id_list.end());
|
|
num_of_grooms = 0;
|
|
for(vector<int>::iterator iter = groom_id_list.begin(); iter != last;iter++){
|
|
num_of_grooms++;
|
|
}*/
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
////////////////the entrance of the building//////////////////////////
|
|
/////////////////////////////////////////////////////////////////////
|
|
ListExpr xTypeInfo;
|
|
nl->ReadFromString(EntranceTidTypeInfo, xTypeInfo);
|
|
ListExpr xNumType = SecondoSystem::GetCatalog()->NumericType(xTypeInfo);
|
|
Relation* s_rel = new Relation(xNumType, true);
|
|
for(int i = 1;i <= r1->GetNoTuples();i++){
|
|
Tuple* door_tuple = r1->GetTuple(i, false);
|
|
int groom_oid2 =
|
|
((CcInt*)door_tuple->GetAttribute(I_GROOM_OID2))->GetIntval();
|
|
// if(groom_oid2 == -1){
|
|
if(groom_oid2 == (int)UNDEFVAL){
|
|
Tuple* new_tuple = new Tuple(nl->Second(xNumType));
|
|
new_tuple->PutAttribute(0, new CcInt(true, door_tuple->GetTupleId()));
|
|
s_rel->AppendTuple(new_tuple);
|
|
new_tuple->DeleteIfAllowed();
|
|
}
|
|
door_tuple->DeleteIfAllowed();
|
|
}
|
|
|
|
|
|
ListExpr ptrList5 = listutils::getPtrList(s_rel);
|
|
|
|
strQuery = "(consume(feed(" + EntranceTidTypeInfo +
|
|
"(ptr " + nl->ToString(ptrList5) + "))))";
|
|
|
|
QueryExecuted = QueryProcessor::ExecuteQuery(strQuery, xResult);
|
|
assert(QueryExecuted);
|
|
entrance_list = (Relation*)xResult.addr;
|
|
s_rel->Delete();
|
|
|
|
// cout<<"number of entrance "<<entrance_list->GetNoTuples()<<endl;
|
|
|
|
if(entrance_list->GetNoTuples() == 0){
|
|
cout<<"invalid building: no entrance"<<endl;
|
|
assert(false);
|
|
}
|
|
|
|
graph_type = type;
|
|
|
|
}
|
|
|
|
/*
|
|
get the position of the door
|
|
|
|
*/
|
|
void IndoorGraph::GetEntranceDoor(vector<Point>& door_loc)
|
|
{
|
|
for(int i = 1;i <= entrance_list->GetNoTuples();i++){
|
|
Tuple* tuple1 = entrance_list->GetTuple(i, false);
|
|
int tid = ((CcInt*)tuple1->GetAttribute(0))->GetIntval();
|
|
|
|
Tuple* tuple2 = node_rel->GetTuple(tid, false);
|
|
Line* l = (Line*)tuple2->GetAttribute(I_DOOR_LOC);
|
|
HalfSegment hs;
|
|
l->Get(0, hs);
|
|
Point lp = hs.GetLeftPoint();
|
|
Point rp = hs.GetRightPoint();
|
|
Point mp(true, (lp.GetX() + rp.GetX())/2, (lp.GetY() + rp.GetY())/2);
|
|
door_loc.push_back(mp);
|
|
tuple2->DeleteIfAllowed();
|
|
|
|
tuple1->DeleteIfAllowed();
|
|
}
|
|
}
|
|
|
|
/*
|
|
get the position of the door by genloc
|
|
|
|
*/
|
|
void IndoorGraph::GetEntranceDoor2(vector<Point>& door_loc,
|
|
vector<int>& groom_list,
|
|
vector<int>& door_tid_list)
|
|
{
|
|
|
|
for(int i = 1;i <= entrance_list->GetNoTuples();i++){
|
|
Tuple* tuple1 = entrance_list->GetTuple(i, false);
|
|
int tid = ((CcInt*)tuple1->GetAttribute(0))->GetIntval();
|
|
|
|
door_tid_list.push_back(tid);
|
|
Tuple* tuple2 = node_rel->GetTuple(tid, false);
|
|
int groom_oid = ((CcInt*)tuple2->GetAttribute(I_GROOM_OID1))->GetIntval();
|
|
///////////////////////////////////////////////////////////////////////////
|
|
/////////////////////////door position////////////////////////////////////
|
|
/////////////////////////////////////////////////////////////////////////
|
|
Line* l = (Line*)tuple2->GetAttribute(I_DOOR_LOC);
|
|
HalfSegment hs;
|
|
l->Get(0, hs);
|
|
Point lp = hs.GetLeftPoint();
|
|
Point rp = hs.GetRightPoint();
|
|
Point mp(true, (lp.GetX() + rp.GetX())/2, (lp.GetY() + rp.GetY())/2);
|
|
door_loc.push_back(mp);
|
|
groom_list.push_back(groom_oid);
|
|
tuple2->DeleteIfAllowed();
|
|
|
|
tuple1->DeleteIfAllowed();
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
collect all doors of a groom by oid
|
|
|
|
*/
|
|
void IndoorGraph::GetDoorsInGRoom(int groom_oid, vector<int>& tid_list)
|
|
{
|
|
|
|
CcInt* search_id = new CcInt(true, groom_oid);
|
|
BTreeIterator* btree_iter = btree_node->ExactMatch(search_id);
|
|
|
|
while(btree_iter->Next()){
|
|
Tuple* tuple = node_rel->GetTuple(btree_iter->GetId(), false);
|
|
tid_list.push_back(tuple->GetTupleId());
|
|
tuple->DeleteIfAllowed();
|
|
}
|
|
delete btree_iter;
|
|
delete search_id;
|
|
}
|
|
|
|
|
|
/*
|
|
get all adjacent nodes for a given node. indoor graph
|
|
|
|
*/
|
|
|
|
void IndoorNav::GetAdjNodeIG(int oid)
|
|
{
|
|
if(oid < 1 || oid > ig->GetNodeRel()->GetNoTuples()){
|
|
cout<<"invalid oid "<<oid<<endl;
|
|
return;
|
|
}
|
|
|
|
cout<<"total "<<ig->GetNodeRel()->GetNoTuples()<<" nodes "<<endl;
|
|
cout<<"total "<<ig->GetEdgeRel()->GetNoTuples()<<" edges "<<endl;
|
|
|
|
vector<int> adj_list;
|
|
ig->FindAdj(oid, adj_list);
|
|
// cout<<"adj_list size "<<adj_list.size()<<endl;
|
|
for(unsigned int i = 0;i < adj_list.size();i++){
|
|
Tuple* edge_tuple = ig->GetEdgeRel()->GetTuple(adj_list[i], false);
|
|
int neighbor_id =
|
|
((CcInt*)edge_tuple->GetAttribute(IndoorGraph::I_DOOR_TID2))->GetIntval();
|
|
Line3D* path = (Line3D*)edge_tuple->GetAttribute(IndoorGraph::I_PATH);
|
|
|
|
door_tid_list1.push_back(oid);
|
|
door_tid_list2.push_back(neighbor_id);
|
|
path_list.push_back(*path);
|
|
edge_tuple->DeleteIfAllowed();
|
|
}
|
|
}
|
|
|
|
/*
|
|
generate interesting indoor points
|
|
do not include the position on the staircase and elevator
|
|
it contains OR, CO, BR
|
|
|
|
*/
|
|
void IndoorNav::GenerateIP1(int num)
|
|
{
|
|
int no_rooms = rel1->GetNoTuples();
|
|
|
|
// struct timeval tval;
|
|
// struct timezone tzone;
|
|
// gettimeofday(&tval, &tzone);
|
|
// srand48(tval.tv_sec);//second
|
|
// srand48(tval.tv_usec);//Microseconds
|
|
|
|
const double TM_EPSILON = 0.001;
|
|
|
|
for(int i = 1;i <= num;){
|
|
unsigned int room_oid;
|
|
|
|
room_oid = GetRandom() % no_rooms + 1;
|
|
|
|
Tuple* room_tuple = rel1->GetTuple(room_oid, false);
|
|
string type = ((CcString*)room_tuple->GetAttribute(I_Type))->GetValue();
|
|
if(GetRoomEnum(type) == ST || GetRoomEnum(type) == EL){
|
|
room_tuple->DeleteIfAllowed();
|
|
continue;
|
|
}
|
|
|
|
GRoom* groom = (GRoom*)room_tuple->GetAttribute(I_Room);
|
|
Region* reg = new Region(0);
|
|
groom->GetRegion(*reg);
|
|
|
|
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() + 1)% (xx*100);
|
|
int y = (GetRandom() + 1)% (yy*100);
|
|
|
|
double coord_x = x/100.0;
|
|
double coord_y = y/100.0;
|
|
|
|
if(coord_x < TM_EPSILON) coord_x = 0.0;
|
|
if(coord_y < TM_EPSILON) coord_y = 0.0;
|
|
|
|
p1.Set(coord_x, coord_y); //set back to relative position
|
|
//lower the precision
|
|
Modify_Point_3(p1);
|
|
|
|
Coord x_cord = p1.GetX() + bbox.MinD(0);
|
|
Coord y_cord = p1.GetY() + bbox.MinD(1);
|
|
p2.Set(x_cord, y_cord); //absolute position
|
|
|
|
inside = p2.Inside(*reg);
|
|
count++;
|
|
}
|
|
if(inside){
|
|
float h = groom->GetLowHeight();////////////always on the lowest level
|
|
Loc loc(p1.GetX(), p1.GetY());
|
|
GenLoc genl(room_oid, loc);
|
|
Point3D q(true, p2.GetX(), p2.GetY(), h);
|
|
genloc_list.push_back(genl);
|
|
p3d_list.push_back(q);
|
|
i++;
|
|
}
|
|
|
|
reg->DeleteIfAllowed();
|
|
room_tuple->DeleteIfAllowed();
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
generate interesting indoor points
|
|
only include the position on the staircase
|
|
|
|
*/
|
|
void IndoorNav::GenerateIP2(int num)
|
|
{
|
|
int no_rooms = rel1->GetNoTuples();
|
|
|
|
const double TM_EPSILON = 0.001;
|
|
|
|
for(int i = 1;i <= num;){
|
|
unsigned int room_oid;
|
|
|
|
room_oid = GetRandom() % no_rooms + 1;
|
|
|
|
Tuple* room_tuple = rel1->GetTuple(room_oid, false);
|
|
string type = ((CcString*)room_tuple->GetAttribute(I_Type))->GetValue();
|
|
if(GetRoomEnum(type) != ST ){
|
|
room_tuple->DeleteIfAllowed();
|
|
continue;
|
|
}
|
|
|
|
GRoom* groom = (GRoom*)room_tuple->GetAttribute(I_Room);
|
|
Region* reg = new Region(0);
|
|
groom->GetRegion(*reg);
|
|
|
|
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() + 1)% (xx*100);
|
|
int y = (GetRandom() + 1)% (yy*100);
|
|
|
|
double coord_x = x/100.0;
|
|
double coord_y = y/100.0;
|
|
if(coord_x < TM_EPSILON) coord_x = 0.0;
|
|
if(coord_y < TM_EPSILON) coord_y = 0.0;
|
|
|
|
|
|
p1.Set(coord_x, coord_y); //set back to relative position
|
|
//lower the precision
|
|
Modify_Point_3(p1);
|
|
|
|
Coord x_cord = p1.GetX() + bbox.MinD(0);
|
|
Coord y_cord = p1.GetY() + bbox.MinD(1);
|
|
p2.Set(x_cord, y_cord); //absolute position
|
|
|
|
inside = p2.Inside(*reg);
|
|
count++;
|
|
}
|
|
|
|
if(inside){
|
|
bool flag = false;
|
|
float h = GetHeightInST2(groom, p2, flag);
|
|
if(flag){
|
|
Loc loc(p1.GetX(), p1.GetY());
|
|
GenLoc genl(room_oid, loc);
|
|
Point3D q(true, p2.GetX(), p2.GetY(), h);
|
|
genloc_list.push_back(genl);
|
|
p3d_list.push_back(q);
|
|
i++;
|
|
}
|
|
}
|
|
|
|
reg->DeleteIfAllowed();
|
|
room_tuple->DeleteIfAllowed();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
generate an indoor location only in Office Room
|
|
|
|
*/
|
|
void IndoorNav::GenerateIP3(int num)
|
|
{
|
|
int no_rooms = rel1->GetNoTuples();
|
|
|
|
// struct timeval tval;
|
|
// struct timezone tzone;
|
|
// gettimeofday(&tval, &tzone);
|
|
// srand48(tval.tv_sec);//second
|
|
// srand48(tval.tv_usec);//Microseconds
|
|
|
|
const double TM_EPSILON = 0.001;
|
|
|
|
for(int i = 1;i <= num;){
|
|
unsigned int room_oid;
|
|
|
|
room_oid = GetRandom() % no_rooms + 1;
|
|
|
|
Tuple* room_tuple = rel1->GetTuple(room_oid, false);
|
|
string type = ((CcString*)room_tuple->GetAttribute(I_Type))->GetValue();
|
|
if(GetRoomEnum(type) != OR){
|
|
room_tuple->DeleteIfAllowed();
|
|
continue;
|
|
}
|
|
|
|
GRoom* groom = (GRoom*)room_tuple->GetAttribute(I_Room);
|
|
Region* reg = new Region(0);
|
|
groom->GetRegion(*reg);
|
|
|
|
////////////////check complexity//////////////////////
|
|
/////////we ignore the complex region here//////////////////////
|
|
/////because it needs to build rtree and btree//////////////////
|
|
////////a lot of somethin sdb files, bdb SMI open too many files/////////
|
|
CompTriangle* ct = new CompTriangle(reg);
|
|
int complex_reg = ct->ComplexRegion();
|
|
delete ct;
|
|
if(complex_reg == 1){
|
|
reg->DeleteIfAllowed();
|
|
room_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() + 1)% (xx*100);
|
|
int y = (GetRandom() + 1)% (yy*100);
|
|
|
|
double coord_x = x/100.0;
|
|
double coord_y = y/100.0;
|
|
|
|
if(coord_x < TM_EPSILON) coord_x = 0.0;
|
|
if(coord_y < TM_EPSILON) coord_y = 0.0;
|
|
|
|
p1.Set(coord_x, coord_y); //set back to relative position
|
|
//lower the precision
|
|
Modify_Point_3(p1);
|
|
|
|
Coord x_cord = p1.GetX() + bbox.MinD(0);
|
|
Coord y_cord = p1.GetY() + bbox.MinD(1);
|
|
p2.Set(x_cord, y_cord); //absolute position
|
|
|
|
inside = p2.Inside(*reg);
|
|
count++;
|
|
}
|
|
if(inside){
|
|
float h = groom->GetLowHeight();////////////always on the lowest level
|
|
Loc loc(p1.GetX(), p1.GetY());
|
|
GenLoc genl(room_oid, loc);
|
|
Point3D q(true, p2.GetX(), p2.GetY(), h);
|
|
genloc_list.push_back(genl);
|
|
p3d_list.push_back(q);
|
|
i++;
|
|
}
|
|
|
|
reg->DeleteIfAllowed();
|
|
room_tuple->DeleteIfAllowed();
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
find the height of the point in a staircase. at which footstep
|
|
|
|
*/
|
|
float IndoorNav::GetHeightInST(GRoom* groom, Point p)
|
|
{
|
|
|
|
for(int i = 0; i < groom->Size(); i++){
|
|
Region temp_reg(0);
|
|
float h;
|
|
groom->Get( i, h, temp_reg);
|
|
if(temp_reg.Contains(p)) return h;
|
|
}
|
|
cout<<"do not find the point in the 2D area"<<endl;
|
|
assert(false);
|
|
return 0;
|
|
}
|
|
|
|
float IndoorNav::GetHeightInST2(GRoom* groom, Point p, bool& flag)
|
|
{
|
|
|
|
for(int i = 0; i < groom->Size(); i++){
|
|
Region temp_reg(0);
|
|
float h;
|
|
groom->Get( i, h, temp_reg);
|
|
if(temp_reg.Contains(p)){
|
|
flag = true;
|
|
return h;
|
|
}
|
|
}
|
|
cout<<"do not find the point in the 2D area"<<endl;
|
|
flag = false;
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
initialize the elevator schedule
|
|
|
|
*/
|
|
void IndoorNav::InitializeElevator(Interval<Instant>& periods,
|
|
vector<Elevator>& elev_list,
|
|
double speed)
|
|
{
|
|
for(int i = 1;i <= rel1->GetNoTuples();i++){
|
|
Tuple* groom_tuple = rel1->GetTuple(i, false);
|
|
string type = ((CcString*)groom_tuple->GetAttribute(I_Type))->GetValue();
|
|
if(GetRoomEnum(type) == EL){
|
|
GRoom* groom = (GRoom*)groom_tuple->GetAttribute(I_Room);
|
|
float h = groom->GetLowHeight();
|
|
Elevator elevator(h, 0.0, 0.0, 0.0, 0.0);
|
|
elev_list.push_back(elevator);
|
|
}
|
|
groom_tuple->DeleteIfAllowed();
|
|
}
|
|
|
|
|
|
if(elev_list.size() < 2){
|
|
// cout<<"only one floor, should not have elevator"<<endl;
|
|
return;
|
|
}
|
|
sort(elev_list.begin(), elev_list.end());
|
|
|
|
|
|
int n_floor = (int)elev_list.size();
|
|
double stay = 10.0/(24.0*60.0*60.0); //at each floor stay 10 seconds
|
|
double delta_h = fabs(elev_list[1].h - elev_list[0].h);
|
|
double time_move = delta_h /(24.0*60.0*60.0*speed);
|
|
|
|
///////////////////////////////////////////////////////////////
|
|
////////////t1: higher -- lower////////////////////////////////
|
|
////////////t2: lower -- hihger////////////////////////////////
|
|
///////////////////////////////////////////////////////////////
|
|
|
|
elev_list[n_floor - 1].t1 = 0.0;
|
|
elev_list[n_floor - 1].t2 = elev_list[n_floor - 1].t1 +
|
|
2*time_move*(n_floor-1) +
|
|
stay*((n_floor-2)*2 + 2);
|
|
elev_list[n_floor - 1].m_t = time_move;
|
|
elev_list[n_floor - 1].w_t = stay;
|
|
|
|
for(int i = n_floor - 2;i >= 0;i --){
|
|
elev_list[i].t1 = elev_list[i + 1].t1 + stay + time_move;
|
|
elev_list[i].t2 = elev_list[i + 1].t2 - stay - time_move;
|
|
elev_list[i].m_t = time_move;
|
|
elev_list[i].w_t = stay;
|
|
}
|
|
|
|
for(unsigned int i = 0;i < elev_list.size();i++){
|
|
// elev_list[i].Print();
|
|
Instant t1 = periods.start;
|
|
t1.ReadFrom(elev_list[i].t1);
|
|
|
|
Instant t2 = periods.start;
|
|
t2.ReadFrom(elev_list[i].t2);
|
|
|
|
// cout<<"first arrive "<<t1<<" second arrive "<<t2<<endl;
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
generate interesting indoor moving objects.
|
|
the result is represented by mpoint3d
|
|
|
|
*/
|
|
void IndoorNav::GenerateMO1(IndoorGraph* ig, BTree* btree,
|
|
R_Tree<3,TupleId>* rtree, int num,
|
|
Periods* peri, bool convert)
|
|
{
|
|
// cout<<"one elevator "<<endl;
|
|
|
|
GenerateIP1(num*2);
|
|
|
|
IndoorNav* indoor_nav = new IndoorNav(ig);
|
|
|
|
Interval<Instant> periods;
|
|
if(peri->GetNoComponents() == 0){
|
|
cout<<"not correct time periods"<<endl;
|
|
assert(false);
|
|
}
|
|
peri->Get(0, periods);
|
|
|
|
double speed = GetMinimumDoorWidth();
|
|
|
|
vector<Elevator> elev_list;
|
|
|
|
InitializeElevator(periods, elev_list, speed);
|
|
|
|
|
|
int count = 0;
|
|
for(unsigned int i = 0;i < genloc_list.size();i++){
|
|
if(i < genloc_list.size() - 1){
|
|
GenLoc loc1 = genloc_list[i];
|
|
GenLoc loc2 = genloc_list[i + 1];
|
|
|
|
/* Loc loc_1(0.3, 0.4);
|
|
Loc loc_2(0.2, 0.5);
|
|
loc1.SetValue(71, loc_1);
|
|
loc2.SetValue(153, loc_2);*/ //using elevator, for testing
|
|
|
|
if(loc1.GetOid() == loc2.GetOid()) continue;
|
|
|
|
cout<<"loc1 "<<loc1<<" loc2 "<<loc2<<endl;
|
|
|
|
indoor_nav->ShortestPath_Length(&loc1, &loc2, rel1, btree);
|
|
|
|
// cout<<indoor_nav->path_list[count].Length()<<endl;
|
|
//////////////////////////////////////////////////////////////////
|
|
Instant start_time = periods.start;
|
|
|
|
//in several minutes: 60 seconds for 12 persons
|
|
start_time.ReadFrom(periods.start.ToDouble() +
|
|
(GetRandom() % (num*5))/(24.0*60.0*60.0));
|
|
|
|
Line3D* l3d = &indoor_nav->path_list[count];
|
|
// l3d->Print();
|
|
if(l3d->Length() > 0.0){
|
|
MPoint3D* mp3d = new MPoint3D(0);
|
|
mp3d->StartBulkLoad();
|
|
for(int j = 0;j < l3d->Size();j++){
|
|
if(j < l3d->Size() - 1){
|
|
Point3D p1, p2;
|
|
l3d->Get(j, p1);
|
|
l3d->Get(j + 1, p2);
|
|
///////////////process the movement in an elevator
|
|
if(AlmostEqual(p1.GetX(), p2.GetX()) &&
|
|
AlmostEqual(p1.GetY(), p2.GetY()) && elev_list.size() > 1){
|
|
|
|
float delta_h = fabs(elev_list[1].h - elev_list[0].h);
|
|
if(AlmostEqual(delta_h, p1.Distance(p2))){
|
|
vector<Point3D> p3d_list;
|
|
p3d_list.push_back(p1);
|
|
p3d_list.push_back(p2);
|
|
int k = j + 1;
|
|
for(;k < l3d->Size();k++){
|
|
if(k < l3d->Size() - 1){
|
|
Point3D q1, q2;
|
|
l3d->Get(k, q1);
|
|
l3d->Get(k + 1, q2);
|
|
|
|
if(AlmostEqual(q1.GetX(), q2.GetX()) &&
|
|
AlmostEqual(q1.GetY(), q2.GetY())){//elevator
|
|
p3d_list.push_back(q2);
|
|
}else
|
|
break;
|
|
}
|
|
}
|
|
k--;
|
|
j = k;
|
|
|
|
AddUnitToMO_Elevator(mp3d, p3d_list, start_time,
|
|
periods.start, elev_list);
|
|
}
|
|
}else
|
|
AddUnitToMO(mp3d, p1, p2, start_time, speed);
|
|
}
|
|
}
|
|
mp3d->EndBulkLoad();
|
|
mo_list.push_back(*mp3d);
|
|
///////////////////////////////////////////////////////////////////
|
|
if(convert)
|
|
ToGenLoc(mp3d, rtree);
|
|
mp3d->DeleteIfAllowed();
|
|
count++;
|
|
}
|
|
if(count == num)break;
|
|
|
|
}
|
|
}
|
|
|
|
delete indoor_nav;
|
|
|
|
}
|
|
|
|
/*
|
|
get the building entrance location
|
|
|
|
*/
|
|
void IndoorNav::GetDoorLoc(IndoorGraph* ig, BTree* btree,
|
|
vector<GenLoc>& doorloc_list, vector<int>& door_tid_list)
|
|
{
|
|
vector<Point> loc_list;
|
|
vector<int> groom_list;
|
|
ig->GetEntranceDoor2(loc_list, groom_list, door_tid_list);
|
|
for(unsigned int i = 0;i < loc_list.size();i++){
|
|
int groom_oid = groom_list[i];
|
|
|
|
CcInt* search_id = new CcInt(true, groom_oid);
|
|
BTreeIterator* btree_iter = btree->ExactMatch(search_id);
|
|
int groom_tid = 0;
|
|
while(btree_iter->Next()){
|
|
groom_tid = btree_iter->GetId();
|
|
break;
|
|
}
|
|
delete btree_iter;
|
|
delete search_id;
|
|
|
|
assert(1 <= groom_tid && groom_tid <= rel1->GetNoTuples());
|
|
|
|
Tuple* groom_tuple = rel1->GetTuple(groom_tid, false);
|
|
GRoom* groom = (GRoom*)groom_tuple->GetAttribute(I_Room);
|
|
Rectangle<2> bbox = groom->BoundingBox();
|
|
// Loc loc(loc_list[i].GetX() - bbox.MinD(0),
|
|
// loc_list[i].GetY() - bbox.MinD(1));
|
|
|
|
double x = loc_list[i].GetX() - bbox.MinD(0);
|
|
double y = loc_list[i].GetY() - bbox.MinD(1);
|
|
const double tm_epsilon = 0.001;
|
|
if( x < tm_epsilon) x = 0.0;
|
|
if( y < tm_epsilon) y = 0.0;
|
|
Loc loc(x,y);
|
|
|
|
GenLoc gloc(groom_oid, loc);
|
|
|
|
// cout<<"gloc "<<gloc<<endl;
|
|
|
|
doorloc_list.push_back(gloc);
|
|
groom_tuple->DeleteIfAllowed();
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
generate interesting indoor moving objects.
|
|
from the building entrance to a location in the building
|
|
|
|
*/
|
|
void IndoorNav::GenerateMO2_Start(IndoorGraph* ig, BTree* btree,
|
|
R_Tree<3,TupleId>* rtree, int num,
|
|
Periods* peri, bool convert)
|
|
{
|
|
// cout<<"GenerateMO2"<<endl;
|
|
// cout<<"one elevator "<<endl;
|
|
|
|
GenerateIP1(num*2);
|
|
|
|
//////////////////get the building entrance position///////////////////////
|
|
vector<GenLoc> doorloc_list;
|
|
vector<int> door_tid_list;
|
|
GetDoorLoc(ig, btree, doorloc_list, door_tid_list);
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
IndoorNav* indoor_nav = new IndoorNav(ig);
|
|
|
|
Interval<Instant> periods;
|
|
if(peri->GetNoComponents() == 0){
|
|
cout<<"not correct time periods"<<endl;
|
|
assert(false);
|
|
}
|
|
peri->Get(0, periods);
|
|
|
|
double speed = GetMinimumDoorWidth();
|
|
|
|
vector<Elevator> elev_list;
|
|
|
|
InitializeElevator(periods, elev_list, speed);
|
|
|
|
int count = 0;
|
|
for(unsigned int i = 0;i < genloc_list.size();i++){
|
|
if(i < genloc_list.size() - 1){
|
|
GenLoc loc2 = genloc_list[i];
|
|
|
|
int door_index = i % doorloc_list.size();
|
|
GenLoc loc1 = doorloc_list[door_index];
|
|
|
|
if(loc1.GetOid() == loc2.GetOid()) continue;
|
|
|
|
cout<<"loc1 "<<loc1<<" loc2 "<<loc2<<endl;
|
|
|
|
indoor_nav->ShortestPath_Length_Start(&loc1, &loc2, rel1, btree,
|
|
door_tid_list[door_index]);
|
|
|
|
// cout<<indoor_nav->path_list[count].Length()<<endl;
|
|
//////////////////////////////////////////////////////////////////
|
|
Instant start_time = periods.start;
|
|
|
|
//in several minutes: 60 seconds for 12 persons
|
|
start_time.ReadFrom(periods.start.ToDouble() +
|
|
(GetRandom() % (num*5))/(24.0*60.0*60.0));
|
|
|
|
Line3D* l3d = &indoor_nav->path_list[count];
|
|
// l3d->Print();
|
|
if(l3d->Length() > 0.0){
|
|
MPoint3D* mp3d = new MPoint3D(0);
|
|
mp3d->StartBulkLoad();
|
|
for(int j = 0;j < l3d->Size();j++){
|
|
if(j < l3d->Size() - 1){
|
|
Point3D p1, p2;
|
|
l3d->Get(j, p1);
|
|
l3d->Get(j + 1, p2);
|
|
///////////////process the movement in an elevator
|
|
if(AlmostEqual(p1.GetX(), p2.GetX()) &&
|
|
AlmostEqual(p1.GetY(), p2.GetY()) && elev_list.size() > 1){
|
|
|
|
float delta_h = fabs(elev_list[1].h - elev_list[0].h);
|
|
if(AlmostEqual(delta_h, p1.Distance(p2))){
|
|
vector<Point3D> p3d_list;
|
|
p3d_list.push_back(p1);
|
|
p3d_list.push_back(p2);
|
|
int k = j + 1;
|
|
for(;k < l3d->Size();k++){
|
|
if(k < l3d->Size() - 1){
|
|
Point3D q1, q2;
|
|
l3d->Get(k, q1);
|
|
l3d->Get(k + 1, q2);
|
|
|
|
if(AlmostEqual(q1.GetX(), q2.GetX()) &&
|
|
AlmostEqual(q1.GetY(), q2.GetY())){//elevator
|
|
p3d_list.push_back(q2);
|
|
}else
|
|
break;
|
|
}
|
|
}
|
|
k--;
|
|
j = k;
|
|
|
|
AddUnitToMO_Elevator(mp3d, p3d_list, start_time,
|
|
periods.start, elev_list);
|
|
}
|
|
}else
|
|
AddUnitToMO(mp3d, p1, p2, start_time, speed);
|
|
}
|
|
}
|
|
mp3d->EndBulkLoad();
|
|
mo_list.push_back(*mp3d);
|
|
entrance_index.push_back(door_index + 1);//maps to tuple id
|
|
///////////////////////////////////////////////////////////////////
|
|
if(convert)
|
|
ToGenLoc(mp3d, rtree);
|
|
mp3d->DeleteIfAllowed();
|
|
count++;
|
|
}
|
|
if(count == num)break;
|
|
|
|
}
|
|
}
|
|
|
|
delete indoor_nav;
|
|
|
|
}
|
|
|
|
/*
|
|
generate interesting indoor moving objects.
|
|
from a location in the building to one of the entrances
|
|
|
|
*/
|
|
void IndoorNav::GenerateMO2_End(IndoorGraph* ig, BTree* btree,
|
|
R_Tree<3,TupleId>* rtree, int num,
|
|
Periods* peri, bool convert)
|
|
{
|
|
// cout<<"GenerateMO2"<<endl;
|
|
// cout<<"one elevator "<<endl;
|
|
|
|
GenerateIP1(num*2);
|
|
|
|
//////////////////get the building entrance position///////////////////////
|
|
vector<GenLoc> doorloc_list;
|
|
vector<int> door_tid_list;
|
|
GetDoorLoc(ig, btree, doorloc_list, door_tid_list);
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
IndoorNav* indoor_nav = new IndoorNav(ig);
|
|
|
|
Interval<Instant> periods;
|
|
if(peri->GetNoComponents() == 0){
|
|
cout<<"not correct time periods"<<endl;
|
|
assert(false);
|
|
}
|
|
peri->Get(0, periods);
|
|
|
|
double speed = GetMinimumDoorWidth();
|
|
|
|
vector<Elevator> elev_list;
|
|
|
|
InitializeElevator(periods, elev_list, speed);
|
|
|
|
int count = 0;
|
|
for(unsigned int i = 0;i < genloc_list.size();i++){
|
|
if(i < genloc_list.size() - 1){
|
|
GenLoc loc1 = genloc_list[i];
|
|
|
|
int door_index = i % doorloc_list.size();
|
|
GenLoc loc2 = doorloc_list[door_index];
|
|
|
|
if(loc1.GetOid() == loc2.GetOid()) continue;
|
|
|
|
cout<<"loc1 "<<loc1<<" loc2 "<<loc2<<endl;
|
|
|
|
indoor_nav->ShortestPath_Length_End(&loc1, &loc2, rel1, btree,
|
|
door_tid_list[door_index]);
|
|
|
|
// cout<<indoor_nav->path_list[count].Length()<<endl;
|
|
//////////////////////////////////////////////////////////////////
|
|
Instant start_time = periods.start;
|
|
|
|
//in several minutes: 60 seconds for 12 persons
|
|
start_time.ReadFrom(periods.start.ToDouble() +
|
|
(GetRandom() % (num*5))/(24.0*60.0*60.0));
|
|
|
|
Line3D* l3d = &indoor_nav->path_list[count];
|
|
// l3d->Print();
|
|
if(l3d->Length() > 0.0){
|
|
MPoint3D* mp3d = new MPoint3D(0);
|
|
mp3d->StartBulkLoad();
|
|
for(int j = 0;j < l3d->Size();j++){
|
|
if(j < l3d->Size() - 1){
|
|
Point3D p1, p2;
|
|
l3d->Get(j, p1);
|
|
l3d->Get(j + 1, p2);
|
|
///////////////process the movement in an elevator
|
|
if(AlmostEqual(p1.GetX(), p2.GetX()) &&
|
|
AlmostEqual(p1.GetY(), p2.GetY()) && elev_list.size() > 1){
|
|
|
|
float delta_h = fabs(elev_list[1].h - elev_list[0].h);
|
|
if(AlmostEqual(delta_h, p1.Distance(p2))){
|
|
vector<Point3D> p3d_list;
|
|
p3d_list.push_back(p1);
|
|
p3d_list.push_back(p2);
|
|
int k = j + 1;
|
|
for(;k < l3d->Size();k++){
|
|
if(k < l3d->Size() - 1){
|
|
Point3D q1, q2;
|
|
l3d->Get(k, q1);
|
|
l3d->Get(k + 1, q2);
|
|
|
|
if(AlmostEqual(q1.GetX(), q2.GetX()) &&
|
|
AlmostEqual(q1.GetY(), q2.GetY())){//elevator
|
|
p3d_list.push_back(q2);
|
|
}else
|
|
break;
|
|
}
|
|
}
|
|
k--;
|
|
j = k;
|
|
|
|
AddUnitToMO_Elevator(mp3d, p3d_list, start_time,
|
|
periods.start, elev_list);
|
|
}
|
|
}else
|
|
AddUnitToMO(mp3d, p1, p2, start_time, speed);
|
|
}
|
|
}
|
|
mp3d->EndBulkLoad();
|
|
mo_list.push_back(*mp3d);
|
|
entrance_index.push_back(door_index + 1);//maps to tuple id
|
|
///////////////////////////////////////////////////////////////////
|
|
if(convert)
|
|
ToGenLoc(mp3d, rtree);
|
|
mp3d->DeleteIfAllowed();
|
|
count++;
|
|
}
|
|
if(count == num)break;
|
|
|
|
}
|
|
}
|
|
|
|
delete indoor_nav;
|
|
|
|
}
|
|
|
|
/*
|
|
create one indoor movement from the building entrance to an indoor location.
|
|
this function is used to create indoor and outdoor trips
|
|
|
|
*/
|
|
void IndoorNav::GenerateMO3_Start(IndoorGraph* ig, BTree* btree,
|
|
R_Tree<3,TupleId>* rtree,
|
|
Instant& start_time, int build_id, int entrance_index,
|
|
MPoint3D* mp3d, GenMO* genmo, Periods* peri)
|
|
{
|
|
// GenerateIP1(1);
|
|
GenerateIP3(1);
|
|
|
|
//////////////////get the building entrance position/////////////////
|
|
vector<GenLoc> doorloc_list;
|
|
vector<int> door_tid_list;
|
|
GetDoorLoc(ig, btree, doorloc_list, door_tid_list);
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
// cout<<"indoor paths size "<<indoor_paths_list.size()<<endl;
|
|
//////////////////////initialize elevator//////////////////////////////
|
|
if(peri->GetNoComponents() == 0){
|
|
cout<<"not correct time periods"<<endl;
|
|
assert(false);
|
|
}
|
|
Interval<Instant> periods;
|
|
peri->Get(0, periods);
|
|
double speed = GetMinimumDoorWidth();
|
|
vector<Elevator> elev_list;
|
|
InitializeElevator(periods, elev_list, speed);
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
int num = 1;
|
|
int count = 0;
|
|
for(unsigned int i = 0;i < genloc_list.size();i++){
|
|
GenLoc loc2 = genloc_list[i];
|
|
|
|
int door_index = entrance_index - 1;
|
|
GenLoc loc1 = doorloc_list[door_index];
|
|
|
|
// cout<<"loc1 "<<loc1<<" loc2 "<<loc2<<endl;
|
|
|
|
// Loc l1(0,19);
|
|
// Loc l2(1,0);
|
|
// loc1.SetValue(8, l1);
|
|
// loc2.SetValue(14, l2);
|
|
//
|
|
|
|
bool find_path = false;
|
|
#ifdef INDOOR_PATH
|
|
int path_oid = GetIndooPathID(entrance_index, loc2.GetOid(), true);
|
|
map<int, Line3D>::iterator iter = indoor_paths_list.find(path_oid);
|
|
if(iter != indoor_paths_list.end()){
|
|
ShortestPath_Length_Start2(&loc1, &loc2, rel1, btree,
|
|
door_tid_list[door_index],
|
|
entrance_index);
|
|
find_path = true;
|
|
}else{
|
|
ShortestPath_Length_Start(&loc1, &loc2, rel1, btree,
|
|
door_tid_list[door_index]);
|
|
}
|
|
#else
|
|
ShortestPath_Length_Start(&loc1, &loc2, rel1, btree,
|
|
door_tid_list[door_index]);
|
|
#endif
|
|
|
|
Line3D* l3d = &path_list[count];
|
|
|
|
|
|
if(l3d->Length() > 0.0){
|
|
Line3D* l_room = NULL;
|
|
#ifdef INDOOR_PATH
|
|
if(find_path){
|
|
l_room = &rooms_id_list[count];
|
|
assert(l3d->Size() == l_room->Size());
|
|
}
|
|
#endif
|
|
|
|
mp3d->StartBulkLoad();
|
|
for(int j = 0;j < l3d->Size();j++){
|
|
if(j < l3d->Size() - 1){
|
|
Point3D p1, p2;
|
|
l3d->Get(j, p1);
|
|
l3d->Get(j + 1, p2);
|
|
///////////////process the movement in an elevator
|
|
if(AlmostEqual(p1.GetX(), p2.GetX()) &&
|
|
AlmostEqual(p1.GetY(), p2.GetY()) && elev_list.size() > 1){
|
|
float delta_h = fabs(elev_list[1].h - elev_list[0].h);
|
|
if(AlmostEqual(delta_h, p1.Distance(p2))){
|
|
int start_pos = j;
|
|
vector<Point3D> p3d_list;
|
|
p3d_list.push_back(p1);
|
|
p3d_list.push_back(p2);
|
|
int k = j + 1;
|
|
for(;k < l3d->Size();k++){
|
|
if(k < l3d->Size() - 1){
|
|
Point3D q1, q2;
|
|
l3d->Get(k, q1);
|
|
l3d->Get(k + 1, q2);
|
|
|
|
if(AlmostEqual(q1.GetX(), q2.GetX()) &&
|
|
AlmostEqual(q1.GetY(), q2.GetY())){//elevator
|
|
p3d_list.push_back(q2);
|
|
}else
|
|
break;
|
|
}
|
|
}
|
|
k--;
|
|
j = k;
|
|
#ifdef INDOOR_PATH
|
|
if(find_path){
|
|
AddUnitToMO_Elevator2(mp3d, p3d_list, start_time,
|
|
periods.start, elev_list, start_pos, l_room, build_id, genmo);
|
|
}else{
|
|
AddUnitToMO_Elevator(mp3d, p3d_list, start_time,
|
|
periods.start, elev_list);
|
|
}
|
|
#else
|
|
AddUnitToMO_Elevator(mp3d, p3d_list, start_time,
|
|
periods.start, elev_list);
|
|
#endif
|
|
}
|
|
}else
|
|
|
|
#ifdef INDOOR_PATH
|
|
if(find_path){
|
|
AddUnitToMO2(mp3d, p1, p2, start_time, speed,
|
|
j, l_room, build_id, genmo);
|
|
}else{
|
|
AddUnitToMO(mp3d, p1, p2, start_time, speed);
|
|
}
|
|
#else
|
|
AddUnitToMO(mp3d, p1, p2, start_time, speed);
|
|
#endif
|
|
|
|
}
|
|
}
|
|
mp3d->EndBulkLoad();
|
|
count++;
|
|
///////////////////////////////////////////////////////////////////
|
|
//the following function takes time
|
|
|
|
#ifdef INDOOR_PATH
|
|
if(find_path){
|
|
}else{
|
|
ToGenLoc2(mp3d, rtree, build_id, genmo);
|
|
}
|
|
#else
|
|
ToGenLoc2(mp3d, rtree, build_id, genmo);
|
|
|
|
#endif
|
|
|
|
}
|
|
if(count == num)break;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
create one indoor movement from a location to the building entrance
|
|
this function is used to create indoor and outdoor trips
|
|
|
|
*/
|
|
void IndoorNav::GenerateMO3_End(IndoorGraph* ig, BTree* btree,
|
|
R_Tree<3,TupleId>* rtree,
|
|
Instant& start_time, int build_id, int entrance_index,
|
|
MPoint3D* mp3d, GenMO* genmo, Periods* peri)
|
|
{
|
|
// GenerateIP1(1);
|
|
GenerateIP3(1);
|
|
//////////////////get the building entrance position/////////////////
|
|
vector<GenLoc> doorloc_list;
|
|
vector<int> door_tid_list;
|
|
GetDoorLoc(ig, btree, doorloc_list, door_tid_list);
|
|
|
|
//////////////////////initialize elevator//////////////////////////////
|
|
if(peri->GetNoComponents() == 0){
|
|
cout<<"not correct time periods"<<endl;
|
|
assert(false);
|
|
}
|
|
Interval<Instant> periods;
|
|
peri->Get(0, periods);
|
|
double speed = GetMinimumDoorWidth();
|
|
vector<Elevator> elev_list;
|
|
InitializeElevator(periods, elev_list, speed);
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
int num = 1;
|
|
int count = 0;
|
|
for(unsigned int i = 0;i < genloc_list.size();i++){
|
|
GenLoc loc1 = genloc_list[i];
|
|
int door_index = entrance_index - 1;
|
|
GenLoc loc2 = doorloc_list[door_index];
|
|
|
|
/////////////////debuging//////////////////////
|
|
/* Loc temp_loc(4.36,11.13);
|
|
GenLoc temp_gloc(195, temp_loc);
|
|
loc1 = temp_gloc;*/
|
|
//////////////////////////////////////////////
|
|
|
|
// cout<<"loc1 "<<loc1<<" loc2 "<<loc2<<endl;
|
|
|
|
bool find_path = false;
|
|
#ifdef INDOOR_PATH
|
|
int path_oid = GetIndooPathID(entrance_index, loc1.GetOid(), true);
|
|
|
|
map<int, Line3D>::iterator iter = indoor_paths_list.find(path_oid);
|
|
if(iter != indoor_paths_list.end()){
|
|
ShortestPath_Length_End2(&loc1, &loc2, rel1, btree,
|
|
door_tid_list[door_index],
|
|
entrance_index);
|
|
find_path = true;
|
|
}else{
|
|
ShortestPath_Length_End(&loc1, &loc2, rel1, btree,
|
|
door_tid_list[door_index]);
|
|
}
|
|
#else
|
|
ShortestPath_Length_End(&loc1, &loc2, rel1, btree,
|
|
door_tid_list[door_index]);
|
|
#endif
|
|
|
|
Line3D* l3d = &path_list[count];
|
|
|
|
if(l3d->Length() > 0.0){
|
|
Line3D* l_room = NULL;
|
|
#ifdef INDOOR_PATH
|
|
if(find_path){
|
|
l_room = &rooms_id_list[count];
|
|
assert(l3d->Size() == l_room->Size());
|
|
}
|
|
#endif
|
|
|
|
mp3d->StartBulkLoad();
|
|
for(int j = 0;j < l3d->Size();j++){
|
|
if(j < l3d->Size() - 1){
|
|
Point3D p1, p2;
|
|
l3d->Get(j, p1);
|
|
l3d->Get(j + 1, p2);
|
|
///////////////process the movement in an elevator
|
|
if(AlmostEqual(p1.GetX(), p2.GetX()) &&
|
|
AlmostEqual(p1.GetY(), p2.GetY()) && elev_list.size() > 1){
|
|
|
|
float delta_h = fabs(elev_list[1].h - elev_list[0].h);
|
|
if(AlmostEqual(delta_h, p1.Distance(p2))){
|
|
int start_pos = j;
|
|
vector<Point3D> p3d_list;
|
|
p3d_list.push_back(p1);
|
|
p3d_list.push_back(p2);
|
|
int k = j + 1;
|
|
for(;k < l3d->Size();k++){
|
|
if(k < l3d->Size() - 1){
|
|
Point3D q1, q2;
|
|
l3d->Get(k, q1);
|
|
l3d->Get(k + 1, q2);
|
|
|
|
if(AlmostEqual(q1.GetX(), q2.GetX()) &&
|
|
AlmostEqual(q1.GetY(), q2.GetY())){//elevator
|
|
p3d_list.push_back(q2);
|
|
}else
|
|
break;
|
|
}
|
|
}
|
|
k--;
|
|
j = k;
|
|
|
|
#ifdef INDOOR_PATH
|
|
if(find_path){
|
|
AddUnitToMO_Elevator2(mp3d, p3d_list, start_time,
|
|
periods.start, elev_list, start_pos, l_room, build_id, genmo);
|
|
}else{
|
|
AddUnitToMO_Elevator(mp3d, p3d_list, start_time,
|
|
periods.start, elev_list);
|
|
}
|
|
|
|
#else
|
|
AddUnitToMO_Elevator(mp3d, p3d_list, start_time,
|
|
periods.start, elev_list);
|
|
#endif
|
|
}
|
|
}else
|
|
|
|
#ifdef INDOOR_PATH
|
|
if(find_path){
|
|
AddUnitToMO2(mp3d, p1, p2, start_time, speed,
|
|
j, l_room, build_id, genmo);
|
|
}else{
|
|
AddUnitToMO(mp3d, p1, p2, start_time, speed);
|
|
}
|
|
#else
|
|
AddUnitToMO(mp3d, p1, p2, start_time, speed);
|
|
#endif
|
|
|
|
}
|
|
}
|
|
mp3d->EndBulkLoad();
|
|
count++;
|
|
/////////////////////////////////////////////////////////////
|
|
#ifdef INDOOR_PATH
|
|
if(find_path){
|
|
|
|
}else{
|
|
ToGenLoc2(mp3d, rtree, build_id, genmo);
|
|
}
|
|
#else
|
|
ToGenLoc2(mp3d, rtree, build_id, genmo);
|
|
#endif
|
|
|
|
}
|
|
if(count == num)break;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
/*
|
|
almost the same as GenerateMO3End by but giving the start location
|
|
|
|
*/
|
|
|
|
void IndoorNav::GenerateMO3_EndExt(IndoorGraph* ig, BTree* btree,
|
|
R_Tree<3,TupleId>* rtree, Instant& start_time,
|
|
int build_id, int entrance_index, MPoint3D* mp3d,
|
|
GenMO* genmo, Periods* peri, GenLoc loc_input)
|
|
{
|
|
|
|
//////////////////get the building entrance position/////////////////
|
|
vector<GenLoc> doorloc_list;
|
|
vector<int> door_tid_list;
|
|
GetDoorLoc(ig, btree, doorloc_list, door_tid_list);
|
|
|
|
//////////////////////initialize elevator//////////////////////////////
|
|
if(peri->GetNoComponents() == 0){
|
|
cout<<"not correct time periods"<<endl;
|
|
assert(false);
|
|
}
|
|
Interval<Instant> periods;
|
|
peri->Get(0, periods);
|
|
double speed = GetMinimumDoorWidth();
|
|
vector<Elevator> elev_list;
|
|
InitializeElevator(periods, elev_list, speed);
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
int num = 1;
|
|
int count = 0;
|
|
genloc_list.push_back(loc_input);
|
|
for(unsigned int i = 0;i < genloc_list.size();i++){
|
|
GenLoc loc1 = genloc_list[i];
|
|
int door_index = entrance_index - 1;
|
|
GenLoc loc2 = doorloc_list[door_index];
|
|
|
|
/////////////////debuging//////////////////////
|
|
/* Loc temp_loc(4.36,11.13);
|
|
GenLoc temp_gloc(195, temp_loc);
|
|
loc1 = temp_gloc;*/
|
|
//////////////////////////////////////////////
|
|
|
|
// cout<<"loc1 "<<loc1<<" loc2 "<<loc2<<endl;
|
|
|
|
bool find_path = false;
|
|
#ifdef INDOOR_PATH
|
|
int path_oid = GetIndooPathID(entrance_index, loc1.GetOid(), true);
|
|
|
|
map<int, Line3D>::iterator iter = indoor_paths_list.find(path_oid);
|
|
if(iter != indoor_paths_list.end()){
|
|
ShortestPath_Length_End2(&loc1, &loc2, rel1, btree,
|
|
door_tid_list[door_index],
|
|
entrance_index);
|
|
find_path = true;
|
|
}else{
|
|
ShortestPath_Length_End(&loc1, &loc2, rel1, btree,
|
|
door_tid_list[door_index]);
|
|
}
|
|
#else
|
|
ShortestPath_Length_End(&loc1, &loc2, rel1, btree,
|
|
door_tid_list[door_index]);
|
|
#endif
|
|
|
|
Line3D* l3d = &path_list[count];
|
|
|
|
if(l3d->Length() > 0.0){
|
|
Line3D* l_room = NULL;
|
|
#ifdef INDOOR_PATH
|
|
if(find_path){
|
|
l_room = &rooms_id_list[count];
|
|
assert(l3d->Size() == l_room->Size());
|
|
}
|
|
#endif
|
|
|
|
mp3d->StartBulkLoad();
|
|
for(int j = 0;j < l3d->Size();j++){
|
|
if(j < l3d->Size() - 1){
|
|
Point3D p1, p2;
|
|
l3d->Get(j, p1);
|
|
l3d->Get(j + 1, p2);
|
|
///////////////process the movement in an elevator
|
|
if(AlmostEqual(p1.GetX(), p2.GetX()) &&
|
|
AlmostEqual(p1.GetY(), p2.GetY()) && elev_list.size() > 1){
|
|
|
|
float delta_h = fabs(elev_list[1].h - elev_list[0].h);
|
|
if(AlmostEqual(delta_h, p1.Distance(p2))){
|
|
int start_pos = j;
|
|
vector<Point3D> p3d_list;
|
|
p3d_list.push_back(p1);
|
|
p3d_list.push_back(p2);
|
|
int k = j + 1;
|
|
for(;k < l3d->Size();k++){
|
|
if(k < l3d->Size() - 1){
|
|
Point3D q1, q2;
|
|
l3d->Get(k, q1);
|
|
l3d->Get(k + 1, q2);
|
|
|
|
if(AlmostEqual(q1.GetX(), q2.GetX()) &&
|
|
AlmostEqual(q1.GetY(), q2.GetY())){//elevator
|
|
p3d_list.push_back(q2);
|
|
}else
|
|
break;
|
|
}
|
|
}
|
|
k--;
|
|
j = k;
|
|
|
|
#ifdef INDOOR_PATH
|
|
if(find_path){
|
|
AddUnitToMO_Elevator2(mp3d, p3d_list, start_time,
|
|
periods.start, elev_list, start_pos, l_room, build_id, genmo);
|
|
}else{
|
|
AddUnitToMO_Elevator(mp3d, p3d_list, start_time,
|
|
periods.start, elev_list);
|
|
}
|
|
|
|
#else
|
|
AddUnitToMO_Elevator(mp3d, p3d_list, start_time,
|
|
periods.start, elev_list);
|
|
#endif
|
|
}
|
|
}else
|
|
|
|
#ifdef INDOOR_PATH
|
|
if(find_path){
|
|
AddUnitToMO2(mp3d, p1, p2, start_time, speed,
|
|
j, l_room, build_id, genmo);
|
|
}else{
|
|
AddUnitToMO(mp3d, p1, p2, start_time, speed);
|
|
}
|
|
#else
|
|
AddUnitToMO(mp3d, p1, p2, start_time, speed);
|
|
#endif
|
|
|
|
}
|
|
}
|
|
mp3d->EndBulkLoad();
|
|
count++;
|
|
/////////////////////////////////////////////////////////////
|
|
#ifdef INDOOR_PATH
|
|
if(find_path){
|
|
|
|
}else{
|
|
ToGenLoc2(mp3d, rtree, build_id, genmo);
|
|
}
|
|
#else
|
|
ToGenLoc2(mp3d, rtree, build_id, genmo);
|
|
#endif
|
|
|
|
}
|
|
if(count == num)break;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
/*
|
|
add temporal units (for movement in an elevator)
|
|
|
|
*/
|
|
void IndoorNav::AddUnitToMO_Elevator(MPoint3D* mp3d, vector<Point3D>& p3d_list,
|
|
Instant& start_time, Instant& st,
|
|
vector<Elevator>& elev_list)
|
|
{
|
|
assert(p3d_list.size() >= 2 && elev_list.size() >= 2);
|
|
////////////get the time for waiting///////////////////////////////////
|
|
double relative_start = start_time.ToDouble() - st.ToDouble();
|
|
double cycle_time = elev_list[elev_list.size() - 1].t2 -
|
|
elev_list[elev_list.size() - 1].t1;
|
|
|
|
while(relative_start > cycle_time){
|
|
relative_start -= cycle_time;
|
|
}
|
|
|
|
// printf("relative time %.12f\n", relative_start*86400000);
|
|
Instant t = start_time;
|
|
t.ReadFrom(relative_start + st.ToDouble());
|
|
// cout<<"relative time "<<t<<endl;
|
|
|
|
float h1 = p3d_list[0].GetZ();
|
|
float h2 = p3d_list[ p3d_list.size() - 1].GetZ();
|
|
|
|
double wait_time = 0.0;
|
|
for(unsigned int i = 0;i < elev_list.size();i++){
|
|
if(AlmostEqual(h1, elev_list[i].h)){
|
|
if(h1 < h2){ //check t2
|
|
if(elev_list[i].t2 > relative_start){
|
|
wait_time = elev_list[i].t2 - relative_start;
|
|
}else{
|
|
wait_time = elev_list[i].t2 + cycle_time - relative_start;
|
|
}
|
|
}else{//check t1
|
|
if(elev_list[i].t1 > relative_start){
|
|
wait_time = elev_list[i].t1 - relative_start;
|
|
}else{
|
|
wait_time = elev_list[i].t1 + cycle_time - relative_start;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
// printf("wait time %.12f, %.12f\n", wait_time, wait_time*86400000);
|
|
////////////////////unit for waiting/////////////////////////
|
|
if(wait_time > 0.0){
|
|
Interval<Instant> up_interval;
|
|
up_interval.start = start_time;
|
|
Instant end = start_time;
|
|
end.ReadFrom(start_time.ToDouble() + wait_time);
|
|
up_interval.end = end;
|
|
|
|
int64_t st = start_time.ToDouble()*86400000.0;
|
|
int64_t et = end.ToDouble()*86400000.0;
|
|
|
|
if(st != et){
|
|
up_interval.lc = true;
|
|
up_interval.rc = false;
|
|
Point3D p = p3d_list[0];
|
|
UPoint3D* unit = new UPoint3D(up_interval, p, p);
|
|
mp3d->Add(*unit);
|
|
delete unit;
|
|
}
|
|
|
|
start_time = end;
|
|
}
|
|
////////////////////////////////////////////////////////////////////////////
|
|
for(int i = 0;i < (int) p3d_list.size();i++){
|
|
if(i < (int)(p3d_list.size() - 1)){
|
|
Point3D p1 = p3d_list[i];
|
|
Point3D p2 = p3d_list[i + 1];
|
|
|
|
Interval<Instant> up_interval;
|
|
up_interval.start = start_time;
|
|
Instant end = start_time;
|
|
end.ReadFrom(start_time.ToDouble() + elev_list[0].m_t);
|
|
up_interval.end = end;
|
|
|
|
up_interval.lc = true;
|
|
up_interval.rc = false;
|
|
UPoint3D* unit = new UPoint3D(up_interval, p1, p2);
|
|
mp3d->Add(*unit);
|
|
delete unit;
|
|
start_time = end;
|
|
|
|
if(i < (int)(p3d_list.size() - 2)){
|
|
Interval<Instant> up_interval2;
|
|
up_interval2.start = start_time;
|
|
Instant end2 = start_time;
|
|
end2.ReadFrom(start_time.ToDouble() + elev_list[0].w_t);
|
|
up_interval2.end = end2;
|
|
|
|
up_interval2.lc = true;
|
|
up_interval2.rc = false;
|
|
UPoint3D* unit = new UPoint3D(up_interval2, p2, p2);
|
|
mp3d->Add(*unit);
|
|
delete unit;
|
|
start_time = end2;
|
|
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
/*
|
|
add temporal units (for movement in an elevator) in implementation by loading
|
|
stored groom oid
|
|
|
|
*/
|
|
void IndoorNav::AddUnitToMO_Elevator2(MPoint3D* mp3d,
|
|
vector<Point3D>& p3d_list,
|
|
Instant& start_time, Instant& st,
|
|
vector<Elevator>& elev_list, int index, Line3D* l_room,
|
|
int build_id, GenMO* genmo)
|
|
{
|
|
assert(p3d_list.size() >= 2 && elev_list.size() >= 2);
|
|
////////////get the time for waiting///////////////////////////////////
|
|
double relative_start = start_time.ToDouble() - st.ToDouble();
|
|
double cycle_time = elev_list[elev_list.size() - 1].t2 -
|
|
elev_list[elev_list.size() - 1].t1;
|
|
|
|
while(relative_start > cycle_time){
|
|
relative_start -= cycle_time;
|
|
}
|
|
|
|
// printf("relative time %.12f\n", relative_start*86400000);
|
|
Instant t = start_time;
|
|
t.ReadFrom(relative_start + st.ToDouble());
|
|
// cout<<"relative time "<<t<<endl;
|
|
|
|
float h1 = p3d_list[0].GetZ();
|
|
float h2 = p3d_list[ p3d_list.size() - 1].GetZ();
|
|
|
|
double wait_time = 0.0;
|
|
for(unsigned int i = 0;i < elev_list.size();i++){
|
|
if(AlmostEqual(h1, elev_list[i].h)){
|
|
if(h1 < h2){ //check t2
|
|
if(elev_list[i].t2 > relative_start){
|
|
wait_time = elev_list[i].t2 - relative_start;
|
|
}else{
|
|
wait_time = elev_list[i].t2 + cycle_time - relative_start;
|
|
}
|
|
}else{//check t1
|
|
if(elev_list[i].t1 > relative_start){
|
|
wait_time = elev_list[i].t1 - relative_start;
|
|
}else{
|
|
wait_time = elev_list[i].t1 + cycle_time - relative_start;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
// printf("wait time %.12f %.12f\n", wait_time, wait_time*86400000);
|
|
////////////////////unit for waiting/////////////////////////
|
|
if(wait_time > 0.0){
|
|
Interval<Instant> up_interval;
|
|
up_interval.start = start_time;
|
|
Instant end = start_time;
|
|
end.ReadFrom(start_time.ToDouble() + wait_time);
|
|
up_interval.end = end;
|
|
|
|
int64_t st = start_time.ToDouble()*86400000.0;
|
|
int64_t et = end.ToDouble()*86400000.0;
|
|
|
|
if(st != et){
|
|
|
|
up_interval.lc = true;
|
|
up_interval.rc = false;
|
|
Point3D p = p3d_list[0];
|
|
UPoint3D* unit = new UPoint3D(up_interval, p, p);
|
|
mp3d->Add(*unit);
|
|
delete unit;
|
|
|
|
/////////////////////////////////////////////
|
|
/////////genric units///////////////////////
|
|
/////////////////////////////////////////////
|
|
Point3D q;
|
|
l_room->Get(index, q);
|
|
int groom_tid = 0;
|
|
if(q.GetX() > 0 ) groom_tid = q.GetX();
|
|
else if(q.GetY() > 0) groom_tid = q.GetY();
|
|
else if(q.GetZ() > 0) groom_tid = q.GetZ();
|
|
else assert(false);
|
|
|
|
Tuple* groom_tuple = rel1->GetTuple(groom_tid, false);
|
|
GRoom* groom = (GRoom*)groom_tuple->GetAttribute(I_Room);
|
|
int groom_oid = ((CcInt*)groom_tuple->GetAttribute(I_OID))->GetIntval();
|
|
string type = ((CcString*)groom_tuple->GetAttribute(I_Type))->GetValue();
|
|
Rectangle<2> bbox = groom->BoundingBox();
|
|
groom_tuple->DeleteIfAllowed();
|
|
|
|
char buffer1[64];
|
|
sprintf(buffer1, "%d", groom_oid);
|
|
char buffer2[64];
|
|
sprintf(buffer2, "%d", build_id);
|
|
strcat(buffer2, buffer1);
|
|
|
|
int new_groom_oid;
|
|
sscanf(buffer2, "%d", &new_groom_oid);//////building id + room id///
|
|
// cout<<"ref oid "<<new_groom_oid<<endl;
|
|
|
|
GenLoc gloc1;
|
|
GenLoc gloc2;
|
|
if(GetRoomEnum(type) == OR || GetRoomEnum(type) == BR ||
|
|
GetRoomEnum(type) == CO || GetRoomEnum(type) == ST){
|
|
Loc loc_1(p.GetX() - bbox.MinD(0), p.GetY() - bbox.MinD(1));
|
|
Loc loc_2(p.GetX() - bbox.MinD(0), p.GetY() - bbox.MinD(1));
|
|
|
|
gloc1.SetValue(new_groom_oid, loc_1);
|
|
gloc2.SetValue(new_groom_oid, loc_2);
|
|
}else if(GetRoomEnum(type) == EL){
|
|
//move in an elevator,we record the height
|
|
|
|
// Loc loc_1(p.GetZ(), -1.0);
|
|
// Loc loc_2(p.GetZ(), -1.0);
|
|
|
|
Loc loc_1(p.GetZ(), UNDEFVAL);
|
|
Loc loc_2(p.GetZ(), UNDEFVAL);
|
|
|
|
gloc1.SetValue(new_groom_oid, loc_1);
|
|
gloc2.SetValue(new_groom_oid, loc_2);
|
|
}else{
|
|
cout<<"should not be here"<<endl;
|
|
assert(false);
|
|
}
|
|
UGenLoc* ugenloc =
|
|
new UGenLoc(up_interval, gloc1, gloc2, GetTM("Indoor"));
|
|
genmo->Add(*ugenloc);
|
|
delete ugenloc;
|
|
}
|
|
|
|
start_time = end;
|
|
}
|
|
////////////////////////////////////////////////////////////////////////////
|
|
for(int i = 0;i < (int) p3d_list.size();i++){
|
|
if(i < (int)(p3d_list.size() - 1)){
|
|
Point3D p1 = p3d_list[i];
|
|
Point3D p2 = p3d_list[i + 1];
|
|
|
|
Interval<Instant> up_interval;
|
|
up_interval.start = start_time;
|
|
Instant end = start_time;
|
|
end.ReadFrom(start_time.ToDouble() + elev_list[0].m_t);
|
|
up_interval.end = end;
|
|
|
|
up_interval.lc = true;
|
|
up_interval.rc = false;
|
|
UPoint3D* unit = new UPoint3D(up_interval, p1, p2);
|
|
mp3d->Add(*unit);
|
|
delete unit;
|
|
start_time = end;
|
|
/////////////////////////////////////////////
|
|
/////////genric units////////////////////////
|
|
/////////////////////////////////////////////
|
|
// int groom_tid = GetRef_RoomTid(index + i, l_room);
|
|
|
|
int groom_tid = GetRef_RoomTid(index + i, l_room, true);
|
|
|
|
Tuple* groom_tuple = rel1->GetTuple(groom_tid, false);
|
|
GRoom* groom = (GRoom*)groom_tuple->GetAttribute(I_Room);
|
|
int groom_oid =
|
|
((CcInt*)groom_tuple->GetAttribute(I_OID))->GetIntval();
|
|
string type =
|
|
((CcString*)groom_tuple->GetAttribute(I_Type))->GetValue();
|
|
Rectangle<2> bbox = groom->BoundingBox();
|
|
groom_tuple->DeleteIfAllowed();
|
|
char buffer1[64];
|
|
sprintf(buffer1, "%d", groom_oid);
|
|
char buffer2[64];
|
|
sprintf(buffer2, "%d", build_id);
|
|
strcat(buffer2, buffer1);
|
|
|
|
int new_groom_oid;
|
|
sscanf(buffer2, "%d", &new_groom_oid);//////building id + room id///
|
|
// cout<<"ref oid "<<new_groom_oid<<endl;
|
|
|
|
GenLoc gloc1;
|
|
GenLoc gloc2;
|
|
if(GetRoomEnum(type) == OR || GetRoomEnum(type) == BR ||
|
|
GetRoomEnum(type) == CO || GetRoomEnum(type) == ST){
|
|
Loc loc_1(p1.GetX() - bbox.MinD(0), p1.GetY() - bbox.MinD(1));
|
|
Loc loc_2(p2.GetX() - bbox.MinD(0), p2.GetY() - bbox.MinD(1));
|
|
|
|
gloc1.SetValue(new_groom_oid, loc_1);
|
|
gloc2.SetValue(new_groom_oid, loc_2);
|
|
}else if(GetRoomEnum(type) == EL){
|
|
//move in an elevator,we record the height
|
|
// Loc loc_1(p1.GetZ(), -1.0);
|
|
// Loc loc_2(p2.GetZ(), -1.0);
|
|
|
|
Loc loc_1(p1.GetZ(), UNDEFVAL);
|
|
Loc loc_2(p2.GetZ(), UNDEFVAL);
|
|
|
|
gloc1.SetValue(new_groom_oid, loc_1);
|
|
gloc2.SetValue(new_groom_oid, loc_2);
|
|
}else{
|
|
cout<<"should not be here"<<endl;
|
|
assert(false);
|
|
}
|
|
UGenLoc* ugenloc =
|
|
new UGenLoc(up_interval, gloc1, gloc2, GetTM("Indoor"));
|
|
genmo->Add(*ugenloc);
|
|
delete ugenloc;
|
|
|
|
if(i < (int)(p3d_list.size() - 2)){
|
|
Interval<Instant> up_interval2;
|
|
up_interval2.start = start_time;
|
|
Instant end2 = start_time;
|
|
end2.ReadFrom(start_time.ToDouble() + elev_list[0].w_t);
|
|
up_interval2.end = end2;
|
|
|
|
up_interval2.lc = true;
|
|
up_interval2.rc = false;
|
|
UPoint3D* unit = new UPoint3D(up_interval2, p2, p2);
|
|
mp3d->Add(*unit);
|
|
delete unit;
|
|
start_time = end2;
|
|
|
|
/////////////////////////////////////////////
|
|
/////////genric units//////////////////////
|
|
/////////////////////////////////////////////
|
|
|
|
GenLoc gloc1;
|
|
GenLoc gloc2;
|
|
if(GetRoomEnum(type) == OR || GetRoomEnum(type) == BR ||
|
|
GetRoomEnum(type) == CO || GetRoomEnum(type) == ST){
|
|
Loc loc_1(p2.GetX() - bbox.MinD(0), p2.GetY() - bbox.MinD(1));
|
|
Loc loc_2(p2.GetX() - bbox.MinD(0), p2.GetY() - bbox.MinD(1));
|
|
|
|
gloc1.SetValue(new_groom_oid, loc_1);
|
|
gloc2.SetValue(new_groom_oid, loc_2);
|
|
}else if(GetRoomEnum(type) == EL){
|
|
//move in an elevator,we record the height
|
|
|
|
// Loc loc_1(p2.GetZ(), -1.0);
|
|
// Loc loc_2(p2.GetZ(), -1.0);
|
|
|
|
Loc loc_1(p2.GetZ(), UNDEFVAL);
|
|
Loc loc_2(p2.GetZ(), UNDEFVAL);
|
|
|
|
|
|
gloc1.SetValue(new_groom_oid, loc_1);
|
|
gloc2.SetValue(new_groom_oid, loc_2);
|
|
}else{
|
|
cout<<"should not be here"<<endl;
|
|
assert(false);
|
|
}
|
|
UGenLoc* ugenloc =
|
|
new UGenLoc(up_interval2, gloc1, gloc2, GetTM("Indoor"));
|
|
genmo->Add(*ugenloc);
|
|
delete ugenloc;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
calculate the number of elevators in a building
|
|
|
|
*/
|
|
unsigned int IndoorNav::NumerOfElevators()
|
|
{
|
|
const double delta_dist = 0.001;
|
|
|
|
vector<Point> center_list;
|
|
for(int i = 1;i <= rel1->GetNoTuples();i++){
|
|
Tuple* groom_tuple = rel1->GetTuple(i, false);
|
|
string type = ((CcString*)groom_tuple->GetAttribute(I_Type))->GetValue();
|
|
if(GetRoomEnum(type) == EL){
|
|
GRoom* groom = (GRoom*)groom_tuple->GetAttribute(I_Room);
|
|
Rectangle<2> bbox = groom->BoundingBox();
|
|
Point p(true, (bbox.MinD(0) + bbox.MaxD(0))/2,
|
|
(bbox.MinD(1) + bbox.MaxD(1))/2);
|
|
if(center_list.size() == 0)center_list.push_back(p);
|
|
else{
|
|
unsigned int j = 0;
|
|
for(;j < center_list.size();j++)
|
|
if(center_list[j].Distance(p) < delta_dist)break;
|
|
if(j == center_list.size())
|
|
center_list.push_back(p);
|
|
}
|
|
}
|
|
groom_tuple->DeleteIfAllowed();
|
|
}
|
|
|
|
return center_list.size();
|
|
|
|
}
|
|
|
|
/*
|
|
several elevators. for each elevator, an array is maintained
|
|
|
|
*/
|
|
void IndoorNav::InitializeElevator_New(Interval<Instant>& periods,
|
|
vector< vector<Elevator> >& elev_list,
|
|
double speed)
|
|
{
|
|
const double delta_dist = 0.001;
|
|
|
|
vector<Point> center_list;
|
|
for(int i = 1;i <= rel1->GetNoTuples();i++){
|
|
Tuple* groom_tuple = rel1->GetTuple(i, false);
|
|
string type = ((CcString*)groom_tuple->GetAttribute(I_Type))->GetValue();
|
|
if(GetRoomEnum(type) == EL){
|
|
GRoom* groom = (GRoom*)groom_tuple->GetAttribute(I_Room);
|
|
Rectangle<2> bbox = groom->BoundingBox();
|
|
Point p(true, (bbox.MinD(0) + bbox.MaxD(0))/2,
|
|
(bbox.MinD(1) + bbox.MaxD(1))/2);
|
|
if(center_list.size() == 0)center_list.push_back(p);
|
|
else{
|
|
unsigned int j = 0;
|
|
for(;j < center_list.size();j++)
|
|
if(center_list[j].Distance(p) < delta_dist)break;
|
|
if(j == center_list.size())
|
|
center_list.push_back(p);
|
|
}
|
|
}
|
|
groom_tuple->DeleteIfAllowed();
|
|
}
|
|
|
|
vector<Elevator> empty_list;
|
|
for(unsigned int i = 0 ; i < center_list.size();i++)
|
|
elev_list.push_back(empty_list);
|
|
|
|
for(int i = 1;i <= rel1->GetNoTuples();i++){
|
|
Tuple* groom_tuple = rel1->GetTuple(i, false);
|
|
string type = ((CcString*)groom_tuple->GetAttribute(I_Type))->GetValue();
|
|
if(GetRoomEnum(type) == EL){
|
|
GRoom* groom = (GRoom*)groom_tuple->GetAttribute(I_Room);
|
|
Rectangle<2> bbox = groom->BoundingBox();
|
|
float h = groom->GetLowHeight();
|
|
Point p(true, (bbox.MinD(0) + bbox.MaxD(0))/2,
|
|
(bbox.MinD(1) + bbox.MaxD(1))/2);
|
|
Elevator elevator(h, 0.0, 0.0, 0.0, 0.0);
|
|
elevator.el_rect = bbox;
|
|
for(unsigned int j = 0;j < center_list.size();j++){
|
|
if(center_list[j].Distance(p) < delta_dist){
|
|
elev_list[j].push_back(elevator);
|
|
|
|
}
|
|
}
|
|
}
|
|
groom_tuple->DeleteIfAllowed();
|
|
}
|
|
|
|
// for(unsigned int i = 0;i < elev_list.size();i++)
|
|
// cout<<"elevator "<<i<<" size "<<elev_list[i].size()<<endl;
|
|
|
|
|
|
if(elev_list.size() < 1 || elev_list[0].size() < 2){
|
|
cout<<"only one floor, should not have elevator"<<endl;
|
|
return;
|
|
}
|
|
|
|
|
|
for(unsigned int i = 0;i < elev_list.size();i++)
|
|
sort(elev_list[i].begin(), elev_list[i].end());
|
|
|
|
|
|
for(unsigned int i = 0;i < elev_list.size();i++){
|
|
|
|
int n_floor = (int)elev_list[i].size();
|
|
double stay = 10.0/(24.0*60.0*60.0); //at each floor stay 10 seconds
|
|
double delta_h = fabs(elev_list[i][1].h - elev_list[i][0].h);
|
|
double time_move = delta_h /(24.0*60.0*60.0*speed);
|
|
|
|
///////////////////////////////////////////////////////////////
|
|
////////////t1: higher -- lower////////////////////////////////
|
|
////////////t2: lower -- higher////////////////////////////////
|
|
///////////////////////////////////////////////////////////////
|
|
|
|
elev_list[i][n_floor - 1].t1 = 0.0;
|
|
elev_list[i][n_floor - 1].t2 = elev_list[i][n_floor - 1].t1 +
|
|
2*time_move*(n_floor-1) +
|
|
stay*((n_floor-2)*2 + 2);
|
|
|
|
elev_list[i][n_floor - 1].m_t = time_move;
|
|
elev_list[i][n_floor - 1].w_t = stay;
|
|
|
|
for(int j = n_floor - 2;j >= 0;j --){
|
|
elev_list[i][j].t1 = elev_list[i][j + 1].t1 + stay + time_move;
|
|
elev_list[i][j].t2 = elev_list[i][j + 1].t2 - stay - time_move;
|
|
elev_list[i][j].m_t = time_move;
|
|
elev_list[i][j].w_t = stay;
|
|
}
|
|
}
|
|
|
|
|
|
// for(unsigned int i = 0;i < elev_list.size();i++){
|
|
// for(unsigned int j = 0;j < elev_list[i].size();j++){
|
|
|
|
// Instant t1 = periods.start;
|
|
// t1.ReadFrom(periods.start.ToDouble() + elev_list[i][j].t1);
|
|
//
|
|
// Instant t2 = periods.start;
|
|
// t2.ReadFrom(periods.start.ToDouble() + elev_list[i][j].t2);
|
|
//
|
|
// cout<<"first arrive "<<t1<<" second arrive "<<t2<<endl;
|
|
// cout<<"rect "<<elev_list[i][j].el_rect<<" h "<<elev_list[i][j].h<<endl;
|
|
// cout<<elev_list[i][j].t1<<" "<<elev_list[i][j].t2<<endl;
|
|
// cout<<elev_list[i][j].t1*86400.0
|
|
// <<" "<<elev_list[i][j].t2*86400.0<<endl;
|
|
// }
|
|
// }
|
|
|
|
}
|
|
|
|
/*
|
|
generate indoor moving objects where the building can have several elevators
|
|
|
|
*/
|
|
void IndoorNav::GenerateMO1_New(IndoorGraph* ig, BTree* btree,
|
|
R_Tree<3,TupleId>* rtree, int num,
|
|
Periods* peri, bool convert, unsigned int num_elev)
|
|
{
|
|
// cout<<"several elevators "<<endl;
|
|
|
|
GenerateIP1(num*2);
|
|
|
|
IndoorNav* indoor_nav = new IndoorNav(ig);
|
|
|
|
Interval<Instant> periods;
|
|
if(peri->GetNoComponents() == 0){
|
|
cout<<"not correct time periods"<<endl;
|
|
assert(false);
|
|
}
|
|
peri->Get(0, periods);
|
|
|
|
double speed = GetMinimumDoorWidth();
|
|
|
|
vector< vector<Elevator> > elev_list;
|
|
|
|
InitializeElevator_New(periods, elev_list, speed);
|
|
|
|
int count = 0;
|
|
for(unsigned int i = 0;i < genloc_list.size();i++){
|
|
if(i < genloc_list.size() - 1){
|
|
GenLoc loc1 = genloc_list[i];
|
|
GenLoc loc2 = genloc_list[i + 1];
|
|
|
|
if(loc1.GetOid() == loc2.GetOid()) continue;
|
|
|
|
// cout<<"loc1 "<<loc1<<" loc2 "<<loc2<<endl;
|
|
|
|
indoor_nav->ShortestPath_Length(&loc1, &loc2, rel1, btree);
|
|
|
|
// cout<<indoor_nav->path_list[count].Length()<<endl;
|
|
//////////////////////////////////////////////////////////////////
|
|
Instant start_time = periods.start;
|
|
|
|
//in several minutes: 60 seconds for 12 persons
|
|
start_time.ReadFrom(periods.start.ToDouble() +
|
|
(GetRandom() % (num*5))/(24.0*60.0*60.0));
|
|
|
|
Line3D* l3d = &indoor_nav->path_list[count];
|
|
// l3d->Print();
|
|
if(l3d->Length() > 0.0){
|
|
MPoint3D* mp3d = new MPoint3D(0);
|
|
mp3d->StartBulkLoad();
|
|
for(int j = 0;j < l3d->Size();j++){
|
|
if(j < l3d->Size() - 1){
|
|
Point3D p1, p2;
|
|
l3d->Get(j, p1);
|
|
l3d->Get(j + 1, p2);
|
|
///////////////process the movement in an elevator
|
|
if(AlmostEqual(p1.GetX(), p2.GetX()) &&
|
|
AlmostEqual(p1.GetY(), p2.GetY()) &&
|
|
(elev_list.size() > 0 && elev_list[0].size() > 1)){
|
|
|
|
float delta_h = fabs(elev_list[0][1].h - elev_list[0][0].h);
|
|
if(AlmostEqual(delta_h, p1.Distance(p2))){
|
|
vector<Point3D> p3d_list;
|
|
p3d_list.push_back(p1);
|
|
p3d_list.push_back(p2);
|
|
int k = j + 1;
|
|
for(;k < l3d->Size();k++){
|
|
if(k < l3d->Size() - 1){
|
|
Point3D q1, q2;
|
|
l3d->Get(k, q1);
|
|
l3d->Get(k + 1, q2);
|
|
|
|
if(AlmostEqual(q1.GetX(), q2.GetX()) &&
|
|
AlmostEqual(q1.GetY(), q2.GetY())){//elevator
|
|
p3d_list.push_back(q2);
|
|
}else
|
|
break;
|
|
}
|
|
}
|
|
k--;
|
|
j = k;
|
|
|
|
AddUnitToMO_Elevator_New(mp3d, p3d_list, start_time,
|
|
periods.start, elev_list);
|
|
}
|
|
}else
|
|
AddUnitToMO(mp3d, p1, p2, start_time, speed);
|
|
}
|
|
}
|
|
mp3d->EndBulkLoad();
|
|
mo_list.push_back(*mp3d);
|
|
///////////////////////////////////////////////////////////////////
|
|
if(convert)
|
|
ToGenLoc(mp3d, rtree);
|
|
mp3d->DeleteIfAllowed();
|
|
count++;
|
|
}
|
|
if(count == num)break;
|
|
|
|
}
|
|
}
|
|
|
|
delete indoor_nav;
|
|
}
|
|
|
|
|
|
void IndoorNav::AddUnitToMO_Elevator_New(MPoint3D* mp3d,
|
|
vector<Point3D>& p3d_list,
|
|
Instant& start_time, Instant& st,
|
|
vector< vector<Elevator> >& elev_list)
|
|
{
|
|
assert(p3d_list.size() >= 2 && elev_list[0].size() >= 2);
|
|
////////////get the time for waiting///////////////////////////////////
|
|
double relative_start = start_time.ToDouble() - st.ToDouble();
|
|
/////////////////////////////////////////////////////////////////////////
|
|
///////////////////find which elevator///////////////////////////////////
|
|
///////////// different elevators (different heights)2 or 3 levels///////
|
|
///////////////// have different cycle time/////////////////////////////
|
|
/////////////////////////////////////////////////////////////////////////
|
|
float h1 = p3d_list[0].GetZ();
|
|
float h2 = p3d_list[ p3d_list.size() - 1].GetZ();
|
|
Point test_p(true, p3d_list[0].GetX(), p3d_list[0].GetY());
|
|
int elev_index = -1;
|
|
for(unsigned int i = 0;i < elev_list.size();i++){
|
|
if(test_p.Inside(elev_list[i][0].el_rect)){
|
|
elev_index = i;
|
|
break;
|
|
}
|
|
}
|
|
assert(elev_index >= 0);
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
double cycle_time =
|
|
elev_list[elev_index][elev_list[elev_index].size() - 1].t2 -
|
|
elev_list[elev_index][elev_list[elev_index].size() - 1].t1;
|
|
|
|
while(relative_start > cycle_time){
|
|
relative_start -= cycle_time;
|
|
}
|
|
|
|
// printf("relative time %.12f\n", relative_start*86400000);
|
|
Instant t = start_time;
|
|
t.ReadFrom(relative_start + st.ToDouble());
|
|
// cout<<"relative time "<<t<<endl;
|
|
|
|
double wait_time = 0.0;
|
|
|
|
bool found = false;
|
|
|
|
// cout<<"arrive time "<<start_time<<endl;
|
|
// cout<<"cycle time "<<cycle_time<<endl;
|
|
|
|
|
|
for(unsigned int i = 0;i < elev_list.size();i++){
|
|
for(unsigned int j = 0;j < elev_list[i].size();j++){
|
|
if(AlmostEqual(h1, elev_list[i][j].h) &&
|
|
test_p.Inside(elev_list[i][j].el_rect)){ //point inside rectangle
|
|
if(h1 < h2){ //check t2
|
|
// cout<<"h1 < h2 "<<elev_list[i][j].t2
|
|
// <<" relative_start"<<relative_start<<endl;
|
|
|
|
if(elev_list[i][j].t2 > relative_start){
|
|
// if(elev_list[i][j].t2 > relative_start ||
|
|
// (int)(elev_list[i][j].t2*86400.0) == relative_start_int){
|
|
|
|
wait_time = elev_list[i][j].t2 - relative_start;
|
|
}else{
|
|
wait_time = elev_list[i][j].t2 + cycle_time - relative_start;
|
|
}
|
|
}else{//check t1
|
|
// cout<<"h1 > h2 "<<elev_list[i][j].t1
|
|
// <<" relative_start "<<relative_start<<endl;
|
|
|
|
if(elev_list[i][j].t1 > relative_start){
|
|
|
|
wait_time = elev_list[i][j].t1 - relative_start;
|
|
}else{
|
|
wait_time = elev_list[i][j].t1 + cycle_time - relative_start;
|
|
}
|
|
}
|
|
found = true;
|
|
|
|
Instant temp = start_time;
|
|
temp.ReadFrom(start_time.ToDouble() + wait_time);
|
|
// cout<<"elevator "<<i<<" h1 "<<h1
|
|
// <<" leave time "<<temp<<" wait time "<<wait_time<<endl;
|
|
|
|
break;
|
|
}
|
|
}
|
|
if(found)break;
|
|
|
|
}
|
|
|
|
// printf("wait time %.12f, %.12f\n", wait_time, wait_time*86400000);
|
|
////////////////////unit for waiting/////////////////////////
|
|
if(wait_time > 0.0){
|
|
Interval<Instant> up_interval;
|
|
up_interval.start = start_time;
|
|
Instant end = start_time;
|
|
end.ReadFrom(start_time.ToDouble() + wait_time);
|
|
up_interval.end = end;
|
|
|
|
int64_t st = start_time.ToDouble()*86400000.0;
|
|
int64_t et = end.ToDouble()*86400000.0;
|
|
|
|
if(st != et){
|
|
up_interval.lc = true;
|
|
up_interval.rc = false;
|
|
Point3D p = p3d_list[0];
|
|
UPoint3D* unit = new UPoint3D(up_interval, p, p);
|
|
mp3d->Add(*unit);
|
|
delete unit;
|
|
}
|
|
|
|
start_time = end;
|
|
}
|
|
////////////////////////////////////////////////////////////////////////////
|
|
for(int i = 0;i < (int) p3d_list.size();i++){
|
|
if(i < (int)(p3d_list.size() - 1)){
|
|
Point3D p1 = p3d_list[i];
|
|
Point3D p2 = p3d_list[i + 1];
|
|
|
|
Interval<Instant> up_interval;
|
|
up_interval.start = start_time;
|
|
Instant end = start_time;
|
|
end.ReadFrom(start_time.ToDouble() + elev_list[0][0].m_t);
|
|
up_interval.end = end;
|
|
|
|
up_interval.lc = true;
|
|
up_interval.rc = false;
|
|
UPoint3D* unit = new UPoint3D(up_interval, p1, p2);
|
|
mp3d->Add(*unit);
|
|
delete unit;
|
|
start_time = end;
|
|
|
|
if(i < (int)(p3d_list.size() - 2)){
|
|
Interval<Instant> up_interval2;
|
|
up_interval2.start = start_time;
|
|
Instant end2 = start_time;
|
|
end2.ReadFrom(start_time.ToDouble() + elev_list[0][0].w_t);
|
|
up_interval2.end = end2;
|
|
|
|
up_interval2.lc = true;
|
|
up_interval2.rc = false;
|
|
UPoint3D* unit = new UPoint3D(up_interval2, p2, p2);
|
|
mp3d->Add(*unit);
|
|
delete unit;
|
|
start_time = end2;
|
|
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
generate indoor moving objects with restored paths, loading from files
|
|
|
|
*/
|
|
|
|
void IndoorNav::AddUnitToMO_Elevator_New2(MPoint3D* mp3d,
|
|
vector<Point3D>& p3d_list,
|
|
Instant& start_time, Instant& st,
|
|
vector< vector<Elevator> >& elev_list, int index,
|
|
Line3D* l_room, int build_id, GenMO* genmo)
|
|
{
|
|
assert(p3d_list.size() >= 2 && elev_list[0].size() >= 2);
|
|
////////////get the time for waiting///////////////////////////////////
|
|
double relative_start = start_time.ToDouble() - st.ToDouble();
|
|
/////////////////////////////////////////////////////////////////////////
|
|
///////////////////find which elevator///////////////////////////////////
|
|
///////////// different elevators (different heights)2 or 3 levels///////
|
|
///////////////// have different cycle time/////////////////////////////
|
|
/////////////////////////////////////////////////////////////////////////
|
|
float h1 = p3d_list[0].GetZ();
|
|
float h2 = p3d_list[ p3d_list.size() - 1].GetZ();
|
|
Point test_p(true, p3d_list[0].GetX(), p3d_list[0].GetY());
|
|
int elev_index = -1;
|
|
for(unsigned int i = 0;i < elev_list.size();i++){
|
|
if(test_p.Inside(elev_list[i][0].el_rect)){
|
|
elev_index = i;
|
|
break;
|
|
}
|
|
}
|
|
assert(elev_index >= 0);
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
double cycle_time =
|
|
elev_list[elev_index][elev_list[elev_index].size() - 1].t2 -
|
|
elev_list[elev_index][elev_list[elev_index].size() - 1].t1;
|
|
|
|
while(relative_start > cycle_time){
|
|
relative_start -= cycle_time;
|
|
}
|
|
|
|
Instant t = start_time;
|
|
t.ReadFrom(relative_start + st.ToDouble());
|
|
|
|
double wait_time = 0.0;
|
|
|
|
bool found = false;
|
|
|
|
for(unsigned int i = 0;i < elev_list.size();i++){
|
|
for(unsigned int j = 0;j < elev_list[i].size();j++){
|
|
if(AlmostEqual(h1, elev_list[i][j].h) &&
|
|
test_p.Inside(elev_list[i][j].el_rect)){ //point inside rectangle
|
|
if(h1 < h2){ //check t2
|
|
|
|
if(elev_list[i][j].t2 > relative_start){
|
|
|
|
wait_time = elev_list[i][j].t2 - relative_start;
|
|
}else{
|
|
wait_time = elev_list[i][j].t2 + cycle_time - relative_start;
|
|
}
|
|
}else{//check t1
|
|
|
|
if(elev_list[i][j].t1 > relative_start){
|
|
|
|
wait_time = elev_list[i][j].t1 - relative_start;
|
|
}else{
|
|
wait_time = elev_list[i][j].t1 + cycle_time - relative_start;
|
|
}
|
|
}
|
|
found = true;
|
|
|
|
Instant temp = start_time;
|
|
temp.ReadFrom(start_time.ToDouble() + wait_time);
|
|
|
|
break;
|
|
}
|
|
}
|
|
if(found)break;
|
|
|
|
}
|
|
|
|
|
|
////////////////////unit for waiting/////////////////////////
|
|
if(wait_time > 0.0){
|
|
Interval<Instant> up_interval;
|
|
up_interval.start = start_time;
|
|
Instant end = start_time;
|
|
end.ReadFrom(start_time.ToDouble() + wait_time);
|
|
up_interval.end = end;
|
|
|
|
|
|
int64_t st = start_time.ToDouble()*86400000.0;
|
|
int64_t et = end.ToDouble()*86400000.0;
|
|
if(st != et){
|
|
|
|
up_interval.lc = true;
|
|
up_interval.rc = false;
|
|
Point3D p = p3d_list[0];
|
|
UPoint3D* unit = new UPoint3D(up_interval, p, p);
|
|
mp3d->Add(*unit);
|
|
delete unit;
|
|
|
|
/////////////////////////////////////////////
|
|
/////////genric units///////////////////////
|
|
/////////////////////////////////////////////
|
|
Point3D q;
|
|
l_room->Get(index, q);
|
|
int groom_tid = 0;
|
|
if(q.GetX() > 0 ) groom_tid = q.GetX();
|
|
else if(q.GetY() > 0) groom_tid = q.GetY();
|
|
else if(q.GetZ() > 0) groom_tid = q.GetZ();
|
|
else assert(false);
|
|
|
|
Tuple* groom_tuple = rel1->GetTuple(groom_tid, false);
|
|
GRoom* groom = (GRoom*)groom_tuple->GetAttribute(I_Room);
|
|
int groom_oid = ((CcInt*)groom_tuple->GetAttribute(I_OID))->GetIntval();
|
|
string type = ((CcString*)groom_tuple->GetAttribute(I_Type))->GetValue();
|
|
Rectangle<2> bbox = groom->BoundingBox();
|
|
groom_tuple->DeleteIfAllowed();
|
|
|
|
char buffer1[64];
|
|
sprintf(buffer1, "%d", groom_oid);
|
|
char buffer2[64];
|
|
sprintf(buffer2, "%d", build_id);
|
|
strcat(buffer2, buffer1);
|
|
|
|
int new_groom_oid;
|
|
sscanf(buffer2, "%d", &new_groom_oid);//////building id + room id///
|
|
// cout<<"ref oid "<<new_groom_oid<<endl;
|
|
|
|
|
|
GenLoc gloc1;
|
|
GenLoc gloc2;
|
|
if(GetRoomEnum(type) == OR || GetRoomEnum(type) == BR ||
|
|
GetRoomEnum(type) == CO || GetRoomEnum(type) == ST){
|
|
Loc loc_1(p.GetX() - bbox.MinD(0), p.GetY() - bbox.MinD(1));
|
|
Loc loc_2(p.GetX() - bbox.MinD(0), p.GetY() - bbox.MinD(1));
|
|
|
|
gloc1.SetValue(new_groom_oid, loc_1);
|
|
gloc2.SetValue(new_groom_oid, loc_2);
|
|
}else if(GetRoomEnum(type) == EL){
|
|
//move in an elevator,we record the height
|
|
|
|
// Loc loc_1(p.GetZ(), -1.0);
|
|
// Loc loc_2(p.GetZ(), -1.0);
|
|
|
|
Loc loc_1(p.GetZ(), UNDEFVAL);
|
|
Loc loc_2(p.GetZ(), UNDEFVAL);
|
|
|
|
gloc1.SetValue(new_groom_oid, loc_1);
|
|
gloc2.SetValue(new_groom_oid, loc_2);
|
|
}else{
|
|
cout<<"should not be here"<<endl;
|
|
assert(false);
|
|
}
|
|
UGenLoc* ugenloc =
|
|
new UGenLoc(up_interval, gloc1, gloc2, GetTM("Indoor"));
|
|
genmo->Add(*ugenloc);
|
|
delete ugenloc;
|
|
}
|
|
start_time = end;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
for(int i = 0;i < (int) p3d_list.size();i++){
|
|
if(i < (int)(p3d_list.size() - 1)){
|
|
Point3D p1 = p3d_list[i];
|
|
Point3D p2 = p3d_list[i + 1];
|
|
|
|
Interval<Instant> up_interval;
|
|
up_interval.start = start_time;
|
|
Instant end = start_time;
|
|
end.ReadFrom(start_time.ToDouble() + elev_list[0][0].m_t);
|
|
up_interval.end = end;
|
|
|
|
up_interval.lc = true;
|
|
up_interval.rc = false;
|
|
UPoint3D* unit = new UPoint3D(up_interval, p1, p2);
|
|
mp3d->Add(*unit);
|
|
delete unit;
|
|
start_time = end;
|
|
|
|
/////////////////////////////////////////////
|
|
/////////generic units///////////////////////
|
|
/////////////////////////////////////////////
|
|
////a point3d can be contained by maximum 3 grooms, so we use point3d//
|
|
////////to record tuple id /////////////////
|
|
// int groom_tid = GetRef_RoomTid(index + i, l_room);
|
|
// cout<<"AddUnitToMO_Elevator_New2"<<endl;
|
|
// cout<<"p1 "<<p1<<" p2 "<<p2<<endl;
|
|
int groom_tid = GetRef_RoomTid(index + i, l_room, true);
|
|
|
|
Tuple* groom_tuple = rel1->GetTuple(groom_tid, false);
|
|
GRoom* groom = (GRoom*)groom_tuple->GetAttribute(I_Room);
|
|
int groom_oid =
|
|
((CcInt*)groom_tuple->GetAttribute(I_OID))->GetIntval();
|
|
string type =
|
|
((CcString*)groom_tuple->GetAttribute(I_Type))->GetValue();
|
|
Rectangle<2> bbox = groom->BoundingBox();
|
|
groom_tuple->DeleteIfAllowed();
|
|
|
|
char buffer1[64];
|
|
sprintf(buffer1, "%d", groom_oid);
|
|
char buffer2[64];
|
|
sprintf(buffer2, "%d", build_id);
|
|
strcat(buffer2, buffer1);
|
|
|
|
int new_groom_oid;
|
|
sscanf(buffer2, "%d", &new_groom_oid);//////building id + room id///
|
|
// cout<<"ref oid "<<new_groom_oid<<endl;
|
|
|
|
|
|
GenLoc gloc1;
|
|
GenLoc gloc2;
|
|
if(GetRoomEnum(type) == OR || GetRoomEnum(type) == BR ||
|
|
GetRoomEnum(type) == CO || GetRoomEnum(type) == ST){
|
|
Loc loc_1(p1.GetX() - bbox.MinD(0), p1.GetY() - bbox.MinD(1));
|
|
Loc loc_2(p2.GetX() - bbox.MinD(0), p2.GetY() - bbox.MinD(1));
|
|
|
|
gloc1.SetValue(new_groom_oid, loc_1);
|
|
gloc2.SetValue(new_groom_oid, loc_2);
|
|
}else if(GetRoomEnum(type) == EL){
|
|
//move in an elevator,we record the height
|
|
// Loc loc_1(p1.GetZ(), -1.0);
|
|
// Loc loc_2(p2.GetZ(), -1.0);
|
|
|
|
Loc loc_1(p1.GetZ(), UNDEFVAL);
|
|
Loc loc_2(p2.GetZ(), UNDEFVAL);
|
|
|
|
gloc1.SetValue(new_groom_oid, loc_1);
|
|
gloc2.SetValue(new_groom_oid, loc_2);
|
|
}else{
|
|
cout<<"should not be here"<<endl;
|
|
assert(false);
|
|
}
|
|
UGenLoc* ugenloc =
|
|
new UGenLoc(up_interval, gloc1, gloc2, GetTM("Indoor"));
|
|
genmo->Add(*ugenloc);
|
|
delete ugenloc;
|
|
|
|
|
|
if(i < (int)(p3d_list.size() - 2)){
|
|
Interval<Instant> up_interval2;
|
|
up_interval2.start = start_time;
|
|
Instant end2 = start_time;
|
|
end2.ReadFrom(start_time.ToDouble() + elev_list[0][0].w_t);
|
|
up_interval2.end = end2;
|
|
|
|
up_interval2.lc = true;
|
|
up_interval2.rc = false;
|
|
UPoint3D* unit = new UPoint3D(up_interval2, p2, p2);
|
|
mp3d->Add(*unit);
|
|
delete unit;
|
|
start_time = end2;
|
|
|
|
/////////////////////////////////////////////
|
|
/////////genric units///////////////////////
|
|
/////////////////////////////////////////////
|
|
GenLoc gloc1;
|
|
GenLoc gloc2;
|
|
if(GetRoomEnum(type) == OR || GetRoomEnum(type) == BR ||
|
|
GetRoomEnum(type) == CO || GetRoomEnum(type) == ST){
|
|
Loc loc_1(p2.GetX() - bbox.MinD(0), p2.GetY() - bbox.MinD(1));
|
|
Loc loc_2(p2.GetX() - bbox.MinD(0), p2.GetY() - bbox.MinD(1));
|
|
|
|
gloc1.SetValue(new_groom_oid, loc_1);
|
|
gloc2.SetValue(new_groom_oid, loc_2);
|
|
}else if(GetRoomEnum(type) == EL){
|
|
//move in an elevator,we record the height
|
|
|
|
// Loc loc_1(p2.GetZ(), -1.0);
|
|
// Loc loc_2(p2.GetZ(), -1.0);
|
|
|
|
Loc loc_1(p2.GetZ(), UNDEFVAL);
|
|
Loc loc_2(p2.GetZ(), UNDEFVAL);
|
|
|
|
gloc1.SetValue(new_groom_oid, loc_1);
|
|
gloc2.SetValue(new_groom_oid, loc_2);
|
|
}else{
|
|
cout<<"should not be here"<<endl;
|
|
assert(false);
|
|
}
|
|
UGenLoc* ugenloc =
|
|
new UGenLoc(up_interval2, gloc1, gloc2, GetTM("Indoor"));
|
|
genmo->Add(*ugenloc);
|
|
delete ugenloc;
|
|
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
a special trip from the building entrance to an office room
|
|
the building has more than one elevators
|
|
|
|
*/
|
|
void IndoorNav::GenerateMO2_New_Start(IndoorGraph* ig, BTree* btree,
|
|
R_Tree<3,TupleId>* rtree, int num,
|
|
Periods* peri, bool convert, unsigned int num_elev)
|
|
{
|
|
// cout<<"several elevators "<<endl;
|
|
|
|
GenerateIP1(num*2);
|
|
|
|
//////////////////get the building entrance position///////////////////////
|
|
vector<GenLoc> doorloc_list;
|
|
vector<int> door_tid_list;
|
|
GetDoorLoc(ig, btree, doorloc_list, door_tid_list);
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
IndoorNav* indoor_nav = new IndoorNav(ig);
|
|
|
|
Interval<Instant> periods;
|
|
if(peri->GetNoComponents() == 0){
|
|
cout<<"not correct time periods"<<endl;
|
|
assert(false);
|
|
}
|
|
peri->Get(0, periods);
|
|
|
|
double speed = GetMinimumDoorWidth();
|
|
|
|
vector< vector<Elevator> > elev_list;
|
|
|
|
InitializeElevator_New(periods, elev_list, speed);
|
|
|
|
int count = 0;
|
|
for(unsigned int i = 0;i < genloc_list.size();i++){
|
|
if(i < genloc_list.size() - 1){
|
|
///////////////////to building entrance///////////////////
|
|
// GenLoc loc1 = genloc_list[i];
|
|
// int door_index = i % doorloc_list.size();
|
|
// GenLoc loc2 = doorloc_list[door_index];
|
|
|
|
//////////////////from building entrance///////////////////////
|
|
GenLoc loc2 = genloc_list[i];
|
|
int door_index = i % doorloc_list.size();
|
|
GenLoc loc1 = doorloc_list[door_index];
|
|
|
|
if(loc1.GetOid() == loc2.GetOid()) continue;
|
|
|
|
cout<<"loc1 "<<loc1<<" loc2 "<<loc2<<endl;
|
|
|
|
indoor_nav->ShortestPath_Length_Start(&loc1, &loc2, rel1, btree,
|
|
door_tid_list[door_index]);
|
|
|
|
// indoor_nav->ShortestPath_Length_End(&loc1, &loc2, rel1, btree,
|
|
// door_tid_list[door_index]);
|
|
|
|
|
|
// cout<<indoor_nav->path_list[count].Length()<<endl;
|
|
//////////////////////////////////////////////////////////////////
|
|
Instant start_time = periods.start;
|
|
|
|
//in several minutes: 60 seconds for 12 persons
|
|
start_time.ReadFrom(periods.start.ToDouble() +
|
|
(GetRandom() % (num*5))/(24.0*60.0*60.0));
|
|
|
|
Line3D* l3d = &indoor_nav->path_list[count];
|
|
// l3d->Print();
|
|
if(l3d->Length() > 0.0){
|
|
MPoint3D* mp3d = new MPoint3D(0);
|
|
mp3d->StartBulkLoad();
|
|
for(int j = 0;j < l3d->Size();j++){
|
|
if(j < l3d->Size() - 1){
|
|
Point3D p1, p2;
|
|
l3d->Get(j, p1);
|
|
l3d->Get(j + 1, p2);
|
|
///////////////process the movement in an elevator
|
|
if(AlmostEqual(p1.GetX(), p2.GetX()) &&
|
|
AlmostEqual(p1.GetY(), p2.GetY()) &&
|
|
(elev_list.size() > 0 && elev_list[0].size() > 1)){
|
|
|
|
float delta_h = fabs(elev_list[0][1].h - elev_list[0][0].h);
|
|
if(AlmostEqual(delta_h, p1.Distance(p2))){
|
|
vector<Point3D> p3d_list;
|
|
p3d_list.push_back(p1);
|
|
p3d_list.push_back(p2);
|
|
int k = j + 1;
|
|
for(;k < l3d->Size();k++){
|
|
if(k < l3d->Size() - 1){
|
|
Point3D q1, q2;
|
|
l3d->Get(k, q1);
|
|
l3d->Get(k + 1, q2);
|
|
|
|
if(AlmostEqual(q1.GetX(), q2.GetX()) &&
|
|
AlmostEqual(q1.GetY(), q2.GetY())){//elevator
|
|
p3d_list.push_back(q2);
|
|
}else
|
|
break;
|
|
}
|
|
}
|
|
k--;
|
|
j = k;
|
|
|
|
AddUnitToMO_Elevator_New(mp3d, p3d_list, start_time,
|
|
periods.start, elev_list);
|
|
}
|
|
}else
|
|
AddUnitToMO(mp3d, p1, p2, start_time, speed);
|
|
}
|
|
}
|
|
mp3d->EndBulkLoad();
|
|
mo_list.push_back(*mp3d);
|
|
entrance_index.push_back(door_index + 1);//maps to tuple id
|
|
///////////////////////////////////////////////////////////////////
|
|
if(convert)
|
|
ToGenLoc(mp3d, rtree);
|
|
mp3d->DeleteIfAllowed();
|
|
count++;
|
|
}
|
|
if(count == num)break;
|
|
|
|
}
|
|
}
|
|
|
|
delete indoor_nav;
|
|
}
|
|
|
|
|
|
/*
|
|
a special trip to the building entrance the building has more than one elevators
|
|
|
|
*/
|
|
void IndoorNav::GenerateMO2_New_End(IndoorGraph* ig, BTree* btree,
|
|
R_Tree<3,TupleId>* rtree, int num,
|
|
Periods* peri, bool convert, unsigned int num_elev)
|
|
{
|
|
|
|
GenerateIP1(num*2);
|
|
|
|
//////////////////get the building entrance position///////////////////////
|
|
vector<GenLoc> doorloc_list;
|
|
vector<int> door_tid_list;
|
|
GetDoorLoc(ig, btree, doorloc_list, door_tid_list);
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
IndoorNav* indoor_nav = new IndoorNav(ig);
|
|
|
|
Interval<Instant> periods;
|
|
if(peri->GetNoComponents() == 0){
|
|
cout<<"not correct time periods"<<endl;
|
|
assert(false);
|
|
}
|
|
peri->Get(0, periods);
|
|
|
|
double speed = GetMinimumDoorWidth();
|
|
|
|
vector< vector<Elevator> > elev_list;
|
|
|
|
InitializeElevator_New(periods, elev_list, speed);
|
|
|
|
int count = 0;
|
|
for(unsigned int i = 0;i < genloc_list.size();i++){
|
|
if(i < genloc_list.size() - 1){
|
|
///////////////////to building entrance///////////////////
|
|
GenLoc loc1 = genloc_list[i];
|
|
int door_index = i % doorloc_list.size();
|
|
GenLoc loc2 = doorloc_list[door_index];
|
|
|
|
if(loc1.GetOid() == loc2.GetOid()) continue;
|
|
|
|
cout<<"loc1 "<<loc1<<" loc2 "<<loc2<<endl;
|
|
|
|
indoor_nav->ShortestPath_Length_End(&loc1, &loc2, rel1, btree,
|
|
door_tid_list[door_index]);
|
|
|
|
// cout<<indoor_nav->path_list[count].Length()<<endl;
|
|
//////////////////////////////////////////////////////////////////
|
|
Instant start_time = periods.start;
|
|
|
|
//in several minutes: 60 seconds for 12 persons
|
|
start_time.ReadFrom(periods.start.ToDouble() +
|
|
(GetRandom() % (num*5))/(24.0*60.0*60.0));
|
|
|
|
Line3D* l3d = &indoor_nav->path_list[count];
|
|
// l3d->Print();
|
|
if(l3d->Length() > 0.0){
|
|
MPoint3D* mp3d = new MPoint3D(0);
|
|
mp3d->StartBulkLoad();
|
|
for(int j = 0;j < l3d->Size();j++){
|
|
if(j < l3d->Size() - 1){
|
|
Point3D p1, p2;
|
|
l3d->Get(j, p1);
|
|
l3d->Get(j + 1, p2);
|
|
///////////////process the movement in an elevator
|
|
if(AlmostEqual(p1.GetX(), p2.GetX()) &&
|
|
AlmostEqual(p1.GetY(), p2.GetY()) &&
|
|
(elev_list.size() > 0 && elev_list[0].size() > 1)){
|
|
|
|
float delta_h = fabs(elev_list[0][1].h - elev_list[0][0].h);
|
|
if(AlmostEqual(delta_h, p1.Distance(p2))){
|
|
vector<Point3D> p3d_list;
|
|
p3d_list.push_back(p1);
|
|
p3d_list.push_back(p2);
|
|
int k = j + 1;
|
|
for(;k < l3d->Size();k++){
|
|
if(k < l3d->Size() - 1){
|
|
Point3D q1, q2;
|
|
l3d->Get(k, q1);
|
|
l3d->Get(k + 1, q2);
|
|
|
|
if(AlmostEqual(q1.GetX(), q2.GetX()) &&
|
|
AlmostEqual(q1.GetY(), q2.GetY())){//elevator
|
|
p3d_list.push_back(q2);
|
|
}else
|
|
break;
|
|
}
|
|
}
|
|
k--;
|
|
j = k;
|
|
|
|
AddUnitToMO_Elevator_New(mp3d, p3d_list, start_time,
|
|
periods.start, elev_list);
|
|
}
|
|
}else
|
|
AddUnitToMO(mp3d, p1, p2, start_time, speed);
|
|
}
|
|
}
|
|
mp3d->EndBulkLoad();
|
|
mo_list.push_back(*mp3d);
|
|
entrance_index.push_back(door_index + 1);//maps to tuple id
|
|
///////////////////////////////////////////////////////////////////
|
|
if(convert)
|
|
ToGenLoc(mp3d, rtree);
|
|
mp3d->DeleteIfAllowed();
|
|
count++;
|
|
}
|
|
if(count == num)break;
|
|
|
|
}
|
|
}
|
|
|
|
delete indoor_nav;
|
|
}
|
|
|
|
/*
|
|
a special trip from the building entrance.
|
|
the building has more than one elevators
|
|
the reference room id is set by building id + room id
|
|
|
|
*/
|
|
void IndoorNav::GenerateMO3_New_Start(IndoorGraph* ig, BTree* btree,
|
|
R_Tree<3,TupleId>* rtree,
|
|
Instant& start_time, int build_id, int entrance_index,
|
|
MPoint3D* mp3d, GenMO* genmo, Periods* peri,
|
|
unsigned int num_elev)
|
|
{
|
|
|
|
// GenerateIP1(1);
|
|
GenerateIP3(1);
|
|
//////////////////get the building entrance position///////////////////////
|
|
vector<GenLoc> doorloc_list;
|
|
vector<int> door_tid_list;
|
|
GetDoorLoc(ig, btree, doorloc_list, door_tid_list);
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
Interval<Instant> periods;
|
|
if(peri->GetNoComponents() == 0){
|
|
cout<<"not correct time periods"<<endl;
|
|
assert(false);
|
|
}
|
|
peri->Get(0, periods);
|
|
|
|
double speed = GetMinimumDoorWidth();
|
|
|
|
vector< vector<Elevator> > elev_list;
|
|
|
|
InitializeElevator_New(periods, elev_list, speed);
|
|
|
|
int num = 1;
|
|
int count = 0;
|
|
for(unsigned int i = 0;i < genloc_list.size();i++){
|
|
//////////////////from building entrance///////////////////////
|
|
GenLoc loc2 = genloc_list[i];
|
|
int door_index = i % doorloc_list.size();
|
|
GenLoc loc1 = doorloc_list[door_index];
|
|
|
|
// cout<<"loc1 "<<loc1<<" loc2 "<<loc2<<endl;
|
|
|
|
bool find_path = false;
|
|
#ifdef INDOOR_PATH
|
|
int path_oid = GetIndooPathID(entrance_index, loc2.GetOid(), true);
|
|
map<int, Line3D>::iterator iter = indoor_paths_list.find(path_oid);
|
|
if(iter != indoor_paths_list.end()){
|
|
ShortestPath_Length_Start2(&loc1, &loc2, rel1, btree,
|
|
door_tid_list[door_index],
|
|
entrance_index);
|
|
find_path = true;
|
|
}else{
|
|
ShortestPath_Length_Start(&loc1, &loc2, rel1, btree,
|
|
door_tid_list[door_index]);
|
|
}
|
|
#else
|
|
|
|
ShortestPath_Length_Start(&loc1, &loc2, rel1, btree,
|
|
door_tid_list[door_index]);
|
|
|
|
#endif
|
|
|
|
Line3D* l3d = &path_list[count];
|
|
|
|
|
|
if(l3d->Length() > 0.0){
|
|
Line3D* l_room = NULL;
|
|
#ifdef INDOOR_PATH
|
|
if(find_path){
|
|
l_room = &rooms_id_list[count];
|
|
assert(l3d->Size() == l_room->Size());
|
|
}
|
|
#endif
|
|
|
|
mp3d->StartBulkLoad();
|
|
for(int j = 0;j < l3d->Size();j++){
|
|
if(j < l3d->Size() - 1){
|
|
Point3D p1, p2;
|
|
l3d->Get(j, p1);
|
|
l3d->Get(j + 1, p2);
|
|
///////////////process the movement in an elevator
|
|
if(AlmostEqual(p1.GetX(), p2.GetX()) &&
|
|
AlmostEqual(p1.GetY(), p2.GetY()) &&
|
|
(elev_list.size() > 0 && elev_list[0].size() > 1)){
|
|
|
|
float delta_h = fabs(elev_list[0][1].h - elev_list[0][0].h);
|
|
if(AlmostEqual(delta_h, p1.Distance(p2))){
|
|
int start_pos = j;
|
|
vector<Point3D> p3d_list;
|
|
p3d_list.push_back(p1);
|
|
p3d_list.push_back(p2);
|
|
int k = j + 1;
|
|
for(;k < l3d->Size();k++){
|
|
if(k < l3d->Size() - 1){
|
|
Point3D q1, q2;
|
|
l3d->Get(k, q1);
|
|
l3d->Get(k + 1, q2);
|
|
|
|
if(AlmostEqual(q1.GetX(), q2.GetX()) &&
|
|
AlmostEqual(q1.GetY(), q2.GetY())){//elevator
|
|
p3d_list.push_back(q2);
|
|
}else
|
|
break;
|
|
}
|
|
}
|
|
k--;
|
|
j = k;
|
|
|
|
#ifdef INDOOR_PATH
|
|
if(find_path){
|
|
AddUnitToMO_Elevator_New2(mp3d, p3d_list, start_time,
|
|
periods.start, elev_list,start_pos, l_room, build_id, genmo);
|
|
}else{
|
|
AddUnitToMO_Elevator_New(mp3d, p3d_list, start_time,
|
|
periods.start, elev_list);
|
|
}
|
|
#else
|
|
AddUnitToMO_Elevator_New(mp3d, p3d_list, start_time,
|
|
periods.start, elev_list);
|
|
#endif
|
|
|
|
}
|
|
}else
|
|
|
|
#ifdef INDOOR_PATH
|
|
if(find_path){
|
|
AddUnitToMO2(mp3d, p1, p2, start_time, speed,
|
|
j, l_room, build_id, genmo);
|
|
}else{
|
|
AddUnitToMO(mp3d, p1, p2, start_time, speed);
|
|
}
|
|
#else
|
|
AddUnitToMO(mp3d, p1, p2, start_time, speed);
|
|
#endif
|
|
|
|
}
|
|
}
|
|
mp3d->EndBulkLoad();
|
|
count++;
|
|
///////////////////////////////////////////////////////////////////
|
|
#ifdef INDOOR_PATH
|
|
if(find_path){
|
|
|
|
}else{
|
|
ToGenLoc2(mp3d, rtree, build_id, genmo);
|
|
}
|
|
#else
|
|
ToGenLoc2(mp3d, rtree, build_id, genmo);
|
|
|
|
#endif
|
|
|
|
}
|
|
if(count == num)break;
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
a special trip to the building entrance
|
|
the building has more than one elevators
|
|
the reference room id is set by building id + room id
|
|
|
|
*/
|
|
void IndoorNav::GenerateMO3_New_End(IndoorGraph* ig, BTree* btree,
|
|
R_Tree<3,TupleId>* rtree,
|
|
Instant& start_time, int build_id, int entrance_index,
|
|
MPoint3D* mp3d, GenMO* genmo, Periods* peri,
|
|
unsigned int num_elev)
|
|
{
|
|
// GenerateIP1(1);
|
|
GenerateIP3(1);
|
|
//////////////////get the building entrance position///////////////////////
|
|
vector<GenLoc> doorloc_list;
|
|
vector<int> door_tid_list;
|
|
GetDoorLoc(ig, btree, doorloc_list, door_tid_list);
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
Interval<Instant> periods;
|
|
if(peri->GetNoComponents() == 0){
|
|
cout<<"not correct time periods"<<endl;
|
|
assert(false);
|
|
}
|
|
peri->Get(0, periods);
|
|
|
|
double speed = GetMinimumDoorWidth();
|
|
|
|
vector< vector<Elevator> > elev_list;
|
|
|
|
InitializeElevator_New(periods, elev_list, speed);
|
|
|
|
int num = 1;
|
|
int count = 0;
|
|
for(unsigned int i = 0;i < genloc_list.size();i++){
|
|
///////////////////to building entrance///////////////////
|
|
GenLoc loc1 = genloc_list[i];
|
|
int door_index = i % doorloc_list.size();
|
|
GenLoc loc2 = doorloc_list[door_index];
|
|
|
|
// cout<<"loc1 "<<loc1<<" loc2 "<<loc2<<endl;
|
|
|
|
bool find_path = false;
|
|
#ifdef INDOOR_PATH
|
|
int path_oid = GetIndooPathID(entrance_index, loc1.GetOid(), true);
|
|
|
|
map<int, Line3D>::iterator iter = indoor_paths_list.find(path_oid);
|
|
if(iter != indoor_paths_list.end()){
|
|
ShortestPath_Length_End2(&loc1, &loc2, rel1, btree,
|
|
door_tid_list[door_index],
|
|
entrance_index);
|
|
find_path = true;
|
|
}else{
|
|
ShortestPath_Length_End(&loc1, &loc2, rel1, btree,
|
|
door_tid_list[door_index]);
|
|
}
|
|
#else
|
|
ShortestPath_Length_End(&loc1, &loc2, rel1, btree,
|
|
door_tid_list[door_index]);
|
|
#endif
|
|
|
|
Line3D* l3d = &path_list[count];
|
|
|
|
if(l3d->Length() > 0.0){
|
|
Line3D* l_room = NULL;
|
|
#ifdef INDOOR_PATH
|
|
if(find_path){
|
|
l_room = &rooms_id_list[count];
|
|
assert(l3d->Size() == l_room->Size());
|
|
}
|
|
#endif
|
|
|
|
mp3d->StartBulkLoad();
|
|
for(int j = 0;j < l3d->Size();j++){
|
|
if(j < l3d->Size() - 1){
|
|
Point3D p1, p2;
|
|
l3d->Get(j, p1);
|
|
l3d->Get(j + 1, p2);
|
|
///////////////process the movement in an elevator
|
|
if(AlmostEqual(p1.GetX(), p2.GetX()) &&
|
|
AlmostEqual(p1.GetY(), p2.GetY()) &&
|
|
(elev_list.size() > 0 && elev_list[0].size() > 1)){
|
|
|
|
float delta_h = fabs(elev_list[0][1].h - elev_list[0][0].h);
|
|
if(AlmostEqual(delta_h, p1.Distance(p2))){
|
|
int start_pos = j;
|
|
vector<Point3D> p3d_list;
|
|
p3d_list.push_back(p1);
|
|
p3d_list.push_back(p2);
|
|
int k = j + 1;
|
|
for(;k < l3d->Size();k++){
|
|
if(k < l3d->Size() - 1){
|
|
Point3D q1, q2;
|
|
l3d->Get(k, q1);
|
|
l3d->Get(k + 1, q2);
|
|
|
|
if(AlmostEqual(q1.GetX(), q2.GetX()) &&
|
|
AlmostEqual(q1.GetY(), q2.GetY())){//elevator
|
|
p3d_list.push_back(q2);
|
|
}else
|
|
break;
|
|
}
|
|
}
|
|
k--;
|
|
j = k;
|
|
|
|
|
|
|
|
#ifdef INDOOR_PATH
|
|
if(find_path){
|
|
AddUnitToMO_Elevator_New2(mp3d, p3d_list, start_time,
|
|
periods.start, elev_list, start_pos, l_room, build_id, genmo);
|
|
}else{
|
|
AddUnitToMO_Elevator_New(mp3d, p3d_list, start_time,
|
|
periods.start, elev_list);
|
|
}
|
|
|
|
#else
|
|
AddUnitToMO_Elevator_New(mp3d, p3d_list, start_time,
|
|
periods.start, elev_list);
|
|
#endif
|
|
|
|
}
|
|
}else
|
|
|
|
#ifdef INDOOR_PATH
|
|
if(find_path){
|
|
AddUnitToMO2(mp3d, p1, p2, start_time, speed,
|
|
j, l_room, build_id, genmo);
|
|
}else{
|
|
AddUnitToMO(mp3d, p1, p2, start_time, speed);
|
|
}
|
|
#else
|
|
AddUnitToMO(mp3d, p1, p2, start_time, speed);
|
|
#endif
|
|
|
|
}
|
|
}
|
|
mp3d->EndBulkLoad();
|
|
count++;
|
|
/////////////////////////////////////////////////////////////////
|
|
#ifdef INDOOR_PATH
|
|
if(find_path){
|
|
|
|
}else{
|
|
ToGenLoc2(mp3d, rtree, build_id, genmo);
|
|
}
|
|
#else
|
|
ToGenLoc2(mp3d, rtree, build_id, genmo);
|
|
#endif
|
|
|
|
}
|
|
if(count == num)break;
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
almost the same as GenerateMO3 New End but giving the start location
|
|
|
|
*/
|
|
void IndoorNav::GenerateMO3_New_EndExt(IndoorGraph* ig, BTree* btree,
|
|
R_Tree<3,TupleId>* rtree,
|
|
Instant& start_time, int build_id, int entrance_index,
|
|
MPoint3D* mp3d, GenMO* genmo, Periods* peri,
|
|
unsigned int num_elev, GenLoc gloc_input)
|
|
{
|
|
|
|
//////////////////get the building entrance position///////////////////////
|
|
vector<GenLoc> doorloc_list;
|
|
vector<int> door_tid_list;
|
|
GetDoorLoc(ig, btree, doorloc_list, door_tid_list);
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
Interval<Instant> periods;
|
|
if(peri->GetNoComponents() == 0){
|
|
cout<<"not correct time periods"<<endl;
|
|
assert(false);
|
|
}
|
|
peri->Get(0, periods);
|
|
|
|
double speed = GetMinimumDoorWidth();
|
|
|
|
vector< vector<Elevator> > elev_list;
|
|
|
|
InitializeElevator_New(periods, elev_list, speed);
|
|
|
|
int num = 1;
|
|
int count = 0;
|
|
genloc_list.push_back(gloc_input);
|
|
for(unsigned int i = 0;i < genloc_list.size();i++){
|
|
///////////////////to building entrance///////////////////
|
|
GenLoc loc1 = genloc_list[i];
|
|
int door_index = i % doorloc_list.size();
|
|
GenLoc loc2 = doorloc_list[door_index];
|
|
|
|
// cout<<"loc1 "<<loc1<<" loc2 "<<loc2<<endl;
|
|
|
|
bool find_path = false;
|
|
#ifdef INDOOR_PATH
|
|
int path_oid = GetIndooPathID(entrance_index, loc1.GetOid(), true);
|
|
|
|
map<int, Line3D>::iterator iter = indoor_paths_list.find(path_oid);
|
|
if(iter != indoor_paths_list.end()){
|
|
ShortestPath_Length_End2(&loc1, &loc2, rel1, btree,
|
|
door_tid_list[door_index],
|
|
entrance_index);
|
|
find_path = true;
|
|
}else{
|
|
ShortestPath_Length_End(&loc1, &loc2, rel1, btree,
|
|
door_tid_list[door_index]);
|
|
}
|
|
#else
|
|
ShortestPath_Length_End(&loc1, &loc2, rel1, btree,
|
|
door_tid_list[door_index]);
|
|
#endif
|
|
|
|
Line3D* l3d = &path_list[count];
|
|
|
|
if(l3d->Length() > 0.0){
|
|
Line3D* l_room = NULL;
|
|
#ifdef INDOOR_PATH
|
|
if(find_path){
|
|
l_room = &rooms_id_list[count];
|
|
assert(l3d->Size() == l_room->Size());
|
|
}
|
|
#endif
|
|
|
|
mp3d->StartBulkLoad();
|
|
for(int j = 0;j < l3d->Size();j++){
|
|
if(j < l3d->Size() - 1){
|
|
Point3D p1, p2;
|
|
l3d->Get(j, p1);
|
|
l3d->Get(j + 1, p2);
|
|
///////////////process the movement in an elevator
|
|
if(AlmostEqual(p1.GetX(), p2.GetX()) &&
|
|
AlmostEqual(p1.GetY(), p2.GetY()) &&
|
|
(elev_list.size() > 0 && elev_list[0].size() > 1)){
|
|
|
|
float delta_h = fabs(elev_list[0][1].h - elev_list[0][0].h);
|
|
if(AlmostEqual(delta_h, p1.Distance(p2))){
|
|
int start_pos = j;
|
|
vector<Point3D> p3d_list;
|
|
p3d_list.push_back(p1);
|
|
p3d_list.push_back(p2);
|
|
int k = j + 1;
|
|
for(;k < l3d->Size();k++){
|
|
if(k < l3d->Size() - 1){
|
|
Point3D q1, q2;
|
|
l3d->Get(k, q1);
|
|
l3d->Get(k + 1, q2);
|
|
|
|
if(AlmostEqual(q1.GetX(), q2.GetX()) &&
|
|
AlmostEqual(q1.GetY(), q2.GetY())){//elevator
|
|
p3d_list.push_back(q2);
|
|
}else
|
|
break;
|
|
}
|
|
}
|
|
k--;
|
|
j = k;
|
|
|
|
|
|
|
|
#ifdef INDOOR_PATH
|
|
if(find_path){
|
|
AddUnitToMO_Elevator_New2(mp3d, p3d_list, start_time,
|
|
periods.start, elev_list, start_pos, l_room, build_id, genmo);
|
|
}else{
|
|
AddUnitToMO_Elevator_New(mp3d, p3d_list, start_time,
|
|
periods.start, elev_list);
|
|
}
|
|
|
|
#else
|
|
AddUnitToMO_Elevator_New(mp3d, p3d_list, start_time,
|
|
periods.start, elev_list);
|
|
#endif
|
|
|
|
}
|
|
}else
|
|
|
|
#ifdef INDOOR_PATH
|
|
if(find_path){
|
|
AddUnitToMO2(mp3d, p1, p2, start_time, speed,
|
|
j, l_room, build_id, genmo);
|
|
}else{
|
|
AddUnitToMO(mp3d, p1, p2, start_time, speed);
|
|
}
|
|
#else
|
|
AddUnitToMO(mp3d, p1, p2, start_time, speed);
|
|
#endif
|
|
|
|
}
|
|
}
|
|
mp3d->EndBulkLoad();
|
|
count++;
|
|
/////////////////////////////////////////////////////////////////
|
|
#ifdef INDOOR_PATH
|
|
if(find_path){
|
|
|
|
}else{
|
|
ToGenLoc2(mp3d, rtree, build_id, genmo);
|
|
}
|
|
#else
|
|
ToGenLoc2(mp3d, rtree, build_id, genmo);
|
|
#endif
|
|
|
|
}
|
|
if(count == num)break;
|
|
}
|
|
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
/*
|
|
get the minimum width of door
|
|
|
|
*/
|
|
float IndoorNav::GetMinimumDoorWidth()
|
|
{
|
|
float door_width = numeric_limits<float>::max(); //the speed for person
|
|
for(int i = 1;i <= rel1->GetNoTuples();i++){
|
|
Tuple* groom_tuple = rel1->GetTuple(i, false);
|
|
Line* door = (Line*)groom_tuple->GetAttribute(I_Door);
|
|
for(int j = 0;j < door->Size();j++){
|
|
HalfSegment hs;
|
|
door->Get(j, hs);
|
|
if(!hs.IsLeftDomPoint())continue;
|
|
if(hs.Length() < door_width)door_width = hs.Length();
|
|
}
|
|
groom_tuple->DeleteIfAllowed();
|
|
}
|
|
return door_width;
|
|
}
|
|
|
|
/*
|
|
add units to the result moving objects
|
|
|
|
*/
|
|
void IndoorNav::AddUnitToMO(MPoint3D* mp3d, Point3D& p1, Point3D& p2,
|
|
Instant& start_time, double speed)
|
|
{
|
|
const double dist_delta = 0.01;
|
|
|
|
double d = p1.Distance(p2);
|
|
if(d < speed || AlmostEqual(d, speed)){//staircase movement
|
|
|
|
Interval<Instant> up_interval;
|
|
up_interval.start = start_time;
|
|
Instant end = start_time;
|
|
// end.ReadFrom(start_time.ToDouble() + d/(24.0*60.0*60.0*speed));
|
|
//////////set 0.75---1, a little slow /////////////////////////
|
|
end.ReadFrom(start_time.ToDouble() + 0.75/(24.0*60.0*60.0));
|
|
up_interval.end = end;
|
|
|
|
up_interval.lc = true;
|
|
up_interval.rc = false;
|
|
|
|
UPoint3D* unit = new UPoint3D(up_interval, p1, p2);
|
|
mp3d->Add(*unit);
|
|
delete unit;
|
|
start_time = end;
|
|
}else if(AlmostEqual(p1.GetX(), p2.GetX()) &&
|
|
AlmostEqual(p1.GetY(), p2.GetY())){
|
|
//for the movement inside an elevator
|
|
// if split, it can not find a groom
|
|
|
|
Interval<Instant> up_interval;
|
|
up_interval.start = start_time;
|
|
Instant end = start_time;
|
|
end.ReadFrom(start_time.ToDouble() + d/(24.0*60.0*60.0*speed));
|
|
up_interval.end = end;
|
|
|
|
up_interval.lc = true;
|
|
up_interval.rc = false;
|
|
|
|
UPoint3D* unit = new UPoint3D(up_interval, p1, p2);
|
|
mp3d->Add(*unit);
|
|
delete unit;
|
|
start_time = end;
|
|
|
|
}else{
|
|
int no = (int)floor(d/speed);
|
|
|
|
// double x = (p2.GetX() - p1.GetX())/no;
|
|
// double y = (p2.GetY() - p1.GetY())/no;
|
|
// double z = (p2.GetZ() - p1.GetZ())/no;
|
|
double x = (p2.GetX() - p1.GetX())/(no + 1);
|
|
double y = (p2.GetY() - p1.GetY())/(no + 1);
|
|
double z = (p2.GetZ() - p1.GetZ())/(no + 1);
|
|
|
|
for(int i = 0;i < no ;i++){
|
|
Point3D q1(true, p1.GetX() + i*x, p1.GetY() + i*y, p1.GetZ() + i*z);
|
|
Point3D q2(true, p1.GetX() + (i+1)*x,
|
|
p1.GetY() + (i+1)*y, p1.GetZ() + (i+1)*z);
|
|
double dist = q1.Distance(q2);
|
|
|
|
Interval<Instant> up_interval;
|
|
up_interval.start = start_time;
|
|
Instant end = start_time;
|
|
end.ReadFrom(start_time.ToDouble() + dist/(24.0*60.0*60.0*speed));
|
|
up_interval.end = end;
|
|
|
|
up_interval.lc = true;
|
|
up_interval.rc = false;
|
|
|
|
UPoint3D* unit = new UPoint3D(up_interval, q1,q2);
|
|
mp3d->Add(*unit);
|
|
delete unit;
|
|
start_time = end;
|
|
// cout<<"q1 "<<q1<<" q2 "<<q2<<endl;
|
|
if(i == no - 1){
|
|
Point3D q3 = q2;
|
|
Point3D q4 = p2;
|
|
double dist = q3.Distance(q4);
|
|
if(dist < dist_delta)continue;
|
|
|
|
up_interval.start = start_time;
|
|
Instant end = start_time;
|
|
end.ReadFrom(start_time.ToDouble() + dist/(24.0*60.0*60.0*speed));
|
|
up_interval.end = end;
|
|
up_interval.lc = true;
|
|
up_interval.rc = false;
|
|
start_time = up_interval.end;
|
|
// cout<<"start "<<up_interval.start<<" end "<<up_interval.end<<endl;
|
|
// cout<<"t: "<<up_interval<<"p0: "<<q3<<"p1: "<<q4<<endl;
|
|
|
|
UPoint3D* unit = new UPoint3D(up_interval, q3, q4);
|
|
|
|
mp3d->Add(*unit);
|
|
delete unit;
|
|
start_time = end;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
get the groom tid from the storing data
|
|
|
|
*/
|
|
int IndoorNav::GetRef_RoomTid(int index, Line3D* l, bool E)
|
|
{
|
|
Point3D q1, q2;
|
|
l->Get(index, q1);
|
|
l->Get(index + 1, q2);
|
|
|
|
// cout<<"E "<<E<<" "<<q1<<" "<<q2<<endl;
|
|
|
|
vector<int> tid_list1;
|
|
if(q1.GetX() > 0) tid_list1.push_back(q1.GetX());
|
|
if(q1.GetY() > 0) tid_list1.push_back(q1.GetY());
|
|
if(q1.GetZ() > 0) tid_list1.push_back(q1.GetZ());
|
|
|
|
vector<int> tid_list2;
|
|
if(q2.GetX() > 0) tid_list2.push_back(q2.GetX());
|
|
if(q2.GetY() > 0) tid_list2.push_back(q2.GetY());
|
|
if(q2.GetZ() > 0) tid_list2.push_back(q2.GetZ());
|
|
|
|
// int tid = -1;
|
|
// bool found = false;
|
|
// for(unsigned int i = 0;i < tid_list1.size();i++){
|
|
// for(unsigned int j = 0;j < tid_list2.size();j++){
|
|
// if(tid_list1[i] == tid_list2[j]){
|
|
// tid = tid_list1[i];
|
|
// found = true;
|
|
// }
|
|
// }
|
|
// }
|
|
//
|
|
// ///////////vertical movement in elevator////////////
|
|
// if(found == false) tid = tid_list1[0];
|
|
//
|
|
// assert(tid > 0);
|
|
//
|
|
// return tid;
|
|
|
|
vector<int> tid_list;
|
|
int tid = -1;
|
|
bool found = false;
|
|
for(unsigned int i = 0;i < tid_list1.size();i++){
|
|
for(unsigned int j = 0;j < tid_list2.size();j++){
|
|
if(tid_list1[i] == tid_list2[j]){
|
|
tid_list.push_back(tid_list1[i]);
|
|
found = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
///////////vertical movement in elevator////////////
|
|
if(found == false){
|
|
// tid = tid_list1[0];
|
|
for(unsigned int i = 0;i < tid_list1.size();i++){
|
|
Tuple* groom_tuple = rel1->GetTuple(tid_list1[i], false);
|
|
string type =
|
|
((CcString*)groom_tuple->GetAttribute(I_Type))->GetValue();
|
|
groom_tuple->DeleteIfAllowed();
|
|
|
|
// if(type.compare("EL") == 0){
|
|
// tid = tid_list1[i];
|
|
// break;
|
|
// }
|
|
|
|
if(E){
|
|
if(type.compare("EL") == 0){
|
|
tid = tid_list1[i];
|
|
break;
|
|
}
|
|
}else{
|
|
if(type.compare("EL") != 0){
|
|
tid = tid_list1[i];
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
}else{
|
|
if(tid_list.size() == 1) tid = tid_list[0];
|
|
else{
|
|
for(unsigned int i = 0;i < tid_list.size();i++){
|
|
Tuple* groom_tuple = rel1->GetTuple(tid_list[i], false);
|
|
string type =
|
|
((CcString*)groom_tuple->GetAttribute(I_Type))->GetValue();
|
|
groom_tuple->DeleteIfAllowed();
|
|
// cout<<" type "<<type<<" E "<<E<<" i "<<i<<endl;
|
|
if(E){
|
|
if(type.compare("EL") == 0){
|
|
tid = tid_list[i];
|
|
break;
|
|
}
|
|
}else{///////no elevator
|
|
//ignore elevator when OR,CO are included
|
|
if(type.compare("EL") != 0){
|
|
tid = tid_list[i];
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
assert(tid > 0);
|
|
|
|
return tid;
|
|
|
|
|
|
}
|
|
|
|
/*
|
|
add units to the result moving objects where the generic moving objects is
|
|
created at the same time
|
|
|
|
*/
|
|
void IndoorNav::AddUnitToMO2(MPoint3D* mp3d, Point3D& p1, Point3D& p2,
|
|
Instant& start_time, double speed, int index,
|
|
Line3D* l_room, int build_id, GenMO* genmo)
|
|
{
|
|
|
|
// cout<<"p1 "<<p1<<" "<<p2<<endl;
|
|
double d = p1.Distance(p2);
|
|
|
|
// int groom_tid = GetRef_RoomTid(index, l_room);
|
|
int groom_tid = GetRef_RoomTid(index, l_room, false);
|
|
Tuple* groom_tuple = rel1->GetTuple(groom_tid, false);
|
|
GRoom* groom = (GRoom*)groom_tuple->GetAttribute(I_Room);
|
|
int groom_oid = ((CcInt*)groom_tuple->GetAttribute(I_OID))->GetIntval();
|
|
string type = ((CcString*)groom_tuple->GetAttribute(I_Type))->GetValue();
|
|
Rectangle<2> bbox = groom->BoundingBox();
|
|
groom_tuple->DeleteIfAllowed();
|
|
|
|
char buffer1[64];
|
|
sprintf(buffer1, "%d", groom_oid);
|
|
char buffer2[64];
|
|
sprintf(buffer2, "%d", build_id);
|
|
strcat(buffer2, buffer1);
|
|
|
|
int new_groom_oid;
|
|
sscanf(buffer2, "%d", &new_groom_oid);//building id + room id//
|
|
|
|
// cout<<"ref oid "<<new_groom_oid<<endl;
|
|
|
|
if(d < speed || AlmostEqual(d, speed)){//staircase movement
|
|
|
|
Interval<Instant> up_interval;
|
|
up_interval.start = start_time;
|
|
Instant end = start_time;
|
|
// end.ReadFrom(start_time.ToDouble() + d/(24.0*60.0*60.0*speed));
|
|
//////////set 0.75---1, a little slow /////////////////////////
|
|
end.ReadFrom(start_time.ToDouble() + 0.75/(24.0*60.0*60.0));
|
|
up_interval.end = end;
|
|
|
|
up_interval.lc = true;
|
|
up_interval.rc = false;
|
|
|
|
UPoint3D* unit = new UPoint3D(up_interval, p1, p2);
|
|
mp3d->Add(*unit);
|
|
delete unit;
|
|
start_time = end;
|
|
////////////////////////////////////////////
|
|
////////////generic units //////////////////
|
|
///////////////////////////////////////////
|
|
GenLoc gloc1;
|
|
GenLoc gloc2;
|
|
if(GetRoomEnum(type) == OR || GetRoomEnum(type) == BR ||
|
|
GetRoomEnum(type) == CO || GetRoomEnum(type) == ST){
|
|
Loc loc_1(p1.GetX() - bbox.MinD(0), p1.GetY() - bbox.MinD(1));
|
|
Loc loc_2(p2.GetX() - bbox.MinD(0), p2.GetY() - bbox.MinD(1));
|
|
|
|
gloc1.SetValue(new_groom_oid, loc_1);
|
|
gloc2.SetValue(new_groom_oid, loc_2);
|
|
}else if(GetRoomEnum(type) == EL){
|
|
//move in an elevator,we record the height
|
|
|
|
// Loc loc_1(p1.GetZ(), -1.0);
|
|
// Loc loc_2(p2.GetZ(), -1.0);
|
|
|
|
Loc loc_1(p1.GetZ(), UNDEFVAL);
|
|
Loc loc_2(p2.GetZ(), UNDEFVAL);
|
|
|
|
|
|
gloc1.SetValue(new_groom_oid, loc_1);
|
|
gloc2.SetValue(new_groom_oid, loc_2);
|
|
}else{
|
|
cout<<"should not be here"<<endl;
|
|
assert(false);
|
|
}
|
|
UGenLoc* ugenloc = new UGenLoc(up_interval, gloc1, gloc2, GetTM("Indoor"));
|
|
genmo->Add(*ugenloc);
|
|
delete ugenloc;
|
|
|
|
}else if(AlmostEqual(p1.GetX(), p2.GetX()) &&
|
|
AlmostEqual(p1.GetY(), p2.GetY())){
|
|
//for the movement inside an elevator
|
|
// if split, it can not find a groom
|
|
|
|
Interval<Instant> up_interval;
|
|
up_interval.start = start_time;
|
|
Instant end = start_time;
|
|
end.ReadFrom(start_time.ToDouble() + d/(24.0*60.0*60.0*speed));
|
|
up_interval.end = end;
|
|
|
|
up_interval.lc = true;
|
|
up_interval.rc = false;
|
|
|
|
UPoint3D* unit = new UPoint3D(up_interval, p1, p2);
|
|
mp3d->Add(*unit);
|
|
delete unit;
|
|
start_time = end;
|
|
|
|
////////////////////////////////////////////
|
|
////////////generic units //////////////////
|
|
///////////////////////////////////////////
|
|
GenLoc gloc1;
|
|
GenLoc gloc2;
|
|
if(GetRoomEnum(type) == OR || GetRoomEnum(type) == BR ||
|
|
GetRoomEnum(type) == CO || GetRoomEnum(type) == ST){
|
|
Loc loc_1(p1.GetX() - bbox.MinD(0), p1.GetY() - bbox.MinD(1));
|
|
Loc loc_2(p2.GetX() - bbox.MinD(0), p2.GetY() - bbox.MinD(1));
|
|
|
|
gloc1.SetValue(new_groom_oid, loc_1);
|
|
gloc2.SetValue(new_groom_oid, loc_2);
|
|
}else if(GetRoomEnum(type) == EL){//move in an elevator,we record the height
|
|
|
|
// Loc loc_1(p1.GetZ(), -1.0);
|
|
// Loc loc_2(p2.GetZ(), -1.0);
|
|
|
|
Loc loc_1(p1.GetZ(), UNDEFVAL);
|
|
Loc loc_2(p2.GetZ(), UNDEFVAL);
|
|
|
|
gloc1.SetValue(new_groom_oid, loc_1);
|
|
gloc2.SetValue(new_groom_oid, loc_2);
|
|
}else{
|
|
cout<<"should not be here"<<endl;
|
|
assert(false);
|
|
}
|
|
UGenLoc* ugenloc = new UGenLoc(up_interval, gloc1, gloc2, GetTM("Indoor"));
|
|
genmo->Add(*ugenloc);
|
|
delete ugenloc;
|
|
|
|
}else{
|
|
|
|
if(GetRoomEnum(type) == BR || GetRoomEnum(type) == ST ||
|
|
GetRoomEnum(type) == EL)
|
|
CreateIUnits1(p1, p2, type, bbox, speed, start_time, mp3d, genmo,
|
|
new_groom_oid);
|
|
else
|
|
CreateIUnits2(p1, p2, type, bbox, speed, start_time, mp3d, genmo,
|
|
new_groom_oid);//merge movements
|
|
|
|
// CreateIUnits1(p1, p2, type, bbox, speed, start_time, mp3d, genmo,
|
|
// new_groom_oid);//no merging for general units
|
|
|
|
}//end for else
|
|
}
|
|
|
|
/*
|
|
no merge units
|
|
|
|
*/
|
|
void IndoorNav::CreateIUnits1(Point3D& p1, Point3D& p2, string type,
|
|
Rectangle<2> bbox, double speed,
|
|
Instant& start_time, MPoint3D* mp3d,
|
|
GenMO* genmo, int new_groom_oid)
|
|
{
|
|
double d = p1.Distance(p2);
|
|
const double dist_delta = 0.01;
|
|
int no = (int)floor(d/speed);
|
|
/* double x = (p2.GetX() - p1.GetX())/no;
|
|
double y = (p2.GetY() - p1.GetY())/no;
|
|
double z = (p2.GetZ() - p1.GetZ())/no; */
|
|
|
|
double x = (p2.GetX() - p1.GetX())/(no + 1);
|
|
double y = (p2.GetY() - p1.GetY())/(no + 1);
|
|
double z = (p2.GetZ() - p1.GetZ())/(no + 1);
|
|
|
|
for(int i = 0;i < no ;i++){
|
|
Point3D q1(true, p1.GetX() + i*x, p1.GetY() + i*y, p1.GetZ() + i*z);
|
|
Point3D q2(true, p1.GetX() + (i+1)*x,
|
|
p1.GetY() + (i+1)*y, p1.GetZ() + (i+1)*z);
|
|
double dist = q1.Distance(q2);
|
|
|
|
Interval<Instant> up_interval;
|
|
up_interval.start = start_time;
|
|
Instant end = start_time;
|
|
end.ReadFrom(start_time.ToDouble() + dist/(24.0*60.0*60.0*speed));
|
|
up_interval.end = end;
|
|
|
|
up_interval.lc = true;
|
|
up_interval.rc = false;
|
|
|
|
UPoint3D* unit = new UPoint3D(up_interval, q1,q2);
|
|
mp3d->Add(*unit);
|
|
delete unit;
|
|
start_time = end;
|
|
|
|
////////////////////////////////////////////
|
|
////////////generic units //////////////////
|
|
///////////////////////////////////////////
|
|
GenLoc gloc1;
|
|
GenLoc gloc2;
|
|
if(GetRoomEnum(type) == BR || GetRoomEnum(type) == ST ||
|
|
GetRoomEnum(type) == OR || GetRoomEnum(type) == CO){//for debug,keep
|
|
Loc loc_1(q1.GetX() - bbox.MinD(0), q1.GetY() - bbox.MinD(1));
|
|
Loc loc_2(q2.GetX() - bbox.MinD(0), q2.GetY() - bbox.MinD(1));
|
|
|
|
gloc1.SetValue(new_groom_oid, loc_1);
|
|
gloc2.SetValue(new_groom_oid, loc_2);
|
|
}else if(GetRoomEnum(type) == EL){
|
|
//move in an elevator,we record the height
|
|
|
|
// Loc loc_1(q1.GetZ(), -1.0);
|
|
// Loc loc_2(q2.GetZ(), -1.0);
|
|
|
|
Loc loc_1(q1.GetZ(), UNDEFVAL);
|
|
Loc loc_2(q2.GetZ(), UNDEFVAL);
|
|
|
|
gloc1.SetValue(new_groom_oid, loc_1);
|
|
gloc2.SetValue(new_groom_oid, loc_2);
|
|
}else{
|
|
cout<<"should not be here"<<endl;
|
|
assert(false);
|
|
}
|
|
UGenLoc* ugenloc =
|
|
new UGenLoc(up_interval, gloc1, gloc2, GetTM("Indoor"));
|
|
genmo->Add(*ugenloc);
|
|
delete ugenloc;
|
|
///////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
if(i == no - 1){
|
|
Point3D q3 = q2;
|
|
Point3D q4 = p2;
|
|
double dist = q3.Distance(q4);
|
|
if(dist < dist_delta) continue;
|
|
|
|
up_interval.start = start_time;
|
|
Instant end = start_time;
|
|
end.ReadFrom(start_time.ToDouble() + dist/(24.0*60.0*60.0*speed));
|
|
up_interval.end = end;
|
|
up_interval.lc = true;
|
|
up_interval.rc = false;
|
|
start_time = up_interval.end;
|
|
// cout<<"start "<<up_interval.start<<" end "<<up_interval.end<<endl;
|
|
// cout<<"t: "<<up_interval<<"p0: "<<q3<<"p1: "<<q4<<endl;
|
|
|
|
UPoint3D* unit = new UPoint3D(up_interval, q3, q4);
|
|
|
|
mp3d->Add(*unit);
|
|
delete unit;
|
|
start_time = end;
|
|
|
|
////////////////////////////////////////////
|
|
////////////generic units //////////////////
|
|
///////////////////////////////////////////
|
|
GenLoc gloc1;
|
|
GenLoc gloc2;
|
|
if(GetRoomEnum(type) == BR ||GetRoomEnum(type) == ST ||
|
|
GetRoomEnum(type) == OR || GetRoomEnum(type) == CO){//keep for debug
|
|
Loc loc_1(q3.GetX() - bbox.MinD(0), q3.GetY() - bbox.MinD(1));
|
|
Loc loc_2(q4.GetX() - bbox.MinD(0), q4.GetY() - bbox.MinD(1));
|
|
|
|
gloc1.SetValue(new_groom_oid, loc_1);
|
|
gloc2.SetValue(new_groom_oid, loc_2);
|
|
}else if(GetRoomEnum(type) == EL){
|
|
//move in an elevator,we record the height
|
|
|
|
// Loc loc_1(q3.GetZ(), -1.0);
|
|
// Loc loc_2(q4.GetZ(), -1.0);
|
|
|
|
Loc loc_1(q3.GetZ(), UNDEFVAL);
|
|
Loc loc_2(q4.GetZ(), UNDEFVAL);
|
|
|
|
gloc1.SetValue(new_groom_oid, loc_1);
|
|
gloc2.SetValue(new_groom_oid, loc_2);
|
|
}else{
|
|
cout<<"should not be here"<<endl;
|
|
assert(false);
|
|
}
|
|
UGenLoc* ugenloc =
|
|
new UGenLoc(up_interval, gloc1, gloc2, GetTM("Indoor"));
|
|
genmo->Add(*ugenloc);
|
|
delete ugenloc;
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
merge general units for OR and CO
|
|
|
|
*/
|
|
void IndoorNav::CreateIUnits2(Point3D& p1, Point3D& p2, string type,
|
|
Rectangle<2> bbox, double speed,
|
|
Instant& start_time, MPoint3D* mp3d,
|
|
GenMO* genmo, int new_groom_oid)
|
|
{
|
|
const double dist_delta = 0.01;
|
|
double d = p1.Distance(p2);
|
|
|
|
int no = (int)floor(d/speed);
|
|
|
|
double x = (p2.GetX() - p1.GetX())/(no + 1);
|
|
double y = (p2.GetY() - p1.GetY())/(no + 1);
|
|
double z = (p2.GetZ() - p1.GetZ())/(no + 1);
|
|
|
|
Instant old_time = start_time;
|
|
|
|
assert(GetRoomEnum(type) == OR || GetRoomEnum(type) == CO);
|
|
for(int i = 0;i < no ;i++){
|
|
Point3D q1(true, p1.GetX() + i*x, p1.GetY() + i*y, p1.GetZ() + i*z);
|
|
Point3D q2(true, p1.GetX() + (i+1)*x,
|
|
p1.GetY() + (i+1)*y, p1.GetZ() + (i+1)*z);
|
|
double dist = q1.Distance(q2);
|
|
|
|
Interval<Instant> up_interval;
|
|
up_interval.start = start_time;
|
|
Instant end = start_time;
|
|
end.ReadFrom(start_time.ToDouble() + dist/(24.0*60.0*60.0*speed));
|
|
up_interval.end = end;
|
|
|
|
up_interval.lc = true;
|
|
up_interval.rc = false;
|
|
|
|
UPoint3D* unit = new UPoint3D(up_interval, q1,q2);
|
|
mp3d->Add(*unit);
|
|
delete unit;
|
|
start_time = end;
|
|
///////////////////////////////////////////////////////////////////
|
|
if(i == no - 1){
|
|
Point3D q3 = q2;
|
|
Point3D q4 = p2;
|
|
double dist = q3.Distance(q4);
|
|
if(dist < dist_delta) continue;
|
|
|
|
up_interval.start = start_time;
|
|
Instant end = start_time;
|
|
end.ReadFrom(start_time.ToDouble() + dist/(24.0*60.0*60.0*speed));
|
|
up_interval.end = end;
|
|
up_interval.lc = true;
|
|
up_interval.rc = false;
|
|
start_time = up_interval.end;
|
|
// cout<<"start "<<up_interval.start<<" end "<<up_interval.end<<endl;
|
|
// cout<<"t: "<<up_interval<<"p0: "<<q3<<"p1: "<<q4<<endl;
|
|
|
|
UPoint3D* unit = new UPoint3D(up_interval, q3, q4);
|
|
|
|
mp3d->Add(*unit);
|
|
delete unit;
|
|
start_time = end;
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////
|
|
////////////generic units //////////////////
|
|
///////////////////////////////////////////
|
|
GenLoc gloc1;
|
|
GenLoc gloc2;
|
|
Loc loc_1(p1.GetX() - bbox.MinD(0), p1.GetY() - bbox.MinD(1));
|
|
Loc loc_2(p2.GetX() - bbox.MinD(0), p2.GetY() - bbox.MinD(1));
|
|
|
|
gloc1.SetValue(new_groom_oid, loc_1);
|
|
gloc2.SetValue(new_groom_oid, loc_2);
|
|
|
|
Interval<Instant> up_interval;
|
|
up_interval.start = old_time;
|
|
up_interval.end = start_time;
|
|
|
|
up_interval.lc = true;
|
|
up_interval.rc = false;
|
|
|
|
UGenLoc* ugenloc =
|
|
new UGenLoc(up_interval, gloc1, gloc2, GetTM("Indoor"));
|
|
genmo->Add(*ugenloc);
|
|
delete ugenloc;
|
|
}
|
|
|
|
/*
|
|
convert a 3d point to genloc
|
|
|
|
*/
|
|
void IndoorNav::ToGenLoc(MPoint3D* mp3d, R_Tree<3,TupleId>* rtree)
|
|
{
|
|
GenMO* genmo = new GenMO(0);
|
|
genmo->StartBulkLoad();
|
|
|
|
for(int i = 0;i < mp3d->GetNoComponents();i++){
|
|
UPoint3D unit;
|
|
mp3d->Get(i, unit);
|
|
GenLoc loc1, loc2;
|
|
Get_GenLoc(unit.p0, unit.p1, loc1, loc2, rtree);
|
|
|
|
UGenLoc* ugenloc = new UGenLoc(unit.timeInterval, loc1, loc2,
|
|
GetTM("Indoor"));
|
|
genmo->Add(*ugenloc);
|
|
delete ugenloc;
|
|
}
|
|
genmo->EndBulkLoad();
|
|
genmo_list.push_back(*genmo);
|
|
genmo->DeleteIfAllowed();
|
|
}
|
|
|
|
|
|
/*
|
|
convert a 3d point to genloc. the reference room id is changed or added the
|
|
building id.finally the reference id is: buildingid + roomid
|
|
|
|
*/
|
|
void IndoorNav::ToGenLoc2(MPoint3D* mp3d,
|
|
R_Tree<3,TupleId>* rtree, int build_id, GenMO* genmo)
|
|
{
|
|
// cout<<"ToGenLoc2 "<<endl;
|
|
for(int i = 0;i < mp3d->GetNoComponents();i++){
|
|
UPoint3D unit;
|
|
mp3d->Get(i, unit);
|
|
GenLoc loc1, loc2;
|
|
// Get_GenLoc(unit.p0, unit.p1, loc1, loc2, rtree);
|
|
|
|
///reset reference oid: building id + room id///
|
|
Get_GenLoc2(unit.p0, unit.p1, loc1, loc2, rtree, build_id);
|
|
|
|
UGenLoc* ugenloc = new UGenLoc(unit.timeInterval, loc1, loc2,
|
|
GetTM("Indoor"));
|
|
genmo->Add(*ugenloc);
|
|
delete ugenloc;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
the two genloc should have the same oid
|
|
|
|
*/
|
|
void IndoorNav::Get_GenLoc(Point3D p1, Point3D p2,
|
|
GenLoc& loc1, GenLoc& loc2, R_Tree<3,TupleId>* rtree)
|
|
{
|
|
SmiRecordId adr = rtree->RootRecordId();
|
|
|
|
vector<int> tid_list1;
|
|
vector<int> tid_list2;
|
|
DFTraverse(rtree, adr, p1, tid_list1);
|
|
DFTraverse(rtree, adr, p1, tid_list2);
|
|
|
|
// cout<<"p3d_1 "<<p1<<" p3d_2"<<p2<<endl;
|
|
|
|
assert(tid_list1.size() > 0);
|
|
assert(tid_list2.size() > 0);
|
|
|
|
int tid1, tid2;
|
|
bool found = false;
|
|
for(unsigned int i = 0;i < tid_list1.size();i++){
|
|
tid1 = tid_list1[i];
|
|
for(unsigned int j = 0;j < tid_list2.size();j++){
|
|
tid2 = tid_list2[j];
|
|
if(tid1 == tid2){
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
if(found) break;
|
|
}
|
|
|
|
/* if(tid1 != tid2){
|
|
cout<<"do not find the same groom for two locations"<<endl;
|
|
assert(false);
|
|
}*/
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
if(found){
|
|
|
|
Tuple* groom_tuple = rel1->GetTuple(tid1, false);
|
|
GRoom* groom = (GRoom*)groom_tuple->GetAttribute(I_Room);
|
|
string type = ((CcString*)groom_tuple->GetAttribute(I_Type))->GetValue();
|
|
int oid = ((CcInt*)groom_tuple->GetAttribute(I_OID))->GetIntval();
|
|
Rectangle<2> bbox = groom->BoundingBox();
|
|
groom_tuple->DeleteIfAllowed();
|
|
|
|
if(GetRoomEnum(type) == OR || GetRoomEnum(type) == BR ||
|
|
GetRoomEnum(type) == CO || GetRoomEnum(type) == ST){
|
|
Loc loc_1(p1.GetX() - bbox.MinD(0), p1.GetY() - bbox.MinD(1));
|
|
Loc loc_2(p2.GetX() - bbox.MinD(0), p2.GetY() - bbox.MinD(1));
|
|
|
|
loc1.SetValue(oid, loc_1);
|
|
loc2.SetValue(oid, loc_2);
|
|
}else if(GetRoomEnum(type) == EL){//move in an elevator,we record the height
|
|
// Loc loc_1(p1.GetZ(), -1);
|
|
// Loc loc_2(p2.GetZ(), -1);
|
|
|
|
Loc loc_1(p1.GetZ(), UNDEFVAL);
|
|
Loc loc_2(p2.GetZ(), UNDEFVAL);
|
|
|
|
loc1.SetValue(oid, loc_1);
|
|
loc2.SetValue(oid, loc_2);
|
|
}else{
|
|
cout<<"should not be here"<<endl;
|
|
assert(false);
|
|
}
|
|
}else{
|
|
unsigned int i = 0;
|
|
for(;i < tid_list1.size();i++){
|
|
tid1 = tid_list1[i];
|
|
Tuple* groom_tuple = rel1->GetTuple(tid1, false);
|
|
string type = ((CcString*)groom_tuple->GetAttribute(I_Type))->GetValue();
|
|
if(GetRoomEnum(type) == EL)break;
|
|
groom_tuple->DeleteIfAllowed();
|
|
}
|
|
assert(i < tid_list1.size());
|
|
Tuple* groom_tuple = rel1->GetTuple(tid1, false);
|
|
GRoom* groom = (GRoom*)groom_tuple->GetAttribute(I_Room);
|
|
string type = ((CcString*)groom_tuple->GetAttribute(I_Type))->GetValue();
|
|
int oid = ((CcInt*)groom_tuple->GetAttribute(I_OID))->GetIntval();
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
Rectangle<2> bbox = groom->BoundingBox();
|
|
groom_tuple->DeleteIfAllowed();
|
|
|
|
if(GetRoomEnum(type) == EL){
|
|
// cout<<"elevator2 "<<endl;
|
|
// Loc loc_1(p1.GetZ(), -1.0);
|
|
// Loc loc_2(p2.GetZ(), -1.0);
|
|
|
|
Loc loc_1(p1.GetZ(), UNDEFVAL);
|
|
Loc loc_2(p2.GetZ(), UNDEFVAL);
|
|
|
|
loc1.SetValue(oid, loc_1);
|
|
loc2.SetValue(oid, loc_2);
|
|
}else{
|
|
cout<<"should not be here"<<endl;
|
|
assert(false);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
/*
|
|
the two genlocs should have the same oid
|
|
the reference id is building id + room id
|
|
|
|
*/
|
|
void IndoorNav::Get_GenLoc2(Point3D p1, Point3D p2,
|
|
GenLoc& loc1, GenLoc& loc2,
|
|
R_Tree<3,TupleId>* rtree, int build_id)
|
|
{
|
|
|
|
SmiRecordId adr = rtree->RootRecordId();
|
|
|
|
vector<int> tid_list1;
|
|
vector<int> tid_list2;
|
|
DFTraverse(rtree, adr, p1, tid_list1);
|
|
DFTraverse(rtree, adr, p2, tid_list2);
|
|
|
|
// cout<<"p3d_1 "<<p1<<" p3d_2"<<p2<<endl;
|
|
|
|
assert(tid_list1.size() > 0);
|
|
assert(tid_list2.size() > 0);
|
|
|
|
//////////maximum 3 for the case of staircase entrance ///////////////
|
|
// cout<<tid_list1.size()<<" "<<tid_list2.size()<<endl;
|
|
|
|
int tid1, tid2;
|
|
bool found = false;
|
|
for(unsigned int i = 0;i < tid_list1.size();i++){
|
|
tid1 = tid_list1[i];
|
|
// cout<<"tid1 "<<tid1<<endl;
|
|
for(unsigned int j = 0;j < tid_list2.size();j++){
|
|
tid2 = tid_list2[j];
|
|
// cout<<"tid2 "<<tid2<<endl;
|
|
if(tid1 == tid2){
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
if(found) break;
|
|
}
|
|
|
|
// if(tid1 != tid2){
|
|
// cout<<"do not find the same groom for two locations"<<endl;
|
|
// assert(false);
|
|
// }
|
|
|
|
|
|
if(found){
|
|
/////////////////////////////////////////////////////////////////////////
|
|
|
|
Tuple* groom_tuple = rel1->GetTuple(tid1, false);
|
|
GRoom* groom = (GRoom*)groom_tuple->GetAttribute(I_Room);
|
|
string type = ((CcString*)groom_tuple->GetAttribute(I_Type))->GetValue();
|
|
int oid = ((CcInt*)groom_tuple->GetAttribute(I_OID))->GetIntval();
|
|
//////////////////////////////////////////////////////////////////////
|
|
//////////reset the oid by plus building id for the first six numbers/
|
|
/////////////////////////////////////////////////////////////////////
|
|
char buffer1[64];
|
|
sprintf(buffer1, "%d", oid);
|
|
char buffer2[64];
|
|
sprintf(buffer2, "%d", build_id);
|
|
|
|
strcat(buffer2, buffer1);
|
|
// cout<<"building id "<<build_id<< " old oid "<<oid<<endl;
|
|
int new_oid;
|
|
sscanf(buffer2, "%d", &new_oid);
|
|
// cout<<"new oid "<<new_oid<<endl;
|
|
oid = new_oid;//////////building id + room id///////////////
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////
|
|
Rectangle<2> bbox = groom->BoundingBox();
|
|
groom_tuple->DeleteIfAllowed();
|
|
|
|
if(GetRoomEnum(type) == OR || GetRoomEnum(type) == BR ||
|
|
GetRoomEnum(type) == CO || GetRoomEnum(type) == ST){
|
|
Loc loc_1(p1.GetX() - bbox.MinD(0), p1.GetY() - bbox.MinD(1));
|
|
Loc loc_2(p2.GetX() - bbox.MinD(0), p2.GetY() - bbox.MinD(1));
|
|
|
|
loc1.SetValue(oid, loc_1);
|
|
loc2.SetValue(oid, loc_2);
|
|
|
|
}else if(GetRoomEnum(type) == EL){//move in an elevator,we record the height
|
|
// cout<<"elevator1 "<<endl;
|
|
// Loc loc_1(p1.GetZ(), -1.0);
|
|
// Loc loc_2(p2.GetZ(), -1.0);
|
|
|
|
Loc loc_1(p1.GetZ(), UNDEFVAL);
|
|
Loc loc_2(p2.GetZ(), UNDEFVAL);
|
|
|
|
loc1.SetValue(oid, loc_1);
|
|
loc2.SetValue(oid, loc_2);
|
|
}else{
|
|
cout<<"should not be here"<<endl;
|
|
assert(false);
|
|
}
|
|
}else{//////////vertical movement in an elevator, at different levels
|
|
|
|
unsigned int i = 0;
|
|
for(;i < tid_list1.size();i++){
|
|
tid1 = tid_list1[i];
|
|
Tuple* groom_tuple = rel1->GetTuple(tid1, false);
|
|
string type = ((CcString*)groom_tuple->GetAttribute(I_Type))->GetValue();
|
|
if(GetRoomEnum(type) == EL) {
|
|
groom_tuple->DeleteIfAllowed();
|
|
break;
|
|
}
|
|
groom_tuple->DeleteIfAllowed();
|
|
}
|
|
assert(i < tid_list1.size());
|
|
Tuple* groom_tuple = rel1->GetTuple(tid1, false);
|
|
GRoom* groom = (GRoom*)groom_tuple->GetAttribute(I_Room);
|
|
string type = ((CcString*)groom_tuple->GetAttribute(I_Type))->GetValue();
|
|
int oid = ((CcInt*)groom_tuple->GetAttribute(I_OID))->GetIntval();
|
|
//////////////////////////////////////////////////////////////////////
|
|
//////////reset the oid by plus building id for the first six numbers/
|
|
/////////////////////////////////////////////////////////////////////
|
|
char buffer1[64];
|
|
sprintf(buffer1, "%d", oid);
|
|
char buffer2[64];
|
|
sprintf(buffer2, "%d", build_id);
|
|
|
|
strcat(buffer2, buffer1);
|
|
// cout<<"building id "<<build_id<< " old oid "<<oid<<endl;
|
|
int new_oid;
|
|
sscanf(buffer2, "%d", &new_oid);
|
|
// cout<<"new oid "<<new_oid<<endl;
|
|
oid = new_oid;//////////building id + room id///////////////
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////
|
|
Rectangle<2> bbox = groom->BoundingBox();
|
|
groom_tuple->DeleteIfAllowed();
|
|
|
|
if(GetRoomEnum(type) == EL){
|
|
// cout<<"elevator2 "<<endl;
|
|
// Loc loc_1(p1.GetZ(), -1.0);
|
|
// Loc loc_2(p2.GetZ(), -1.0);
|
|
|
|
Loc loc_1(p1.GetZ(), UNDEFVAL);
|
|
Loc loc_2(p2.GetZ(), UNDEFVAL);
|
|
|
|
loc1.SetValue(oid, loc_1);
|
|
loc2.SetValue(oid, loc_2);
|
|
}else{
|
|
cout<<"should not be here"<<endl;
|
|
assert(false);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
check whether a 3d box contains a 3d point
|
|
|
|
*/
|
|
bool BBoxContainPoint3D(Rectangle<3> bbox, Point3D& p)
|
|
{
|
|
assert(bbox.IsDefined());
|
|
assert(p.IsDefined());
|
|
if( (bbox.MinD(0) < p.GetX() || AlmostEqual(bbox.MinD(0), p.GetX())) &&
|
|
(bbox.MaxD(0) > p.GetX() || AlmostEqual(bbox.MaxD(0), p.GetX())) &&
|
|
(bbox.MinD(1) < p.GetY() || AlmostEqual(bbox.MinD(1), p.GetY())) &&
|
|
(bbox.MaxD(1) > p.GetY() || AlmostEqual(bbox.MaxD(1), p.GetY())) &&
|
|
(bbox.MinD(2) < p.GetZ() || AlmostEqual(bbox.MinD(2), p.GetZ())) &&
|
|
(bbox.MaxD(2) > p.GetZ() || AlmostEqual(bbox.MaxD(2), p.GetZ())) )
|
|
return true;
|
|
else
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
traverse the 3D rtree to find whether a groom contains the 3d point
|
|
|
|
*/
|
|
void IndoorNav::DFTraverse(R_Tree<3,TupleId>* rtree, SmiRecordId adr,
|
|
Point3D p, vector<int>& tid_list)
|
|
{
|
|
R_TreeNode<3,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<3,TupleId> e =
|
|
(R_TreeLeafEntry<3,TupleId>&)(*node)[j];
|
|
Tuple* groom_tuple = rel1->GetTuple(e.info,false);
|
|
GRoom* groom = (GRoom*)groom_tuple->GetAttribute(I_Room);
|
|
Rectangle<3> groom_box = groom->BoundingBox3D();
|
|
if(BBoxContainPoint3D(groom_box, p)){
|
|
// tid_list.push_back(e.info);
|
|
|
|
Region r(0);
|
|
groom->GetRegion(r);
|
|
Point q(true, p.GetX(), p.GetY());
|
|
if(q.Inside(r))tid_list.push_back(e.info);
|
|
}
|
|
|
|
groom_tuple->DeleteIfAllowed();
|
|
}else{
|
|
R_TreeInternalEntry<3> e =
|
|
(R_TreeInternalEntry<3>&)(*node)[j];
|
|
if(BBoxContainPoint3D(e.box, p)){
|
|
DFTraverse(rtree, e.pointer, p, tid_list);
|
|
}
|
|
}
|
|
}
|
|
delete node;
|
|
|
|
}
|
|
|
|
|
|
|
|
ostream& operator<<(ostream& o, const IPath_elem& elem)
|
|
{
|
|
o<<"tri_index "<< elem.tri_index<<" "
|
|
<<"realweight "<<elem.real_w<<" "
|
|
<<"weight "<<elem.weight<<endl;
|
|
return o;
|
|
}
|
|
|
|
/*
|
|
find a path from the building entrance to one office room
|
|
|
|
*/
|
|
void IndoorNav::ShortestPath_Length_Start(GenLoc* gloc1, GenLoc* gloc2,
|
|
Relation* rel, BTree* groom_btree,
|
|
int start_tid)
|
|
{
|
|
if(IsLocEqual(gloc1, gloc2, rel)){
|
|
cout<<"the two locations are equal to each other"<<endl;
|
|
Line3D* l3d = new Line3D(0);
|
|
path_list.push_back(*l3d);
|
|
l3d->DeleteIfAllowed();
|
|
return;
|
|
}
|
|
|
|
unsigned int groom_oid1 = gloc1->GetOid();
|
|
unsigned int groom_oid2 = gloc2->GetOid();
|
|
// cout<<"groom oid1 "<<groom_oid1<<" groom oid2 "<<groom_oid2<<endl;
|
|
if(groom_oid1 == groom_oid2){
|
|
PathInOneRoom(gloc1, gloc2, rel, groom_btree);
|
|
return;
|
|
}
|
|
|
|
Relation* node_rel = ig->GetNodeRel();
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
///////////////collect all doors in start room//////////////////////
|
|
////////////////////////////////////////////////////////////////////
|
|
BTree* btree = ig->GetBTree();
|
|
|
|
vector<int> tid_list1;
|
|
tid_list1.push_back(start_tid);
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
///////////////collect all doors in end room//////////////////////
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
CcInt* search_id2 = new CcInt(true, groom_oid2);
|
|
BTreeIterator* btree_iter2 = btree->ExactMatch(search_id2);
|
|
vector<int> tid_list2;
|
|
vector<Point3D> door_end;
|
|
while(btree_iter2->Next()){
|
|
Tuple* tuple = node_rel->GetTuple(btree_iter2->GetId(), false);
|
|
int door_tid = tuple->GetTupleId();
|
|
if(DeadDoor(door_tid, groom_oid2, groom_oid1, door_end) == false)
|
|
tid_list2.push_back(door_tid);
|
|
tuple->DeleteIfAllowed();
|
|
}
|
|
delete btree_iter2;
|
|
delete search_id2;
|
|
|
|
// cout<<"tid_list1 size "<<tid_list1.size()<<endl;
|
|
// cout<<"tid_list2 size "<<tid_list2.size()<<endl;
|
|
|
|
////////calculate once for the connection between start loc and its door////
|
|
vector<Line3D> start_door_path;
|
|
float start_h1 = INVALID_HEIGHT;
|
|
float start_h2 = INVALID_HEIGHT;
|
|
if(!ConnectEndLoc2(gloc1, rel, groom_btree, start_door_path,
|
|
start_h1, start_h2)){
|
|
cout<<"connect start location to doors error"<<endl;
|
|
Line3D* l3d = new Line3D(0);
|
|
path_list.push_back(*l3d);
|
|
l3d->DeleteIfAllowed();
|
|
return;
|
|
}
|
|
// cout<<start_h1<<" "<<start_h2<<endl;
|
|
|
|
assert(start_h1 > INVALID_HEIGHT && start_h2 > INVALID_HEIGHT);
|
|
|
|
float min_h1 = MIN(start_h1, start_h2);
|
|
float max_h1 = MAX(start_h1, start_h2);
|
|
|
|
// for(unsigned int i = 0;i < start_door_path.size();i++)
|
|
// path_list.push_back(start_door_path[i]);
|
|
//
|
|
// return;
|
|
|
|
|
|
//////////calculate once for the connection between end loc and its door////
|
|
vector<Line3D> end_door_path;
|
|
float end_h1 = INVALID_HEIGHT;
|
|
float end_h2 = INVALID_HEIGHT;
|
|
|
|
if(!ConnectEndLoc(gloc2, tid_list2, rel, groom_btree,
|
|
end_door_path, end_h1, end_h2)){
|
|
cout<<"connect end location to doors error"<<endl;
|
|
Line3D* l3d = new Line3D(0);
|
|
path_list.push_back(*l3d);
|
|
l3d->DeleteIfAllowed();
|
|
return;
|
|
}
|
|
|
|
// cout<<end_h1<<" "<<end_h2<<endl;
|
|
|
|
assert(end_h1 > INVALID_HEIGHT && end_h2 > INVALID_HEIGHT);
|
|
float min_h2 = MIN(end_h1, end_h2);
|
|
float max_h2 = MAX(end_h1, end_h2);
|
|
|
|
float min_h = MIN(min_h1, min_h2);
|
|
float max_h = MAX(max_h1, max_h2);
|
|
|
|
// cout<<"min h "<<min_h<<" max_h "<<max_h<<endl;
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
////////////////////for each possible door, search the path/////////////
|
|
////////////////////////////////////////////////////////////////////////
|
|
vector<Line3D> candidate_path;
|
|
double prune_dist = -1.0;
|
|
for(unsigned int i = 0;i < tid_list1.size();i++){
|
|
// cout<<"source door tid "<<tid_list1[i]<<endl;
|
|
Tuple* door_tuple1 = node_rel->GetTuple(tid_list1[i], false);
|
|
unsigned int gri1 =
|
|
((CcInt*)door_tuple1->GetAttribute(IndoorGraph::I_GROOM_OID1))->GetIntval();
|
|
|
|
assert(gri1 == groom_oid1);
|
|
|
|
for(unsigned int j = 0;j < tid_list2.size();j++){
|
|
// cout<<"dest door tid "<<tid_list2[j]<<endl;
|
|
Tuple* door_tuple2 = node_rel->GetTuple(tid_list2[j], false);
|
|
unsigned int gri2 =
|
|
((CcInt*)door_tuple2->GetAttribute(IndoorGraph::I_GROOM_OID1))->GetIntval();
|
|
|
|
assert(gri2 == groom_oid2);
|
|
|
|
IndoorShortestPath(tid_list1[i], tid_list2[j], candidate_path,
|
|
&start_door_path[i], &end_door_path[j],
|
|
prune_dist, min_h, max_h, -1);
|
|
door_tuple2->DeleteIfAllowed();
|
|
|
|
// cout<<candidate_path[candidate_path.size() - 1].Length()<<endl;
|
|
|
|
}
|
|
|
|
door_tuple1->DeleteIfAllowed();
|
|
}
|
|
|
|
|
|
///////////////////select the path with minimum length////////////////////
|
|
if(candidate_path.size() > 0){
|
|
double l = numeric_limits<double>::max();
|
|
int index = 0;
|
|
for(unsigned int i = 0; i < candidate_path.size();i++){
|
|
if(candidate_path[i].Size() > 0 && candidate_path[i].Length() < l){
|
|
l = candidate_path[i].Length();
|
|
index = i;
|
|
}
|
|
}
|
|
path_list.push_back(candidate_path[index]);
|
|
}else{
|
|
// cout<<"no path available"<<endl;
|
|
Line3D* l3d = new Line3D(0);
|
|
path_list.push_back(*l3d);
|
|
l3d->DeleteIfAllowed();
|
|
}
|
|
|
|
|
|
}
|
|
|
|
/*
|
|
find a path from the building entrance to one office room
|
|
where the path from building entrance to office room is already found
|
|
|
|
*/
|
|
void IndoorNav::ShortestPath_Length_Start2(GenLoc* gloc1, GenLoc* gloc2,
|
|
Relation* rel, BTree* groom_btree,
|
|
int start_tid, int entrance_id)
|
|
{
|
|
if(IsLocEqual(gloc1, gloc2, rel)){
|
|
cout<<"the two locations are equal to each other"<<endl;
|
|
Line3D* l3d = new Line3D(0);
|
|
path_list.push_back(*l3d);
|
|
l3d->DeleteIfAllowed();
|
|
return;
|
|
}
|
|
|
|
unsigned int groom_oid1 = gloc1->GetOid();
|
|
unsigned int groom_oid2 = gloc2->GetOid();
|
|
|
|
if(groom_oid1 == groom_oid2){
|
|
PathInOneRoom(gloc1, gloc2, rel, groom_btree);
|
|
return;
|
|
}
|
|
|
|
Relation* node_rel = ig->GetNodeRel();
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
///////////////collect all doors in start room//////////////////////
|
|
////////////////////////////////////////////////////////////////////
|
|
BTree* btree = ig->GetBTree();
|
|
|
|
vector<int> tid_list1;
|
|
tid_list1.push_back(start_tid);
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
///////////////collect all doors in end room//////////////////////
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
CcInt* search_id2 = new CcInt(true, groom_oid2);
|
|
BTreeIterator* btree_iter2 = btree->ExactMatch(search_id2);
|
|
vector<int> tid_list2;
|
|
vector<Point3D> door_end;
|
|
|
|
vector<int> door_tid_list;
|
|
while(btree_iter2->Next()){
|
|
Tuple* tuple = node_rel->GetTuple(btree_iter2->GetId(), false);
|
|
int door_tid = tuple->GetTupleId();
|
|
door_tid_list.push_back(door_tid);/////////all doors include dead doors
|
|
if(DeadDoor(door_tid, groom_oid2, groom_oid1, door_end) == false){
|
|
tid_list2.push_back(door_tid);
|
|
}else{
|
|
//////////do not consier such a connection///////////////
|
|
door_tid_list[door_tid_list.size() - 1] = 0;
|
|
}
|
|
tuple->DeleteIfAllowed();
|
|
}
|
|
delete btree_iter2;
|
|
delete search_id2;
|
|
|
|
////////calculate once for the connection between start loc and its door////
|
|
vector<Line3D> start_door_path;
|
|
float start_h1 = INVALID_HEIGHT;
|
|
float start_h2 = INVALID_HEIGHT;
|
|
if(!ConnectEndLoc2(gloc1, rel, groom_btree, start_door_path,
|
|
start_h1, start_h2)){
|
|
cout<<"connect start location to doors error"<<endl;
|
|
Line3D* l3d = new Line3D(0);
|
|
path_list.push_back(*l3d);
|
|
l3d->DeleteIfAllowed();
|
|
return;
|
|
}
|
|
// cout<<start_h1<<" "<<start_h2<<endl;
|
|
|
|
assert(start_h1 > INVALID_HEIGHT && start_h2 > INVALID_HEIGHT);
|
|
|
|
//////////calculate once for the connection between end loc and its door////
|
|
vector<Line3D> end_door_path;
|
|
float end_h1 = INVALID_HEIGHT;
|
|
float end_h2 = INVALID_HEIGHT;
|
|
|
|
if(!ConnectEndLoc(gloc2, tid_list2, rel, groom_btree,
|
|
end_door_path, end_h1, end_h2)){
|
|
cout<<"connect end location to doors error"<<endl;
|
|
Line3D* l3d = new Line3D(0);
|
|
path_list.push_back(*l3d);
|
|
l3d->DeleteIfAllowed();
|
|
return;
|
|
}
|
|
|
|
/* for(unsigned int i = 0;i < end_door_path.size();i++){
|
|
Point3D q;
|
|
end_door_path[i].Get(0, q);
|
|
cout<<"i "<<i<<q<<endl;
|
|
}*/
|
|
|
|
vector<Line3D> candidate_path;
|
|
vector<Line3D> rooms_oid; //store groom oid for point3d
|
|
int count = 0;
|
|
|
|
for(unsigned int i = 0;i < door_tid_list.size();i++){
|
|
if(door_tid_list[i] > 0){
|
|
int path_oid = GetIndooPathID2(entrance_id, groom_oid2,i, true);
|
|
map<int, Line3D>::iterator iter = indoor_paths_list.find(path_oid);
|
|
map<int, Line3D>::iterator iter_room = rooms_list.find(path_oid);
|
|
if(iter != indoor_paths_list.end() && iter_room != rooms_list.end()){
|
|
// cout<<path_oid<<" "<<iter->second.Length()<<endl;
|
|
|
|
Line3D* l3d = new Line3D(0);
|
|
l3d->StartBulkLoad();
|
|
|
|
Line3D* l_room = new Line3D(0);
|
|
l_room->StartBulkLoad();
|
|
assert(iter->second.Size() == iter_room->second.Size());
|
|
for(int j = 0;j < iter->second.Size();j++){
|
|
Point3D q;
|
|
iter->second.Get(j, q);
|
|
*l3d += q;
|
|
|
|
Point3D p;
|
|
iter_room->second.Get(j, p);
|
|
*l_room += p;
|
|
}
|
|
Point3D q1;
|
|
iter->second.Get(iter->second.Size() - 1, q1);
|
|
Point3D q2;
|
|
|
|
end_door_path[count].Get(0, q2);
|
|
const double delta_d = 0.001;
|
|
assert(q1.Distance(q2) < delta_d);
|
|
for(int j = 1;j < end_door_path[count].Size();j++){
|
|
Point3D q;
|
|
end_door_path[count].Get(j, q);
|
|
*l3d += q;
|
|
|
|
Point3D p(true, groom_oid2, groom_oid2, groom_oid2);
|
|
*l_room += p;
|
|
}
|
|
|
|
l_room->EndBulkLoad();
|
|
l3d->EndBulkLoad();
|
|
candidate_path.push_back(*l3d);
|
|
rooms_oid.push_back(*l_room);
|
|
|
|
l3d->DeleteIfAllowed();
|
|
l_room->DeleteIfAllowed();
|
|
}else{
|
|
cout<<"path_id "<<path_oid<<" not found "<<endl;
|
|
cout<<"this should not occur here"<<endl;
|
|
assert(false);
|
|
}
|
|
count++;
|
|
}
|
|
}
|
|
|
|
|
|
///////////////////select the path with minimum length////////////////////
|
|
if(candidate_path.size() > 0){
|
|
double l = numeric_limits<double>::max();
|
|
int index = 0;
|
|
for(unsigned int i = 0; i < candidate_path.size();i++){
|
|
if(candidate_path[i].Size() > 0 && candidate_path[i].Length() < l){
|
|
l = candidate_path[i].Length();
|
|
index = i;
|
|
}
|
|
}
|
|
path_list.push_back(candidate_path[index]);
|
|
rooms_id_list.push_back(rooms_oid[index]);
|
|
}else{
|
|
// cout<<"no path available"<<endl;
|
|
Line3D* l3d = new Line3D(0);
|
|
path_list.push_back(*l3d);
|
|
rooms_id_list.push_back(*l3d);
|
|
l3d->DeleteIfAllowed();
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
return the shortest path with minimum length for indoor navigation
|
|
the start location is in a room and the end location is the building
|
|
entrance
|
|
|
|
*/
|
|
void IndoorNav::ShortestPath_Length_End(GenLoc* gloc1, GenLoc* gloc2,
|
|
Relation* rel, BTree* groom_btree,
|
|
int end_tid)
|
|
{
|
|
|
|
if(IsLocEqual(gloc1, gloc2, rel)){
|
|
cout<<"the two locations are equal to each other"<<endl;
|
|
Line3D* l3d = new Line3D(0);
|
|
path_list.push_back(*l3d);
|
|
l3d->DeleteIfAllowed();
|
|
return;
|
|
}
|
|
unsigned int groom_oid1 = gloc1->GetOid();
|
|
unsigned int groom_oid2 = gloc2->GetOid();
|
|
// cout<<"groom oid1 "<<groom_oid1<<" groom oid2 "<<groom_oid2<<endl;
|
|
if(groom_oid1 == groom_oid2){
|
|
PathInOneRoom(gloc1, gloc2, rel, groom_btree);
|
|
return;
|
|
}
|
|
|
|
Relation* node_rel = ig->GetNodeRel();
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
///////////////collect all doors in start room//////////////////////
|
|
////////////////////////////////////////////////////////////////////
|
|
BTree* btree = ig->GetBTree();
|
|
CcInt* search_id1 = new CcInt(true, groom_oid1);
|
|
BTreeIterator* btree_iter1 = btree->ExactMatch(search_id1);
|
|
vector<int> tid_list1;
|
|
vector<Point3D> door_start;
|
|
while(btree_iter1->Next()){
|
|
Tuple* tuple = node_rel->GetTuple(btree_iter1->GetId(), false);
|
|
int door_tid = tuple->GetTupleId();
|
|
if(DeadDoor(door_tid, groom_oid1, groom_oid2, door_start) == false)
|
|
tid_list1.push_back(door_tid);
|
|
tuple->DeleteIfAllowed();
|
|
}
|
|
delete btree_iter1;
|
|
delete search_id1;
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
///////////////collect all doors in end room//////////////////////
|
|
////////////////////////////////////////////////////////////////////
|
|
vector<int> tid_list2;
|
|
tid_list2.push_back(end_tid);
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
// cout<<"tid_list1 size "<<tid_list1.size()<<endl;
|
|
// cout<<"tid_list2 size "<<tid_list2.size()<<endl;
|
|
|
|
////////calculate once for the connection between start loc and its door////
|
|
vector<Line3D> start_door_path;
|
|
float start_h1 = INVALID_HEIGHT;
|
|
float start_h2 = INVALID_HEIGHT;
|
|
if(!ConnectStartLoc(gloc1, tid_list1, rel, groom_btree,
|
|
start_door_path, start_h1, start_h2)){
|
|
cout<<"connect start location to doors error"<<endl;
|
|
Line3D* l3d = new Line3D(0);
|
|
path_list.push_back(*l3d);
|
|
l3d->DeleteIfAllowed();
|
|
return;
|
|
}
|
|
// cout<<start_h1<<" "<<start_h2<<endl;
|
|
|
|
assert(start_h1 > INVALID_HEIGHT && start_h2 > INVALID_HEIGHT);
|
|
|
|
float min_h1 = MIN(start_h1, start_h2);
|
|
float max_h1 = MAX(start_h1, start_h2);
|
|
|
|
// for(unsigned int i = 0;i < start_door_path.size();i++)
|
|
// path_list.push_back(start_door_path[i]);
|
|
//
|
|
// return;
|
|
|
|
|
|
//////////calculate once for the connection between end loc and its door////
|
|
vector<Line3D> end_door_path;
|
|
|
|
float end_h1 = INVALID_HEIGHT;
|
|
float end_h2 = INVALID_HEIGHT;
|
|
|
|
if(!ConnectEndLoc2(gloc2, rel, groom_btree,
|
|
end_door_path, end_h1, end_h2)){
|
|
cout<<"connect end location to doors error"<<endl;
|
|
Line3D* l3d = new Line3D(0);
|
|
path_list.push_back(*l3d);
|
|
l3d->DeleteIfAllowed();
|
|
return;
|
|
}
|
|
|
|
|
|
// cout<<end_h1<<" "<<end_h2<<endl;
|
|
|
|
assert(end_h1 > INVALID_HEIGHT && end_h2 > INVALID_HEIGHT);
|
|
float min_h2 = MIN(end_h1, end_h2);
|
|
float max_h2 = MAX(end_h1, end_h2);
|
|
|
|
float min_h = MIN(min_h1, min_h2);
|
|
float max_h = MAX(max_h1, max_h2);
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
////////////////////for each possible door, search the path/////////////
|
|
////////////////////////////////////////////////////////////////////////
|
|
vector<Line3D> candidate_path;
|
|
double prune_dist = -1.0;
|
|
for(unsigned int i = 0;i < tid_list1.size();i++){
|
|
// cout<<"source door tid "<<tid_list1[i]<<endl;
|
|
Tuple* door_tuple1 = node_rel->GetTuple(tid_list1[i], false);
|
|
unsigned int gri1 =
|
|
((CcInt*)door_tuple1->GetAttribute(IndoorGraph::I_GROOM_OID1))->GetIntval();
|
|
assert(gri1 == groom_oid1);
|
|
|
|
for(unsigned int j = 0;j < tid_list2.size();j++){
|
|
// cout<<"dest door tid "<<tid_list2[j]<<endl;
|
|
Tuple* door_tuple2 = node_rel->GetTuple(tid_list2[j], false);
|
|
unsigned int gri2 =
|
|
((CcInt*)door_tuple2->GetAttribute(IndoorGraph::I_GROOM_OID1))->GetIntval();
|
|
|
|
assert(gri2 == groom_oid2);
|
|
|
|
IndoorShortestPath(tid_list1[i], tid_list2[j], candidate_path,
|
|
&start_door_path[i], &end_door_path[j],
|
|
prune_dist, min_h, max_h, groom_oid1);
|
|
door_tuple2->DeleteIfAllowed();
|
|
|
|
// cout<<candidate_path[candidate_path.size() - 1].Length()<<endl;
|
|
|
|
}
|
|
|
|
door_tuple1->DeleteIfAllowed();
|
|
}
|
|
|
|
|
|
///////////////////select the path with minimum length////////////////////
|
|
if(candidate_path.size() > 0){
|
|
double l = numeric_limits<double>::max();
|
|
int index = 0;
|
|
for(unsigned int i = 0; i < candidate_path.size();i++){
|
|
if(candidate_path[i].Size() > 0 && candidate_path[i].Length() < l){
|
|
l = candidate_path[i].Length();
|
|
index = i;
|
|
}
|
|
}
|
|
path_list.push_back(candidate_path[index]);
|
|
}else{
|
|
// cout<<"no path available"<<endl;
|
|
Line3D* l3d = new Line3D(0);
|
|
path_list.push_back(*l3d);
|
|
l3d->DeleteIfAllowed();
|
|
}
|
|
|
|
|
|
}
|
|
|
|
/*
|
|
find the paths by loading from disk files
|
|
from a room to the entrance of a building
|
|
|
|
*/
|
|
|
|
void IndoorNav::ShortestPath_Length_End2(GenLoc* gloc1, GenLoc* gloc2,
|
|
Relation* rel, BTree* groom_btree,
|
|
int end_tid, int entrance_id)
|
|
{
|
|
|
|
if(IsLocEqual(gloc1, gloc2, rel)){
|
|
cout<<"the two locations are equal to each other"<<endl;
|
|
Line3D* l3d = new Line3D(0);
|
|
path_list.push_back(*l3d);
|
|
l3d->DeleteIfAllowed();
|
|
return;
|
|
}
|
|
unsigned int groom_oid1 = gloc1->GetOid();
|
|
unsigned int groom_oid2 = gloc2->GetOid();
|
|
// cout<<"groom oid1 "<<groom_oid1<<" groom oid2 "<<groom_oid2<<endl;
|
|
if(groom_oid1 == groom_oid2){
|
|
PathInOneRoom(gloc1, gloc2, rel, groom_btree);
|
|
return;
|
|
}
|
|
|
|
Relation* node_rel = ig->GetNodeRel();
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
///////////////collect all doors in start room//////////////////////
|
|
////////////////////////////////////////////////////////////////////
|
|
BTree* btree = ig->GetBTree();
|
|
CcInt* search_id1 = new CcInt(true, groom_oid1);
|
|
BTreeIterator* btree_iter1 = btree->ExactMatch(search_id1);
|
|
vector<int> tid_list1;
|
|
vector<Point3D> door_start;
|
|
|
|
vector<int> door_tid_list;
|
|
while(btree_iter1->Next()){
|
|
Tuple* tuple = node_rel->GetTuple(btree_iter1->GetId(), false);
|
|
int door_tid = tuple->GetTupleId();
|
|
///all doors should be included (dead doors)////////////////
|
|
door_tid_list.push_back(door_tid);
|
|
if(DeadDoor(door_tid, groom_oid1, groom_oid2, door_start) == false)
|
|
tid_list1.push_back(door_tid);
|
|
else{
|
|
//////such connection are not considered//////////
|
|
door_tid_list[door_tid_list.size() - 1] = 0;
|
|
}
|
|
tuple->DeleteIfAllowed();
|
|
}
|
|
delete btree_iter1;
|
|
delete search_id1;
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
///////////////collect all doors in end room//////////////////////
|
|
////////////////////////////////////////////////////////////////////
|
|
vector<int> tid_list2;
|
|
tid_list2.push_back(end_tid);
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
// cout<<"tid_list1 size "<<tid_list1.size()<<endl;
|
|
// cout<<"tid_list2 size "<<tid_list2.size()<<endl;
|
|
|
|
////////calculate once for the connection between start loc and its door////
|
|
vector<Line3D> start_door_path;
|
|
float start_h1 = INVALID_HEIGHT;
|
|
float start_h2 = INVALID_HEIGHT;
|
|
if(!ConnectStartLoc(gloc1, tid_list1, rel, groom_btree,
|
|
start_door_path, start_h1, start_h2)){
|
|
cout<<"connect start location to doors error"<<endl;
|
|
Line3D* l3d = new Line3D(0);
|
|
path_list.push_back(*l3d);
|
|
l3d->DeleteIfAllowed();
|
|
return;
|
|
}
|
|
// cout<<start_h1<<" "<<start_h2<<endl;
|
|
|
|
assert(start_h1 > INVALID_HEIGHT && start_h2 > INVALID_HEIGHT);
|
|
|
|
//////////calculate once for the connection between end loc and its door////
|
|
vector<Line3D> end_door_path;
|
|
|
|
float end_h1 = INVALID_HEIGHT;
|
|
float end_h2 = INVALID_HEIGHT;
|
|
|
|
if(!ConnectEndLoc2(gloc2, rel, groom_btree,
|
|
end_door_path, end_h1, end_h2)){
|
|
cout<<"connect end location to doors error"<<endl;
|
|
Line3D* l3d = new Line3D(0);
|
|
path_list.push_back(*l3d);
|
|
l3d->DeleteIfAllowed();
|
|
return;
|
|
}
|
|
|
|
assert(end_h1 > INVALID_HEIGHT && end_h2 > INVALID_HEIGHT);
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
////////////////////for each possible door, search the path/////////////
|
|
////////////////////////////////////////////////////////////////////////
|
|
vector<Line3D> candidate_path;
|
|
vector<Line3D> rooms_oid;
|
|
int count = 0;
|
|
|
|
for(unsigned int i = 0;i < door_tid_list.size();i++){
|
|
if(door_tid_list[i] > 0){
|
|
int path_oid = GetIndooPathID2(entrance_id, groom_oid1, i, false);
|
|
// cout<<"path_oid "<<path_oid<<endl;
|
|
map<int, Line3D>::iterator iter = indoor_paths_list.find(path_oid);
|
|
map<int, Line3D>::iterator iter_room = rooms_list.find(path_oid);
|
|
if(iter != indoor_paths_list.end() && iter_room != rooms_list.end()){
|
|
|
|
Line3D* l3d = new Line3D(0);
|
|
l3d->StartBulkLoad();
|
|
|
|
Line3D* l_room = new Line3D(0);
|
|
l_room->StartBulkLoad();
|
|
|
|
assert(iter->second.Size() == iter_room->second.Size());
|
|
|
|
for(int j = 0; j < start_door_path[count].Size();j++){
|
|
Point3D q;
|
|
start_door_path[count].Get(j, q);
|
|
*l3d += q;
|
|
|
|
////////groom oid of the current point3d---old method////////////
|
|
// Point3D p(true, groom_oid1, groom_oid1, groom_oid1);
|
|
// *l_room += p;
|
|
|
|
//////////////more groom oids---new method ///////////////////
|
|
if(j < start_door_path[count].Size() - 1){//use the data from file
|
|
Point3D p(true, groom_oid1, groom_oid1, groom_oid1);
|
|
*l_room += p;
|
|
}
|
|
}
|
|
|
|
/////////end point of path in the room should be equal to door loc////
|
|
Point3D q1;
|
|
iter->second.Get(0, q1);
|
|
Point3D q2;
|
|
start_door_path[count].Get(start_door_path[count].Size() - 1, q2);
|
|
const double delta_d = 0.001;
|
|
|
|
assert(q1.Distance(q2) < delta_d);
|
|
|
|
for(int j = 1;j < iter->second.Size();j++){
|
|
Point3D q;
|
|
iter->second.Get(j, q);
|
|
*l3d += q;
|
|
|
|
//////////////////add the data is missing in the above////////////
|
|
if(j == 1){/////use the data from disk file, has more groom oids
|
|
Point3D tmp_p;
|
|
iter_room->second.Get(0, tmp_p);
|
|
*l_room += tmp_p;
|
|
}
|
|
Point3D p;
|
|
iter_room->second.Get(j, p);
|
|
*l_room += p;
|
|
}
|
|
|
|
l3d->EndBulkLoad();
|
|
l_room->EndBulkLoad();
|
|
|
|
candidate_path.push_back(*l3d);
|
|
rooms_oid.push_back(*l_room);
|
|
|
|
l3d->DeleteIfAllowed();
|
|
l_room->DeleteIfAllowed();
|
|
|
|
|
|
}else{
|
|
cout<<"path_id "<<path_oid<<" not found "<<endl;
|
|
cout<<"this should not occur here"<<endl;
|
|
assert(false);
|
|
}
|
|
count++;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
///////////////////select the path with minimum length////////////////////
|
|
if(candidate_path.size() > 0){
|
|
double l = numeric_limits<double>::max();
|
|
int index = 0;
|
|
for(unsigned int i = 0; i < candidate_path.size();i++){
|
|
if(candidate_path[i].Size() > 0 && candidate_path[i].Length() < l){
|
|
l = candidate_path[i].Length();
|
|
index = i;
|
|
}
|
|
}
|
|
path_list.push_back(candidate_path[index]);
|
|
rooms_id_list.push_back(rooms_oid[index]);
|
|
}else{
|
|
// cout<<"no path available"<<endl;
|
|
Line3D* l3d = new Line3D(0);
|
|
path_list.push_back(*l3d);
|
|
rooms_id_list.push_back(*l3d);
|
|
l3d->DeleteIfAllowed();
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
return the shortest path with minimum length for indoor navigation
|
|
|
|
*/
|
|
void IndoorNav::ShortestPath_Length(GenLoc* gloc1, GenLoc* gloc2,
|
|
Relation* rel, BTree* groom_btree)
|
|
{
|
|
//////////////////////////////////////////
|
|
/////////////for debuging////////////////
|
|
/////////////////////////////////////////
|
|
|
|
/* Loc temp_loc1(4.36, 11.13);
|
|
Loc temp_loc2(0, 31);
|
|
GenLoc temp_gloc1(195, temp_loc1);
|
|
GenLoc temp_gloc2(52, temp_loc2);
|
|
gloc1 = &temp_gloc1;
|
|
gloc2 = &temp_gloc2;*/
|
|
|
|
if(IsLocEqual(gloc1, gloc2, rel)){
|
|
cout<<"the two locations are equal to each other"<<endl;
|
|
Line3D* l3d = new Line3D(0);
|
|
path_list.push_back(*l3d);
|
|
l3d->DeleteIfAllowed();
|
|
return;
|
|
}
|
|
unsigned int groom_oid1 = gloc1->GetOid();
|
|
unsigned int groom_oid2 = gloc2->GetOid();
|
|
// cout<<"groom oid1 "<<groom_oid1<<" groom oid2 "<<groom_oid2<<endl;
|
|
if(groom_oid1 == groom_oid2){
|
|
PathInOneRoom(gloc1, gloc2, rel, groom_btree);
|
|
return;
|
|
}
|
|
|
|
Relation* node_rel = ig->GetNodeRel();
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
///////////////collect all doors in start room//////////////////////
|
|
////////////////////////////////////////////////////////////////////
|
|
BTree* btree = ig->GetBTree();
|
|
CcInt* search_id1 = new CcInt(true, groom_oid1);
|
|
BTreeIterator* btree_iter1 = btree->ExactMatch(search_id1);
|
|
vector<int> tid_list1;
|
|
vector<Point3D> door_start;
|
|
while(btree_iter1->Next()){
|
|
Tuple* tuple = node_rel->GetTuple(btree_iter1->GetId(), false);
|
|
int door_tid = tuple->GetTupleId();
|
|
if(DeadDoor(door_tid, groom_oid1, groom_oid2, door_start) == false)
|
|
tid_list1.push_back(door_tid);
|
|
tuple->DeleteIfAllowed();
|
|
}
|
|
delete btree_iter1;
|
|
delete search_id1;
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
///////////////collect all doors in end room//////////////////////
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
CcInt* search_id2 = new CcInt(true, groom_oid2);
|
|
BTreeIterator* btree_iter2 = btree->ExactMatch(search_id2);
|
|
vector<int> tid_list2;
|
|
vector<Point3D> door_end;
|
|
while(btree_iter2->Next()){
|
|
Tuple* tuple = node_rel->GetTuple(btree_iter2->GetId(), false);
|
|
int door_tid = tuple->GetTupleId();
|
|
if(DeadDoor(door_tid, groom_oid2, groom_oid1, door_end) == false)
|
|
tid_list2.push_back(door_tid);
|
|
tuple->DeleteIfAllowed();
|
|
}
|
|
delete btree_iter2;
|
|
delete search_id2;
|
|
|
|
// cout<<"tid_list1 size "<<tid_list1.size()<<endl;
|
|
// cout<<"tid_list2 size "<<tid_list2.size()<<endl;
|
|
|
|
////////calculate once for the connection between start loc and its door////
|
|
vector<Line3D> start_door_path;
|
|
float start_h1 = INVALID_HEIGHT;
|
|
float start_h2 = INVALID_HEIGHT;
|
|
if(!ConnectStartLoc(gloc1, tid_list1, rel, groom_btree,
|
|
start_door_path, start_h1, start_h2)){
|
|
cout<<"connect start location to doors error"<<endl;
|
|
Line3D* l3d = new Line3D(0);
|
|
path_list.push_back(*l3d);
|
|
l3d->DeleteIfAllowed();
|
|
return;
|
|
}
|
|
// cout<<start_h1<<" "<<start_h2<<endl;
|
|
|
|
assert(start_h1 > INVALID_HEIGHT && start_h2 > INVALID_HEIGHT);
|
|
|
|
float min_h1 = MIN(start_h1, start_h2);
|
|
float max_h1 = MAX(start_h1, start_h2);
|
|
|
|
// for(unsigned int i = 0;i < start_door_path.size();i++)
|
|
// path_list.push_back(start_door_path[i]);
|
|
//
|
|
// return;
|
|
|
|
|
|
//////////calculate once for the connection between end loc and its door////
|
|
vector<Line3D> end_door_path;
|
|
float end_h1 = INVALID_HEIGHT;
|
|
float end_h2 = INVALID_HEIGHT;
|
|
|
|
if(!ConnectEndLoc(gloc2, tid_list2, rel, groom_btree,
|
|
end_door_path, end_h1, end_h2)){
|
|
cout<<"connect end location to doors error"<<endl;
|
|
Line3D* l3d = new Line3D(0);
|
|
path_list.push_back(*l3d);
|
|
l3d->DeleteIfAllowed();
|
|
return;
|
|
}
|
|
|
|
// cout<<end_h1<<" "<<end_h2<<endl;
|
|
|
|
assert(end_h1 > INVALID_HEIGHT && end_h2 > INVALID_HEIGHT);
|
|
float min_h2 = MIN(end_h1, end_h2);
|
|
float max_h2 = MAX(end_h1, end_h2);
|
|
|
|
float min_h = MIN(min_h1, min_h2);
|
|
float max_h = MAX(max_h1, max_h2);
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
////////////////////for each possible door, search the path/////////////
|
|
////////////////////////////////////////////////////////////////////////
|
|
vector<Line3D> candidate_path;
|
|
double prune_dist = -1.0;
|
|
for(unsigned int i = 0;i < tid_list1.size();i++){
|
|
// cout<<"source door tid "<<tid_list1[i]<<endl;
|
|
Tuple* door_tuple1 = node_rel->GetTuple(tid_list1[i], false);
|
|
unsigned int gri1 =
|
|
((CcInt*)door_tuple1->GetAttribute(IndoorGraph::I_GROOM_OID1))->GetIntval();
|
|
assert(gri1 == groom_oid1);
|
|
|
|
for(unsigned int j = 0;j < tid_list2.size();j++){
|
|
// cout<<"dest door tid "<<tid_list2[j]<<endl;
|
|
Tuple* door_tuple2 = node_rel->GetTuple(tid_list2[j], false);
|
|
unsigned int gri2 =
|
|
((CcInt*)door_tuple2->GetAttribute(IndoorGraph::I_GROOM_OID1))->GetIntval();
|
|
|
|
assert(gri2 == groom_oid2);
|
|
|
|
IndoorShortestPath(tid_list1[i], tid_list2[j], candidate_path,
|
|
&start_door_path[i], &end_door_path[j],
|
|
prune_dist, min_h, max_h, groom_oid1);
|
|
door_tuple2->DeleteIfAllowed();
|
|
|
|
// cout<<candidate_path[candidate_path.size() - 1].Length()<<endl;
|
|
|
|
}
|
|
|
|
door_tuple1->DeleteIfAllowed();
|
|
}
|
|
|
|
|
|
///////////////////select the path with minimum length////////////////////
|
|
if(candidate_path.size() > 0){
|
|
double l = numeric_limits<double>::max();
|
|
int index = 0;
|
|
for(unsigned int i = 0; i < candidate_path.size();i++){
|
|
if(candidate_path[i].Size() > 0 && candidate_path[i].Length() < l){
|
|
l = candidate_path[i].Length();
|
|
index = i;
|
|
}
|
|
}
|
|
path_list.push_back(candidate_path[index]);
|
|
}else{
|
|
// cout<<"no path available"<<endl;
|
|
Line3D* l3d = new Line3D(0);
|
|
path_list.push_back(*l3d);
|
|
l3d->DeleteIfAllowed();
|
|
}
|
|
|
|
|
|
}
|
|
|
|
/*
|
|
new method to compute the connection between a location and all its doors
|
|
use dual graph and visual graph if the region is complex
|
|
|
|
*/
|
|
bool IndoorNav::ConnectEndLoc(GenLoc* gloc, vector<int> tid_list,
|
|
Relation* rel,
|
|
BTree* btree, vector<Line3D>& candidate_path,
|
|
float& low_h, float& high_h)
|
|
{
|
|
unsigned int groom_oid = gloc->GetOid();
|
|
|
|
///////////////find the room////////////////////////////////////////////
|
|
CcInt* search_id = new CcInt(true, groom_oid);
|
|
BTreeIterator* btree_iter = btree->ExactMatch(search_id);
|
|
int groom_tid = 0;
|
|
while(btree_iter->Next()){
|
|
groom_tid = btree_iter->GetId();
|
|
break;
|
|
}
|
|
delete btree_iter;
|
|
delete search_id;
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// cout<<"groom tid "<<groom_tid<<endl;
|
|
|
|
assert(1<= groom_tid && groom_tid <= rel->GetNoTuples());
|
|
|
|
Tuple* groom_tuple = rel->GetTuple(groom_tid, false);
|
|
|
|
string type = ((CcString*)groom_tuple->GetAttribute(I_Type))->GetValue();
|
|
GRoom* groom = (GRoom*)groom_tuple->GetAttribute(I_Room);
|
|
low_h = groom->GetLowHeight();
|
|
high_h = groom->GetHighHeight();
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
if(GetRoomEnum(type) == ST){/////////in the staircase
|
|
ConnectEndLocST(groom_tuple, gloc, tid_list, candidate_path);
|
|
groom_tuple->DeleteIfAllowed();
|
|
return true;
|
|
}
|
|
|
|
if(GetRoomEnum(type) == EL){
|
|
groom_tuple->DeleteIfAllowed();
|
|
cout<<"inside the elevator. not interesting places"<<endl;
|
|
cout<<"it should not arrive here"<<endl;
|
|
return false;
|
|
}
|
|
///////////////////////////////////////////////////////////////////////
|
|
///////////////get the position of the start point////////////////////
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
Region* reg = new Region(0);
|
|
groom->GetRegion(*reg);
|
|
BBox<2> bbox = reg->BoundingBox();
|
|
float h = groom->GetLowHeight();
|
|
double x1 = gloc->GetLoc().loc1 + bbox.MinD(0);
|
|
double y1 = gloc->GetLoc().loc2 + bbox.MinD(1);
|
|
Point p1(true, x1, y1);
|
|
Modify_Point2(p1);// numeric problem, not so many digit after dot
|
|
reg->DeleteIfAllowed();
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
/////////////////////////get the 2D area/////////////////////////////////
|
|
/////////////////////////////////////////////////////////////////////////
|
|
const double dist_delta = 0.001;
|
|
Region* r = new Region(0);
|
|
int i = 0;
|
|
for(;i < groom->Size();i++){
|
|
float temp_h;
|
|
groom->Get(i, temp_h, *r);
|
|
if(fabs(h - temp_h) < dist_delta){
|
|
break;
|
|
}
|
|
r->Clear();
|
|
}
|
|
if(i == groom->Size()){
|
|
cout<<" such height " <<h <<"does not exist in the GRoom"<<endl;
|
|
assert(false);
|
|
}
|
|
//////////////////////////////////////////////////////////////////////////
|
|
CompTriangle* ct = new CompTriangle(r);
|
|
int complex_reg = ct->ComplexRegion();
|
|
delete ct;
|
|
assert(complex_reg >= 0);
|
|
|
|
vector<string> obj_name;
|
|
DualGraph* dg = NULL;
|
|
VisualGraph* vg = NULL;
|
|
Relation* tri_rel = NULL;
|
|
int oid1 = 0;
|
|
if(complex_reg == 1){ ///complex region, we build dual graph and visual graph
|
|
// cout<<"complex region"<<endl;
|
|
GetSecondoObj(r, obj_name);
|
|
assert(obj_name.size() == 3);
|
|
SecondoCatalog* ctlg = SecondoSystem::GetCatalog();
|
|
bool dg_def, vg_def, rel_def;
|
|
Word dg_addr, vg_addr, rel_addr;
|
|
ctlg->GetObject(obj_name[0], dg_addr, dg_def);
|
|
ctlg->GetObject(obj_name[1], vg_addr, vg_def);
|
|
ctlg->GetObject(obj_name[2], rel_addr, rel_def);
|
|
|
|
if(dg_def && vg_def && rel_def){
|
|
dg = (DualGraph*)dg_addr.addr;
|
|
vg = (VisualGraph*)vg_addr.addr;
|
|
tri_rel = (Relation*)rel_addr.addr;
|
|
assert(dg != NULL);
|
|
assert(vg != NULL);
|
|
assert(tri_rel != NULL);
|
|
FindPointInDG1(dg, &p1, oid1);
|
|
assert(1 <= oid1 && oid1 <= dg->node_rel->GetNoTuples());
|
|
}else{
|
|
cout<<"open dual graph or visual graph error"<<endl;
|
|
r->DeleteIfAllowed();
|
|
groom_tuple->DeleteIfAllowed();
|
|
DeleteSecondoObj(obj_name);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
////////////build the connection between loc and all doors in that room//////
|
|
Relation* node_rel = ig->GetNodeRel();
|
|
for(unsigned int j = 0;j < tid_list.size();j++){
|
|
int door_tid = tid_list[j];
|
|
// cout<<"door tid "<<door_tid<<endl;
|
|
Tuple* door_tuple = node_rel->GetTuple(door_tid, false);
|
|
unsigned int gri2 =
|
|
((CcInt*)door_tuple->GetAttribute(IndoorGraph::I_GROOM_OID1))->GetIntval();
|
|
|
|
assert(gri2 == groom_oid);
|
|
///////////////////////////////////////////////////////////////////
|
|
/////////////////get the position of the door//////////////////////
|
|
///////////////////////////////////////////////////////////////////
|
|
Line* l = (Line*)door_tuple->GetAttribute(IndoorGraph::I_DOOR_LOC);
|
|
assert(l->Size() == 2);
|
|
HalfSegment hs;
|
|
l->Get(0, hs);
|
|
double x2 = (hs.GetLeftPoint().GetX() + hs.GetRightPoint().GetX())/2;
|
|
double y2 = (hs.GetLeftPoint().GetY() + hs.GetRightPoint().GetY())/2;
|
|
|
|
door_tuple->DeleteIfAllowed();
|
|
|
|
Point p2(true, x2, y2);
|
|
Modify_Point2(p2); // numeric problem, not so many digit after dot
|
|
|
|
////////////////computes the shortest path////////////////////////////
|
|
|
|
Line* sp_path = new Line(0);
|
|
|
|
if(complex_reg == 1){
|
|
//////////////////////////////////////////////////////////////////
|
|
//////////////////////////!!!! careful!!!!!///////////////////////
|
|
//////////////////////////////////////////////////////////////////
|
|
if(EuclideanConnection(r, &p2, &p1, sp_path)){
|
|
|
|
}
|
|
else{
|
|
Walk_SP* wsp = new Walk_SP(dg, vg, NULL, NULL);
|
|
wsp->rel3 = tri_rel;
|
|
int oid2 = 0;
|
|
FindPointInDG1(dg, &p2, oid2);
|
|
assert(1 <= oid2 && oid2 <= dg->node_rel->GetNoTuples());
|
|
wsp->WalkShortestPath2(oid2, oid1, p2, p1, sp_path);
|
|
delete wsp;
|
|
}
|
|
}else{
|
|
///////////////////////////////////////////////////////////////////
|
|
//////////////////////////!!!! careful!!!!!///////////////////////
|
|
//////////////////////////////////////////////////////////////////
|
|
ShortestPath_InRegion(r, &p2, &p1, sp_path);
|
|
}
|
|
|
|
if(sp_path->Size() == 0){
|
|
if(p1.Distance(p2) < EPSDIST){//the position happens to be the door
|
|
Line3D* l3d = new Line3D(0);
|
|
l3d->StartBulkLoad();
|
|
Point3D q(true, p1.GetX(), p1.GetY(), h);
|
|
*l3d += q;
|
|
l3d->EndBulkLoad();
|
|
candidate_path.push_back(*l3d);
|
|
l3d->DeleteIfAllowed();
|
|
}
|
|
sp_path->DeleteIfAllowed();
|
|
continue;
|
|
}
|
|
/////////////////////////////////////////////////////////////////////
|
|
SimpleLine* sl = new SimpleLine(0);
|
|
sl->fromLine(*sp_path);
|
|
SpacePartition* sp = new SpacePartition();
|
|
vector<MyHalfSegment> mhs;
|
|
sp->ReorderLine(sl, mhs);
|
|
delete sp;
|
|
sl->DeleteIfAllowed();
|
|
sp_path->DeleteIfAllowed();
|
|
|
|
if(mhs[0].from.Distance(p2) < dist_delta &&
|
|
mhs[mhs.size() - 1].to.Distance(p1) < dist_delta){
|
|
|
|
}else{
|
|
assert(mhs[mhs.size() - 1].to.Distance(p2) < dist_delta &&
|
|
mhs[0].from.Distance(p1) < dist_delta);
|
|
|
|
vector<MyHalfSegment> temp_mhs;
|
|
for(int i = mhs.size() - 1;i >= 0;i--){
|
|
MyHalfSegment seg = mhs[i];
|
|
Point p = seg.from;
|
|
seg.from = seg.to;
|
|
seg.to = p;
|
|
temp_mhs.push_back(seg);
|
|
}
|
|
mhs.clear();
|
|
for(unsigned int i = 0;i < temp_mhs.size();i++)
|
|
mhs.push_back(temp_mhs[i]);
|
|
assert(mhs[0].from.Distance(p2) < dist_delta &&
|
|
mhs[mhs.size() - 1].to.Distance(p1) < dist_delta);
|
|
}
|
|
///////////////////////////////////////////////////////////////////
|
|
///////////////////construct 3D line//////////////////////////////
|
|
///////////////////////////////////////////////////////////////////
|
|
Line3D* l3d = new Line3D(0);
|
|
l3d->StartBulkLoad();
|
|
|
|
for(unsigned int i = 0;i < mhs.size();i++){
|
|
Point p = mhs[i].from;
|
|
Point3D q(true, p.GetX(), p.GetY(), h);
|
|
*l3d += q;
|
|
if(i == mhs.size() - 1){
|
|
Point temp_p = mhs[i].to;
|
|
Point3D q1(true, temp_p.GetX(), temp_p.GetY(), h);
|
|
*l3d += q1;
|
|
}
|
|
}
|
|
l3d->EndBulkLoad();
|
|
|
|
candidate_path.push_back(*l3d);
|
|
l3d->DeleteIfAllowed();
|
|
|
|
}
|
|
r->DeleteIfAllowed();
|
|
groom_tuple->DeleteIfAllowed();
|
|
if(complex_reg == 1)DeleteSecondoObj(obj_name);
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
the location is a door (building entrance)
|
|
|
|
*/
|
|
bool IndoorNav::ConnectEndLoc2(GenLoc* gloc, Relation* rel,
|
|
BTree* btree, vector<Line3D>& candidate_path,
|
|
float& low_h, float& high_h)
|
|
{
|
|
unsigned int groom_oid = gloc->GetOid();
|
|
///////////////find the room////////////////////////////////////////////
|
|
CcInt* search_id = new CcInt(true, groom_oid);
|
|
BTreeIterator* btree_iter = btree->ExactMatch(search_id);
|
|
int groom_tid = 0;
|
|
while(btree_iter->Next()){
|
|
groom_tid = btree_iter->GetId();
|
|
break;
|
|
}
|
|
delete btree_iter;
|
|
delete search_id;
|
|
//////////////////////////////////////////////////////////////////////////
|
|
assert(1<= groom_tid && groom_tid <= rel->GetNoTuples());
|
|
|
|
Tuple* groom_tuple = rel->GetTuple(groom_tid, false);
|
|
|
|
string type = ((CcString*)groom_tuple->GetAttribute(I_Type))->GetValue();
|
|
GRoom* groom = (GRoom*)groom_tuple->GetAttribute(I_Room);
|
|
low_h = groom->GetLowHeight();
|
|
high_h = groom->GetHighHeight();
|
|
groom_tuple->DeleteIfAllowed();
|
|
|
|
Line3D* l3d = new Line3D(0);
|
|
candidate_path.push_back(*l3d);
|
|
l3d->DeleteIfAllowed();
|
|
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
shortest path of two locations in the same staircase
|
|
|
|
*/
|
|
void IndoorNav::ComputePath3DST(GRoom* groom, Point loc1, Point loc2, float h1,
|
|
float h2, vector<Line3D>& candidate_path)
|
|
{
|
|
const double delta_dist = 0.001;
|
|
if(fabs(h1-h2) < delta_dist){
|
|
float h = h1;
|
|
vector<MyHalfSegment> mhs;
|
|
FindPathInRegion(groom, h, mhs, &loc1, &loc2);
|
|
///////////////// convert to 3D line //////////////////////////////
|
|
Line3D* l3d = new Line3D(0);
|
|
l3d->StartBulkLoad();
|
|
for(unsigned int i = 0;i < mhs.size();i++){
|
|
Point p = mhs[i].from;
|
|
Point3D q(true, p.GetX(), p.GetY(), h);
|
|
*l3d += q;
|
|
if(i == mhs.size() - 1){
|
|
Point p1 = mhs[i].to;
|
|
Point3D q1(true, p1.GetX(), p1.GetY(), h);
|
|
*l3d += q1;
|
|
}
|
|
}
|
|
l3d->EndBulkLoad();
|
|
candidate_path.push_back(*l3d);
|
|
l3d->DeleteIfAllowed();
|
|
}else if(h1 < h2){
|
|
|
|
vector<Point3D> middle_path; //from low to high
|
|
ConstructMiddlePath2(groom, middle_path, h1, h2);
|
|
Point q1(true, middle_path[0].GetX(), middle_path[0].GetY());
|
|
Point q2(true, middle_path[middle_path.size() - 1].GetX(),
|
|
middle_path[middle_path.size() - 1].GetY());
|
|
|
|
vector<MyHalfSegment> mhs1;
|
|
FindPathInRegion(groom, h1, mhs1, &loc1, &q1);
|
|
vector<MyHalfSegment> mhs2;
|
|
FindPathInRegion(groom, h2, mhs2, &q2, &loc2);
|
|
Line3D* l3d = new Line3D(0);
|
|
l3d->StartBulkLoad();
|
|
|
|
for(unsigned int i = 0 ;i < mhs1.size();i++){
|
|
Point p = mhs1[i].from;
|
|
Point3D q(true, p.GetX(), p.GetY(), h1);
|
|
*l3d += q;
|
|
}
|
|
|
|
for(unsigned int i = 0 ;i < middle_path.size() - 1;i++){
|
|
*l3d += middle_path[i];
|
|
}
|
|
// cout<<"mhs2 size "<<mhs2.size()<<endl;
|
|
for(unsigned int i = 0 ;i < mhs2.size();i++){
|
|
Point p = mhs2[i].from;
|
|
Point3D q(true, p.GetX(), p.GetY(), h2);
|
|
*l3d += q;
|
|
if(i == mhs2.size() - 1){
|
|
Point p = mhs2[i].to;
|
|
Point3D q(true, p.GetX(), p.GetY(), h2);
|
|
*l3d += q;
|
|
}
|
|
}
|
|
|
|
l3d->EndBulkLoad();
|
|
candidate_path.push_back(*l3d);
|
|
l3d->DeleteIfAllowed();
|
|
}else if(h1 > h2){
|
|
vector<Point3D> middle_path; //from low to high
|
|
ConstructMiddlePath2(groom, middle_path, h2, h1);
|
|
|
|
Point q1(true, middle_path[middle_path.size() - 1].GetX(),
|
|
middle_path[middle_path.size() - 1].GetY());
|
|
|
|
Point q2(true, middle_path[0].GetX(), middle_path[0].GetY());
|
|
|
|
vector<MyHalfSegment> mhs1;
|
|
FindPathInRegion(groom, h1, mhs1, &loc1, &q1);
|
|
vector<MyHalfSegment> mhs2;
|
|
FindPathInRegion(groom, h2, mhs2, &q2, &loc2);
|
|
|
|
Line3D* l3d = new Line3D(0);
|
|
l3d->StartBulkLoad();
|
|
|
|
for(unsigned int i = 0 ;i < mhs1.size();i++){
|
|
Point p = mhs1[i].from;
|
|
Point3D q(true, p.GetX(), p.GetY(), h1);
|
|
*l3d += q;
|
|
}
|
|
|
|
for(int i = middle_path.size() - 1;i > 0; i--){
|
|
*l3d += middle_path[i];
|
|
}
|
|
|
|
for(unsigned int i = 0 ;i < mhs2.size();i++){
|
|
Point p = mhs2[i].from;
|
|
Point3D q(true, p.GetX(), p.GetY(), h2);
|
|
*l3d += q;
|
|
if(i == mhs2.size() - 1){
|
|
Point p = mhs2[i].to;
|
|
Point3D q(true, p.GetX(), p.GetY(), h2);
|
|
*l3d += q;
|
|
}
|
|
}
|
|
|
|
l3d->EndBulkLoad();
|
|
candidate_path.push_back(*l3d);
|
|
l3d->DeleteIfAllowed();
|
|
}else assert(false);
|
|
|
|
}
|
|
|
|
/*
|
|
build the connection from the end location to all doors in a staircase
|
|
|
|
*/
|
|
void IndoorNav::ConnectEndLocST(Tuple* groom_tuple, GenLoc* gloc,
|
|
vector<int> tid_list, vector<Line3D>& candidate_path)
|
|
{
|
|
unsigned int groom_oid = gloc->GetOid();
|
|
|
|
GRoom* groom = (GRoom*)groom_tuple->GetAttribute(I_Room);
|
|
Region* reg = new Region(0);
|
|
groom->GetRegion(*reg);
|
|
BBox<2> bbox = reg->BoundingBox();
|
|
reg->DeleteIfAllowed();
|
|
|
|
Point loc2;
|
|
Coord x_cord1 = gloc->GetLoc().loc1 + bbox.MinD(0);
|
|
Coord y_cord1 = gloc->GetLoc().loc2 + bbox.MinD(1);
|
|
loc2.Set(x_cord1, y_cord1); //absolute position
|
|
float h2 = GetHeightInST(groom, loc2);
|
|
|
|
|
|
Relation* node_rel = ig->GetNodeRel();
|
|
for(unsigned int j = 0;j < tid_list.size();j++){
|
|
int door_tid = tid_list[j];
|
|
// cout<<"door tid "<<door_tid<<endl;
|
|
Tuple* door_tuple = node_rel->GetTuple(door_tid, false);
|
|
unsigned int gri2 =
|
|
((CcInt*)door_tuple->GetAttribute(IndoorGraph::I_GROOM_OID1))->GetIntval();
|
|
|
|
assert(gri2 == groom_oid);
|
|
///////////////////////////////////////////////////////////////////
|
|
/////////////////get the position of the door//////////////////////
|
|
///////////////////////////////////////////////////////////////////
|
|
Line* l = (Line*)door_tuple->GetAttribute(IndoorGraph::I_DOOR_LOC);
|
|
assert(l->Size() == 2);
|
|
HalfSegment hs;
|
|
l->Get(0, hs);
|
|
double x2 = (hs.GetLeftPoint().GetX() + hs.GetRightPoint().GetX())/2;
|
|
double y2 = (hs.GetLeftPoint().GetY() + hs.GetRightPoint().GetY())/2;
|
|
|
|
Line3D* l3 = (Line3D*)door_tuple->GetAttribute(IndoorGraph::I_DOOR_LOC_3D);
|
|
Point3D temp3d_p;
|
|
l3->Get(0, temp3d_p);
|
|
float h1 = temp3d_p.GetZ();
|
|
door_tuple->DeleteIfAllowed();
|
|
|
|
Point loc1(true, x2, y2);
|
|
|
|
ComputePath3DST(groom, loc1, loc2, h1, h2, candidate_path);
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
connect the start location to all doors in that room.
|
|
if the region is complex, it calls the dual graph, visual graph
|
|
|
|
*/
|
|
bool IndoorNav::ConnectStartLoc(GenLoc* gloc, vector<int> tid_list,
|
|
Relation* rel,
|
|
BTree* btree, vector<Line3D>& candidate_path,
|
|
float& low_h, float& high_h)
|
|
{
|
|
unsigned int groom_oid = gloc->GetOid();
|
|
|
|
///////////////find the room////////////////////////////////////////////
|
|
CcInt* search_id = new CcInt(true, groom_oid);
|
|
BTreeIterator* btree_iter = btree->ExactMatch(search_id);
|
|
int groom_tid = 0;
|
|
while(btree_iter->Next()){
|
|
groom_tid = btree_iter->GetId();
|
|
break;
|
|
}
|
|
delete btree_iter;
|
|
delete search_id;
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// cout<<"groom tid "<<groom_tid<<endl;
|
|
|
|
assert(1<= groom_tid && groom_tid <= rel->GetNoTuples());
|
|
|
|
Tuple* groom_tuple = rel->GetTuple(groom_tid, false);
|
|
|
|
string type = ((CcString*)groom_tuple->GetAttribute(I_Type))->GetValue();
|
|
GRoom* groom = (GRoom*)groom_tuple->GetAttribute(I_Room);
|
|
low_h = groom->GetLowHeight();
|
|
high_h = groom->GetHighHeight();
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
if(GetRoomEnum(type) == ST){/////////in the staircase
|
|
ConnectStartLocST(groom_tuple, gloc, tid_list, candidate_path);
|
|
groom_tuple->DeleteIfAllowed();
|
|
return true;
|
|
}
|
|
|
|
if(GetRoomEnum(type) == EL){
|
|
groom_tuple->DeleteIfAllowed();
|
|
cout<<"inside the elevator. not interesting places"<<endl;
|
|
cout<<"it should not arrive here"<<endl;
|
|
return false;
|
|
}
|
|
///////////////////////////////////////////////////////////////////////
|
|
///////////////get the position of the start point////////////////////
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
Region* reg = new Region(0);
|
|
groom->GetRegion(*reg);
|
|
BBox<2> bbox = reg->BoundingBox();
|
|
float h = groom->GetLowHeight();
|
|
double x1 = gloc->GetLoc().loc1 + bbox.MinD(0);
|
|
double y1 = gloc->GetLoc().loc2 + bbox.MinD(1);
|
|
Point p1(true, x1, y1);
|
|
Modify_Point2(p1);//numeric problem, we do not need so many number after dot
|
|
reg->DeleteIfAllowed();
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
/////////////////////////get the 2D area/////////////////////////////////
|
|
/////////////////////////////////////////////////////////////////////////
|
|
const double dist_delta = 0.001;
|
|
Region* r = new Region(0);
|
|
int i = 0;
|
|
for(;i < groom->Size();i++){
|
|
float temp_h;
|
|
groom->Get(i, temp_h, *r);
|
|
if(fabs(h - temp_h) < dist_delta){
|
|
break;
|
|
}
|
|
r->Clear();
|
|
}
|
|
if(i == groom->Size()){
|
|
cout<<" such height " <<h <<"does not exist in the GRoom"<<endl;
|
|
assert(false);
|
|
}
|
|
//////////////////////////////////////////////////////////////////////////
|
|
CompTriangle* ct = new CompTriangle(r);
|
|
int complex_reg = ct->ComplexRegion();
|
|
delete ct;
|
|
assert(complex_reg >= 0);
|
|
|
|
vector<string> obj_name;
|
|
DualGraph* dg = NULL;
|
|
VisualGraph* vg = NULL;
|
|
Relation* tri_rel = NULL;
|
|
int oid1 = 0;
|
|
if(complex_reg == 1){ ///complex region, we build dual graph and visual graph
|
|
GetSecondoObj(r, obj_name);
|
|
assert(obj_name.size() == 3);
|
|
SecondoCatalog* ctlg = SecondoSystem::GetCatalog();
|
|
bool dg_def, vg_def, rel_def;
|
|
Word dg_addr, vg_addr, rel_addr;
|
|
ctlg->GetObject(obj_name[0], dg_addr, dg_def);
|
|
ctlg->GetObject(obj_name[1], vg_addr, vg_def);
|
|
ctlg->GetObject(obj_name[2], rel_addr, rel_def);
|
|
|
|
if(dg_def && vg_def && rel_def){
|
|
dg = (DualGraph*)dg_addr.addr;
|
|
vg = (VisualGraph*)vg_addr.addr;
|
|
tri_rel = (Relation*)rel_addr.addr;
|
|
assert(dg != NULL);
|
|
assert(vg != NULL);
|
|
assert(tri_rel != NULL);
|
|
FindPointInDG1(dg, &p1, oid1);
|
|
assert(1 <= oid1 && oid1 <= dg->node_rel->GetNoTuples());
|
|
}else{
|
|
cout<<"open dual graph or visual graph error"<<endl;
|
|
r->DeleteIfAllowed();
|
|
groom_tuple->DeleteIfAllowed();
|
|
DeleteSecondoObj(obj_name);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
////////////build the connection between loc and all doors in that room//////
|
|
Relation* node_rel = ig->GetNodeRel();
|
|
for(unsigned int j = 0;j < tid_list.size();j++){
|
|
int door_tid = tid_list[j];
|
|
// cout<<"door tid "<<door_tid<<endl;
|
|
Tuple* door_tuple = node_rel->GetTuple(door_tid, false);
|
|
unsigned int gri2 =
|
|
((CcInt*)door_tuple->GetAttribute(IndoorGraph::I_GROOM_OID1))->GetIntval();
|
|
|
|
assert(gri2 == groom_oid);
|
|
///////////////////////////////////////////////////////////////////
|
|
/////////////////get the position of the door//////////////////////
|
|
///////////////////////////////////////////////////////////////////
|
|
Line* l = (Line*)door_tuple->GetAttribute(IndoorGraph::I_DOOR_LOC);
|
|
assert(l->Size() == 2);
|
|
HalfSegment hs;
|
|
l->Get(0, hs);
|
|
double x2 = (hs.GetLeftPoint().GetX() + hs.GetRightPoint().GetX())/2;
|
|
double y2 = (hs.GetLeftPoint().GetY() + hs.GetRightPoint().GetY())/2;
|
|
|
|
door_tuple->DeleteIfAllowed();
|
|
|
|
Point p2(true, x2, y2);
|
|
Modify_Point2(p2);//numeric problem, do not need so many number after dot
|
|
////////////////computes the shortest path////////////////////////////
|
|
|
|
Line* sp_path = new Line(0);
|
|
if(complex_reg == 1){
|
|
//////////////////////////////////////////////////////////////////
|
|
//////////////////////////!!!! careful!!!!!///////////////////////
|
|
//////////////////////////////////////////////////////////////////
|
|
if(EuclideanConnection(r, &p1, &p2, sp_path)){
|
|
|
|
}else{
|
|
Walk_SP* wsp = new Walk_SP(dg, vg, NULL, NULL);
|
|
wsp->rel3 = tri_rel;
|
|
int oid2 = 0;
|
|
FindPointInDG1(dg, &p2, oid2);
|
|
assert(1 <= oid2 && oid2 <= dg->node_rel->GetNoTuples());
|
|
wsp->WalkShortestPath2(oid1, oid2, p1, p2, sp_path);
|
|
delete wsp;
|
|
}
|
|
|
|
}else{
|
|
///////////////////////////////////////////////////////////////////
|
|
//////////////////////////!!!! careful!!!!!///////////////////////
|
|
//////////////////////////////////////////////////////////////////
|
|
ShortestPath_InRegion(r, &p1, &p2, sp_path);
|
|
}
|
|
|
|
if(sp_path->Size() == 0){
|
|
if(p1.Distance(p2) < EPSDIST){//the position happens to be the door
|
|
Line3D* l3d = new Line3D(0);
|
|
l3d->StartBulkLoad();
|
|
Point3D q(true, p1.GetX(), p1.GetY(), h);
|
|
*l3d += q;
|
|
l3d->EndBulkLoad();
|
|
candidate_path.push_back(*l3d);
|
|
l3d->DeleteIfAllowed();
|
|
}
|
|
sp_path->DeleteIfAllowed();
|
|
continue;
|
|
}
|
|
/////////////////////////////////////////////////////////////////////
|
|
SimpleLine* sl = new SimpleLine(0);
|
|
sl->fromLine(*sp_path);
|
|
SpacePartition* sp = new SpacePartition();
|
|
vector<MyHalfSegment> mhs;
|
|
sp->ReorderLine(sl, mhs);
|
|
delete sp;
|
|
|
|
sl->DeleteIfAllowed();
|
|
sp_path->DeleteIfAllowed();
|
|
|
|
|
|
// cout<<mhs[0].from.Distance(p1)<<" "
|
|
// <<mhs[mhs.size() - 1].to.Distance(p2)<<endl;
|
|
|
|
// cout<<" from "<<mhs[0].from<<" to "<<mhs[mhs.size() - 1].to<<endl;
|
|
|
|
if(mhs[0].from.Distance(p1) < dist_delta &&
|
|
mhs[mhs.size() - 1].to.Distance(p2) < dist_delta){
|
|
|
|
}else{
|
|
|
|
assert(mhs[mhs.size() - 1].to.Distance(p1) < dist_delta &&
|
|
mhs[0].from.Distance(p2) < dist_delta);
|
|
|
|
vector<MyHalfSegment> temp_mhs;
|
|
for(int i = mhs.size() - 1;i >= 0;i--){
|
|
MyHalfSegment seg = mhs[i];
|
|
Point p = seg.from;
|
|
seg.from = seg.to;
|
|
seg.to = p;
|
|
temp_mhs.push_back(seg);
|
|
}
|
|
mhs.clear();
|
|
for(unsigned int i = 0;i < temp_mhs.size();i++)
|
|
mhs.push_back(temp_mhs[i]);
|
|
assert(mhs[0].from.Distance(p1) < dist_delta &&
|
|
mhs[mhs.size() - 1].to.Distance(p2) < dist_delta);
|
|
}
|
|
///////////////////////////////////////////////////////////////////
|
|
///////////////////construct 3D line//////////////////////////////
|
|
///////////////////////////////////////////////////////////////////
|
|
Line3D* l3d = new Line3D(0);
|
|
l3d->StartBulkLoad();
|
|
|
|
for(unsigned int i = 0;i < mhs.size();i++){
|
|
Point p = mhs[i].from;
|
|
Point3D q(true, p.GetX(), p.GetY(), h);
|
|
*l3d += q;
|
|
if(i == mhs.size() - 1){
|
|
Point temp_p = mhs[i].to;
|
|
Point3D q1(true, temp_p.GetX(), temp_p.GetY(), h);
|
|
*l3d += q1;
|
|
}
|
|
}
|
|
l3d->EndBulkLoad();
|
|
|
|
candidate_path.push_back(*l3d);
|
|
l3d->DeleteIfAllowed();
|
|
|
|
}
|
|
r->DeleteIfAllowed();
|
|
groom_tuple->DeleteIfAllowed();
|
|
if(complex_reg == 1)DeleteSecondoObj(obj_name);
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
build the connection from the start location to all doors in a staircase
|
|
|
|
*/
|
|
void IndoorNav::ConnectStartLocST(Tuple* groom_tuple, GenLoc* gloc,
|
|
vector<int> tid_list, vector<Line3D>& candidate_path)
|
|
{
|
|
unsigned int groom_oid = gloc->GetOid();
|
|
|
|
GRoom* groom = (GRoom*)groom_tuple->GetAttribute(I_Room);
|
|
Region* reg = new Region(0);
|
|
groom->GetRegion(*reg);
|
|
BBox<2> bbox = reg->BoundingBox();
|
|
reg->DeleteIfAllowed();
|
|
|
|
Point loc1;
|
|
Coord x_cord1 = gloc->GetLoc().loc1 + bbox.MinD(0);
|
|
Coord y_cord1 = gloc->GetLoc().loc2 + bbox.MinD(1);
|
|
loc1.Set(x_cord1, y_cord1); //absolute position
|
|
float h1 = GetHeightInST(groom, loc1);
|
|
|
|
Relation* node_rel = ig->GetNodeRel();
|
|
for(unsigned int j = 0;j < tid_list.size();j++){
|
|
int door_tid = tid_list[j];
|
|
// cout<<"door tid "<<door_tid<<endl;
|
|
Tuple* door_tuple = node_rel->GetTuple(door_tid, false);
|
|
unsigned int gri2 =
|
|
((CcInt*)door_tuple->GetAttribute(IndoorGraph::I_GROOM_OID1))->GetIntval();
|
|
|
|
assert(gri2 == groom_oid);
|
|
///////////////////////////////////////////////////////////////////
|
|
/////////////////get the position of the door//////////////////////
|
|
///////////////////////////////////////////////////////////////////
|
|
Line* l = (Line*)door_tuple->GetAttribute(IndoorGraph::I_DOOR_LOC);
|
|
assert(l->Size() == 2);
|
|
HalfSegment hs;
|
|
l->Get(0, hs);
|
|
double x2 = (hs.GetLeftPoint().GetX() + hs.GetRightPoint().GetX())/2;
|
|
double y2 = (hs.GetLeftPoint().GetY() + hs.GetRightPoint().GetY())/2;
|
|
|
|
Line3D* l3 = (Line3D*)door_tuple->GetAttribute(IndoorGraph::I_DOOR_LOC_3D);
|
|
Point3D temp3d_p;
|
|
l3->Get(0, temp3d_p);
|
|
float h2 = temp3d_p.GetZ();
|
|
door_tuple->DeleteIfAllowed();
|
|
|
|
Point loc2(true, x2, y2);
|
|
ComputePath3DST(groom, loc1, loc2, h1, h2, candidate_path);
|
|
///////////////////////////////////////////////////////////////////////
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
the door is connected to a room which has only one entrance, and the entrance
|
|
equals to the door
|
|
|
|
an example query: loc1 oid 342 (2.65 0.96 ) loc2 oid 74 (1.99 9.21 )
|
|
shortest path in minimum length
|
|
|
|
include dead door for connecton:
|
|
Total runtime ... Times (elapsed / cpu): 39.8204sec / 39.03sec = 1.02025
|
|
Total runtime ... Times (elapsed / cpu): 3.78682sec / 3.73sec = 1.01523
|
|
|
|
do not include dead door:
|
|
Total runtime ... Times (elapsed / cpu): 2.73761sec / 2.74sec = 0.999128
|
|
Total runtime ... Times (elapsed / cpu): 0.828596sec / 0.83sec = 0.998308
|
|
|
|
big improvement
|
|
|
|
shortest path in time
|
|
Times (elapsed / cpu): 7.82145sec / 7.81sec = 1.00147
|
|
Times (elapsed / cpu): 1:03min (62.6424sec) /61.33sec = 1.0214
|
|
|
|
|
|
Times (elapsed / cpu): 2.22701sec / 2.22sec = 1.00316
|
|
Times (elapsed / cpu): 6.33788sec / 6.33sec = 1.00124
|
|
|
|
shortest path in room
|
|
|
|
Times (elapsed / cpu): 1:34min (94.291sec) /92.23sec = 1.02235
|
|
Times (elapsed / cpu): 3.27043sec / 3.26sec = 1.0032
|
|
|
|
*/
|
|
bool IndoorNav::DeadDoor(int door_tid, int groomoid, int groom_oid_end,
|
|
vector<Point3D>& door_list)
|
|
{
|
|
// cout<<"check Dead Door"<<endl;
|
|
Tuple* door_tuple = ig->GetNodeRel()->GetTuple(door_tid, false);
|
|
int gri1 =
|
|
((CcInt*)door_tuple->GetAttribute(IndoorGraph::I_GROOM_OID1))->GetIntval();
|
|
|
|
int gri2 =
|
|
((CcInt*)door_tuple->GetAttribute(IndoorGraph::I_GROOM_OID2))->GetIntval();
|
|
|
|
Line3D* l3d1 = (Line3D*)door_tuple->GetAttribute(IndoorGraph::I_DOOR_LOC_3D);
|
|
Point3D p3d_1, p3d_2;
|
|
l3d1->Get(0, p3d_1);
|
|
l3d1->Get(1, p3d_2);
|
|
Point3D p3d1(true, (p3d_1.GetX() + p3d_2.GetX())/2,
|
|
(p3d_1.GetY() + p3d_2.GetY())/2, p3d_1.GetZ());
|
|
|
|
door_tuple->DeleteIfAllowed();
|
|
int groom_oid;
|
|
if(gri1 == groomoid)
|
|
groom_oid = gri2;
|
|
else if(gri2 == groomoid)
|
|
groom_oid = gri1;
|
|
else assert(false);
|
|
|
|
// cout<<l3d1->Size()<<" p3d1 "<<p3d1<<endl;
|
|
// cout<<"groom oid "<<groom_oid<<endl;
|
|
BTree* btree = ig->GetBTree();
|
|
CcInt* search_id = new CcInt(true, groom_oid);
|
|
BTreeIterator* btree_iter = btree->ExactMatch(search_id);
|
|
vector<int> tid_list;
|
|
const double delta_dist = 0.001;
|
|
while(btree_iter->Next()){
|
|
Tuple* tuple = ig->GetNodeRel()->GetTuple(btree_iter->GetId(), false);
|
|
int tid = tuple->GetTupleId();
|
|
if(groom_oid == groom_oid_end){////////////the end room
|
|
tid_list.push_back(tid);
|
|
tuple->DeleteIfAllowed();
|
|
continue;
|
|
}
|
|
// int gr1 =
|
|
// ((CcInt*)tuple->GetAttribute(IndoorGraph::I_GROOM_OID1))->GetIntval();
|
|
// int gr2 =
|
|
// ((CcInt*)tuple->GetAttribute(IndoorGraph::I_GROOM_OID2))->GetIntval();
|
|
//
|
|
// if(!((gri1 == gr1 && gri2 == gr2) ||(gri1 == gr2 && gri2 == gr1))){
|
|
// tid_list.push_back(tid);
|
|
// }
|
|
|
|
Line3D* l3d2 = (Line3D*)tuple->GetAttribute(IndoorGraph::I_DOOR_LOC_3D);
|
|
Point3D q3d_1, q3d_2;
|
|
l3d2->Get(0, q3d_1);
|
|
l3d2->Get(1, q3d_2);
|
|
Point3D p3d2(true, (q3d_1.GetX() + q3d_2.GetX())/2,
|
|
(q3d_1.GetY() + q3d_2.GetY())/2, q3d_1.GetZ());
|
|
// cout<<l3d2->Size()<<" p3d2 "<<p3d2<<endl;
|
|
if(p3d1.Distance(p3d2) < delta_dist){//////////the same door
|
|
|
|
tuple->DeleteIfAllowed();
|
|
continue;
|
|
}
|
|
|
|
|
|
tid_list.push_back(tid);
|
|
tuple->DeleteIfAllowed();
|
|
}
|
|
delete btree_iter;
|
|
delete search_id;
|
|
|
|
// cout<<"door tid "<<door_tid<<" "<<tid_list.size()<<endl;
|
|
if(tid_list.size() > 0){
|
|
//////////////////////////////////////////////////////////////
|
|
/////////the door with the same location is included already//
|
|
/////////////////////////////////////////////////////////////
|
|
// cout<<"check door pos "<<p3d1<<endl;
|
|
unsigned int i = 0;
|
|
for(;i < door_list.size();i++){
|
|
// cout<<"exist door "<<door_list[i]<<endl;
|
|
if(p3d1.Distance(door_list[i]) < delta_dist) return true;
|
|
}
|
|
door_list.push_back(p3d1);
|
|
return false;
|
|
}
|
|
else
|
|
return true;
|
|
}
|
|
|
|
|
|
/*
|
|
check whether the two locations are equal to each other
|
|
|
|
*/
|
|
bool IndoorNav::IsLocEqual(GenLoc* gloc1, GenLoc* gloc2, Relation* rel)
|
|
{
|
|
int groom_oid1 = gloc1->GetOid();
|
|
int groom_oid2 = gloc2->GetOid();
|
|
|
|
assert(1 <= groom_oid1 && groom_oid1 <= rel->GetNoTuples());
|
|
assert(1 <= groom_oid2 && groom_oid2 <= rel->GetNoTuples());
|
|
|
|
Tuple* groom_tuple1 = rel->GetTuple(groom_oid1, false);
|
|
Tuple* groom_tuple2 = rel->GetTuple(groom_oid2, false);
|
|
GRoom* groom1 = (GRoom*)groom_tuple1->GetAttribute(I_Room);
|
|
GRoom* groom2 = (GRoom*)groom_tuple2->GetAttribute(I_Room);
|
|
|
|
Region* reg1 = new Region(0);
|
|
Region* reg2 = new Region(0);
|
|
groom1->GetRegion(*reg1);
|
|
groom2->GetRegion(*reg2);
|
|
BBox<2> bbox1 = reg1->BoundingBox();
|
|
BBox<2> bbox2 = reg2->BoundingBox();
|
|
|
|
float h1 = groom1->GetLowHeight();
|
|
float h2 = groom2->GetLowHeight();
|
|
|
|
reg1->DeleteIfAllowed();
|
|
reg2->DeleteIfAllowed();
|
|
groom_tuple1->DeleteIfAllowed();
|
|
groom_tuple2->DeleteIfAllowed();
|
|
|
|
double x1 = gloc1->GetLoc().loc1 + bbox1.MinD(0);
|
|
double y1 = gloc1->GetLoc().loc2 + bbox1.MinD(1);
|
|
|
|
double x2 = gloc2->GetLoc().loc1 + bbox2.MinD(0);
|
|
double y2 = gloc2->GetLoc().loc2 + bbox2.MinD(1);
|
|
|
|
Point3D p1(true, x1, y1, h1);
|
|
Point3D p2(true, x2, y2, h2);
|
|
|
|
const double dist_delta = 0.001;
|
|
if(p1.Distance(p2) < dist_delta) return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
two locations are in the same room
|
|
|
|
*/
|
|
void IndoorNav::PathInOneRoom(GenLoc* gloc1, GenLoc* gloc2,
|
|
Relation* rel, BTree* btree)
|
|
{
|
|
int groom_oid = gloc1->GetOid();
|
|
///////////////find the room////////////////////////////////////////////
|
|
CcInt* search_id = new CcInt(true, groom_oid);
|
|
BTreeIterator* btree_iter = btree->ExactMatch(search_id);
|
|
int groom_tid = 0;
|
|
while(btree_iter->Next()){
|
|
groom_tid = btree_iter->GetId();
|
|
break;
|
|
}
|
|
delete btree_iter;
|
|
delete search_id;
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
// Tuple* groom_tuple = rel->GetTuple(groom_oid, false);
|
|
assert(1<= groom_tid && groom_tid <= rel->GetNoTuples());
|
|
|
|
Tuple* groom_tuple = rel->GetTuple(groom_tid, false);
|
|
string type = ((CcString*)groom_tuple->GetAttribute(I_Type))->GetValue();
|
|
//////////////////////////////////////////////////////////////////////////
|
|
if(GetRoomEnum(type) == ST){//////////location is in the staircase
|
|
Line3D* l3d = new Line3D(0);
|
|
PathInOneST(groom_tuple, gloc1, gloc2, l3d);
|
|
groom_tuple->DeleteIfAllowed();
|
|
path_list.push_back(*l3d);
|
|
l3d->DeleteIfAllowed();
|
|
return;
|
|
}
|
|
|
|
|
|
if(GetRoomEnum(type) == EL){
|
|
groom_tuple->DeleteIfAllowed();
|
|
Line3D* l3d = new Line3D(0);
|
|
path_list.push_back(*l3d);
|
|
l3d->DeleteIfAllowed();
|
|
cout<<"inside the elevator. not interesting places"<<endl;
|
|
cout<<"it should not arrive here"<<endl;
|
|
return;
|
|
}
|
|
|
|
|
|
GRoom* groom = (GRoom*)groom_tuple->GetAttribute(I_Room);
|
|
Region* reg = new Region(0);
|
|
groom->GetRegion(*reg);
|
|
BBox<2> bbox = reg->BoundingBox();
|
|
float h = groom->GetLowHeight();
|
|
|
|
|
|
double x1 = gloc1->GetLoc().loc1 + bbox.MinD(0);
|
|
double y1 = gloc1->GetLoc().loc2 + bbox.MinD(1);
|
|
|
|
double x2 = gloc2->GetLoc().loc1 + bbox.MinD(0);
|
|
double y2 = gloc2->GetLoc().loc2 + bbox.MinD(1);
|
|
|
|
Point p1(true, x1, y1);
|
|
Point p2(true, x2, y2);
|
|
|
|
// cout<<"p1 "<<p1<<" p2"<<p2<<endl;
|
|
|
|
vector<MyHalfSegment> mhs;
|
|
|
|
FindPathInRegion(groom, h, mhs, &p1, &p2);
|
|
|
|
reg->DeleteIfAllowed();
|
|
groom_tuple->DeleteIfAllowed();
|
|
|
|
///////////////// conver to 3D line //////////////////////////////
|
|
Line3D* l3d = new Line3D(0);
|
|
l3d->StartBulkLoad();
|
|
|
|
for(unsigned int i = 0;i < mhs.size();i++){
|
|
Point p = mhs[i].from;
|
|
Point3D q(true, p.GetX(), p.GetY(), h);
|
|
*l3d += q;
|
|
if(i == mhs.size() - 1){
|
|
Point p1 = mhs[i].to;
|
|
Point3D q1(true, p1.GetX(), p1.GetY(), h);
|
|
*l3d += q1;
|
|
}
|
|
}
|
|
l3d->EndBulkLoad();
|
|
|
|
path_list.push_back(*l3d);
|
|
l3d->DeleteIfAllowed();
|
|
}
|
|
|
|
/*
|
|
find the path from one door (id1) to another (id2)
|
|
|
|
*/
|
|
inline bool IndoorNav::MiddlePoint(Line3D* l, Point3D& p)
|
|
{
|
|
if(l->Size() != 2) return false;
|
|
Point3D q1, q2;
|
|
l->Get(0, q1);
|
|
l->Get(1, q2);
|
|
|
|
double x = (q1.GetX() + q2.GetX())/2;
|
|
double y = (q1.GetY() + q2.GetY())/2;
|
|
double z = (q1.GetZ() + q2.GetZ())/2;
|
|
|
|
Point3D result(true, x, y, z);
|
|
p = result;
|
|
return true;
|
|
}
|
|
|
|
|
|
/*
|
|
compute the shortest in a staircase. two locations are in the same staircase
|
|
|
|
*/
|
|
void IndoorNav::PathInOneST(Tuple* groom_tuple, GenLoc* gloc1, GenLoc* gloc2,
|
|
Line3D* l3d)
|
|
{
|
|
// cout<<"PathInOneST "<<endl;
|
|
GRoom* groom = (GRoom*)groom_tuple->GetAttribute(I_Room);
|
|
Region* reg = new Region(0);
|
|
groom->GetRegion(*reg);
|
|
BBox<2> bbox = reg->BoundingBox();
|
|
reg->DeleteIfAllowed();
|
|
|
|
Point loc1, loc2;
|
|
Coord x_cord1 = gloc1->GetLoc().loc1 + bbox.MinD(0);
|
|
Coord y_cord1 = gloc1->GetLoc().loc2 + bbox.MinD(1);
|
|
loc1.Set(x_cord1, y_cord1); //absolute position
|
|
|
|
Coord x_cord2 = gloc2->GetLoc().loc1 + bbox.MinD(0);
|
|
Coord y_cord2 = gloc2->GetLoc().loc2 + bbox.MinD(1);
|
|
loc2.Set(x_cord2, y_cord2); //absolute position
|
|
|
|
float h1 = GetHeightInST(groom, loc1);
|
|
float h2 = GetHeightInST(groom, loc2);
|
|
|
|
vector<Line3D> path_line3d;
|
|
ComputePath3DST(groom, loc1, loc2, h1, h2, path_line3d);
|
|
if(path_line3d.size() == 1)
|
|
l3d = &path_line3d[0];
|
|
else
|
|
assert(false);
|
|
|
|
|
|
}
|
|
/*
|
|
compute the shortest path from one door to another door
|
|
|
|
*/
|
|
void IndoorNav::IndoorShortestPath(int id1, int id2,
|
|
vector<Line3D>& candidate_path,
|
|
Line3D* l3d_s, Line3D* l3d_d,
|
|
double& prune_dist,
|
|
float min_h, float max_h,
|
|
int start_groom_oid)
|
|
{
|
|
// cout<<"start_groom_oid "<<start_groom_oid<<endl;
|
|
|
|
// cout<<"min_h "<<min_h<<" max_h "<<max_h<<endl;
|
|
// cout<<"prune_dist "<<prune_dist<<endl;
|
|
const double dist_delta = 0.001;
|
|
// cout<<"IndoorShortestPath "<<"doorid1 "<<id1<<" doorid2 "<<id2<<endl;
|
|
if(id1 == id2){
|
|
cout<<"two doors are equal"<<endl;
|
|
// assert(false);
|
|
return;
|
|
}
|
|
|
|
Relation* node_rel = ig->GetNodeRel();
|
|
|
|
Tuple* door_tuple1 = node_rel->GetTuple(id1, false);
|
|
Tuple* door_tuple2 = node_rel->GetTuple(id2, false);
|
|
Line3D* l3d1 = (Line3D*)door_tuple1->GetAttribute(IndoorGraph::I_DOOR_LOC_3D);
|
|
Line3D* l3d2 = (Line3D*)door_tuple2->GetAttribute(IndoorGraph::I_DOOR_LOC_3D);
|
|
|
|
Point3D start_p, end_p;
|
|
|
|
if(MiddlePoint(l3d1, start_p) == false ||
|
|
MiddlePoint(l3d2, end_p) == false){
|
|
cout<<"incorrect door "<<endl;
|
|
assert(false);
|
|
}
|
|
|
|
// start_p.Print();
|
|
// end_p.Print();
|
|
|
|
door_tuple1->DeleteIfAllowed();
|
|
door_tuple2->DeleteIfAllowed();
|
|
|
|
if(start_p.Distance(end_p) < dist_delta){////the same location
|
|
|
|
Line3D* l3d = new Line3D(0);
|
|
l3d->StartBulkLoad();
|
|
//////////////////connect to the start point////////////////////
|
|
for(int i = 0;i < l3d_s->Size() - 1;i++){
|
|
Point3D q;
|
|
l3d_s->Get(i, q);
|
|
*l3d += q;
|
|
}
|
|
///////////////////////////////////////////////////////////////
|
|
*l3d += start_p;
|
|
////////////////////connect to the end point/////////////////////
|
|
for(int i = 1;i < l3d_d->Size();i++){
|
|
Point3D q;
|
|
l3d_d->Get(i, q);
|
|
*l3d += q;
|
|
}
|
|
|
|
l3d->EndBulkLoad();
|
|
candidate_path.push_back(*l3d);
|
|
l3d->DeleteIfAllowed();
|
|
|
|
return;
|
|
}
|
|
|
|
priority_queue<IPath_elem> path_queue;
|
|
vector<IPath_elem> expand_queue;
|
|
|
|
vector<bool> visit_flag1;////////////door visit
|
|
for(int i = 1; i <= node_rel->GetNoTuples();i++)
|
|
visit_flag1.push_back(false);
|
|
|
|
|
|
// ofstream output("debug.txt");
|
|
/////////// initialize the queue //////////////////////////////
|
|
InitializeQueue(id1, &start_p, &end_p, path_queue, expand_queue);
|
|
////////////////////////////////////////////////////////////////
|
|
bool find = false;
|
|
IPath_elem dest;//////////destination
|
|
|
|
|
|
while(path_queue.empty() == false){
|
|
IPath_elem top = path_queue.top();
|
|
path_queue.pop();
|
|
|
|
if(visit_flag1[top.tri_index - 1]) continue;
|
|
|
|
////////////larger than an existing value///////////////
|
|
if(prune_dist > 0.0 && top.real_w > prune_dist){
|
|
return;
|
|
}
|
|
/////////////////////////////////////////////////////////////
|
|
|
|
// top.Print();
|
|
|
|
if(top.tri_index == id2){
|
|
// cout<<"find the shortest path"<<endl;
|
|
find = true;
|
|
dest = top;
|
|
break;
|
|
}
|
|
|
|
Tuple* door_tuple = node_rel->GetTuple(top.tri_index, false);
|
|
/////////////////get the position of the door////////////////////////////
|
|
Point3D q;
|
|
Line3D* door_loc =
|
|
(Line3D*)door_tuple->GetAttribute(IndoorGraph::I_DOOR_LOC_3D);
|
|
assert(MiddlePoint(door_loc, q));
|
|
// int groom_oid1 =
|
|
// ((CcInt*)door_tuple->GetAttribute(IndoorGraph::I_GROOM_OID1))->GetIntval();
|
|
// int groom_oid2 =
|
|
// ((CcInt*)door_tuple->GetAttribute(IndoorGraph::I_GROOM_OID2))->GetIntval();
|
|
|
|
door_tuple->DeleteIfAllowed();
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
////////////////out of the height range///////////////////////////
|
|
///////////////////////////////////////////////////////////////////
|
|
// for the train station, the same height on different platform
|
|
// can not be pruned
|
|
if(fabs(min_h - max_h) > EPSDIST){ //not equal to each other
|
|
if(q.GetZ() - max_h > dist_delta || min_h - q.GetZ() > dist_delta){
|
|
continue;
|
|
}
|
|
}
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
|
|
// output<<"top door goid1 "<<groom_oid1<<" goid2 "<<groom_oid2<<endl;
|
|
|
|
////////find its adjacecy element, and push them into queue and path//////
|
|
vector<int> adj_list;
|
|
ig->FindAdj(top.tri_index, adj_list);
|
|
|
|
/////////////////////////////////////////////////////////////
|
|
int pos_expand_path = top.cur_index;
|
|
|
|
for(unsigned int i = 0;i < adj_list.size();i++){
|
|
|
|
Tuple* edge_tuple = ig->GetEdgeRel()->GetTuple(adj_list[i], false);
|
|
int neighbor_id =
|
|
((CcInt*)edge_tuple->GetAttribute(IndoorGraph::I_DOOR_TID2))->GetIntval();
|
|
Line3D* path = (Line3D*)edge_tuple->GetAttribute(IndoorGraph::I_PATH);
|
|
|
|
int groom_oid =
|
|
((CcInt*)edge_tuple->GetAttribute(IndoorGraph::I_GROOM_OID))->GetIntval();
|
|
|
|
if(visit_flag1[neighbor_id - 1]){
|
|
// output<<"door visit already"<<endl;
|
|
edge_tuple->DeleteIfAllowed();
|
|
continue;
|
|
}
|
|
if(groom_oid == start_groom_oid){
|
|
edge_tuple->DeleteIfAllowed();
|
|
continue;
|
|
}
|
|
|
|
Tuple* door_tuple1 = node_rel->GetTuple(neighbor_id, false);
|
|
|
|
Line3D* l = (Line3D*)door_tuple1->GetAttribute(IndoorGraph::I_DOOR_LOC_3D);
|
|
Point3D p;
|
|
|
|
assert(MiddlePoint(l, p));//get the point of next door
|
|
door_tuple1->DeleteIfAllowed();
|
|
|
|
if(fabs(min_h - max_h) > EPSDIST){//train station, different platforms
|
|
if(p.GetZ() - max_h > dist_delta || min_h - p.GetZ() > dist_delta){
|
|
edge_tuple->DeleteIfAllowed();
|
|
continue;
|
|
}
|
|
}
|
|
|
|
int cur_size = expand_queue.size();
|
|
|
|
double w = top.real_w + path->Length();
|
|
double hw = p.Distance(end_p);
|
|
IPath_elem elem(pos_expand_path, cur_size,
|
|
neighbor_id, w + hw, w, *path);
|
|
path_queue.push(elem);
|
|
expand_queue.push_back(elem);
|
|
|
|
edge_tuple->DeleteIfAllowed();
|
|
}
|
|
|
|
visit_flag1[top.tri_index - 1] = true;
|
|
|
|
}
|
|
|
|
////////////////construct the result//////////////////////////////
|
|
if(find){
|
|
|
|
vector<Point3D> ps_list;
|
|
while(dest.prev_index != -1){
|
|
// cout<<"sub path "<<endl;
|
|
// dest.Print();
|
|
if(dest.path.Size() > 0){
|
|
if(ps_list.size() == 0){
|
|
for(int i = dest.path.Size() - 1;i >= 0;i--){
|
|
Point3D q;
|
|
dest.path.Get(i, q);
|
|
ps_list.push_back(q);
|
|
}
|
|
}else{
|
|
for(int i = dest.path.Size() - 2;i >= 0;i--){
|
|
Point3D q;
|
|
dest.path.Get(i, q);
|
|
ps_list.push_back(q);
|
|
}
|
|
}
|
|
}
|
|
dest = expand_queue[dest.prev_index];
|
|
}
|
|
// cout<<"sub path"<<endl;
|
|
// dest.path.Print();
|
|
if(dest.path.Size() > 0){
|
|
for(int i = dest.path.Size() - 2;i >= 0;i--){
|
|
Point3D q;
|
|
dest.path.Get(i, q);
|
|
ps_list.push_back(q);
|
|
}
|
|
}
|
|
|
|
Line3D* l3d = new Line3D(0);
|
|
l3d->StartBulkLoad();
|
|
//////////////////connect to the start point////////////////////
|
|
for(int i = 0;i < l3d_s->Size() - 1;i++){
|
|
Point3D q;
|
|
l3d_s->Get(i, q);
|
|
*l3d += q;
|
|
}
|
|
///////////////////////////////////////////////////////////////
|
|
|
|
for(int i = ps_list.size() - 1;i >= 0; i--){
|
|
*l3d += ps_list[i];
|
|
}
|
|
////////////////////connect to the end point/////////////////////
|
|
|
|
for(int i = 1;i < l3d_d->Size();i++){
|
|
Point3D q;
|
|
l3d_d->Get(i, q);
|
|
*l3d += q;
|
|
}
|
|
|
|
|
|
l3d->EndBulkLoad();
|
|
candidate_path.push_back(*l3d);
|
|
|
|
if(prune_dist < 0.0){
|
|
prune_dist = l3d->Length();
|
|
}else if(l3d->Length() < prune_dist){
|
|
prune_dist = l3d->Length();
|
|
}
|
|
|
|
// cout<<"length: "<<l3d->Length()<<endl;
|
|
l3d->DeleteIfAllowed();
|
|
}else{
|
|
// cout<<"no path available "<<endl;
|
|
Line3D* l3d = new Line3D(0);
|
|
l3d->StartBulkLoad();
|
|
l3d->EndBulkLoad();
|
|
candidate_path.push_back(*l3d);
|
|
l3d->DeleteIfAllowed();
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
Initialize the queue, put the start door into the queue
|
|
|
|
*/
|
|
void IndoorNav::InitializeQueue(int id, Point3D* start_p,
|
|
Point3D* end_p,
|
|
priority_queue<IPath_elem>& path_queue,
|
|
vector<IPath_elem>& expand_queue)
|
|
{
|
|
// cout<<"InitializeQueue "<<endl;
|
|
|
|
int cur_size = expand_queue.size();
|
|
|
|
double w = 0.0;
|
|
double hw = start_p->Distance(*end_p);
|
|
Line3D* l3d = new Line3D(0);
|
|
IPath_elem elem(-1, cur_size, id, w + hw, w, *l3d);
|
|
path_queue.push(elem);
|
|
expand_queue.push_back(elem);
|
|
l3d->DeleteIfAllowed();
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//////////////////////////minimum number of rooms////////////////////////////
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void IndoorNav::ShortestPath_Room(GenLoc* gloc1, GenLoc* gloc2,
|
|
Relation* rel, BTree* groom_btree)
|
|
{
|
|
|
|
if(IsLocEqual(gloc1, gloc2, rel)){
|
|
cout<<"the two locations are equal to each other"<<endl;
|
|
|
|
CcInt* search_id = new CcInt(true, gloc1->GetOid());
|
|
BTreeIterator* btree_iter = groom_btree->ExactMatch(search_id);
|
|
int groom_tid = 0;
|
|
while(btree_iter->Next()){
|
|
groom_tid = btree_iter->GetId();
|
|
break;
|
|
}
|
|
delete btree_iter;
|
|
delete search_id;
|
|
assert(1 <= groom_tid && groom_tid <= rel->GetNoTuples());
|
|
Tuple* groom_tuple = rel->GetTuple(groom_tid, false);
|
|
GRoom* groom = (GRoom*)groom_tuple->GetAttribute(I_Room);
|
|
|
|
groom_oid_list.push_back(gloc1->GetOid());
|
|
room_list.push_back(*groom);
|
|
groom_tuple->DeleteIfAllowed();
|
|
|
|
return;
|
|
}
|
|
unsigned int groom_oid1 = gloc1->GetOid();
|
|
unsigned int groom_oid2 = gloc2->GetOid();
|
|
// cout<<"groom oid1 "<<groom_oid1<<" groom oid2 "<<groom_oid2<<endl;
|
|
if(groom_oid1 == groom_oid2){
|
|
|
|
CcInt* search_id = new CcInt(true, groom_oid1);
|
|
BTreeIterator* btree_iter = groom_btree->ExactMatch(search_id);
|
|
int groom_tid = 0;
|
|
while(btree_iter->Next()){
|
|
groom_tid = btree_iter->GetId();
|
|
break;
|
|
}
|
|
delete btree_iter;
|
|
delete search_id;
|
|
assert(1 <= groom_tid && groom_tid <= rel->GetNoTuples());
|
|
Tuple* groom_tuple = rel->GetTuple(groom_tid, false);
|
|
GRoom* groom = (GRoom*)groom_tuple->GetAttribute(I_Room);
|
|
|
|
groom_oid_list.push_back(groom_oid1);
|
|
room_list.push_back(*groom);
|
|
groom_tuple->DeleteIfAllowed();
|
|
return;
|
|
}
|
|
|
|
|
|
Relation* node_rel = ig->GetNodeRel();
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
///////////////collect all doors in start room//////////////////////
|
|
///////////////////////////////////////////////////////////////////
|
|
BTree* btree = ig->GetBTree();
|
|
CcInt* search_id1 = new CcInt(true, groom_oid1);
|
|
BTreeIterator* btree_iter1 = btree->ExactMatch(search_id1);
|
|
vector<int> tid_list1;
|
|
vector<Point3D> door_start;
|
|
while(btree_iter1->Next()){
|
|
Tuple* tuple = node_rel->GetTuple(btree_iter1->GetId(), false);
|
|
int door_tid = tuple->GetTupleId();
|
|
if(DeadDoor(door_tid, groom_oid1, groom_oid2, door_start) == false)
|
|
tid_list1.push_back(door_tid);
|
|
tuple->DeleteIfAllowed();
|
|
}
|
|
delete btree_iter1;
|
|
delete search_id1;
|
|
|
|
float start_h1 = INVALID_HEIGHT;
|
|
float start_h2 = INVALID_HEIGHT;
|
|
GetHeightOfGRoom(groom_oid1, groom_btree, rel, start_h1, start_h2);
|
|
assert(start_h1 > INVALID_HEIGHT && start_h2 > INVALID_HEIGHT);
|
|
|
|
float min_h1 = MIN(start_h1, start_h2);
|
|
float max_h1 = MAX(start_h1, start_h2);
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
///////////////collect all doors in end room//////////////////////
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
CcInt* search_id2 = new CcInt(true, groom_oid2);
|
|
BTreeIterator* btree_iter2 = btree->ExactMatch(search_id2);
|
|
vector<int> tid_list2;
|
|
vector<Point3D> door_end;
|
|
while(btree_iter2->Next()){
|
|
Tuple* tuple = node_rel->GetTuple(btree_iter2->GetId(), false);
|
|
int door_tid = tuple->GetTupleId();
|
|
if(DeadDoor(door_tid, groom_oid2, groom_oid1, door_end) == false)
|
|
tid_list2.push_back(door_tid);
|
|
tuple->DeleteIfAllowed();
|
|
}
|
|
delete btree_iter2;
|
|
delete search_id2;
|
|
|
|
// cout<<"tid1 size "<<tid_list1.size()<<endl;
|
|
// cout<<"tid2 size "<<tid_list2.size()<<endl;
|
|
|
|
float end_h1 = INVALID_HEIGHT;
|
|
float end_h2 = INVALID_HEIGHT;
|
|
GetHeightOfGRoom(groom_oid2, groom_btree, rel, end_h1, end_h2);
|
|
assert(end_h1 > INVALID_HEIGHT && end_h2 > INVALID_HEIGHT);
|
|
|
|
float min_h2 = MIN(end_h1, end_h2);
|
|
float max_h2 = MAX(end_h1, end_h2);
|
|
|
|
float min_h = MIN(min_h1, min_h2);
|
|
float max_h = MAX(max_h1, max_h2);
|
|
|
|
////////////////////for each possible door, search the path/////////////
|
|
vector< vector<TupleId> > candidate_path;
|
|
int start_groom_oid = gloc1->GetOid();
|
|
|
|
int end_groom_oid = gloc2->GetOid();
|
|
|
|
for(unsigned int i = 0;i < tid_list1.size();i++){
|
|
// cout<<"source door tid "<<tid_list[i]<<endl;
|
|
Tuple* door_tuple1 = node_rel->GetTuple(tid_list1[i], false);
|
|
unsigned int gri1 =
|
|
((CcInt*)door_tuple1->GetAttribute(IndoorGraph::I_GROOM_OID1))->GetIntval();
|
|
assert(gri1 == groom_oid1);
|
|
|
|
|
|
for(unsigned int j = 0;j < tid_list2.size();j++){
|
|
|
|
Tuple* door_tuple2 = node_rel->GetTuple(tid_list2[j], false);
|
|
unsigned int gri2 =
|
|
((CcInt*)door_tuple2->GetAttribute(IndoorGraph::I_GROOM_OID1))->GetIntval();
|
|
|
|
assert(gri2 == groom_oid2);
|
|
IndoorShortestPath_Room(tid_list1[i], tid_list2[j], candidate_path,
|
|
start_groom_oid, end_groom_oid, min_h, max_h);
|
|
door_tuple2->DeleteIfAllowed();
|
|
|
|
}
|
|
|
|
door_tuple1->DeleteIfAllowed();
|
|
|
|
}
|
|
|
|
|
|
///////////////////select the path with minimum length////////////////////
|
|
if(candidate_path.size() > 0){
|
|
unsigned int l = candidate_path[0].size();
|
|
int index = 0;
|
|
for(unsigned int i = 1; i < candidate_path.size();i++){
|
|
// cout<<"i "<<i<<" length "<<candidate_path[i].Length()<<endl;
|
|
if(candidate_path[i].size() < l){
|
|
l = candidate_path[i].size();
|
|
index = i;
|
|
}
|
|
}
|
|
|
|
for(unsigned int i = 0;i < candidate_path[index].size();i++){
|
|
|
|
Tuple* groom_tuple = rel->GetTuple(candidate_path[index][i],false);
|
|
string type = ((CcString*)groom_tuple->GetAttribute(I_Type))->GetValue();
|
|
GRoom* groom = (GRoom*)groom_tuple->GetAttribute(I_Room);
|
|
if(GetRoomEnum(type) == EL){//process special part
|
|
vector<unsigned int> el_id;
|
|
el_id.push_back(candidate_path[index][i]);
|
|
unsigned int j = i + 1;
|
|
for(; j < candidate_path[index].size();j++){
|
|
Tuple* tuple = rel->GetTuple(candidate_path[index][j],false);
|
|
string groom_type =
|
|
((CcString*)tuple->GetAttribute(I_Type))->GetValue();
|
|
if(GetRoomEnum(groom_type) == EL)
|
|
el_id.push_back(candidate_path[index][j]);
|
|
else{
|
|
tuple->DeleteIfAllowed();
|
|
break;
|
|
}
|
|
tuple->DeleteIfAllowed();
|
|
}
|
|
|
|
assert(i != 0);
|
|
/////////start and end locations are in OR or CO/////////////
|
|
assert(j < candidate_path[index].size() - 1);//impossible to end in EL
|
|
|
|
Tuple* gr_tuple1 = rel->GetTuple(candidate_path[index][i - 1],false);
|
|
GRoom* groom1 = (GRoom*)gr_tuple1->GetAttribute(I_Room);
|
|
float h1 = groom1->GetLowHeight();
|
|
gr_tuple1->DeleteIfAllowed();
|
|
|
|
|
|
Tuple* gr_tuple2 = rel->GetTuple(candidate_path[index][j],false);
|
|
GRoom* groom2 = (GRoom*)gr_tuple2->GetAttribute(I_Room);
|
|
float h2 = groom2->GetLowHeight();
|
|
gr_tuple2->DeleteIfAllowed();
|
|
|
|
const double delta_d = 0.01;
|
|
Point center_p;
|
|
|
|
if(h1 < h2){////// add after
|
|
// cout<<"h1 < h2"<<" h1:"<<h1<<" h2: "<<h2<<endl;
|
|
for(unsigned int k = 0;k < el_id.size();k++){
|
|
Tuple* t = rel->GetTuple(el_id[k], false);
|
|
GRoom* gr = (GRoom*)t->GetAttribute(I_Room);
|
|
int groom_oid = ((CcInt*)t->GetAttribute(I_OID))->GetIntval();
|
|
groom_oid_list.push_back(groom_oid);
|
|
room_list.push_back(*gr);
|
|
|
|
// cout<<"oid "<<groom_oid<<endl;
|
|
if(k == 0){
|
|
Rectangle<2> gr_box = gr->BoundingBox();
|
|
double center_x = (gr_box.MinD(0) + gr_box.MaxD(0))/2;
|
|
double center_y = (gr_box.MinD(1) + gr_box.MaxD(1))/2;
|
|
center_p.Set(center_x, center_y);
|
|
}
|
|
|
|
t->DeleteIfAllowed();
|
|
}
|
|
|
|
for(int k = 1; k <= rel->GetNoTuples();k++){
|
|
Tuple* t = rel->GetTuple(k, false);
|
|
GRoom* gr = (GRoom*)t->GetAttribute(I_Room);
|
|
string groom_type =
|
|
((CcString*)t->GetAttribute(I_Type))->GetValue();
|
|
if(GetRoomEnum(groom_type) == EL &&
|
|
AlmostEqual(gr->GetLowHeight(), h2)){
|
|
|
|
Rectangle<2> box = gr->BoundingBox();
|
|
double x = (box.MinD(0) + box.MaxD(0))/2;
|
|
double y = (box.MinD(1) + box.MaxD(1))/2;
|
|
Point p(true, x, y);
|
|
|
|
/////several elevators, compare the center point /////
|
|
if(center_p.Distance(p) < delta_d){
|
|
int groom_oid =
|
|
((CcInt*)t->GetAttribute(I_OID))->GetIntval();
|
|
groom_oid_list.push_back(groom_oid);
|
|
// cout<<"groom oid "<<groom_oid<<endl;
|
|
|
|
room_list.push_back(*gr);
|
|
t->DeleteIfAllowed();
|
|
break;
|
|
}
|
|
}
|
|
|
|
t->DeleteIfAllowed();
|
|
}
|
|
|
|
}else{//add before
|
|
// cout<<"h1 > h2 "<<"h1 :"<<h1<<" h2: "<<h2<<endl;
|
|
|
|
Tuple* t = rel->GetTuple(el_id[0], false);
|
|
GRoom* gr = (GRoom*)t->GetAttribute(I_Room);
|
|
Rectangle<2> gr_box = gr->BoundingBox();
|
|
double center_x = (gr_box.MinD(0) + gr_box.MaxD(0))/2;
|
|
double center_y = (gr_box.MinD(1) + gr_box.MaxD(1))/2;
|
|
center_p.Set(center_x, center_y);
|
|
t->DeleteIfAllowed();
|
|
|
|
|
|
for(int k = 1; k <= rel->GetNoTuples();k++){
|
|
Tuple* t = rel->GetTuple(k, false);
|
|
GRoom* gr = (GRoom*)t->GetAttribute(I_Room);
|
|
string groom_type =
|
|
((CcString*)t->GetAttribute(I_Type))->GetValue();
|
|
if(GetRoomEnum(groom_type) == EL &&
|
|
AlmostEqual(gr->GetLowHeight(), h1)){
|
|
|
|
|
|
Rectangle<2> box = gr->BoundingBox();
|
|
double x = (box.MinD(0) + box.MaxD(0))/2;
|
|
double y = (box.MinD(1) + box.MaxD(1))/2;
|
|
Point p(true, x, y);
|
|
|
|
if(center_p.Distance(p) < delta_d){
|
|
int groom_oid =
|
|
((CcInt*)t->GetAttribute(I_OID))->GetIntval();
|
|
groom_oid_list.push_back(groom_oid);
|
|
room_list.push_back(*gr);
|
|
t->DeleteIfAllowed();
|
|
// cout<<"find "<<endl;
|
|
break;
|
|
}
|
|
}
|
|
|
|
t->DeleteIfAllowed();
|
|
}
|
|
for(unsigned int k = 0;k < el_id.size();k++){
|
|
Tuple* t = rel->GetTuple(el_id[k], false);
|
|
GRoom* gr = (GRoom*)t->GetAttribute(I_Room);
|
|
int groom_oid = ((CcInt*)t->GetAttribute(I_OID))->GetIntval();
|
|
groom_oid_list.push_back(groom_oid);
|
|
room_list.push_back(*gr);
|
|
t->DeleteIfAllowed();
|
|
}
|
|
|
|
}
|
|
|
|
i = j - 1;
|
|
}else{
|
|
|
|
// groom_oid_list.push_back(candidate_path[index][i]);
|
|
int groom_oid = ((CcInt*)groom_tuple->GetAttribute(I_OID))->GetIntval();
|
|
groom_oid_list.push_back(groom_oid);
|
|
room_list.push_back(*groom);
|
|
}
|
|
groom_tuple->DeleteIfAllowed();
|
|
|
|
}
|
|
|
|
}else{
|
|
cout<<"no path available"<<endl;
|
|
}
|
|
}
|
|
|
|
/*
|
|
get the lowest and highest height of a groom
|
|
|
|
*/
|
|
void IndoorNav::GetHeightOfGRoom(int groom_oid, BTree* groom_btree,
|
|
Relation* rel,
|
|
float& start_h1, float& start_h2)
|
|
{
|
|
CcInt* search_id = new CcInt(true, groom_oid);
|
|
BTreeIterator* btree_iter = groom_btree->ExactMatch(search_id);
|
|
int groom_tid = 0;
|
|
while(btree_iter->Next()){
|
|
groom_tid = btree_iter->GetId();
|
|
break;
|
|
}
|
|
delete btree_iter;
|
|
delete search_id;
|
|
assert(1 <= groom_tid && groom_tid <= rel->GetNoTuples());
|
|
Tuple* groom_tuple = rel->GetTuple(groom_tid, false);
|
|
GRoom* groom = (GRoom*)groom_tuple->GetAttribute(I_Room);
|
|
start_h1 = groom->GetLowHeight();
|
|
start_h2 = groom->GetHighHeight();
|
|
groom_tuple->DeleteIfAllowed();
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
shortest path from one door to another door, decided by the number of rooms
|
|
|
|
*/
|
|
|
|
void IndoorNav::IndoorShortestPath_Room(int id1, int id2,
|
|
vector<vector<TupleId> >& candidate_path,
|
|
int s_room_oid, int e_room_oid,
|
|
float min_h, float max_h)
|
|
{
|
|
// cout<<"s_room_oid "<<s_room_oid<<" e_room_oid "<<e_room_oid<<endl;
|
|
const double dist_delta = 0.001;
|
|
|
|
if(id1 == id2){
|
|
cout<<"two doors are equal"<<endl;
|
|
// assert(false);
|
|
return;
|
|
}
|
|
|
|
Relation* node_rel = ig->GetNodeRel();
|
|
|
|
Tuple* door_tuple1 = node_rel->GetTuple(id1, false);
|
|
Tuple* door_tuple2 = node_rel->GetTuple(id2, false);
|
|
Line3D* l3d1 = (Line3D*)door_tuple1->GetAttribute(IndoorGraph::I_DOOR_LOC_3D);
|
|
Line3D* l3d2 = (Line3D*)door_tuple2->GetAttribute(IndoorGraph::I_DOOR_LOC_3D);
|
|
|
|
Point3D start_p, end_p;
|
|
|
|
if(MiddlePoint(l3d1, start_p) == false ||
|
|
MiddlePoint(l3d2, end_p) == false){
|
|
cout<<"incorrect door "<<endl;
|
|
assert(false);
|
|
}
|
|
|
|
|
|
door_tuple1->DeleteIfAllowed();
|
|
door_tuple2->DeleteIfAllowed();
|
|
|
|
if(start_p.Distance(end_p) < dist_delta){//two doors at the same location
|
|
vector<TupleId> temp_list;
|
|
temp_list.push_back(s_room_oid);
|
|
temp_list.push_back(e_room_oid);
|
|
candidate_path.push_back(temp_list);
|
|
return;
|
|
}
|
|
|
|
|
|
priority_queue<IPath_elem> path_queue;
|
|
vector<IPath_elem> expand_queue;
|
|
|
|
vector<bool> visit_flag1;////////////door visit
|
|
for(int i = 1; i <= node_rel->GetNoTuples();i++)
|
|
visit_flag1.push_back(false);
|
|
|
|
|
|
// ofstream output("debug.txt");
|
|
/////////// initialize the queue //////////////////////////////
|
|
int cur_size = expand_queue.size();
|
|
|
|
double w = 0.0;
|
|
// double hw = start_p.Distance(end_p);
|
|
double hw = 0.0;
|
|
Line3D* l3d = new Line3D(0);
|
|
IPath_elem elem(-1, cur_size, id1, w + hw, w, *l3d, s_room_oid);
|
|
path_queue.push(elem);
|
|
expand_queue.push_back(elem);
|
|
l3d->DeleteIfAllowed();
|
|
////////////////////////////////////////////////////////////////
|
|
bool find = false;
|
|
IPath_elem dest;//////////destination
|
|
while(path_queue.empty() == false){
|
|
IPath_elem top = path_queue.top();
|
|
path_queue.pop();
|
|
|
|
if(visit_flag1[top.tri_index - 1])continue;
|
|
|
|
if(top.tri_index == id2){
|
|
// cout<<"find the shortest path"<<endl;
|
|
find = true;
|
|
dest = top;
|
|
break;
|
|
}
|
|
|
|
// top.Print();
|
|
Tuple* door_tuple = node_rel->GetTuple(top.tri_index, false);
|
|
/////////////////get the position of the door////////////////////////////
|
|
Point3D q;
|
|
Line3D* door_loc =
|
|
(Line3D*)door_tuple->GetAttribute(IndoorGraph::I_DOOR_LOC_3D);
|
|
assert(MiddlePoint(door_loc, q));
|
|
|
|
door_tuple->DeleteIfAllowed();
|
|
|
|
if(fabs(min_h - max_h) > EPSDIST){//train station, different platforms
|
|
if(q.GetZ() - max_h > dist_delta || min_h - q.GetZ() > dist_delta){
|
|
continue;
|
|
}
|
|
}
|
|
|
|
////////find its adjacecy element, and push them into queue and path//////
|
|
vector<int> adj_list;
|
|
ig->FindAdj(top.tri_index, adj_list);
|
|
|
|
/////////////////////////////////////////////////////////////
|
|
int pos_expand_path = top.cur_index;
|
|
|
|
for(unsigned int i = 0;i < adj_list.size();i++){
|
|
|
|
Tuple* edge_tuple = ig->GetEdgeRel()->GetTuple(adj_list[i], false);
|
|
int neighbor_id =
|
|
((CcInt*)edge_tuple->GetAttribute(IndoorGraph::I_DOOR_TID2))->GetIntval();
|
|
Line3D* path = (Line3D*)edge_tuple->GetAttribute(IndoorGraph::I_PATH);
|
|
int groom_oid =
|
|
((CcInt*)edge_tuple->GetAttribute(IndoorGraph::I_GROOM_OID))->GetIntval();
|
|
|
|
if(visit_flag1[neighbor_id - 1]){
|
|
edge_tuple->DeleteIfAllowed();
|
|
continue;
|
|
}
|
|
|
|
if(groom_oid == s_room_oid){
|
|
edge_tuple->DeleteIfAllowed();
|
|
continue;
|
|
}
|
|
|
|
Tuple* door_tuple1 = node_rel->GetTuple(neighbor_id, false);
|
|
|
|
Line3D* l = (Line3D*)door_tuple1->GetAttribute(IndoorGraph::I_DOOR_LOC_3D);
|
|
Point3D p;
|
|
|
|
assert(MiddlePoint(l, p));//get the point of next door
|
|
door_tuple1->DeleteIfAllowed();
|
|
|
|
if(fabs(min_h - max_h) > EPSDIST){//train station, different platforms
|
|
if(p.GetZ() - max_h > dist_delta || min_h - p.GetZ() > dist_delta){
|
|
continue;
|
|
}
|
|
}
|
|
|
|
int cur_size = expand_queue.size();
|
|
|
|
// double w = top.real_w + path->Length();
|
|
// double hw = p.Distance(end_p);
|
|
double w = top.real_w;
|
|
if(path->Length() > 0.0) w++; //one more room
|
|
double hw = 0.0;
|
|
|
|
IPath_elem elem(pos_expand_path, cur_size,
|
|
neighbor_id, w + hw, w, *path, groom_oid);
|
|
path_queue.push(elem);
|
|
expand_queue.push_back(elem);
|
|
|
|
edge_tuple->DeleteIfAllowed();
|
|
}
|
|
|
|
visit_flag1[top.tri_index - 1] = true;
|
|
|
|
}
|
|
|
|
////////////////construct the result//////////////////////////////
|
|
if(find){
|
|
|
|
vector<int> groom_oid_list;
|
|
groom_oid_list.push_back(e_room_oid);
|
|
while(dest.prev_index != -1){
|
|
// cout<<"sub path "<<endl;
|
|
// dest.Print();
|
|
// cout<<"groom oid "<<dest.groom_oid<<endl;
|
|
if(dest.path.Size() > 0){
|
|
int oid = groom_oid_list[groom_oid_list.size() - 1];
|
|
if(oid != dest.groom_oid)
|
|
groom_oid_list.push_back(dest.groom_oid);
|
|
}
|
|
dest = expand_queue[dest.prev_index];
|
|
}
|
|
// cout<<"sub path"<<endl;
|
|
// dest.path.Print();
|
|
|
|
groom_oid_list.push_back(dest.groom_oid);
|
|
|
|
vector<TupleId> temp_list;
|
|
for(int i = groom_oid_list.size() - 1;i >= 0;i--){
|
|
// cout<<"groom_oid "<<groom_oid_list[i]<<endl;
|
|
temp_list.push_back(groom_oid_list[i]);
|
|
}
|
|
candidate_path.push_back(temp_list);
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//////////////// minimum travelling time////////////////////////////////
|
|
/////////////////////////////////////////////////////////////////////////
|
|
|
|
void IndoorNav::ShortestPath_Time(GenLoc* gloc1, GenLoc* gloc2,
|
|
Relation* rel, BTree* groom_btree)
|
|
{
|
|
if(IsLocEqual(gloc1, gloc2, rel)){
|
|
cout<<"the two locations are equal to each other"<<endl;
|
|
Line3D* l3d = new Line3D(0);
|
|
path_list.push_back(*l3d);
|
|
cost_list.push_back(0.0);
|
|
l3d->DeleteIfAllowed();
|
|
return;
|
|
}
|
|
|
|
////////////get some parameters///////////////////////////////////////
|
|
///// 1. the height of the elevator, 2. the number of floors ////////
|
|
///// 3. the average speed of people 4.the speed of the elevator /////
|
|
//////////// 1 = 4 /////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
vector<float> height_list;
|
|
float door_width = numeric_limits<float>::max(); //the speed for person
|
|
bool haselevator = false;
|
|
for(int i = 1;i <= rel->GetNoTuples();i++){
|
|
Tuple* groom_tuple = rel->GetTuple(i, false);
|
|
Line* door = (Line*)groom_tuple->GetAttribute(I_Door);
|
|
for(int j = 0;j < door->Size();j++){
|
|
HalfSegment hs;
|
|
door->Get(j, hs);
|
|
if(!hs.IsLeftDomPoint())continue;
|
|
if(hs.Length() < door_width)door_width = hs.Length();
|
|
}
|
|
string type =
|
|
((CcString*)groom_tuple->GetAttribute(I_Type))->GetValue();
|
|
if(GetRoomEnum(type) == EL){
|
|
GRoom* groom = (GRoom*)groom_tuple->GetAttribute(I_Room);
|
|
height_list.push_back(groom->GetLowHeight());
|
|
haselevator = true;
|
|
}
|
|
groom_tuple->DeleteIfAllowed();
|
|
}
|
|
sort(height_list.begin(), height_list.end());
|
|
|
|
|
|
float floor_height = 0;
|
|
if(height_list.size() >= 2){
|
|
floor_height = height_list[1] - height_list[0];
|
|
}
|
|
|
|
int num_floors = height_list.size();
|
|
|
|
// cout<<"floor height "<<floor_height<<endl; //the speed for elevator
|
|
|
|
float speed_person = door_width;
|
|
float speed_elevator = floor_height;
|
|
|
|
// cout<<"speed person "<<speed_person
|
|
// <<" speed elevator "<<speed_elevator<<endl;
|
|
|
|
struct I_Parameter param(num_floors, floor_height,
|
|
speed_person, speed_elevator);
|
|
////////////////two locations are inside the same room/////////////////////
|
|
|
|
unsigned int groom_oid1 = gloc1->GetOid();
|
|
unsigned int groom_oid2 = gloc2->GetOid();
|
|
|
|
if(groom_oid1 == groom_oid2){
|
|
PathInOneRoom(gloc1, gloc2, rel, groom_btree);
|
|
cost_list.push_back(path_list[0].Length() / speed_person);
|
|
return;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
|
|
Relation* node_rel = ig->GetNodeRel();
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
///////////////collect all doors in start room//////////////////////
|
|
///////////////////////////////////////////////////////////////////
|
|
BTree* btree = ig->GetBTree();
|
|
CcInt* search_id1 = new CcInt(true, groom_oid1);
|
|
BTreeIterator* btree_iter1 = btree->ExactMatch(search_id1);
|
|
vector<int> tid_list1;
|
|
vector<Point3D> door_start;
|
|
while(btree_iter1->Next()){
|
|
Tuple* tuple = node_rel->GetTuple(btree_iter1->GetId(), false);
|
|
int door_tid = tuple->GetTupleId();
|
|
if(DeadDoor(door_tid, groom_oid1, groom_oid2, door_start) == false)
|
|
tid_list1.push_back(door_tid);
|
|
tuple->DeleteIfAllowed();
|
|
}
|
|
delete btree_iter1;
|
|
delete search_id1;
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
///////////////collect all doors in end room//////////////////////
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
CcInt* search_id2 = new CcInt(true, groom_oid2);
|
|
BTreeIterator* btree_iter2 = btree->ExactMatch(search_id2);
|
|
vector<int> tid_list2;
|
|
vector<Point3D> door_end;
|
|
while(btree_iter2->Next()){
|
|
Tuple* tuple = node_rel->GetTuple(btree_iter2->GetId(), false);
|
|
int door_tid = tuple->GetTupleId();
|
|
if(DeadDoor(door_tid, groom_oid2, groom_oid1, door_end) == false)
|
|
tid_list2.push_back(door_tid);
|
|
tuple->DeleteIfAllowed();
|
|
}
|
|
delete btree_iter2;
|
|
delete search_id2;
|
|
|
|
|
|
// cout<<tid_list1.size()<<" "<<tid_list2.size()<<endl;
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
///////calculate once for the connection between start loc and its door//
|
|
/////////////////////////////////////////////////////////////////////////
|
|
vector<Line3D> start_door_path;
|
|
float start_h1 = INVALID_HEIGHT;
|
|
float start_h2 = INVALID_HEIGHT;
|
|
if(!ConnectStartLoc(gloc1, tid_list1, rel, groom_btree,
|
|
start_door_path, start_h1, start_h2)){
|
|
cout<<"connect start location to doors error"<<endl;
|
|
Line3D* l3d = new Line3D(0);
|
|
path_list.push_back(*l3d);
|
|
l3d->DeleteIfAllowed();
|
|
return;
|
|
}
|
|
|
|
assert(start_h1 > INVALID_HEIGHT && start_h2 > INVALID_HEIGHT);
|
|
|
|
float min_h1 = MIN(start_h1, start_h2);
|
|
float max_h1 = MAX(start_h1, start_h2);
|
|
|
|
vector<Line3D> end_door_path;
|
|
float end_h1 = INVALID_HEIGHT;
|
|
float end_h2 = INVALID_HEIGHT;
|
|
//////calculate once for the connection between end loc and all its door///
|
|
if(!ConnectEndLoc(gloc2, tid_list2, rel, groom_btree,
|
|
end_door_path, end_h1, end_h2)){
|
|
cout<<"connect end location to doors error"<<endl;
|
|
Line3D* l3d = new Line3D(0);
|
|
path_list.push_back(*l3d);
|
|
l3d->DeleteIfAllowed();
|
|
return;
|
|
}
|
|
|
|
assert(end_h1 > INVALID_HEIGHT && end_h2 > INVALID_HEIGHT);
|
|
float min_h2 = MIN(end_h1, end_h2);
|
|
float max_h2 = MAX(end_h1, end_h2);
|
|
|
|
float min_h = MIN(min_h1, min_h2);
|
|
float max_h = MAX(max_h1, max_h2);
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
////////////////////for each possible door, search the path/////////////
|
|
///////////////////////////////////////////////////////////////////////
|
|
vector<Line3D> candidate_path;
|
|
vector<double> timecost;
|
|
double prune_time = -1.0;
|
|
for(unsigned int i = 0;i < tid_list1.size();i++){
|
|
|
|
Tuple* door_tuple1 = node_rel->GetTuple(tid_list1[i], false);
|
|
unsigned int gri1 =
|
|
((CcInt*)door_tuple1->GetAttribute(IndoorGraph::I_GROOM_OID1))->GetIntval();
|
|
|
|
assert(gri1 == groom_oid1);
|
|
|
|
for(unsigned int j = 0;j < tid_list2.size();j++){
|
|
|
|
Tuple* door_tuple2 = node_rel->GetTuple(tid_list2[j], false);
|
|
unsigned int gri1 =
|
|
((CcInt*)door_tuple2->GetAttribute(IndoorGraph::I_GROOM_OID1))->GetIntval();
|
|
|
|
/*path with minimum travelling time.
|
|
it calculate two shortest paths: one is without elevator and the other
|
|
might include elevator. if it includes the elevator, then the cost on the
|
|
elevator is rest (uncertain value). Finally, compare the two costs. */
|
|
|
|
assert(gri1 == groom_oid2);
|
|
IndoorShortestPath_Time1(tid_list1[i], tid_list2[j], candidate_path,
|
|
&start_door_path[i], &end_door_path[j], timecost, param,
|
|
rel, groom_btree, prune_time, min_h, max_h, groom_oid1);
|
|
if(haselevator){
|
|
IndoorShortestPath_Time2(tid_list1[i], tid_list2[j], candidate_path,
|
|
&start_door_path[i], &end_door_path[j], timecost, param,
|
|
rel, groom_btree, prune_time, min_h, max_h, groom_oid1);
|
|
}
|
|
|
|
door_tuple2->DeleteIfAllowed();
|
|
}
|
|
|
|
door_tuple1->DeleteIfAllowed();
|
|
|
|
|
|
}
|
|
|
|
assert(candidate_path.size() == timecost.size());
|
|
///////////////////select the path with minimum length////////////////////
|
|
if(candidate_path.size() > 0 && timecost.size() > 0){
|
|
double l = timecost[0];
|
|
int index = 0;
|
|
for(unsigned int i = 1; i < timecost.size();i++){
|
|
if(timecost[i] < l){
|
|
l = timecost[i];
|
|
index = i;
|
|
}
|
|
}
|
|
|
|
path_list.push_back(candidate_path[index]);
|
|
cost_list.push_back(timecost[index]);
|
|
|
|
}else
|
|
cout<<"no path available"<<endl;
|
|
|
|
}
|
|
|
|
/*
|
|
the weight in the priority queue is changed to time instead of distance
|
|
A star algorithm can still be applied.
|
|
distance: Euclidean distance is set as the path length
|
|
speed: the maximum speed between person and elevator
|
|
heuristic value = distacne div speed
|
|
It searches the path without elevator
|
|
|
|
*/
|
|
void IndoorNav::IndoorShortestPath_Time1(int id1, int id2,
|
|
vector<Line3D>& candidate_path, Line3D* l3d_s,
|
|
Line3D* l3d_d, vector<double>& timecost,
|
|
I_Parameter& param, Relation* rel,
|
|
BTree* btree, double& prune_time,
|
|
float min_h, float max_h, int start_groom_oid)
|
|
{
|
|
// cout<<"IndoorShortestPath_Time1()"<<endl;
|
|
|
|
const double dist_delta = 0.001;
|
|
|
|
if(id1 == id2){
|
|
cout<<"two doors are equal"<<endl;
|
|
// assert(false);
|
|
return;
|
|
}
|
|
|
|
Relation* node_rel = ig->GetNodeRel();
|
|
|
|
Tuple* door_tuple1 = node_rel->GetTuple(id1, false);
|
|
Tuple* door_tuple2 = node_rel->GetTuple(id2, false);
|
|
Line3D* l3d1 = (Line3D*)door_tuple1->GetAttribute(IndoorGraph::I_DOOR_LOC_3D);
|
|
Line3D* l3d2 = (Line3D*)door_tuple2->GetAttribute(IndoorGraph::I_DOOR_LOC_3D);
|
|
|
|
Point3D start_p, end_p;
|
|
|
|
if(MiddlePoint(l3d1, start_p) == false ||
|
|
MiddlePoint(l3d2, end_p) == false){
|
|
cout<<"incorrect door "<<endl;
|
|
assert(false);
|
|
}
|
|
|
|
door_tuple1->DeleteIfAllowed();
|
|
door_tuple2->DeleteIfAllowed();
|
|
|
|
|
|
if(start_p.Distance(end_p) < dist_delta){////the same location
|
|
|
|
Line3D* l3d = new Line3D(0);
|
|
l3d->StartBulkLoad();
|
|
//////////////////connect to the start point////////////////////
|
|
for(int i = 0;i < l3d_s->Size() - 1;i++){
|
|
Point3D q;
|
|
l3d_s->Get(i, q);
|
|
*l3d += q;
|
|
}
|
|
///////////////////////////////////////////////////////////////
|
|
*l3d += start_p;
|
|
////////////////////connect to the end point/////////////////////
|
|
for(int i = 1;i < l3d_d->Size();i++){
|
|
Point3D q;
|
|
l3d_d->Get(i, q);
|
|
*l3d += q;
|
|
}
|
|
|
|
l3d->EndBulkLoad();
|
|
candidate_path.push_back(*l3d);
|
|
double cost_t = l3d->Length()/param.speed_person;
|
|
timecost.push_back(cost_t);
|
|
l3d->DeleteIfAllowed();
|
|
return;
|
|
}
|
|
|
|
|
|
priority_queue<IPath_elem> path_queue;
|
|
vector<IPath_elem> expand_queue;
|
|
|
|
vector<bool> visit_flag1;////////////door visit
|
|
for(int i = 1; i <= node_rel->GetNoTuples();i++)
|
|
visit_flag1.push_back(false);
|
|
|
|
|
|
float max_speed = MAX(param.speed_person, param.speed_elevator);
|
|
/////////// initialize the queue //////////////////////////////
|
|
int cur_size = expand_queue.size();
|
|
|
|
double w = 0;
|
|
double hw = start_p.Distance(end_p) / max_speed;
|
|
Line3D* l3d = new Line3D(0);
|
|
IPath_elem elem(-1, cur_size, id1, w + hw, w, *l3d);
|
|
path_queue.push(elem);
|
|
expand_queue.push_back(elem);
|
|
l3d->DeleteIfAllowed();
|
|
////////////////////////////////////////////////////////////////
|
|
///////////////////the path belongs to an elevator//////////////////////
|
|
vector<float> h_list; //all possible values
|
|
for(int i = 0;i <= 2*param.num_floors;i++){
|
|
h_list.push_back(param.floor_height + i*param.floor_height);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
bool find = false;
|
|
IPath_elem dest;//////////destination
|
|
while(path_queue.empty() == false){
|
|
IPath_elem top = path_queue.top();
|
|
path_queue.pop();
|
|
|
|
if(visit_flag1[top.tri_index - 1])continue;
|
|
|
|
if(prune_time > 0.0 && top.real_w > prune_time){
|
|
return;
|
|
}
|
|
|
|
if(top.tri_index == id2){
|
|
// cout<<"find the shortest path"<<endl;
|
|
find = true;
|
|
dest = top;
|
|
break;
|
|
}
|
|
|
|
Tuple* door_tuple = node_rel->GetTuple(top.tri_index, false);
|
|
/////////////////get the position of the door////////////////////////////
|
|
Point3D q;
|
|
Line3D* door_loc =
|
|
(Line3D*)door_tuple->GetAttribute(IndoorGraph::I_DOOR_LOC_3D);
|
|
assert(MiddlePoint(door_loc, q));
|
|
|
|
door_tuple->DeleteIfAllowed();
|
|
|
|
if(fabs(min_h - max_h) > EPSDIST){//train station, different platforms
|
|
if(q.GetZ() - max_h > dist_delta || min_h - q.GetZ() > dist_delta){
|
|
continue;
|
|
}
|
|
}
|
|
|
|
|
|
////////find its adjacecy element, and push them into queue and path//////
|
|
vector<int> adj_list;
|
|
ig->FindAdj(top.tri_index, adj_list);
|
|
|
|
/////////////////////////////////////////////////////////////
|
|
int pos_expand_path = top.cur_index;
|
|
|
|
for(unsigned int i = 0;i < adj_list.size();i++){
|
|
|
|
Tuple* edge_tuple = ig->GetEdgeRel()->GetTuple(adj_list[i], false);
|
|
int neighbor_id =
|
|
((CcInt*)edge_tuple->GetAttribute(IndoorGraph::I_DOOR_TID2))->GetIntval();
|
|
Line3D* path = (Line3D*)edge_tuple->GetAttribute(IndoorGraph::I_PATH);
|
|
int groom_oid =
|
|
((CcInt*)edge_tuple->GetAttribute(IndoorGraph::I_GROOM_OID))->GetIntval();
|
|
|
|
if(groom_oid > 0 && IsElevator(groom_oid, rel, btree)){
|
|
edge_tuple->DeleteIfAllowed();
|
|
continue;
|
|
}
|
|
|
|
|
|
if(visit_flag1[neighbor_id - 1]){
|
|
edge_tuple->DeleteIfAllowed();
|
|
continue;
|
|
}
|
|
|
|
if(groom_oid == start_groom_oid){
|
|
edge_tuple->DeleteIfAllowed();
|
|
continue;
|
|
}
|
|
|
|
Tuple* door_tuple1 = node_rel->GetTuple(neighbor_id, false);
|
|
|
|
Line3D* l = (Line3D*)door_tuple1->GetAttribute(IndoorGraph::I_DOOR_LOC_3D);
|
|
Point3D p;
|
|
|
|
assert(MiddlePoint(l, p));//get the point of next door
|
|
door_tuple1->DeleteIfAllowed();
|
|
|
|
///////////////////////////////////////////
|
|
/////////////height limitation/////////////
|
|
///////////////////////////////////////////
|
|
if(fabs(min_h - max_h) > EPSDIST){//train station, different platforms
|
|
if(p.GetZ() - max_h > dist_delta || min_h - p.GetZ() > dist_delta){
|
|
continue;
|
|
}
|
|
}
|
|
|
|
int cur_size = expand_queue.size();
|
|
////////////// set the weight //////////////////////////////////////
|
|
|
|
double w = top.real_w +
|
|
SetTimeWeight(path->Length(), groom_oid, rel, btree, param);
|
|
|
|
double hw = p.Distance(end_p) / max_speed;
|
|
//////////////////////////////////////////////////////////////////////
|
|
IPath_elem elem(pos_expand_path, cur_size,
|
|
neighbor_id, w + hw, w, *path);
|
|
path_queue.push(elem);
|
|
expand_queue.push_back(elem);
|
|
|
|
edge_tuple->DeleteIfAllowed();
|
|
}
|
|
|
|
visit_flag1[top.tri_index - 1] = true;
|
|
|
|
}
|
|
|
|
////////////////construct the result//////////////////////////////
|
|
if(find){
|
|
double cost_t = dest.real_w;
|
|
// cout<<"cost_t "<<cost_t<<endl;
|
|
|
|
vector<Point3D> ps_list;
|
|
while(dest.prev_index != -1){
|
|
if(dest.path.Size() > 0){
|
|
if(ps_list.size() == 0){
|
|
for(int i = dest.path.Size() - 1;i >= 0;i--){
|
|
Point3D q;
|
|
dest.path.Get(i, q);
|
|
ps_list.push_back(q);
|
|
}
|
|
}else{
|
|
for(int i = dest.path.Size() - 2;i >= 0;i--){
|
|
Point3D q;
|
|
dest.path.Get(i, q);
|
|
ps_list.push_back(q);
|
|
}
|
|
}
|
|
}
|
|
dest = expand_queue[dest.prev_index];
|
|
}
|
|
|
|
if(dest.path.Size() > 0){
|
|
for(int i = dest.path.Size() - 2;i >= 0;i--){
|
|
Point3D q;
|
|
dest.path.Get(i, q);
|
|
ps_list.push_back(q);
|
|
}
|
|
}
|
|
|
|
Line3D* l3d = new Line3D(0);
|
|
l3d->StartBulkLoad();
|
|
//////////////////connect to the start point////////////////////
|
|
for(int i = 0;i < l3d_s->Size() - 1;i++){
|
|
Point3D q;
|
|
l3d_s->Get(i, q);
|
|
*l3d += q;
|
|
}
|
|
///////////////////////////////////////////////////////////////
|
|
|
|
for(int i = ps_list.size() - 1;i >= 0; i--){
|
|
*l3d += ps_list[i];
|
|
}
|
|
////////////////////connect to the end point/////////////////////
|
|
for(int i = 1;i < l3d_d->Size();i++){
|
|
Point3D q;
|
|
l3d_d->Get(i, q);
|
|
*l3d += q;
|
|
}
|
|
|
|
l3d->EndBulkLoad();
|
|
candidate_path.push_back(*l3d);
|
|
l3d->DeleteIfAllowed();
|
|
|
|
if(l3d_s->Size() > 0)
|
|
cost_t += l3d_s->Length() / param.speed_person;
|
|
if(l3d_d->Size() > 0)
|
|
cost_t += l3d_d->Length() / param.speed_person;
|
|
|
|
timecost.push_back(cost_t);
|
|
|
|
if(prune_time < 0.0)
|
|
prune_time = cost_t;
|
|
else if(cost_t < prune_time)
|
|
prune_time = cost_t;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
check whether the room is an elevator
|
|
|
|
*/
|
|
bool IndoorNav::IsElevator(int groom_oid, Relation* rel, BTree* btree)
|
|
{
|
|
CcInt* search_id = new CcInt(true, groom_oid);
|
|
BTreeIterator* btree_iter = btree->ExactMatch(search_id);
|
|
int groom_tid = 0;
|
|
while(btree_iter->Next()){
|
|
groom_tid = btree_iter->GetId();
|
|
break;
|
|
}
|
|
delete btree_iter;
|
|
delete search_id;
|
|
|
|
assert(1 <= groom_tid && groom_tid <= rel->GetNoTuples());
|
|
Tuple* groom_tuple = rel->GetTuple(groom_tid, false);
|
|
string type = ((CcString*)groom_tuple->GetAttribute(I_Type))->GetValue();
|
|
groom_tuple->DeleteIfAllowed();
|
|
|
|
if(GetRoomEnum(type) == EL){//////////// an elevator
|
|
return true;
|
|
}else
|
|
return false;
|
|
}
|
|
|
|
|
|
/*
|
|
calculate the time cost of an edge: use the length of path and speed value
|
|
|
|
*/
|
|
|
|
float IndoorNav::SetTimeWeight(double l, int groom_oid, Relation* rel,
|
|
BTree* btree, I_Parameter& param)
|
|
{
|
|
if(groom_oid == 0){/////////no real connection.two doors at the same lcoation
|
|
return 0;
|
|
}
|
|
///////////////find the room////////////////////////////////////////////
|
|
CcInt* search_id = new CcInt(true, groom_oid);
|
|
BTreeIterator* btree_iter = btree->ExactMatch(search_id);
|
|
int groom_tid = 0;
|
|
while(btree_iter->Next()){
|
|
groom_tid = btree_iter->GetId();
|
|
break;
|
|
}
|
|
delete btree_iter;
|
|
delete search_id;
|
|
|
|
assert(1 <= groom_tid && groom_tid <= rel->GetNoTuples());
|
|
Tuple* groom_tuple = rel->GetTuple(groom_tid, false);
|
|
string type = ((CcString*)groom_tuple->GetAttribute(I_Type))->GetValue();
|
|
groom_tuple->DeleteIfAllowed();
|
|
|
|
if(GetRoomEnum(type) != EL){////////////not an elevator
|
|
return l/param.speed_person;
|
|
}else if(GetRoomEnum(type) == EL){
|
|
return l/param.speed_elevator;
|
|
}
|
|
|
|
cout<<"should not visit here"<<endl;
|
|
assert(false);
|
|
return l/param.speed_elevator;
|
|
|
|
}
|
|
|
|
/*
|
|
the weight in the priority queue is changed to time instead of distance
|
|
A star algorithm can still be applied.
|
|
distance: Euclidean distance is set as the path length
|
|
speed: the maximum speed between person and elevator
|
|
heuristic value = distacne div speed
|
|
|
|
If the shortest path uses the elevator, the weight value should be reset
|
|
|
|
*/
|
|
void IndoorNav::IndoorShortestPath_Time2(int id1, int id2,
|
|
vector<Line3D>& candidate_path, Line3D* l3d_s,
|
|
Line3D* l3d_d, vector<double>& timecost,
|
|
I_Parameter& param, Relation* rel,
|
|
BTree* btree, double& prune_time,
|
|
float min_h, float max_h, int start_groom_oid)
|
|
{
|
|
// cout<<"IndoorShortestPath_Time2 "<<endl;
|
|
|
|
const double dist_delta = 0.001;
|
|
|
|
if(id1 == id2){
|
|
cout<<"two doors are equal"<<endl;
|
|
// assert(false);
|
|
return;
|
|
}
|
|
|
|
Relation* node_rel = ig->GetNodeRel();
|
|
|
|
Tuple* door_tuple1 = node_rel->GetTuple(id1, false);
|
|
Tuple* door_tuple2 = node_rel->GetTuple(id2, false);
|
|
Line3D* l3d1 = (Line3D*)door_tuple1->GetAttribute(IndoorGraph::I_DOOR_LOC_3D);
|
|
Line3D* l3d2 = (Line3D*)door_tuple2->GetAttribute(IndoorGraph::I_DOOR_LOC_3D);
|
|
|
|
Point3D start_p, end_p;
|
|
|
|
if(MiddlePoint(l3d1, start_p) == false ||
|
|
MiddlePoint(l3d2, end_p) == false){
|
|
cout<<"incorrect door "<<endl;
|
|
assert(false);
|
|
}
|
|
|
|
|
|
door_tuple1->DeleteIfAllowed();
|
|
door_tuple2->DeleteIfAllowed();
|
|
|
|
|
|
if(start_p.Distance(end_p) < dist_delta){////the same location
|
|
|
|
Line3D* l3d = new Line3D(0);
|
|
l3d->StartBulkLoad();
|
|
//////////////////connect to the start point////////////////////
|
|
for(int i = 0;i < l3d_s->Size() - 1;i++){
|
|
Point3D q;
|
|
l3d_s->Get(i, q);
|
|
*l3d += q;
|
|
}
|
|
///////////////////////////////////////////////////////////////
|
|
*l3d += start_p;
|
|
////////////////////connect to the end point/////////////////////
|
|
for(int i = 1;i < l3d_d->Size();i++){
|
|
Point3D q;
|
|
l3d_d->Get(i, q);
|
|
*l3d += q;
|
|
}
|
|
|
|
l3d->EndBulkLoad();
|
|
candidate_path.push_back(*l3d);
|
|
double cost_t = l3d->Length()/param.speed_person;
|
|
timecost.push_back(cost_t);
|
|
l3d->DeleteIfAllowed();
|
|
return;
|
|
}
|
|
|
|
priority_queue<IPath_elem> path_queue;
|
|
vector<IPath_elem> expand_queue;
|
|
|
|
vector<bool> visit_flag1;////////////door visit
|
|
for(int i = 1; i <= node_rel->GetNoTuples();i++)
|
|
visit_flag1.push_back(false);
|
|
|
|
/////////// initialize the queue //////////////////////////////
|
|
int cur_size = expand_queue.size();
|
|
|
|
double w = 0;
|
|
double hw = start_p.Distance(end_p);
|
|
Line3D* l3d = new Line3D(0);
|
|
IPath_elem elem(-1, cur_size, id1, w + hw, w, *l3d);
|
|
path_queue.push(elem);
|
|
expand_queue.push_back(elem);
|
|
l3d->DeleteIfAllowed();
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
bool find = false;
|
|
IPath_elem dest;//////////destination
|
|
while(path_queue.empty() == false){
|
|
IPath_elem top = path_queue.top();
|
|
path_queue.pop();
|
|
|
|
if(visit_flag1[top.tri_index - 1])continue;
|
|
|
|
if(prune_time > 0.0 && top.real_w > prune_time){
|
|
return;
|
|
}
|
|
|
|
if(top.tri_index == id2){
|
|
// cout<<"find the shortest path"<<endl;
|
|
find = true;
|
|
dest = top;
|
|
break;
|
|
}
|
|
|
|
|
|
Tuple* door_tuple = node_rel->GetTuple(top.tri_index, false);
|
|
/////////////////get the position of the door////////////////////////////
|
|
Point3D q;
|
|
Line3D* door_loc =
|
|
(Line3D*)door_tuple->GetAttribute(IndoorGraph::I_DOOR_LOC_3D);
|
|
assert(MiddlePoint(door_loc, q));
|
|
|
|
door_tuple->DeleteIfAllowed();
|
|
|
|
///////////////////////////////////////////
|
|
/////////////height limitation/////////////
|
|
///////////////////////////////////////////
|
|
if(fabs(min_h - max_h) > EPSDIST){//train station, different platforms
|
|
if(q.GetZ() - max_h > dist_delta || min_h - q.GetZ() > dist_delta){
|
|
continue;
|
|
}
|
|
}
|
|
|
|
////////find its adjacecy element, and push them into queue and path//////
|
|
vector<int> adj_list;
|
|
ig->FindAdj(top.tri_index, adj_list);
|
|
|
|
/////////////////////////////////////////////////////////////
|
|
int pos_expand_path = top.cur_index;
|
|
|
|
for(unsigned int i = 0;i < adj_list.size();i++){
|
|
|
|
Tuple* edge_tuple = ig->GetEdgeRel()->GetTuple(adj_list[i], false);
|
|
int neighbor_id =
|
|
((CcInt*)edge_tuple->GetAttribute(IndoorGraph::I_DOOR_TID2))->GetIntval();
|
|
Line3D* path = (Line3D*)edge_tuple->GetAttribute(IndoorGraph::I_PATH);
|
|
int groom_oid =
|
|
((CcInt*)edge_tuple->GetAttribute(IndoorGraph::I_GROOM_OID))->GetIntval();
|
|
|
|
if(visit_flag1[neighbor_id - 1]){
|
|
edge_tuple->DeleteIfAllowed();
|
|
continue;
|
|
}
|
|
if(groom_oid == start_groom_oid){
|
|
edge_tuple->DeleteIfAllowed();
|
|
continue;
|
|
}
|
|
|
|
Tuple* door_tuple1 = node_rel->GetTuple(neighbor_id, false);
|
|
|
|
Line3D* l = (Line3D*)door_tuple1->GetAttribute(IndoorGraph::I_DOOR_LOC_3D);
|
|
Point3D p;
|
|
|
|
assert(MiddlePoint(l, p));//get the point of next door
|
|
door_tuple1->DeleteIfAllowed();
|
|
|
|
///////////////////////////////////////////
|
|
/////////////height limitation/////////////
|
|
///////////////////////////////////////////
|
|
if(fabs(min_h - max_h) > EPSDIST){//train station, different platforms
|
|
if(p.GetZ() - max_h > dist_delta || min_h - p.GetZ() > dist_delta){
|
|
continue;
|
|
}
|
|
}
|
|
|
|
int cur_size = expand_queue.size();
|
|
////////////// set the weight //////////////////////////////////////
|
|
|
|
double w = top.real_w +
|
|
SetTimeWeight(path->Length(), groom_oid, rel, btree, param);
|
|
|
|
double hw = p.Distance(end_p);
|
|
//////////////////////////////////////////////////////////////////////
|
|
IPath_elem elem(pos_expand_path, cur_size,
|
|
neighbor_id, w + hw, w, *path, groom_oid);
|
|
path_queue.push(elem);
|
|
expand_queue.push_back(elem);
|
|
|
|
edge_tuple->DeleteIfAllowed();
|
|
}
|
|
|
|
visit_flag1[top.tri_index - 1] = true;
|
|
|
|
}
|
|
|
|
////////////////construct the result//////////////////////////////
|
|
if(find){
|
|
double cost_t = 0;
|
|
// cout<<"cost_t "<<cost_t<<endl;
|
|
|
|
vector<Point3D> ps_list;
|
|
double elevator_length = 0;
|
|
while(dest.prev_index != -1){
|
|
if(dest.path.Size() > 0){
|
|
int groom_oid = dest.groom_oid;
|
|
|
|
///////////////////if the path belongs to lift//////////////////
|
|
|
|
if(groom_oid > 0 && IsElevator(groom_oid, rel, btree))
|
|
elevator_length += dest.path.Length();
|
|
|
|
if(ps_list.size() == 0){
|
|
for(int i = dest.path.Size() - 1;i >= 0;i--){
|
|
Point3D q;
|
|
dest.path.Get(i, q);
|
|
ps_list.push_back(q);
|
|
}
|
|
}else{
|
|
for(int i = dest.path.Size() - 2;i >= 0;i--){
|
|
Point3D q;
|
|
dest.path.Get(i, q);
|
|
ps_list.push_back(q);
|
|
}
|
|
}
|
|
}
|
|
dest = expand_queue[dest.prev_index];
|
|
}
|
|
|
|
if(dest.path.Size() > 0){
|
|
for(int i = dest.path.Size() - 2;i >= 0;i--){
|
|
Point3D q;
|
|
dest.path.Get(i, q);
|
|
ps_list.push_back(q);
|
|
}
|
|
}
|
|
|
|
Line3D* l3d = new Line3D(0);
|
|
l3d->StartBulkLoad();
|
|
//////////////////connect to the start point////////////////////
|
|
for(int i = 0;i < l3d_s->Size() - 1;i++){
|
|
Point3D q;
|
|
l3d_s->Get(i, q);
|
|
*l3d += q;
|
|
}
|
|
///////////////////////////////////////////////////////////////
|
|
|
|
for(int i = ps_list.size() - 1;i >= 0; i--){
|
|
*l3d += ps_list[i];
|
|
}
|
|
////////////////////connect to the end point/////////////////////
|
|
for(int i = 1;i < l3d_d->Size();i++){
|
|
Point3D q;
|
|
l3d_d->Get(i, q);
|
|
*l3d += q;
|
|
}
|
|
|
|
l3d->EndBulkLoad();
|
|
candidate_path.push_back(*l3d);
|
|
if(elevator_length > 0.0){
|
|
cost_t = (l3d->Length() - elevator_length) / param.speed_person;
|
|
cost_t += CostInElevator( elevator_length, param);
|
|
}else
|
|
cost_t = l3d->Length() / param.speed_person;
|
|
|
|
l3d->DeleteIfAllowed();
|
|
|
|
timecost.push_back(cost_t);
|
|
|
|
if(prune_time < 0.0)
|
|
prune_time = cost_t;
|
|
else if(cost_t < prune_time)
|
|
prune_time = cost_t;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
the uncertain cost value on an elevator:
|
|
let l be absolute length of two floors and h be the distance between two
|
|
consecutive floors, there are n floors.
|
|
the distribution is: l, l+h, l+2h, l+3h, ...l+2nh
|
|
|
|
*/
|
|
float IndoorNav::CostInElevator(double l, I_Parameter& param)
|
|
{
|
|
vector<float> h_list; //all possible values
|
|
for(int i = 0;i <= 2*param.num_floors;i++){
|
|
h_list.push_back(l + i*param.floor_height);
|
|
}
|
|
|
|
const int size = h_list.size();
|
|
int index = GetRandom() % size;
|
|
|
|
return h_list[index]/param.speed_elevator;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/////////////temporal unit: UPoint3D ///////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////
|
|
/*
|
|
interporlation function for the location
|
|
|
|
*/
|
|
void UPoint3D::TemporalFunction( const Instant& t, Point3D& result,
|
|
bool ignoreLimits ) const
|
|
{
|
|
if( !IsDefined() ||
|
|
!t.IsDefined() ||
|
|
(!timeInterval.Contains( t ) && !ignoreLimits) )
|
|
{
|
|
result.SetDefined(false);
|
|
}
|
|
else if( t == timeInterval.start )
|
|
{
|
|
result = p0;
|
|
result.SetDefined(true);
|
|
}
|
|
else if( t == timeInterval.end )
|
|
{
|
|
result = p1;
|
|
result.SetDefined(true);
|
|
}
|
|
else
|
|
{
|
|
Instant t0 = timeInterval.start;
|
|
Instant t1 = timeInterval.end;
|
|
|
|
|
|
double x = (p1.GetX() - p0.GetX()) * ((t - t0) / (t1 - t0)) + p0.GetX();
|
|
double y = (p1.GetY() - p0.GetY()) * ((t - t0) / (t1 - t0)) + p0.GetY();
|
|
double z = (p1.GetZ() - p0.GetZ()) * ((t - t0) / (t1 - t0)) + p0.GetZ();
|
|
|
|
Point3D p(true, x, y, z);
|
|
result = p;
|
|
}
|
|
}
|
|
|
|
/*
|
|
check whether a location is visited
|
|
|
|
*/
|
|
bool UPoint3D::Passes( const Point3D& gloc ) const
|
|
{
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
restrict the movement at a location
|
|
|
|
*/
|
|
|
|
bool UPoint3D::At( const Point3D& loc, TemporalUnit<Point3D>& res ) const
|
|
{
|
|
return false;
|
|
}
|
|
|
|
UPoint3D* UPoint3D::Clone() const
|
|
{
|
|
UPoint3D* res;
|
|
if(this->IsDefined()){
|
|
|
|
res = new UPoint3D(timeInterval, p0, p1);
|
|
res->del.isDefined = del.isDefined;
|
|
}else{
|
|
res = new UPoint3D(false);
|
|
}
|
|
return res;
|
|
}
|
|
|
|
|
|
void UPoint3D::CopyFrom(const Attribute* right)
|
|
{
|
|
const UPoint3D* loc = static_cast<const UPoint3D*>(right);
|
|
if(loc->del.isDefined){
|
|
timeInterval.CopyFrom(loc->timeInterval);
|
|
p0 = loc->p0;
|
|
p1 = loc->p1;
|
|
}
|
|
del.isDefined = loc->del.isDefined;
|
|
}
|
|
|
|
const Rectangle<4> UPoint3D::BoundingBox(const Geoid* geoid) const
|
|
{
|
|
if(this->IsDefined()){
|
|
double minMax[] = {MIN(p0.GetX(), p1.GetX()),
|
|
MAX(p0.GetX(), p1.GetX()),
|
|
MIN(p0.GetY(), p1.GetY()),
|
|
MAX(p0.GetY(), p1.GetY()),
|
|
MIN(p0.GetZ(), p1.GetZ()),
|
|
MAX(p0.GetZ(), p1.GetZ()),
|
|
timeInterval.start.ToDouble(),
|
|
timeInterval.end.ToDouble()};
|
|
return Rectangle<4>(true,minMax );
|
|
}else
|
|
return Rectangle<4>(false);
|
|
|
|
}
|
|
|
|
|
|
ListExpr UPoint3DProperty()
|
|
{
|
|
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("upoint3d"),
|
|
nl->StringAtom("(<interval,x,y,z>)"),
|
|
nl->StringAtom("((interval (1.0 12.0 3.0)))"))));
|
|
}
|
|
|
|
/*
|
|
Output (interval, p0, p1)
|
|
|
|
*/
|
|
|
|
ListExpr OutUPoint3D( ListExpr typeInfo, Word value )
|
|
{
|
|
// cout<<"OutUPoint3D"<<endl;
|
|
UPoint3D* loc = (UPoint3D*)(value.addr);
|
|
if(!loc->IsDefined()){
|
|
return nl->SymbolAtom("undef");
|
|
}
|
|
|
|
if( loc->IsEmpty() ){
|
|
return nl->TheEmptyList();
|
|
}
|
|
ListExpr timeintervalList = nl->FourElemList(
|
|
OutDateTime( nl->TheEmptyList(),
|
|
SetWord(&loc->timeInterval.start) ),
|
|
OutDateTime( nl->TheEmptyList(),
|
|
SetWord(&loc->timeInterval.end) ),
|
|
nl->BoolAtom( loc->timeInterval.lc ),
|
|
nl->BoolAtom( loc->timeInterval.rc));
|
|
ListExpr loc1 = OutPoint3D(nl->TheEmptyList(), &(loc->p0));
|
|
ListExpr loc2 = OutPoint3D(nl->TheEmptyList(), &(loc->p1));
|
|
|
|
return nl->ThreeElemList(timeintervalList,loc1,loc2);
|
|
}
|
|
|
|
/*
|
|
In function
|
|
|
|
*/
|
|
Word InUPoint3D( const ListExpr typeInfo, const ListExpr instance,
|
|
const int errorPos, ListExpr& errorInfo, bool& correct )
|
|
{
|
|
string errmsg;
|
|
if ( nl->ListLength( instance ) == 3 ){
|
|
ListExpr first = nl->First( instance );
|
|
|
|
if( nl->ListLength( first ) == 4 &&
|
|
nl->IsAtom( nl->Third( first ) ) &&
|
|
nl->AtomType( nl->Third( first ) ) == BoolType &&
|
|
nl->IsAtom( nl->Fourth( first ) ) &&
|
|
nl->AtomType( nl->Fourth( first ) ) == BoolType ){
|
|
|
|
correct = true;
|
|
Instant *start = (Instant *)InInstant( nl->TheEmptyList(),
|
|
nl->First( first ),
|
|
errorPos, errorInfo, correct ).addr;
|
|
|
|
if( !correct || !start->IsDefined() ){
|
|
errmsg = "InUPoint3D(): first instant must be defined!.";
|
|
errorInfo = nl->Append(errorInfo, nl->StringAtom(errmsg));
|
|
delete start;
|
|
return SetWord( Address(0) );
|
|
}
|
|
|
|
Instant *end = (Instant *)InInstant( nl->TheEmptyList(),
|
|
nl->Second( first ),
|
|
errorPos, errorInfo, correct ).addr;
|
|
|
|
if( !correct || !end->IsDefined() )
|
|
{
|
|
errmsg = "InUPoint3D(): second instant must be defined!.";
|
|
errorInfo = nl->Append(errorInfo, nl->StringAtom(errmsg));
|
|
delete start;
|
|
delete end;
|
|
return SetWord( Address(0) );
|
|
}
|
|
|
|
Interval<Instant> tinterval( *start, *end,
|
|
nl->BoolValue( nl->Third( first ) ),
|
|
nl->BoolValue( nl->Fourth( first ) ) );
|
|
delete start;
|
|
delete end;
|
|
|
|
correct = tinterval.IsValid();
|
|
if (!correct)
|
|
{
|
|
errmsg = "InUPoint3D(): Non valid time interval.";
|
|
errorInfo = nl->Append(errorInfo, nl->StringAtom(errmsg));
|
|
return SetWord( Address(0) );
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
ListExpr second = nl->Second( instance );
|
|
if(nl->ListLength(second) != 3){
|
|
errmsg = "InUPoint3D(): three parameters for Point3D.";
|
|
errorInfo = nl->Append(errorInfo, nl->StringAtom(errmsg));
|
|
return SetWord( Address(0) );
|
|
}
|
|
|
|
bool loc1_correct;
|
|
Point3D* loc1 = (Point3D*)InPoint3D(typeInfo, second,
|
|
errorPos,errorInfo, loc1_correct).addr;
|
|
if(loc1_correct == false){
|
|
errmsg = "InUPoint3D(): Non correct first location.";
|
|
errorInfo = nl->Append(errorInfo, nl->StringAtom(errmsg));
|
|
return SetWord( Address(0) );
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
ListExpr third = nl->Third(instance);
|
|
if(nl->ListLength(third) != 3){
|
|
errmsg = "InUPoint3D(): three parameters for Point3D.";
|
|
errorInfo = nl->Append(errorInfo, nl->StringAtom(errmsg));
|
|
return SetWord( Address(0) );
|
|
}
|
|
bool loc2_correct;
|
|
Point3D* loc2 = (Point3D*)InPoint3D(typeInfo, third,
|
|
errorPos,errorInfo, loc2_correct).addr;
|
|
if(loc2_correct == false){
|
|
errmsg = "InUPoint3D(): Non correct second location.";
|
|
errorInfo = nl->Append(errorInfo, nl->StringAtom(errmsg));
|
|
return SetWord( Address(0) );
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
// cout<<tinterval<<*loc1<<*loc2<<endl;
|
|
|
|
UPoint3D *up = new UPoint3D( tinterval, *loc1, *loc2);
|
|
|
|
correct = up->IsValid();
|
|
if( correct )
|
|
return SetWord( up );
|
|
|
|
errmsg = "InUPoint3D(): Error in start/end point.";
|
|
errorInfo = nl->Append(errorInfo, nl->StringAtom(errmsg));
|
|
delete up;
|
|
}
|
|
}else if ( nl->IsAtom( instance ) && nl->AtomType( instance ) == SymbolType
|
|
&& nl->SymbolValue( instance ) == "undef" ){
|
|
UPoint3D *loc = new UPoint3D(false);
|
|
loc->timeInterval=
|
|
Interval<DateTime>(DateTime(instanttype),
|
|
DateTime(instanttype),true,true);
|
|
correct = loc->timeInterval.IsValid();
|
|
if ( correct )
|
|
return (SetWord( loc ));
|
|
}
|
|
errmsg = "InUPoint3D(): Error in representation.";
|
|
errorInfo = nl->Append(errorInfo, nl->StringAtom(errmsg));
|
|
correct = false;
|
|
return SetWord( Address(0) );
|
|
}
|
|
|
|
/*
|
|
Open a UPoint3D object
|
|
|
|
*/
|
|
bool OpenUPoint3D(SmiRecord& valueRecord, size_t& offset,
|
|
const ListExpr typeInfo, Word& value)
|
|
{
|
|
// cout<<"OpenUPoint3D()"<<endl;
|
|
|
|
UPoint3D* genl = (UPoint3D*)Attribute::Open(valueRecord, offset, typeInfo);
|
|
value = SetWord(genl);
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
Save a UPoint3D object
|
|
|
|
*/
|
|
bool SaveUPoint3D(SmiRecord& valueRecord, size_t& offset,
|
|
const ListExpr typeInfo, Word& value)
|
|
{
|
|
// cout<<"SaveUPoint3D"<<endl;
|
|
UPoint3D* genl = (UPoint3D*)value.addr;
|
|
Attribute::Save(valueRecord, offset, typeInfo, genl);
|
|
return true;
|
|
|
|
}
|
|
|
|
Word CreateUPoint3D(const ListExpr typeInfo)
|
|
{
|
|
// cout<<"CreateUPoint3D()"<<endl;
|
|
return SetWord (new UPoint3D(0));
|
|
}
|
|
|
|
|
|
void DeleteUPoint3D(const ListExpr typeInfo, Word& w)
|
|
{
|
|
// cout<<"DeleteUPoint3D()"<<endl;
|
|
UPoint3D* up = (UPoint3D*)w.addr;
|
|
delete up;
|
|
w.addr = NULL;
|
|
}
|
|
|
|
|
|
void CloseUPoint3D( const ListExpr typeInfo, Word& w )
|
|
{
|
|
// cout<<"CloseUPoint3D"<<endl;
|
|
((UPoint3D*)w.addr)->DeleteIfAllowed();
|
|
w.addr = 0;
|
|
}
|
|
|
|
Word CloneUPoint3D( const ListExpr typeInfo, const Word& w )
|
|
{
|
|
// cout<<"CloneUPoint3D"<<endl;
|
|
return SetWord( new UPoint3D( *((UPoint3D*)w.addr) ) );
|
|
}
|
|
|
|
int SizeOfUPoint3D()
|
|
{
|
|
// cout<<"SizeOfUPoint3D"<<endl;
|
|
return sizeof(UPoint3D);
|
|
}
|
|
|
|
bool CheckUPoint3D( ListExpr type, ListExpr& errorInfo )
|
|
{
|
|
// cout<<"CheckUPoint3D"<<endl;
|
|
return (nl->IsEqual( type, "upoint3d" ));
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
////////// MPoinr3D /////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////
|
|
ListExpr MPoint3DProperty()
|
|
{
|
|
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("-> MAPPING"),
|
|
nl->StringAtom("mpoint3d"),
|
|
nl->StringAtom("(u1,...,un)"),
|
|
nl->StringAtom("((interval (1 10.0 1.0)(1 12.0 3.0)))"))));
|
|
}
|
|
|
|
|
|
bool CheckMPoint3D( ListExpr type, ListExpr& errorInfo )
|
|
{
|
|
// cout<<"CheckMPoint3D"<<endl;
|
|
return (nl->IsEqual( type, "mpoint3d" ));
|
|
}
|
|
|
|
void MPoint3D::Clear()
|
|
{
|
|
Mapping<UPoint3D, Point3D>::Clear();
|
|
}
|
|
|
|
|
|
/*
|
|
copy it from another data
|
|
|
|
*/
|
|
void MPoint3D::CopyFrom(const Attribute* right)
|
|
{
|
|
|
|
const MPoint3D *mo = (const MPoint3D*)right;
|
|
assert( mo->IsOrdered() );
|
|
Clear();
|
|
this->SetDefined(mo->IsDefined());
|
|
if( !this->IsDefined() ) {
|
|
return;
|
|
}
|
|
StartBulkLoad();
|
|
UPoint3D unit;
|
|
for( int i = 0; i < mo->GetNoComponents(); i++ ){
|
|
mo->Get( i, unit );
|
|
Add( unit );
|
|
}
|
|
EndBulkLoad( false );
|
|
|
|
}
|
|
|
|
Attribute* MPoint3D::Clone() const
|
|
{
|
|
assert( IsOrdered() );
|
|
MPoint3D* result;
|
|
if( !this->IsDefined() ){
|
|
result = new MPoint3D( 0 );
|
|
} else {
|
|
result = new MPoint3D( GetNoComponents() );
|
|
if(GetNoComponents()>0){
|
|
result->units.resize(GetNoComponents());
|
|
}
|
|
result->StartBulkLoad();
|
|
UPoint3D unit;
|
|
for( int i = 0; i < GetNoComponents(); i++ ){
|
|
Get( i, unit );
|
|
result->Add( unit );
|
|
}
|
|
result->EndBulkLoad( false );
|
|
}
|
|
result->SetDefined(this->IsDefined());
|
|
return (Attribute*) result;
|
|
|
|
}
|
|
|
|
/*
|
|
put new unit. it only inserts the new unit and does not calculate the bounding
|
|
box.
|
|
|
|
*/
|
|
void MPoint3D::Add(const UPoint3D& unit)
|
|
{
|
|
assert(unit.IsDefined());
|
|
assert(unit.IsValid());
|
|
if(!IsDefined()){
|
|
SetDefined(false);
|
|
return;
|
|
}
|
|
units.Append(unit);
|
|
}
|
|
|
|
bool MPoint3D::EndBulkLoad(const bool sort, const bool checkvalid)
|
|
{
|
|
return Mapping<UPoint3D, Point3D>::EndBulkLoad(sort, checkvalid);
|
|
|
|
}
|
|
|
|
/*
|
|
3d line representing the trajectory of indoor moving objects
|
|
|
|
*/
|
|
void MPoint3D::Trajectory(Line3D& l)
|
|
{
|
|
l.Clear();
|
|
l.StartBulkLoad();
|
|
for(int i = 0;i < GetNoComponents();i++){
|
|
UPoint3D unit;
|
|
Get(i, unit);
|
|
l += unit.p0;
|
|
if(i == GetNoComponents() - 1)
|
|
l+= unit.p1;
|
|
}
|
|
l.EndBulkLoad();
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//////////////////////Building////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////////
|
|
string Building::RoomBTreeTypeInfo = "(rel (tuple ((oid int) (Name string) \
|
|
(Type string) (Room groom) (Door line))) int)";
|
|
|
|
string Building::Indoor_GRoom_Door_Extend = "(rel (tuple ((Oid int) \
|
|
(Name string) (Type string) (Room groom) (Door line) (TID tid) (BBox rect3))))";
|
|
|
|
string Building::RoomRTreeTypeInfo = "(rel (tuple ((oid int) (Name string)\
|
|
(Type string) (Room groom) (Door line) (TID tid) (BBox rect3))) rect3 FALSE)";
|
|
|
|
ListExpr BuildingProperty()
|
|
{
|
|
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("building"),
|
|
nl->StringAtom("((def, id))"),
|
|
nl->StringAtom("((TRUE 1))"))));
|
|
}
|
|
|
|
void* Building::Cast(void* addr)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
int SizeOfBuilding()
|
|
{
|
|
// cout<<"SizeOfBuilding"<<endl;
|
|
return sizeof(Building);
|
|
}
|
|
|
|
bool CheckBuilding( ListExpr type, ListExpr& errorInfo )
|
|
{
|
|
// cout<<"CheckBuilding"<<endl;
|
|
return (nl->IsEqual( type, "building" ));
|
|
}
|
|
|
|
|
|
void CloseBuilding( const ListExpr typeInfo, Word& w )
|
|
{
|
|
// cout<<"CloseBuilding"<<endl;
|
|
delete static_cast<Building*>(w.addr);
|
|
w.addr = 0;
|
|
}
|
|
|
|
Word CloneBuilding( const ListExpr typeInfo, const Word& w )
|
|
{
|
|
// cout<<"CloneBuilding"<<endl;
|
|
return SetWord( new Address(0));
|
|
}
|
|
|
|
Word CreateBuilding(const ListExpr typeInfo)
|
|
{
|
|
// cout<<"CreateBuilding()"<<endl;
|
|
return SetWord (new Building());
|
|
}
|
|
|
|
void DeleteBuilding(const ListExpr typeInfo, Word& w)
|
|
{
|
|
// cout<<"DeleteBuilding()"<<endl;
|
|
Building* build = (Building*)w.addr;
|
|
delete build;
|
|
w.addr = NULL;
|
|
}
|
|
|
|
|
|
/*
|
|
In function. there is not nested list expression here.
|
|
|
|
*/
|
|
Word InBuilding( const ListExpr typeInfo, const ListExpr instance,
|
|
const int errorPos, ListExpr& errorInfo, bool& correct )
|
|
{
|
|
|
|
// cout<<"length "<<nl->ListLength(instance)<<endl;
|
|
|
|
if( !nl->IsAtom( instance ) ){
|
|
|
|
if(nl->ListLength(instance) != 3){
|
|
cout<<"length should be 3"<<endl;
|
|
correct = false;
|
|
return SetWord(Address(0));
|
|
}
|
|
ListExpr first = nl->First(instance);
|
|
ListExpr second = nl->Second(instance);
|
|
ListExpr third = nl->Third(instance);
|
|
|
|
if(!nl->IsAtom(first) || nl->AtomType(first) != BoolType){
|
|
cout<< "building(): 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<< "building(): building id must be int type"<<endl;
|
|
correct = false;
|
|
return SetWord(Address(0));
|
|
}
|
|
unsigned int id = nl->IntValue(second);
|
|
|
|
if(!nl->IsAtom(third) || nl->AtomType(third) != StringType){
|
|
cout<< "building(): building type must be string type"<<endl;
|
|
correct = false;
|
|
return SetWord(Address(0));
|
|
}
|
|
string type = nl->StringValue(third);
|
|
|
|
Building* building = new Building(d, id, GetBuildingType(type));
|
|
|
|
////////////////very important /////////////////////////////
|
|
correct = true;
|
|
///////////////////////////////////////////////////////////
|
|
return SetWord(building);
|
|
}
|
|
|
|
correct = false;
|
|
return SetWord(Address(0));
|
|
}
|
|
|
|
/*
|
|
output the building
|
|
|
|
*/
|
|
ListExpr OutBuilding( ListExpr typeInfo, Word value )
|
|
{
|
|
// cout<<"OutBuilding"<<endl;
|
|
Building* build = (Building*)(value.addr);
|
|
if(!build->IsDefined()){
|
|
return nl->SymbolAtom("undef");
|
|
}
|
|
|
|
ListExpr list1 = nl->TwoElemList(
|
|
nl->StringAtom("Building Id:"),
|
|
nl->IntAtom(build->GetId()));
|
|
|
|
ListExpr list2 = nl->TheEmptyList();
|
|
list2 = nl->TwoElemList(
|
|
nl->StringAtom("Building Type :"),
|
|
nl->StringAtom(GetBuildingStr(build->GetType())));
|
|
|
|
ListExpr list3 = nl->TheEmptyList();
|
|
if(build->IsIGInit()){
|
|
list3 = nl->TwoElemList(
|
|
nl->StringAtom("Indoor Graph Id:"),
|
|
nl->IntAtom(build->GetIGId()));
|
|
}else
|
|
list3 = nl->OneElemList( nl->StringAtom("Indoor Graph undef"));
|
|
|
|
ListExpr list4 = nl->TheEmptyList();
|
|
|
|
|
|
return nl->FourElemList(list1, list2, list3, list4);
|
|
}
|
|
|
|
bool SaveBuilding(SmiRecord& valueRecord, size_t& offset,
|
|
const ListExpr typeInfo, Word& value)
|
|
{
|
|
Building* build = (Building*)value.addr;
|
|
return build->Save(valueRecord, offset, typeInfo);
|
|
}
|
|
|
|
bool OpenBuilding(SmiRecord& valueRecord, size_t& offset,
|
|
const ListExpr typeInfo, Word& value)
|
|
{
|
|
value.addr = Building::Open(valueRecord, offset, typeInfo);
|
|
return value.addr != NULL;
|
|
}
|
|
|
|
Building::Building():def(false), building_id(0), building_type(-1),
|
|
indoorgraph_init(false), indoorgraph_id(0), rel_rooms(NULL),
|
|
btree_room(NULL), rtree_rel_box(NULL)
|
|
{
|
|
// cout<<"default constructor"<<endl;
|
|
}
|
|
|
|
Building::Building(bool d, int id, unsigned int type): def(d), building_id(id),
|
|
building_type(type), indoorgraph_init(false), indoorgraph_id(0),
|
|
rel_rooms(NULL), btree_room(NULL), rtree_rel_box(NULL)
|
|
{
|
|
// cout<<id<<" type"<<type<<endl;
|
|
|
|
|
|
}
|
|
|
|
Building::Building(SmiRecord& valueRecord, size_t& offset,
|
|
const ListExpr typeInfo): def(false), building_id(0),
|
|
building_type(-1), indoorgraph_init(false), indoorgraph_id(0),
|
|
rel_rooms(NULL), btree_room(NULL), rtree_rel_box(NULL)
|
|
{
|
|
|
|
valueRecord.Read(&def, sizeof(bool), offset);
|
|
offset += sizeof(bool);
|
|
|
|
valueRecord.Read(&building_id, sizeof(int), offset);
|
|
offset += sizeof(int);
|
|
|
|
valueRecord.Read(&building_type, sizeof(unsigned int), offset);
|
|
offset += sizeof(unsigned int);
|
|
|
|
valueRecord.Read(&indoorgraph_init, sizeof(bool), offset);
|
|
offset += sizeof(bool);
|
|
|
|
valueRecord.Read(&indoorgraph_id, sizeof(unsigned int), offset);
|
|
offset += sizeof(unsigned int);
|
|
|
|
|
|
ListExpr xType;
|
|
ListExpr xNumericType;
|
|
/***********************Open relation for rooms*********************/
|
|
nl->ReadFromString(IndoorNav::Indoor_GRoom_Door,xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
rel_rooms = Relation::Open(valueRecord, offset, xNumericType);
|
|
if(!rel_rooms) {
|
|
return;
|
|
}
|
|
|
|
nl->ReadFromString(RoomBTreeTypeInfo,xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
btree_room = BTree::Open(valueRecord, offset, xNumericType);
|
|
if(!btree_room) {
|
|
rel_rooms->Delete();
|
|
return;
|
|
}
|
|
|
|
///////////////////rtree on bus stops //////////////////////////////
|
|
Word xValue;
|
|
if(!(rtree_rel_box->Open(valueRecord,offset, RoomRTreeTypeInfo,xValue))){
|
|
rel_rooms->Delete();
|
|
delete btree_room;
|
|
return;
|
|
}
|
|
|
|
rtree_rel_box = ( R_Tree<3,TupleId>* ) xValue.addr;
|
|
|
|
// cout<<"rtree root node id "<<rtree_rel_box->RootRecordId()<<endl;
|
|
|
|
}
|
|
|
|
Building::~Building()
|
|
{
|
|
if(rel_rooms != NULL) rel_rooms->Close();
|
|
if(btree_room != NULL) delete btree_room;
|
|
if(rtree_rel_box != NULL) delete rtree_rel_box;
|
|
|
|
}
|
|
|
|
bool Building::Save(SmiRecord& valueRecord, size_t& offset,
|
|
const ListExpr typeInfo)
|
|
{
|
|
valueRecord.Write(&def, sizeof(bool), offset);
|
|
offset += sizeof(bool);
|
|
|
|
valueRecord.Write(&building_id, sizeof(int), offset);
|
|
offset += sizeof(int);
|
|
|
|
valueRecord.Write(&building_type, sizeof(unsigned int), offset);
|
|
offset += sizeof(unsigned int);
|
|
|
|
valueRecord.Write(&indoorgraph_init, sizeof(bool), offset);
|
|
offset += sizeof(bool);
|
|
|
|
valueRecord.Write(&indoorgraph_id, sizeof(unsigned int), offset);
|
|
offset += sizeof(unsigned int);
|
|
|
|
ListExpr xType;
|
|
ListExpr xNumericType;
|
|
|
|
////////////////////rooms relation/////////////////////////////
|
|
nl->ReadFromString(IndoorNav::Indoor_GRoom_Door, xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
if(!rel_rooms->Save(valueRecord,offset,xNumericType))
|
|
return false;
|
|
|
|
////////////////////btree on rooms relation/////////////////////////////
|
|
nl->ReadFromString(RoomBTreeTypeInfo, xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
if(!btree_room->Save(valueRecord, offset, xNumericType))
|
|
return false;
|
|
|
|
////////////////////rtree on rooms relation////////////////////////////
|
|
if(!rtree_rel_box->Save(valueRecord, offset)){
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void Building::SetIndoorGraphId(int gid)
|
|
{
|
|
if(gid > 0){
|
|
indoorgraph_id = gid;
|
|
indoorgraph_init = true;
|
|
StorePaths();
|
|
}else{
|
|
cout<<"invalid indoor graph id "<<gid<<endl;
|
|
indoorgraph_init = false;
|
|
}
|
|
}
|
|
|
|
/*
|
|
store the indoor paths from building entrance to rooms door
|
|
and from rooms door to building entrance
|
|
|
|
*/
|
|
void Building::StorePaths()
|
|
{
|
|
string str1 = GetBuildingStr(building_type);
|
|
string path_str = IndoorPathPrefix + str1 + IndoorPathSuffix;
|
|
// cout<<"path name "<<path_str<<endl;
|
|
|
|
FILE *fp = fopen(path_str.c_str(), "a");
|
|
long size = ftell(fp);
|
|
if(size > 0){
|
|
cout<<"paths file already exists"<<endl;
|
|
fclose(fp);
|
|
return;
|
|
}
|
|
|
|
|
|
IndoorGraph* ig = OpenIndoorGraph();
|
|
vector<GenLoc> doorloc_list;
|
|
vector<int> door_tid_list;
|
|
IndoorNav* indoornav = new IndoorNav(rel_rooms, NULL);
|
|
indoornav->ig = ig;
|
|
indoornav->GetDoorLoc(ig, btree_room, doorloc_list, door_tid_list);
|
|
// cout<<"number of entrances "<<door_tid_list.size()<<endl;
|
|
if(door_tid_list.size() >= MAX_ENTRANCE){
|
|
cout<<"error: assume the number is less than "<<MAX_ENTRANCE<<endl;
|
|
delete indoornav;
|
|
fclose(fp);
|
|
return;
|
|
}
|
|
if(rel_rooms->GetNoTuples() >= MAX_ROOM_NO){
|
|
cout<<"error:assume the number is less than "<<MAX_ROOM_NO<<endl;
|
|
delete indoornav;
|
|
fclose(fp);
|
|
return;
|
|
}
|
|
///////////////////////////////////////////////////////////////////////
|
|
////////1. for each entrance door, get tid and genloc ////////////////
|
|
////////for each room, according groom oid and indoor graph////////////
|
|
//find all doors of that room, filter the entrance room itself ////////
|
|
////////compute the shortest path/////////////////////////////////////
|
|
/////////////////////////////////////////////////////////////////////
|
|
int sum_paths = 0;
|
|
for(unsigned int i = 0;i < door_tid_list.size();i++){
|
|
GenLoc door_gloc = doorloc_list[i];
|
|
Tuple* door_room_tuple = rel_rooms->GetTuple(door_gloc.GetOid(), false);
|
|
GRoom* door_groom =
|
|
(GRoom*)door_room_tuple->GetAttribute(IndoorNav::I_Room);
|
|
float low_h1 = door_groom->GetLowHeight();
|
|
float high_h1 = door_groom->GetHighHeight();
|
|
float min_h1 = MIN(low_h1, high_h1);
|
|
float max_h1 = MAX(low_h1, high_h1);
|
|
|
|
for(int j = 1; j <= rel_rooms->GetNoTuples();j++){
|
|
Tuple* room_tuple = rel_rooms->GetTuple(j, false);
|
|
int groom_oid =
|
|
((CcInt*)room_tuple->GetAttribute(IndoorNav::I_OID))->GetIntval();
|
|
string groom_type =
|
|
((CcString*)room_tuple->GetAttribute(IndoorNav::I_Type))->GetValue();
|
|
if(groom_oid == (int)door_gloc.GetOid()){
|
|
room_tuple->DeleteIfAllowed();
|
|
continue;
|
|
}
|
|
|
|
if((GetRoomEnum(groom_type) == ST || GetRoomEnum(groom_type) == EL)){
|
|
room_tuple->DeleteIfAllowed();
|
|
continue;
|
|
}
|
|
|
|
GRoom* groom = (GRoom*)room_tuple->GetAttribute(IndoorNav::I_Room);
|
|
float low_h2 = groom->GetLowHeight();
|
|
float high_h2 = groom->GetHighHeight();
|
|
float min_h2 = MIN(low_h2, high_h2);
|
|
float max_h2 = MAX(low_h2, high_h2);
|
|
|
|
////////////////////////////////////////////////////////////////
|
|
////////////////find all doors of this room////////////////////
|
|
///////////////////////////////////////////////////////////////
|
|
float min_h = MIN(min_h1, min_h2);
|
|
float max_h = MAX(max_h1, max_h2);
|
|
|
|
|
|
vector<int> doors_list;
|
|
ig->GetDoorsInGRoom(groom_oid, doors_list);
|
|
if(doors_list.size() >= MAX_DOOR_INROOM){
|
|
room_tuple->DeleteIfAllowed();
|
|
continue;
|
|
}
|
|
|
|
|
|
Line3D* l3d_s = new Line3D(0);
|
|
Line3D* l3d_e = new Line3D(0);
|
|
|
|
double prune_dist = -1.0;
|
|
for(unsigned int k = 0;k < doors_list.size();k++){
|
|
|
|
//!!! use -1, 0 is used already for entrance door/////////
|
|
|
|
/////////////from entrance to rooms///////////////////////////
|
|
vector<Line3D> from_path_list;
|
|
indoornav->IndoorShortestPath(door_tid_list[i], doors_list[k],
|
|
from_path_list, l3d_s, l3d_e,
|
|
prune_dist, min_h, max_h, -1);
|
|
prune_dist = -1.0;
|
|
|
|
WritePathToFile(fp, &from_path_list[0], i + 1, groom_oid, k, true);
|
|
|
|
/////////from rooms to entrance//////////////////////
|
|
vector<Line3D> to_path_list;
|
|
indoornav->IndoorShortestPath(doors_list[k], door_tid_list[i],
|
|
to_path_list, l3d_s, l3d_e,
|
|
prune_dist, min_h, max_h, -1);
|
|
prune_dist = -1.0;
|
|
WritePathToFile(fp, &to_path_list[0], i + 1, groom_oid, k, false);
|
|
}
|
|
|
|
l3d_s->DeleteIfAllowed();
|
|
l3d_e->DeleteIfAllowed();
|
|
|
|
room_tuple->DeleteIfAllowed();
|
|
|
|
sum_paths += doors_list.size()*2;
|
|
// break;
|
|
}
|
|
|
|
door_room_tuple->DeleteIfAllowed();
|
|
}
|
|
delete indoornav;
|
|
CloseIndoorGraph(ig);
|
|
|
|
// cout<<"total paths "<<sum_paths<<endl;
|
|
|
|
fclose(fp);
|
|
|
|
}
|
|
|
|
/*
|
|
write the path into file
|
|
|
|
*/
|
|
void Building::WritePathToFile(FILE* fp, Line3D* path, int entrance,
|
|
int groom_oid, int door_num, bool from)
|
|
{
|
|
///////////////construct a number //////////////////////////////
|
|
////////entrance id + groom id + door sequence + from or to/////
|
|
///////1 + 4 + 2 + 1 ///////////////////////////
|
|
vector<int> oid_num(8,0);
|
|
oid_num[0] = entrance;
|
|
if(from)
|
|
oid_num[7] = 1;
|
|
else
|
|
oid_num[7] = 0;
|
|
unsigned int index = 4;
|
|
int num1 = groom_oid;
|
|
while(index > 0){
|
|
oid_num[index] = num1%10;
|
|
index--;
|
|
num1 = num1/10;
|
|
if(num1 == 0) break;
|
|
}
|
|
|
|
num1 = door_num;
|
|
index = 6;
|
|
while(index > 4){
|
|
oid_num[index] = num1%10;
|
|
index--;
|
|
num1 = num1/10;
|
|
if(num1 == 0) break;
|
|
}
|
|
|
|
/* cout<<"entrance id "<<entrance<<" groom oid "<<groom_oid
|
|
<<" door id "<<door_num<<" from "<<oid_num[7]<<endl;*/
|
|
int path_oid = 0;
|
|
for(unsigned int l = 0;l < oid_num.size();l++){
|
|
// cout<<oid_num[l];
|
|
int expo = oid_num.size() - 1 - l;
|
|
if(expo > 0)
|
|
// path_oid += oid_num[l]*pow(10, expo);
|
|
path_oid += oid_num[l]*pow((double)10, expo);
|
|
else
|
|
path_oid += oid_num[l];
|
|
}
|
|
// cout<<" path_oid "<<path_oid<<endl;
|
|
|
|
fprintf(fp, "%d %d\n", path_oid, path->Size());
|
|
for(int i = 0;i < path->Size();i++){
|
|
Point3D q;
|
|
path->Get(i, q);
|
|
// fprintf(fp, "%f %f %f\n", q.GetX(), q.GetY(), q.GetZ());
|
|
fprintf(fp, "%f %f %f ", q.GetX(), q.GetY(), q.GetZ());
|
|
///////////////////////////////////////////////////////////////////////
|
|
//use rtree rel box in Building to find all groom containing the point//
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
vector<int> groom_tid_list;
|
|
DFTraverse(rtree_rel_box->RootRecordId(), q, groom_tid_list);
|
|
const unsigned int max_groom = 3;
|
|
const unsigned int min_groom = 1;
|
|
if(groom_tid_list.size() > max_groom ||groom_tid_list.size() < min_groom){
|
|
cout<<"this should not occur"<<endl;
|
|
cout<<groom_tid_list.size()<<endl;
|
|
cout<<"point3d "<<q<<endl;
|
|
for(unsigned int index = 0; index < groom_tid_list.size(); index++)
|
|
cout<<groom_tid_list[index]<<endl;
|
|
|
|
assert(false);
|
|
}else{
|
|
//////////use Point3D////////////////////
|
|
double a = 0;
|
|
double b = 0;
|
|
double c = 0;
|
|
for(unsigned int i = 0;i < groom_tid_list.size();i++){
|
|
if(i == 0) a = groom_tid_list[i];
|
|
if(i == 1) b = groom_tid_list[i];
|
|
if(i == 2) c = groom_tid_list[i];
|
|
}
|
|
|
|
fprintf(fp, "%f %f %f\n", a, b, c);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
/*
|
|
find which groom contains the point
|
|
|
|
*/
|
|
void Building::DFTraverse(SmiRecordId adr, Point3D p, vector<int>& tid_list)
|
|
{
|
|
R_TreeNode<3,TupleId>* node = rtree_rel_box->GetMyNode(adr,false,
|
|
rtree_rel_box->MinEntries(0), rtree_rel_box->MaxEntries(0));
|
|
for(int j = 0;j < node->EntryCount();j++){
|
|
if(node->IsLeaf()){
|
|
R_TreeLeafEntry<3,TupleId> e =
|
|
(R_TreeLeafEntry<3,TupleId>&)(*node)[j];
|
|
Tuple* groom_tuple = rel_rooms->GetTuple(e.info,false);
|
|
GRoom* groom = (GRoom*)groom_tuple->GetAttribute(IndoorNav::I_Room);
|
|
Rectangle<3> groom_box = groom->BoundingBox3D();
|
|
if(BBoxContainPoint3D(groom_box, p)){
|
|
Region r(0);
|
|
groom->GetRegion(r);
|
|
Point q(true, p.GetX(), p.GetY());
|
|
if(q.Inside(r)){
|
|
tid_list.push_back(e.info);
|
|
/* int oid =
|
|
((CcInt*)groom_tuple->GetAttribute(IndoorNav::I_OID))->GetIntval();
|
|
oid_list.push_back(oid);*/
|
|
}
|
|
}
|
|
groom_tuple->DeleteIfAllowed();
|
|
}else{
|
|
R_TreeInternalEntry<3> e =
|
|
(R_TreeInternalEntry<3>&)(*node)[j];
|
|
if(BBoxContainPoint3D(e.box, p)){
|
|
DFTraverse(e.pointer, p, tid_list);
|
|
}
|
|
}
|
|
}
|
|
delete node;
|
|
}
|
|
|
|
|
|
/*
|
|
read the path from disk file
|
|
|
|
*/
|
|
void ReadIndoorPath(string name, int path_oid, Line3D* l3d_res)
|
|
{
|
|
// cout<<"building "<<name<<endl;
|
|
////////////////////////////////////////////////
|
|
////////read all paths from the file////////////
|
|
///////////////////////////////////////////////
|
|
int building_type = GetBuildingType(name);
|
|
if(building_type < 0){
|
|
cout<<"error:no such a building"<<endl;
|
|
return;
|
|
}
|
|
|
|
string path_str = IndoorPathPrefix + name + IndoorPathSuffix;
|
|
// cout<<"path "<<path_str<<endl;
|
|
|
|
FILE *fp = fopen(path_str.c_str(), "r");
|
|
if(fp == NULL){
|
|
cout<<"file does not exist"<<endl;
|
|
return;
|
|
}
|
|
fseek(fp, 0L, SEEK_END);
|
|
long file_size = ftell(fp);
|
|
if(file_size == 0){
|
|
cout<<"No paths stored!"<<endl;
|
|
fclose(fp);
|
|
return;
|
|
}
|
|
fseek(fp, 0L, SEEK_SET);
|
|
|
|
map<int, Line3D> path_list;//////implemented by a binary tree
|
|
while (!feof(fp)){
|
|
int path_id, no;
|
|
if(fscanf(fp, "%d %d", &path_id, &no) < 0){
|
|
// cout<<"read path error1"<<endl;
|
|
break;
|
|
}
|
|
// cout<<"path_id "<<path_id<<" no "<<no<<endl;
|
|
|
|
Line3D* l3d = new Line3D(0);
|
|
l3d->StartBulkLoad();
|
|
float x, y, z;
|
|
float temp_x, temp_y, temp_z;
|
|
for(int i = 0;i < no;i++){
|
|
int res = fscanf(fp, "%f %f %f %f %f %f",
|
|
&x, &y, &z, &temp_x, &temp_y, &temp_z);
|
|
if(res > 0){
|
|
Point3D q(true, x, y, z);
|
|
*l3d += q;
|
|
}
|
|
}
|
|
l3d->EndBulkLoad();
|
|
assert(l3d->Length() > 0.0);
|
|
// IndoorPath i_path(path_id, *l3d);
|
|
// path_list.push_back(i_path);
|
|
path_list.insert(pair<int, Line3D>(path_id, *l3d));
|
|
l3d->DeleteIfAllowed();
|
|
|
|
|
|
}
|
|
|
|
fclose(fp);
|
|
|
|
// sort(path_list.begin(), path_list.end());
|
|
|
|
|
|
map<int, Line3D>::iterator iter = path_list.find(path_oid);
|
|
if(iter != path_list.end()){
|
|
*l3d_res = iter->second;
|
|
}else{
|
|
cout<<" path "<<path_oid<<" not found"<<endl;
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
get the path id from entrance, groom oid,
|
|
we do not consider the door number here.
|
|
because for a room, if the path is recorded, the door number 0 is recorded.
|
|
we store all paths for a room, not only one. so by default, here we take the
|
|
number 0 for the door
|
|
|
|
*/
|
|
int GetIndooPathID(int entrance, int groom_oid, bool b)
|
|
{
|
|
vector<int> oid_num(8,0);
|
|
oid_num[0] = entrance;
|
|
if(b)
|
|
oid_num[7] = 1;
|
|
else
|
|
oid_num[7] = 0;
|
|
unsigned int index = 4;
|
|
int num1 = groom_oid;
|
|
while(index > 0){
|
|
oid_num[index] = num1%10;
|
|
index--;
|
|
num1 = num1/10;
|
|
if(num1 == 0) break;
|
|
}
|
|
|
|
int path_oid = 0;
|
|
for(unsigned int l = 0;l < oid_num.size();l++){
|
|
int expo = oid_num.size() - 1 - l;
|
|
if(expo > 0)
|
|
// path_oid += oid_num[l]*pow(10, expo);
|
|
path_oid += oid_num[l]*pow((double)10, expo);
|
|
else
|
|
path_oid += oid_num[l];
|
|
}
|
|
|
|
return path_oid;
|
|
}
|
|
|
|
int GetIndooPathID2(int entrance, int groom_oid, int door_num, bool b)
|
|
{
|
|
vector<int> oid_num(8,0);
|
|
oid_num[0] = entrance;
|
|
if(b)
|
|
oid_num[7] = 1;
|
|
else
|
|
oid_num[7] = 0;
|
|
unsigned int index = 4;
|
|
int num1 = groom_oid;
|
|
while(index > 0){
|
|
oid_num[index] = num1%10;
|
|
index--;
|
|
num1 = num1/10;
|
|
if(num1 == 0) break;
|
|
}
|
|
|
|
num1 = door_num;
|
|
index = 6;
|
|
while(index > 4){
|
|
oid_num[index] = num1%10;
|
|
index--;
|
|
num1 = num1/10;
|
|
if(num1 == 0) break;
|
|
}
|
|
|
|
int path_oid = 0;
|
|
for(unsigned int l = 0;l < oid_num.size();l++){
|
|
int expo = oid_num.size() - 1 - l;
|
|
if(expo > 0)
|
|
// path_oid += oid_num[l]*pow(10, expo);
|
|
path_oid += oid_num[l]*pow((double)10, expo);
|
|
else
|
|
path_oid += oid_num[l];
|
|
}
|
|
|
|
return path_oid;
|
|
}
|
|
|
|
/*
|
|
load paths from disk file
|
|
|
|
*/
|
|
void Building::LoadPaths(map<int, Line3D>& path_list,
|
|
map<int, Line3D>& room_id_list)
|
|
{
|
|
|
|
string name = GetBuildingStr(building_type);
|
|
string path_str = IndoorPathPrefix + name + IndoorPathSuffix;
|
|
|
|
FILE *fp = fopen(path_str.c_str(), "r");
|
|
if(fp == NULL){
|
|
cout<<path_str.c_str()<<" file does not exist"<<endl;
|
|
return;
|
|
}
|
|
|
|
fseek(fp, 0L, SEEK_END);
|
|
long file_size = ftell(fp);
|
|
if(file_size == 0){
|
|
cout<<"No paths stored!"<<endl;
|
|
fclose(fp);
|
|
return;
|
|
}
|
|
fseek(fp, 0L, SEEK_SET);
|
|
|
|
while (!feof(fp)){
|
|
int path_id, no;
|
|
if(fscanf(fp, "%d %d", &path_id, &no) < 0){
|
|
// cout<<"read path error1"<<endl;
|
|
break;
|
|
}
|
|
// cout<<"path_id "<<path_id<<" no "<<no<<endl;
|
|
|
|
Line3D* l3d = new Line3D(0);
|
|
Line3D* room_id = new Line3D(0);
|
|
|
|
l3d->StartBulkLoad();
|
|
room_id->StartBulkLoad();
|
|
|
|
float x, y, z;
|
|
float temp_x, temp_y, temp_z;
|
|
for(int i = 0;i < no;i++){
|
|
int res = fscanf(fp, "%f %f %f %f %f %f",
|
|
&x, &y, &z, &temp_x, &temp_y, &temp_z);
|
|
if(res > 0){
|
|
Point3D q(true, x, y, z);
|
|
*l3d += q;
|
|
|
|
Point3D p(true, temp_x, temp_y, temp_z);
|
|
*room_id += p;
|
|
}
|
|
}
|
|
l3d->EndBulkLoad();
|
|
room_id->EndBulkLoad();
|
|
|
|
assert(l3d->Length() > 0.0);
|
|
assert(l3d->Size() == room_id->Size());
|
|
|
|
// IndoorPath i_path(path_id, *l3d);
|
|
// path_list.push_back(i_path);
|
|
path_list.insert(pair<int, Line3D>(path_id, *l3d));
|
|
room_id_list.insert(pair<int, Line3D>(path_id, *room_id));
|
|
|
|
l3d->DeleteIfAllowed();
|
|
delete room_id;
|
|
}
|
|
|
|
fclose(fp);
|
|
// cout<<path_list.size()<<endl;
|
|
}
|
|
|
|
|
|
/*
|
|
return the indoor graph id of a building
|
|
|
|
*/
|
|
unsigned int Building::GetIGId()
|
|
{
|
|
if(indoorgraph_init) return indoorgraph_id;
|
|
else return 0;
|
|
}
|
|
|
|
Building* Building::Open(SmiRecord& valueRecord, size_t& offset,
|
|
const ListExpr typeInfo)
|
|
{
|
|
return new Building(valueRecord, offset, typeInfo);
|
|
}
|
|
|
|
/*
|
|
load a building from input relations
|
|
|
|
*/
|
|
void Building::Load(int id, int type, Relation* rel1, Relation* rel2)
|
|
{
|
|
building_id = id;
|
|
if(type >= 0){
|
|
building_type = type;
|
|
def = true;
|
|
}else{
|
|
def = true;
|
|
}
|
|
|
|
// cout<<rel1->GetNoTuples()<<" rooms "<<endl;
|
|
|
|
ListExpr ptrList1 = listutils::getPtrList(rel1);
|
|
string strQuery = "(consume(feed(" + IndoorNav::Indoor_GRoom_Door +
|
|
"(ptr " + nl->ToString(ptrList1) + "))))";
|
|
|
|
// cout<<strQuery<<endl;
|
|
|
|
Word xResult;
|
|
int QueryExecuted = QueryProcessor::ExecuteQuery(strQuery, xResult);
|
|
assert(QueryExecuted);
|
|
rel_rooms = (Relation*)xResult.addr;
|
|
|
|
////////////////////////////btree on rooms///////////////////////////
|
|
|
|
ListExpr ptrList2 = listutils::getPtrList(rel1);
|
|
|
|
strQuery = "(createbtree (" + IndoorNav::Indoor_GRoom_Door +
|
|
"(ptr " + nl->ToString(ptrList2) + "))" + "Oid)";
|
|
QueryExecuted = QueryProcessor::ExecuteQuery(strQuery, xResult);
|
|
assert(QueryExecuted);
|
|
btree_room = (BTree*)xResult.addr;
|
|
|
|
|
|
ListExpr ptrList3 = listutils::getPtrList(rel2);
|
|
|
|
strQuery = "(bulkloadrtree(feed (" + Indoor_GRoom_Door_Extend +
|
|
" (ptr " + nl->ToString(ptrList3) + "))) BBox)";
|
|
QueryExecuted = QueryProcessor::ExecuteQuery ( strQuery, xResult );
|
|
assert ( QueryExecuted );
|
|
rtree_rel_box = ( R_Tree<3,TupleId>* ) xResult.addr;
|
|
|
|
}
|
|
|
|
IndoorGraph* Building::OpenIndoorGraph()
|
|
{
|
|
if(indoorgraph_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) == "indoorgraph"){
|
|
// Get name of the bus graph
|
|
ListExpr xObjectName = nl->Second(xCurrent);
|
|
string strObjectName = nl->SymbolValue(xObjectName);
|
|
|
|
// Load object to find out the id of the pavement
|
|
Word xValue;
|
|
bool bDefined;
|
|
bool bOk = SecondoSystem::GetCatalog()->GetObject(strObjectName,
|
|
xValue,
|
|
bDefined);
|
|
if(!bDefined || !bOk){
|
|
// Undefined
|
|
continue;
|
|
}
|
|
IndoorGraph* ig = (IndoorGraph*)xValue.addr;
|
|
if(ig->g_id == indoorgraph_id &&
|
|
ig->GetGraphType() == (int)building_type){
|
|
// This is the indoor graph we have been looking for
|
|
return ig;
|
|
}else{
|
|
SecondoSystem::GetCatalog()->CloseObject(nl->SymbolAtom("indoorgraph"),
|
|
xValue);
|
|
}
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
void Building::CloseIndoorGraph(IndoorGraph* ig)
|
|
{
|
|
if(ig == NULL) return;
|
|
Word xValue;
|
|
xValue.addr = ig;
|
|
SecondoSystem::GetCatalog()->CloseObject(nl->SymbolAtom( "indoorgraph" ),
|
|
xValue);
|
|
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
/////////// Indoor Building Infrastructure/////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////
|
|
string IndoorInfra::BuildingPath_Info = "(rel (tuple ((Reg_id int) (Sp point)\
|
|
(Sp_index int) (Ep point) (Ep2 point) (Ep2_gloc genloc) (Path line))))";
|
|
|
|
string IndoorInfra::RegId1BTreeTypeInfo = "(rel (tuple ((Reg_id int)(Sp point)\
|
|
(Sp_index int) (Ep point) (Ep2 point) (Ep2_gloc genloc) (Path line))) int)";
|
|
|
|
|
|
string IndoorInfra::BuildingType_Info = "(rel (tuple ((Reg_id int)\
|
|
(GeoData rect) (Poly_id int) (Reg_type int) (Building_type int)\
|
|
(Building_type2 string) (Building_id int))))";
|
|
|
|
string IndoorInfra::RegId2BTreeTypeInfo = "(rel (tuple ((Reg_id int) \
|
|
(GeoData rect) (Poly_id int) (Reg_type int) (Building_type int) \
|
|
(Building_type2 string) (Building_id int))) int)";
|
|
|
|
|
|
string IndoorInfra::BuildingTypeRtreeInfo = "(rtree (tuple ((Reg_id int)\
|
|
(GeoData rect) (Poly_id int) (Reg_type int) (Building_type int)\
|
|
(Building_type2 string) (Building_id int))) rect FALSE)";
|
|
|
|
|
|
|
|
ListExpr IndoorInfraProperty()
|
|
{
|
|
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("indoorinfra"),
|
|
nl->StringAtom("((def, id))"),
|
|
nl->StringAtom("((TRUE 1))"))));
|
|
}
|
|
|
|
/*
|
|
In function. there is not nested list expression here.
|
|
|
|
*/
|
|
Word InIndoorInfra( 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<< "indoorinfra(): 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<< "indoorinfra(): building id must be int type"<<endl;
|
|
correct = false;
|
|
return SetWord(Address(0));
|
|
}
|
|
unsigned int id = nl->IntValue(second);
|
|
|
|
IndoorInfra* indoor = new IndoorInfra(d, id);
|
|
|
|
////////////////very important /////////////////////////////
|
|
correct = true;
|
|
///////////////////////////////////////////////////////////
|
|
return SetWord(indoor);
|
|
}
|
|
|
|
correct = false;
|
|
return SetWord(Address(0));
|
|
}
|
|
|
|
/*
|
|
output the indoorinfra
|
|
|
|
*/
|
|
ListExpr OutIndoorInfra( ListExpr typeInfo, Word value )
|
|
{
|
|
// cout<<"OutIndoorInfra"<<endl;
|
|
IndoorInfra* indoor = (IndoorInfra*)(value.addr);
|
|
if(!indoor->IsDefined()){
|
|
return nl->SymbolAtom("undef");
|
|
}
|
|
|
|
ListExpr list1 = nl->TwoElemList(
|
|
nl->StringAtom("IndoorInfra Id:"),
|
|
nl->IntAtom(indoor->GetId()));
|
|
|
|
ListExpr list2 = nl->TheEmptyList();
|
|
|
|
|
|
return nl->TwoElemList(list1, list2);
|
|
}
|
|
|
|
bool OpenIndoorInfra(SmiRecord& valueRecord, size_t& offset,
|
|
const ListExpr typeInfo, Word& value)
|
|
{
|
|
value.addr = IndoorInfra::Open(valueRecord, offset, typeInfo);
|
|
return value.addr != NULL;
|
|
}
|
|
|
|
bool SaveIndoorInfra(SmiRecord& valueRecord, size_t& offset,
|
|
const ListExpr typeInfo, Word& value)
|
|
{
|
|
IndoorInfra* indoor = (IndoorInfra*)value.addr;
|
|
return indoor->Save(valueRecord, offset, typeInfo);
|
|
}
|
|
|
|
|
|
Word CreateIndoorInfra(const ListExpr typeInfo)
|
|
{
|
|
// cout<<"CreateIndoorInfra()"<<endl;
|
|
return SetWord (new IndoorInfra());
|
|
}
|
|
|
|
void DeleteIndoorInfra(const ListExpr typeInfo, Word& w)
|
|
{
|
|
// cout<<"DeleteIndoorInfra()"<<endl;
|
|
IndoorInfra* indoorinfra = (IndoorInfra*)w.addr;
|
|
delete indoorinfra;
|
|
w.addr = NULL;
|
|
}
|
|
|
|
void CloseIndoorInfra( const ListExpr typeInfo, Word& w )
|
|
{
|
|
// cout<<"CloseIndoorInfra"<<endl;
|
|
delete static_cast<IndoorInfra*>(w.addr);
|
|
w.addr = 0;
|
|
}
|
|
|
|
Word CloneIndoorInfra( const ListExpr typeInfo, const Word& w )
|
|
{
|
|
// cout<<"CloneIndoorInfra"<<endl;
|
|
return SetWord( new Address(0));
|
|
}
|
|
|
|
|
|
void* IndoorInfra::Cast(void* addr)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
int SizeOfIndoorInfra()
|
|
{
|
|
// cout<<"SizeOfIndoorInfra"<<endl;
|
|
return sizeof(IndoorInfra);
|
|
}
|
|
|
|
bool CheckIndoorInfra( ListExpr type, ListExpr& errorInfo )
|
|
{
|
|
// cout<<"CheckIndoorInfra"<<endl;
|
|
return (nl->IsEqual( type, "indoorinfra" ));
|
|
}
|
|
|
|
IndoorInfra::IndoorInfra():def(false),indoor_id(0), digit_build_id(0),
|
|
building_path(NULL),
|
|
btree_reg_id1(NULL), building_type(NULL), btree_reg_id2(NULL),
|
|
rtree_building(NULL)
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
IndoorInfra::IndoorInfra(bool b, int id):def(b),indoor_id(id),digit_build_id(0),
|
|
building_path(NULL), btree_reg_id1(NULL),
|
|
building_type(NULL), btree_reg_id2(NULL),
|
|
rtree_building(NULL)
|
|
{
|
|
|
|
|
|
}
|
|
|
|
IndoorInfra::IndoorInfra(SmiRecord& valueRecord, size_t& offset,
|
|
const ListExpr typeInfo):def(false), indoor_id(0),
|
|
digit_build_id(0),
|
|
building_path(NULL), btree_reg_id1(NULL),
|
|
building_type(NULL), btree_reg_id2(NULL),
|
|
rtree_building(NULL)
|
|
{
|
|
|
|
valueRecord.Read(&def, sizeof(bool), offset);
|
|
offset += sizeof(bool);
|
|
|
|
valueRecord.Read(&indoor_id, sizeof(int), offset);
|
|
offset += sizeof(int);
|
|
|
|
|
|
valueRecord.Read(&digit_build_id, sizeof(int), offset);
|
|
offset += sizeof(int);
|
|
|
|
ListExpr xType;
|
|
ListExpr xNumericType;
|
|
/**************Open relation for buildings with paths*******************/
|
|
nl->ReadFromString(BuildingPath_Info, xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
building_path = Relation::Open(valueRecord, offset, xNumericType);
|
|
if(!building_path) {
|
|
return;
|
|
}
|
|
|
|
// cout<<"open "<<building_path->GetNoTuples()<<endl;
|
|
|
|
///////////////////btree on relation for buildings with paths//////////////
|
|
nl->ReadFromString(RegId1BTreeTypeInfo, xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
btree_reg_id1 = BTree::Open(valueRecord, offset, xNumericType);
|
|
if(!btree_reg_id1) {
|
|
building_path->Delete();
|
|
return;
|
|
}
|
|
|
|
nl->ReadFromString(BuildingType_Info,xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
building_type = Relation::Open(valueRecord, offset, xNumericType);
|
|
if(!building_type) {
|
|
building_path->Delete();
|
|
delete btree_reg_id1;
|
|
return;
|
|
}
|
|
|
|
///////////////////btree on relation for buildings with paths//////////////
|
|
nl->ReadFromString(RegId2BTreeTypeInfo, xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
btree_reg_id2 = BTree::Open(valueRecord, offset, xNumericType);
|
|
if(!btree_reg_id2) {
|
|
building_path->Delete();
|
|
delete btree_reg_id1;
|
|
building_type->Delete();
|
|
return;
|
|
}
|
|
|
|
///////////////////rtree on building rectangles//////////////////////////////
|
|
Word xValue;
|
|
if(!(rtree_building->Open(valueRecord,offset, BuildingTypeRtreeInfo,xValue))){
|
|
building_path->Delete();
|
|
delete btree_reg_id1;
|
|
building_type->Delete();
|
|
delete btree_reg_id2;
|
|
return;
|
|
}
|
|
|
|
rtree_building = ( R_Tree<2,TupleId>* ) xValue.addr;
|
|
|
|
// cout<<"open "<<building_type->GetNoTuples()<<endl;
|
|
|
|
}
|
|
|
|
IndoorInfra::~IndoorInfra()
|
|
{
|
|
if(building_path != NULL) building_path->Close();
|
|
if(btree_reg_id1 != NULL) delete btree_reg_id1;
|
|
if(building_type != NULL) building_type->Close();
|
|
if(btree_reg_id2 != NULL) delete btree_reg_id2;
|
|
if(rtree_building != NULL) delete rtree_building;
|
|
|
|
}
|
|
|
|
IndoorInfra* IndoorInfra::Open(SmiRecord& valueRecord, size_t& offset,
|
|
const ListExpr typeInfo)
|
|
{
|
|
return new IndoorInfra(valueRecord, offset, typeInfo);
|
|
}
|
|
|
|
|
|
bool IndoorInfra::Save(SmiRecord& valueRecord, size_t& offset,
|
|
const ListExpr typeInfo)
|
|
{
|
|
valueRecord.Write(&def, sizeof(bool), offset);
|
|
offset += sizeof(bool);
|
|
|
|
valueRecord.Write(&indoor_id, sizeof(int), offset);
|
|
offset += sizeof(int);
|
|
|
|
valueRecord.Write(&digit_build_id, sizeof(int), offset);
|
|
offset += sizeof(int);
|
|
|
|
ListExpr xType;
|
|
ListExpr xNumericType;
|
|
|
|
////////////////////building with paths relation///////////////////////////
|
|
nl->ReadFromString(BuildingPath_Info, xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
if(!building_path->Save(valueRecord,offset,xNumericType))
|
|
return false;
|
|
|
|
///////////////btree on relation for buildings with paths////////////////
|
|
nl->ReadFromString(RegId1BTreeTypeInfo, xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
if(!btree_reg_id1->Save(valueRecord, offset, xNumericType))
|
|
return false;
|
|
|
|
////////////////////building with types relation///////////////////////////
|
|
nl->ReadFromString(BuildingType_Info, xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
if(!building_type->Save(valueRecord,offset,xNumericType))
|
|
return false;
|
|
|
|
///////////////btree on relation for buildings with types////////////////
|
|
nl->ReadFromString(RegId2BTreeTypeInfo, xType);
|
|
xNumericType = SecondoSystem::GetCatalog()->NumericType(xType);
|
|
if(!btree_reg_id2->Save(valueRecord, offset, xNumericType))
|
|
return false;
|
|
|
|
///////////////////////rtree on building rectangles ///////////////////////
|
|
if(!rtree_building->Save(valueRecord, offset)){
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
load relations for indoor infrastructure
|
|
|
|
*/
|
|
void IndoorInfra::Load(int id, Relation* rel1, Relation* rel2)
|
|
{
|
|
// cout<<rel1->GetNoTuples()<<endl;
|
|
// cout<<rel2->GetNoTuples()<<endl;
|
|
|
|
if(id <= 0){
|
|
def = false;
|
|
return;
|
|
}
|
|
def = true;
|
|
indoor_id = id;
|
|
|
|
///////////////////building relation with paths/////////////////////////////
|
|
|
|
ListExpr ptrList1 = listutils::getPtrList(rel1);
|
|
|
|
string strQuery = "(consume(feed(" + BuildingPath_Info +
|
|
"(ptr " + nl->ToString(ptrList1) + "))))";
|
|
|
|
// cout<<strQuery<<endl;
|
|
|
|
Word xResult;
|
|
int QueryExecuted = QueryProcessor::ExecuteQuery(strQuery, xResult);
|
|
assert(QueryExecuted);
|
|
building_path = (Relation*)xResult.addr;
|
|
|
|
|
|
/////////////btree on building relation with paths///////////////////////
|
|
|
|
ListExpr ptrList2 = listutils::getPtrList(rel1);
|
|
strQuery = "(createbtree (" + BuildingPath_Info +
|
|
"(ptr " + nl->ToString(ptrList2) + "))" + "Reg_id)";
|
|
|
|
QueryExecuted = QueryProcessor::ExecuteQuery(strQuery, xResult);
|
|
assert(QueryExecuted);
|
|
btree_reg_id1 = (BTree*)xResult.addr;
|
|
|
|
////////////////building relation with types///////////////////////////////
|
|
|
|
ListExpr ptrList3 = listutils::getPtrList(rel2);
|
|
|
|
strQuery = "(consume(feed(" + BuildingType_Info +
|
|
"(ptr " + nl->ToString(ptrList3) + "))))";
|
|
|
|
// cout<<strQuery<<endl;
|
|
|
|
QueryExecuted = QueryProcessor::ExecuteQuery(strQuery, xResult);
|
|
assert(QueryExecuted);
|
|
building_type = (Relation*)xResult.addr;
|
|
|
|
/////////////btree on building relation with types///////////////////////
|
|
|
|
ListExpr ptrList4 = listutils::getPtrList(rel2);
|
|
|
|
strQuery = "(createbtree (" + BuildingType_Info +
|
|
"(ptr " + nl->ToString(ptrList4) + "))" + "Reg_id)";
|
|
|
|
QueryExecuted = QueryProcessor::ExecuteQuery(strQuery, xResult);
|
|
assert(QueryExecuted);
|
|
btree_reg_id2 = (BTree*)xResult.addr;
|
|
|
|
|
|
int min_id = numeric_limits<int>::max();
|
|
int max_id = numeric_limits<int>::min();
|
|
for(int i = 1;i <= rel2->GetNoTuples();i++){
|
|
Tuple* tuple = rel2->GetTuple(i, false);
|
|
int build_id =
|
|
((CcInt*)tuple->GetAttribute(INDOORIF_BUILD_ID))->GetIntval();
|
|
if(build_id < min_id) min_id = build_id;
|
|
if(build_id > max_id) max_id = build_id;
|
|
tuple->DeleteIfAllowed();
|
|
}
|
|
|
|
char buf1[64], buf2[64];
|
|
sprintf(buf1, "%d", min_id);
|
|
sprintf(buf2, "%d", max_id);
|
|
assert(strlen(buf1) == strlen(buf2));
|
|
|
|
//////////record how many numbers are used to recored building id//////////
|
|
digit_build_id = strlen(buf1);
|
|
|
|
|
|
//////////////////////////////////////////////////
|
|
/////////////////building rtree /////////////////
|
|
/////////////////////////////////////////////////
|
|
|
|
ListExpr ptrList5 = listutils::getPtrList(building_type);
|
|
|
|
strQuery = "(bulkloadrtree(addid(feed (" + BuildingType_Info +
|
|
" (ptr " + nl->ToString(ptrList5) + ")))) GeoData)";
|
|
|
|
QueryExecuted = QueryProcessor::ExecuteQuery ( strQuery, xResult );
|
|
assert ( QueryExecuted );
|
|
rtree_building = ( R_Tree<2,TupleId>* ) xResult.addr;
|
|
|
|
}
|
|
|
|
/*
|
|
given a reg id, it finds the corresponding tuples in path relation and
|
|
returns the tuple id for the path relation
|
|
the path relation stores the path from building entrance to the pavement
|
|
area
|
|
|
|
*/
|
|
void IndoorInfra::GetPathIDFromTypeID(int reg_id, vector<int>& path_id_list)
|
|
{
|
|
CcInt* search_id = new CcInt(true, reg_id);
|
|
BTreeIterator* btree_iter = btree_reg_id1->ExactMatch(search_id);
|
|
while(btree_iter->Next()){
|
|
Tuple* tuple = building_path->GetTuple(btree_iter->GetId(), false);
|
|
int regid = ((CcInt*)tuple->GetAttribute(INDOORIF_REG_ID))->GetIntval();
|
|
assert(reg_id == regid);
|
|
path_id_list.push_back(btree_iter->GetId());
|
|
tuple->DeleteIfAllowed();
|
|
}
|
|
delete btree_iter;
|
|
delete search_id;
|
|
}
|
|
|
|
/*
|
|
given a rectangle id, it returns the building type
|
|
|
|
*/
|
|
|
|
void IndoorInfra::GetTypeFromRegId(int reg_id, int& type, int& build_id,
|
|
Rectangle<2>& build_rect)
|
|
{
|
|
CcInt* search_id = new CcInt(true, reg_id);
|
|
BTreeIterator* btree_iter = btree_reg_id2->ExactMatch(search_id);
|
|
while(btree_iter->Next()){
|
|
Tuple* tuple = building_type->GetTuple(btree_iter->GetId(), false);
|
|
int regid = ((CcInt*)tuple->GetAttribute(INDOORIF_REG_ID_2))->GetIntval();
|
|
type = ((CcInt*)tuple->GetAttribute(INDOORIF_BUILD_TYPE))->GetIntval();
|
|
build_id = ((CcInt*)tuple->GetAttribute(INDOORIF_BUILD_ID))->GetIntval();
|
|
build_rect = *((Rectangle<2>*)tuple->GetAttribute(INDOORIF_GEODATA));
|
|
assert(reg_id == regid);
|
|
tuple->DeleteIfAllowed();
|
|
}
|
|
delete btree_iter;
|
|
delete search_id;
|
|
}
|
|
|