7409 lines
169 KiB
C++
7409 lines
169 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 ] [}]
|
|
|
|
[1] SemanticTrajectory Algebra
|
|
Author: Catherine Higgins
|
|
|
|
1 Overview
|
|
|
|
Briefly describe here what this algebra is for.
|
|
|
|
2 Defines, includes, and constants
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "SemanticTrajectoryAlgebra.h"
|
|
#include "Algebra.h"
|
|
#include "NestedList.h"
|
|
#include "QueryProcessor.h"
|
|
#include "StandardTypes.h"
|
|
#include "Attribute.h"
|
|
#include "Symbols.h"
|
|
#include "ListUtils.h"
|
|
#include "Algebras/Relation-C++/RelationAlgebra.h"
|
|
#include "Algebras/Rectangle/CellGrid.h"
|
|
#include "Stream.h"
|
|
#include "Algebras/FText/FTextAlgebra.h"
|
|
|
|
extern NestedList* nl;
|
|
extern QueryProcessor *qp;
|
|
|
|
|
|
using std::cout;
|
|
using std::endl;
|
|
namespace semtraj {
|
|
|
|
/*
|
|
|
|
3 Implementation of class SemanticTrajectory
|
|
|
|
3.1 Constructors and Destructor
|
|
|
|
*/
|
|
|
|
/*
|
|
Non-stardard constructor must be used when using Flobs or DbArrays
|
|
Initialize each type of Flob to 0
|
|
|
|
*/
|
|
|
|
SemanticTrajectory::SemanticTrajectory(int dummy):
|
|
Attribute(true),
|
|
coordinates(0),
|
|
semantics(0),
|
|
semantics_Flob(0),
|
|
cells(0),
|
|
words(0),
|
|
words_Flob(0),
|
|
bbox(false)
|
|
{
|
|
|
|
}
|
|
|
|
SemanticTrajectory::
|
|
SemanticTrajectory(const SemanticTrajectory& st) :
|
|
Attribute(st.IsDefined()),
|
|
coordinates(st.coordinates.Size()),
|
|
semantics(st.semantics.Size()),
|
|
semantics_Flob(st.semantics_Flob.getSize()),
|
|
cells(st.cells.Size()),
|
|
words(st.words.Size()),
|
|
words_Flob(st.words_Flob.getSize()),
|
|
bbox(st.bbox)
|
|
{
|
|
|
|
bool success = false;
|
|
success = semantics.Append(st.semantics);
|
|
assert(success);
|
|
success = coordinates.Append(st.coordinates);
|
|
assert(success);
|
|
success = semantics_Flob.copyFrom(st.semantics_Flob);
|
|
assert(success);
|
|
success = cells.Append(st.cells);
|
|
assert(success);
|
|
success = words.Append(st.words);
|
|
success = words_Flob.copyFrom(st.words_Flob);
|
|
assert(success);
|
|
bbox = st.bbox;
|
|
// Maybe add here bbox is defined ?
|
|
// Is that part of the rectangle class
|
|
|
|
}
|
|
|
|
SemanticTrajectory::~SemanticTrajectory()
|
|
{
|
|
|
|
}
|
|
|
|
SemanticTrajectory& SemanticTrajectory::
|
|
operator=(const SemanticTrajectory& st)
|
|
{
|
|
SetDefined(st.IsDefined());
|
|
|
|
bool success = false;
|
|
success = semantics.clean();
|
|
assert(success);
|
|
success = semantics.copyFrom(st.semantics);
|
|
assert(success);
|
|
success = coordinates.clean();
|
|
assert(success);
|
|
success = coordinates.copyFrom(st.coordinates);
|
|
assert(success);
|
|
success = semantics_Flob.clean();
|
|
assert(success);
|
|
success = semantics_Flob.copyFrom(st.semantics_Flob);
|
|
bbox = st.bbox;
|
|
success = cells.clean();
|
|
assert(success);
|
|
success = cells.Append(st.cells);
|
|
assert(success);
|
|
success = words.clean();
|
|
assert(success);
|
|
success = words.Append(st.words);
|
|
success = words_Flob.clean();
|
|
assert(success);
|
|
success = words_Flob.copyFrom(st.words_Flob);
|
|
return *this;
|
|
}
|
|
|
|
/*
|
|
3.2 Functions implementing virtual
|
|
function from class
|
|
|
|
*/
|
|
/*
|
|
i == 0 return coordinates
|
|
i == 1 return st\_TextData
|
|
i == 2 return st\_TextFlob
|
|
i == 3 returns cells
|
|
i == 4 returns words
|
|
|
|
*/
|
|
Flob *SemanticTrajectory::GetFLOB(const int i)
|
|
{
|
|
Flob* stFlob = 0;
|
|
if (i == 0) {
|
|
stFlob = &coordinates;
|
|
} else if (i == 1) {
|
|
stFlob = &semantics;
|
|
} else if (i == 2) {
|
|
stFlob = &semantics_Flob;
|
|
} else if (i == 3) {
|
|
stFlob = &cells;
|
|
} else if (i == 4) {
|
|
stFlob = &words;
|
|
} else if (i == 5)
|
|
{
|
|
stFlob = &words_Flob;
|
|
}
|
|
return stFlob;
|
|
}
|
|
|
|
|
|
void SemanticTrajectory::CopyFrom(
|
|
const Attribute* right)
|
|
{
|
|
|
|
if(right != 0)
|
|
{
|
|
const SemanticTrajectory* st =
|
|
static_cast<
|
|
const SemanticTrajectory*>(right);
|
|
if(st != 0)
|
|
{
|
|
*this = *st;
|
|
}
|
|
}
|
|
}
|
|
|
|
SemanticTrajectory*
|
|
SemanticTrajectory::Clone() const
|
|
{
|
|
|
|
SemanticTrajectory *st =
|
|
new SemanticTrajectory(*this);
|
|
assert(st != 0);
|
|
return st;
|
|
|
|
}
|
|
|
|
/*
|
|
3.3 The mandatory set of algebra support functions
|
|
|
|
3.3.1 Out-function
|
|
|
|
*/
|
|
|
|
|
|
/*
|
|
List represenation
|
|
TODO UPDATE THIS INFO AS IT IS NOT UP TO DATE
|
|
((id xl xr yl yr)...(id xl xr yl yr))
|
|
Nested list of two: first is a 4 coordinates to represent a rectangle
|
|
|
|
*/
|
|
|
|
|
|
ListExpr
|
|
SemanticTrajectory::Out(
|
|
ListExpr typeInfo,
|
|
Word value )
|
|
{
|
|
|
|
// the addr pointer of value
|
|
SemanticTrajectory* st =
|
|
(SemanticTrajectory*)(value.addr);
|
|
if (!st->IsDefined()) {
|
|
return nl->SymbolAtom(Symbol::UNDEFINED());
|
|
}
|
|
if( st->IsEmpty() )
|
|
{
|
|
return (nl->TheEmptyList());
|
|
}
|
|
else
|
|
{
|
|
std::string holdValue;
|
|
bool success = st->GetSemString(0, holdValue);
|
|
|
|
if (success == false) {
|
|
holdValue = "";
|
|
}
|
|
ListExpr result =
|
|
nl->OneElemList(
|
|
nl->ThreeElemList(
|
|
nl->RealAtom(st->GetCoordinate(0).x),
|
|
nl->RealAtom(st->GetCoordinate(0).y),
|
|
nl->TextAtom(holdValue)));
|
|
ListExpr last = result;
|
|
|
|
for( int i = 1; i < st->GetNumCoordinates(); i++ )
|
|
{
|
|
bool success = st->GetSemString(i, holdValue);
|
|
if (success == false) {
|
|
holdValue = "";
|
|
}
|
|
|
|
last = nl->Append(last,
|
|
nl->ThreeElemList(
|
|
nl->RealAtom(st->GetCoordinate(i).x),
|
|
nl->RealAtom(st->GetCoordinate(i).y),
|
|
nl->TextAtom(holdValue)));
|
|
|
|
}
|
|
|
|
ListExpr textual = nl->Empty();
|
|
ListExpr spatial = nl->Empty();
|
|
|
|
/* Need to retrieve spatial information if any */
|
|
if (!st->IsEmptySpatialSum())
|
|
{
|
|
|
|
spatial =
|
|
nl->OneElemList(
|
|
nl->ThreeElemList(
|
|
nl->IntAtom(st->GetCell(0).tripId),
|
|
nl->IntAtom(st->GetCell(0).origx),
|
|
nl->IntAtom(st->GetCell(0).origy)
|
|
)
|
|
);
|
|
ListExpr spatiallast = spatial;
|
|
|
|
for( int i = 1; i < st->GetNumCells(); i++ )
|
|
{
|
|
spatiallast = nl->Append(spatiallast,
|
|
nl->ThreeElemList(
|
|
nl->IntAtom(st->GetCell(i).tripId),
|
|
nl->IntAtom(st->GetCell(i).origx),
|
|
nl->IntAtom(st->GetCell(i).origy)
|
|
)
|
|
);
|
|
}
|
|
|
|
}
|
|
|
|
if (!st->IsEmptyTextualSum())
|
|
{
|
|
|
|
std::string holdValue;
|
|
bool success = st->GetStringSum(0, holdValue);
|
|
|
|
if (success == false) {
|
|
holdValue = "";
|
|
}
|
|
textual =
|
|
nl->OneElemList(
|
|
nl->ThreeElemList(
|
|
nl->IntAtom(st->GetWord(0).indexId),
|
|
nl->IntAtom(st->GetWord(0).count),
|
|
nl->TextAtom(holdValue)
|
|
)
|
|
);
|
|
ListExpr textuallast = textual;
|
|
for( int i = 1; i < st->GetNumWords(); i++ )
|
|
{
|
|
|
|
bool success = st->GetStringSum(i, holdValue);
|
|
|
|
if (success == false) {
|
|
holdValue = "";
|
|
}
|
|
textuallast = nl->Append(textuallast,
|
|
nl->ThreeElemList(
|
|
nl->IntAtom(st->GetWord(i).indexId),
|
|
nl->IntAtom(st->GetWord(i).count),
|
|
nl->TextAtom(holdValue)
|
|
)
|
|
);
|
|
}
|
|
|
|
}
|
|
|
|
ListExpr final =
|
|
nl->FourElemList(
|
|
nl->FourElemList(
|
|
nl->RealAtom(st->bbox.getMinX()),
|
|
nl->RealAtom(st->bbox.getMinY()),
|
|
nl->RealAtom(st->bbox.getMaxX()),
|
|
nl->RealAtom(st->bbox.getMaxY())
|
|
),
|
|
spatial,
|
|
textual,
|
|
result
|
|
);
|
|
|
|
return final;
|
|
}
|
|
}
|
|
|
|
/*
|
|
3.3.2 In-function
|
|
|
|
*/
|
|
|
|
/*
|
|
List represenation
|
|
Nested list of four:
|
|
first nested list: Represents bounding box which is a 4 coordinates
|
|
to represent a rectangle
|
|
second nested list: Represents the spatial summary
|
|
(this can be expected to be empty until operator is makespatialsum
|
|
is called)
|
|
third nested list: Represents the textual summary
|
|
(this can be expected to be empty until operator is called)
|
|
fourth nested list: Represents the trajectory data
|
|
|
|
*/
|
|
|
|
/* The bouding box get's calculated everytime */
|
|
|
|
Word
|
|
SemanticTrajectory::In(
|
|
const ListExpr typeInfo,
|
|
const ListExpr instance,
|
|
const int errorPos,
|
|
ListExpr& errorInfo,
|
|
bool& correct )
|
|
{
|
|
|
|
Word word;
|
|
correct = false;
|
|
SemanticTrajectory* st = new SemanticTrajectory(0);
|
|
st->SetDefined(true);
|
|
|
|
// This is if list is undefined
|
|
// ~ setDefined to false
|
|
if(listutils::isSymbolUndefined( instance ))
|
|
{
|
|
st->SetDefined(false);
|
|
correct = true;
|
|
word.addr = st;
|
|
return word;
|
|
}
|
|
|
|
if (nl != 0)
|
|
{
|
|
|
|
int nListLength = nl->ListLength(instance);
|
|
// If list has 4 arguments
|
|
// and undefined content
|
|
//~ setDefined to false
|
|
if (nListLength == 4 &&
|
|
nl->IsAtom(nl->Fourth(instance)) &&
|
|
nl->AtomType(nl->Fourth(instance)) == SymbolType &&
|
|
listutils::isSymbolUndefined(nl->Fourth(instance)))
|
|
{
|
|
correct = true;
|
|
st->SetDefined(false);
|
|
correct = true;
|
|
word.addr = st;
|
|
return word;
|
|
}
|
|
|
|
if (nListLength == 4)
|
|
{
|
|
ListExpr first = nl->Empty();
|
|
ListExpr rest = nl->Fourth(instance);
|
|
double mind[2];
|
|
double maxd[2];
|
|
double c_x1;
|
|
double c_y1;
|
|
double c_x2;
|
|
double c_y2;
|
|
/* TODO Add check here to make sure
|
|
list rest is at least two points
|
|
to be valid semantic trajectory (maybe)*/
|
|
while (nl->IsEmpty(rest) == false)
|
|
{
|
|
first = nl->First( rest );
|
|
rest = nl->Rest( rest );
|
|
|
|
if( nl->ListLength(first) == 3 &&
|
|
nl->IsAtom(nl->First(first)) &&
|
|
nl->AtomType(nl->First(first))
|
|
== RealType &&
|
|
nl->IsAtom(nl->Second(first)) &&
|
|
nl->AtomType(nl->Second(first))
|
|
== RealType &&
|
|
nl->IsAtom(nl->Third(first)))
|
|
{
|
|
double x1 = nl->RealValue(nl->First(first));
|
|
double y1 = nl->RealValue(nl->Second(first));
|
|
Coordinate c(x1, y1);
|
|
st->AddCoordinate(c);
|
|
bool typeString =
|
|
nl->AtomType(nl->Third(first)) == StringType;
|
|
bool typeText =
|
|
nl->AtomType(nl->Third(first)) == TextType;
|
|
std::string stringValue;
|
|
if (typeString == true)
|
|
{
|
|
stringValue =
|
|
nl->StringValue(nl->Third(first));
|
|
}
|
|
if (typeText == true)
|
|
{
|
|
stringValue =
|
|
nl->TextValue(nl->Third(first));
|
|
}
|
|
|
|
st->AddSemString(stringValue);
|
|
|
|
/* Set bounding box here */
|
|
if (st->GetNumCoordinates() == 1)
|
|
{
|
|
c_x1 = x1;
|
|
c_y1 = y1;
|
|
c_x2 = x1;
|
|
c_y2 = y1;
|
|
}
|
|
else
|
|
{
|
|
c_x1 = std::min(c_x1, x1);
|
|
c_y1 = std::min(c_y1, y1);
|
|
c_x2 = std::max(c_x2, x1);
|
|
c_y2 = std::max(c_y2, y1);
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
correct = false;
|
|
delete st;
|
|
return SetWord( Address(0) );
|
|
}
|
|
if (c_x1 <= c_x2 && c_y1 <= c_y2)
|
|
{
|
|
mind[0] = c_x1;
|
|
mind[1] = c_y1;
|
|
maxd[0] = c_x2;
|
|
maxd[1] = c_y2;
|
|
st->bbox.Set(true, mind, maxd);
|
|
}
|
|
}
|
|
/* TODO add extra checks and conditions */
|
|
/* Extract info for spatial summary if any */
|
|
if (!listutils::isSymbolUndefined(
|
|
nl->Second(instance)))
|
|
{
|
|
|
|
ListExpr first = nl->Empty();
|
|
ListExpr rest = nl->Second(instance);
|
|
|
|
while (nl->IsEmpty(rest) == false)
|
|
{
|
|
first = nl->First( rest );
|
|
rest = nl->Rest( rest );
|
|
if( nl->ListLength(first) == 3 &&
|
|
nl->IsAtom(nl->First(first)) &&
|
|
nl->AtomType(nl->First(first))
|
|
== IntType &&
|
|
nl->IsAtom(nl->Second(first)) &&
|
|
nl->AtomType(nl->Second(first))
|
|
== IntType &&
|
|
nl->IsAtom(nl->Third(first)) &&
|
|
nl->AtomType(nl->Third(first))
|
|
== IntType
|
|
)
|
|
{
|
|
Cell c(nl->IntValue(nl->First(first)),
|
|
nl->IntValue(nl->Second(first)),
|
|
nl->IntValue(nl->Third(first))
|
|
);
|
|
st->AddCell(c);
|
|
|
|
}
|
|
else
|
|
{
|
|
correct = false;
|
|
delete st;
|
|
return SetWord( Address(0) );
|
|
}
|
|
|
|
|
|
} // end of while
|
|
} // end of if
|
|
/* TODO add extra checks and conditions */
|
|
/* Extract info for textual summary if any */
|
|
if (!listutils::isSymbolUndefined(nl->Third(instance)))
|
|
{
|
|
ListExpr first = nl->Empty();
|
|
ListExpr rest = nl->Third(instance);
|
|
|
|
while (nl->IsEmpty(rest) == false)
|
|
{
|
|
first = nl->First( rest );
|
|
rest = nl->Rest( rest );
|
|
if( nl->ListLength(first) == 3 &&
|
|
nl->IsAtom(nl->First(first)) &&
|
|
nl->AtomType(nl->First(first))
|
|
== IntType &&
|
|
nl->IsAtom(nl->Second(first)) &&
|
|
nl->AtomType(nl->Second(first))
|
|
== IntType && nl->IsAtom(nl->Third(first))
|
|
)
|
|
{
|
|
|
|
bool typeString =
|
|
nl->AtomType(nl->Third(first)) == StringType;
|
|
|
|
std::string stringValue;
|
|
if (typeString == true)
|
|
{
|
|
stringValue =
|
|
nl->StringValue(nl->Third(first));
|
|
} else {
|
|
stringValue =
|
|
nl->TextValue(nl->Third(first));
|
|
}
|
|
|
|
st->AddStringSum(stringValue,
|
|
nl->IntValue(nl->First(first)),
|
|
nl->IntValue(nl->Second(first)));
|
|
|
|
}
|
|
else
|
|
{
|
|
correct = false;
|
|
delete st;
|
|
return SetWord( Address(0) );
|
|
}
|
|
}
|
|
}
|
|
|
|
} // end of if n ===4
|
|
correct = true;
|
|
return SetWord(st);
|
|
} // end of n != 0
|
|
|
|
return word;
|
|
}
|
|
|
|
/*
|
|
3.3.3 Property function
|
|
|
|
*/
|
|
ListExpr
|
|
SemanticTrajectory::Property()
|
|
{
|
|
return
|
|
(nl->TwoElemList(
|
|
nl->FiveElemList(
|
|
nl->StringAtom("Signature"),
|
|
nl->StringAtom("Example Type List"),
|
|
nl->StringAtom("List Rep"),
|
|
nl->StringAtom("Example List"),
|
|
nl->StringAtom("Remarks")),
|
|
nl->FiveElemList(nl->StringAtom(
|
|
"->" + Kind::DATA()
|
|
),
|
|
nl->StringAtom(
|
|
SemanticTrajectory::BasicType()
|
|
),
|
|
nl->TextAtom(
|
|
"((minx miny maxx maxy)"
|
|
"((tripid xl1 xr1 yl1 yr1)"
|
|
"(tripid xl xr yl yr))"
|
|
"()(<x1> <y1> <Text1>)..."
|
|
"(<xn> <yn> <Text2>))"),
|
|
nl->TextAtom(
|
|
"((3.2 15.4 6.34 15.4)"
|
|
"()()"
|
|
"((3.2 15.4 text1)"
|
|
"(6.34 20.8 text2)))"),
|
|
nl->TextAtom(
|
|
"x- and y-coordinates"
|
|
" must be "
|
|
"of type real."))));
|
|
}
|
|
|
|
/*
|
|
3.3.4 Kind Checking Function
|
|
|
|
*/
|
|
bool
|
|
SemanticTrajectory::KindCheck(
|
|
ListExpr type,
|
|
ListExpr& errorInfo )
|
|
{
|
|
return (nl->IsEqual(
|
|
type,
|
|
SemanticTrajectory::BasicType() ));
|
|
}
|
|
|
|
/*
|
|
3.3.5 ~Create~-function
|
|
|
|
*/
|
|
Word SemanticTrajectory::Create(
|
|
const ListExpr typeInfo)
|
|
{
|
|
SemanticTrajectory* st = new SemanticTrajectory(0);
|
|
return (SetWord(st));
|
|
}
|
|
|
|
/*
|
|
3.3.6 ~Destroy~-function
|
|
|
|
*/
|
|
void SemanticTrajectory::Destroy()
|
|
{
|
|
|
|
semantics.Destroy();
|
|
semantics_Flob.destroy();
|
|
coordinates.Destroy();
|
|
cells.Destroy();
|
|
words.Destroy();
|
|
words_Flob.destroy();
|
|
}
|
|
|
|
/*
|
|
3.3.7 ~Delete~-function
|
|
|
|
*/
|
|
void SemanticTrajectory::Delete(
|
|
const ListExpr typeInfo,
|
|
Word& w)
|
|
{
|
|
|
|
SemanticTrajectory* st =
|
|
(SemanticTrajectory*)w.addr;
|
|
st->Destroy();
|
|
delete st;
|
|
}
|
|
|
|
/*
|
|
3.3.8 ~Open~-function
|
|
|
|
*/
|
|
bool
|
|
SemanticTrajectory::Open(
|
|
SmiRecord& valueRecord,
|
|
size_t& offset,
|
|
const ListExpr typeInfo,
|
|
Word& value )
|
|
{
|
|
|
|
SemanticTrajectory *st =
|
|
(SemanticTrajectory*)Attribute::Open(
|
|
valueRecord, offset, typeInfo );
|
|
value.setAddr( st );
|
|
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
3.3.9 ~Save~-function
|
|
|
|
*/
|
|
bool
|
|
SemanticTrajectory::Save( SmiRecord& valueRecord,
|
|
size_t& offset,
|
|
const ListExpr typeInfo,
|
|
Word& value )
|
|
{
|
|
|
|
SemanticTrajectory *st =
|
|
(SemanticTrajectory *)value.addr;
|
|
Attribute::Save( valueRecord, offset, typeInfo, st );
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
3.3.10 ~Close~-function
|
|
|
|
*/
|
|
void SemanticTrajectory::Close(
|
|
const ListExpr typeInfo,
|
|
Word& w)
|
|
{
|
|
|
|
SemanticTrajectory* st = (SemanticTrajectory*)w.addr;
|
|
delete st;
|
|
}
|
|
|
|
/*
|
|
3.3.11 ~Clone~ funtion
|
|
|
|
*/
|
|
Word SemanticTrajectory::Clone(
|
|
const ListExpr typeInfo,
|
|
const Word& rWord)
|
|
{
|
|
|
|
Word word;
|
|
SemanticTrajectory* pSemanticTrajectory =
|
|
static_cast<SemanticTrajectory*>(rWord.addr);
|
|
if (pSemanticTrajectory != 0)
|
|
{
|
|
word.addr =
|
|
new SemanticTrajectory(*pSemanticTrajectory);
|
|
assert(word.addr != 0);
|
|
}
|
|
return word;
|
|
}
|
|
|
|
/*
|
|
3.3.12 ~SizeOf~-function
|
|
|
|
*/
|
|
int SemanticTrajectory::SizeOfObj()
|
|
{
|
|
return sizeof(SemanticTrajectory);
|
|
}
|
|
|
|
/*
|
|
3.3.13 ~Cast~-function
|
|
|
|
*/
|
|
void* SemanticTrajectory::Cast(void* addr)
|
|
{
|
|
|
|
return (new (addr) SemanticTrajectory);
|
|
}
|
|
|
|
|
|
/*
|
|
3.4 Implementation of new functions
|
|
|
|
3.4.1 ~AddCoordinate~ function
|
|
|
|
Responsible for adding a <x,y> Coordinate object
|
|
to DbArray coordinates
|
|
|
|
*/
|
|
void SemanticTrajectory::
|
|
AddCoordinate(
|
|
const Coordinate& c)
|
|
{
|
|
coordinates.Append(c);
|
|
|
|
}
|
|
|
|
/*
|
|
3.4.2 ~GetCoordinate~ function
|
|
|
|
Retrieve a Coordinate from the DbArray coordinates
|
|
|
|
*/
|
|
Coordinate SemanticTrajectory::
|
|
GetCoordinate( int i ) const
|
|
{
|
|
assert( 0 <= i && i < GetNumCoordinates() );
|
|
Coordinate c;
|
|
coordinates.Get( i, &c );
|
|
return c;
|
|
}
|
|
|
|
/*
|
|
3.4.3 ~AddSemString~ function
|
|
|
|
*/
|
|
bool SemanticTrajectory::AddSemString(const std::string& stString)
|
|
{
|
|
/*
|
|
Important that even if a string is Empty
|
|
that the information is stored in the
|
|
semantics DbArray. If not this might
|
|
impact the position of the string in the Out:: function
|
|
|
|
*/
|
|
TextData td;
|
|
td.Offset = semantics_Flob.getSize();
|
|
td.Length = stString.length();
|
|
bool success = semantics.Append(td);
|
|
assert(success);
|
|
if (!stString.empty())
|
|
{
|
|
semantics_Flob.write(
|
|
stString.c_str(),
|
|
td.Length,
|
|
td.Offset);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
3.4.4 ~GetSemString~ function
|
|
|
|
*/
|
|
bool SemanticTrajectory::
|
|
GetSemString(int index, std::string& rString) const
|
|
{
|
|
|
|
bool success = false;
|
|
int numString = semantics.Size();
|
|
if (index < numString)
|
|
{
|
|
TextData textData;
|
|
success = semantics.Get(index, &textData);
|
|
if (success == true)
|
|
{
|
|
SmiSize bufferSize = textData.Length + 1;
|
|
char* pBuffer = new char[bufferSize];
|
|
if (pBuffer != 0)
|
|
{
|
|
memset(
|
|
pBuffer,
|
|
0,
|
|
bufferSize * sizeof(char));
|
|
success = semantics_Flob.read(
|
|
pBuffer,
|
|
textData.Length,
|
|
textData.Offset);
|
|
}
|
|
if(success == true)
|
|
{
|
|
rString = pBuffer;
|
|
}
|
|
delete [] pBuffer;
|
|
}
|
|
}
|
|
return success;
|
|
}
|
|
|
|
/*
|
|
3.4.5 ~AddStringSum~ function
|
|
|
|
*/
|
|
|
|
/*
|
|
Each trajectory has textual summary which consists of all the
|
|
individual unique words found in one semantic SemanticTrajectory
|
|
This function adds a string to the Flob X and string info to DbArray X.
|
|
|
|
*/
|
|
bool SemanticTrajectory::AddStringSum(
|
|
const std::string& stString, int id, int count)
|
|
{
|
|
if (!stString.empty())
|
|
{
|
|
WordST td;
|
|
td.Offset = words_Flob.getSize();
|
|
td.Length = stString.length();
|
|
td.indexId = id;
|
|
td.count = count;
|
|
bool success = words.Append(td);
|
|
assert(success);
|
|
words_Flob.write(
|
|
stString.c_str(),
|
|
td.Length,
|
|
td.Offset);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
3.4.6 ~GetStringSum~ function
|
|
|
|
*/
|
|
bool SemanticTrajectory::
|
|
GetStringSum(int index, std::string& rString) const
|
|
{
|
|
|
|
bool success = false;
|
|
int numString = words.Size();
|
|
if (index < numString)
|
|
{
|
|
WordST textData;
|
|
success = words.Get(index, &textData);
|
|
if (success == true)
|
|
{
|
|
SmiSize bufferSize = textData.Length + 1;
|
|
char* pBuffer = new char[bufferSize];
|
|
if (pBuffer != 0)
|
|
{
|
|
memset(
|
|
pBuffer,
|
|
0,
|
|
bufferSize * sizeof(char));
|
|
success = words_Flob.read(
|
|
pBuffer,
|
|
textData.Length,
|
|
textData.Offset);
|
|
}
|
|
if(success == true)
|
|
{
|
|
rString = pBuffer;
|
|
}
|
|
delete [] pBuffer;
|
|
}
|
|
}
|
|
return success;
|
|
}
|
|
|
|
/*
|
|
3.4.7 GetStringArray function
|
|
|
|
|
|
*/
|
|
std::list<std::string> SemanticTrajectory::GetStringArray() const
|
|
{
|
|
|
|
|
|
std::list<std::string> stringArray;
|
|
|
|
int nStrings = semantics.Size();
|
|
bool bOK = false;
|
|
std::string holdString;
|
|
|
|
for(int i = 0; i < nStrings; i++)
|
|
{
|
|
bOK = GetSemString(i, holdString);
|
|
stringutils::StringTokenizer parse(holdString, " ");
|
|
if (bOK == true)
|
|
{
|
|
while(parse.hasNextToken())
|
|
{
|
|
std::string eval = parse.nextToken();
|
|
stringutils::trim(eval);
|
|
if (eval.length() > 0)
|
|
{
|
|
stringArray.push_back(eval);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
stringArray.sort(SemanticTrajectory::compare_nocase);
|
|
return stringArray;
|
|
}
|
|
|
|
|
|
/*
|
|
3.4.8 ~AddCell~ function
|
|
|
|
TODO
|
|
|
|
*/
|
|
void SemanticTrajectory::
|
|
AddCell(const Cell& c)
|
|
{
|
|
cells.Append(c);
|
|
}
|
|
|
|
/*
|
|
3.4.9 GetCellList function
|
|
|
|
TODO
|
|
|
|
*/
|
|
DbArray<Cell> SemanticTrajectory::
|
|
GetCellList() const
|
|
{
|
|
assert(IsDefined());
|
|
return cells;
|
|
}
|
|
|
|
/*
|
|
3.4.9 ~GetTextSumList~ function
|
|
|
|
TODO
|
|
|
|
*/
|
|
DbArray<WordST> SemanticTrajectory::
|
|
GetTextSumList() const
|
|
{
|
|
assert(IsDefined());
|
|
return words;
|
|
}
|
|
|
|
|
|
/*
|
|
3.5 Operator helper functions
|
|
|
|
3.5.1 ~Relevance~ Function
|
|
|
|
*/
|
|
|
|
double SemanticTrajectory::Relevance(int i,
|
|
std::string& str,
|
|
SemanticTrajectory& st,
|
|
double diag, double alpha)
|
|
{
|
|
// Return the max of all return similarity equation
|
|
|
|
double max = -999999; /*TODO use a max varialble */
|
|
int numOfCoor2 = st.GetNumCoordinates();
|
|
for (int y = 0; y <numOfCoor2; y++)
|
|
{
|
|
double temp = Sim(i, y, str, st, diag, alpha);
|
|
|
|
if (temp > max)
|
|
{
|
|
max = temp;
|
|
}
|
|
}
|
|
|
|
return max;
|
|
}
|
|
|
|
/*
|
|
3.5.2 ~Sim~ Function
|
|
TODO
|
|
|
|
*/
|
|
double SemanticTrajectory::Sim(int i, int y,
|
|
std::string& str, SemanticTrajectory& st,
|
|
double diag, double alpha)
|
|
{
|
|
double dist = SpatialDist(i, y, st);
|
|
|
|
double normalizedscore = 1 - (double)(dist/diag);
|
|
// It's inversly proportional to the
|
|
// distance so we need to substract from 1
|
|
double LS = alpha * normalizedscore;
|
|
|
|
double textscore = 0.0;
|
|
if (str.length() > 0)
|
|
{
|
|
textscore = TextualScore(str, y, st);
|
|
}
|
|
|
|
double RH = double (1 - alpha) * textscore;
|
|
return LS + RH;
|
|
}
|
|
|
|
/*
|
|
3.5.3 ~GetDiagonal~ Function
|
|
TODO
|
|
|
|
*/
|
|
double SemanticTrajectory::GetDiagonal(
|
|
Rectangle<2>& rec)
|
|
{
|
|
double x1 = rec.getMinX();
|
|
double y1 = rec.getMinY();
|
|
double x2 = rec.getMaxX();
|
|
double y2 = rec.getMaxY();
|
|
double result = sqrt(pow((x1 - x2),2)
|
|
+ pow((y1 - y2),2));
|
|
return result;
|
|
}
|
|
|
|
/*
|
|
3.5.4 ~GetDiag~ Function
|
|
TODO
|
|
|
|
*/
|
|
double GetDiag(
|
|
Rectangle<2>& rec)
|
|
{
|
|
double x1 = rec.getMinX();
|
|
double y1 = rec.getMinY();
|
|
double x2 = rec.getMaxX();
|
|
double y2 = rec.getMaxY();
|
|
double result = sqrt(pow((x1 - x2),2)
|
|
+ pow((y1 - y2),2));
|
|
return result;
|
|
}
|
|
|
|
/*
|
|
3.5.5 ~SpatialDist~ Function
|
|
TODO
|
|
|
|
*/
|
|
double SemanticTrajectory::SpatialDist(int i, int y,
|
|
SemanticTrajectory& st)
|
|
{
|
|
double x1 = GetCoordinate(i).x;
|
|
double y1 = GetCoordinate(i).y;
|
|
double x2 = st.GetCoordinate(y).x;
|
|
double y2 = st.GetCoordinate(y).y;
|
|
|
|
double result =
|
|
sqrt(pow((x1 - x2),2)
|
|
+ pow((y1 - y2),2));
|
|
return result;
|
|
}
|
|
|
|
/*
|
|
3.5.6 TextualScore Function
|
|
|
|
Used with operator sim to return the textual score between
|
|
two trajectories
|
|
|
|
*/
|
|
double SemanticTrajectory::TextualScore(std::string& str, int y,
|
|
SemanticTrajectory& st)
|
|
{
|
|
|
|
bool success = false;
|
|
std::string s2;
|
|
success = st.GetSemString(y, s2);
|
|
assert(success);
|
|
if (str.length() > 0 && s2.length() > 0)
|
|
{
|
|
|
|
int numMatches = 0;
|
|
stringutils::StringTokenizer st1(str, " ");
|
|
stringutils::StringTokenizer st2(s2, " ");
|
|
int numToken1 = str.length();
|
|
int numToken2 = s2.length();
|
|
std::string eval = "";
|
|
std::string eval2 = "";
|
|
bool noToks1 = false;
|
|
bool noToks2 = false;
|
|
if (st1.hasNextToken())
|
|
{
|
|
eval = st1.nextToken();
|
|
} else {
|
|
noToks1 = true;
|
|
}
|
|
if (st2.hasNextToken())
|
|
{
|
|
eval2 = st2.nextToken();
|
|
} else {
|
|
noToks2 = true;
|
|
}
|
|
|
|
while(!noToks2 && !noToks1)
|
|
{
|
|
|
|
if((eval).compare(eval2) == 0)
|
|
{
|
|
numMatches++;
|
|
|
|
if (st1.hasNextToken())
|
|
{
|
|
eval = st1.nextToken();
|
|
} else {
|
|
noToks1 = true;
|
|
}
|
|
if (st2.hasNextToken())
|
|
{
|
|
eval2 = st2.nextToken();
|
|
} else {
|
|
noToks2 = true;
|
|
}
|
|
}
|
|
|
|
else if ((eval).compare(eval2) < 0) {
|
|
|
|
if (st1.hasNextToken())
|
|
{
|
|
eval = st1.nextToken();
|
|
} else {
|
|
noToks1 = true;
|
|
}
|
|
|
|
} else {
|
|
|
|
if (st2.hasNextToken())
|
|
{
|
|
eval2 = st2.nextToken();
|
|
}
|
|
else
|
|
{
|
|
noToks2 = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (numMatches == 0.0)
|
|
{
|
|
return 0.0;
|
|
}
|
|
double uniquewords = (double)
|
|
(numToken2 + numToken1 - numMatches);
|
|
double result = (double) numMatches / uniquewords;
|
|
return result;
|
|
}
|
|
|
|
|
|
return 0.0;
|
|
}
|
|
|
|
/*
|
|
3.5.7 Placename Function
|
|
TODO
|
|
|
|
*/
|
|
double SemanticTrajectory::Similarity(
|
|
SemanticTrajectory& st,
|
|
double diag,
|
|
double alpha)
|
|
{
|
|
|
|
int numCoordinates1 = GetNumCoordinates();
|
|
double sumOfRelevance1 = 0;
|
|
double leftTotal = 0;
|
|
bool success = false;
|
|
std::string str;
|
|
for (int i = 0; i < numCoordinates1; i++)
|
|
{
|
|
|
|
success = GetSemString(i, str);
|
|
|
|
assert(success);
|
|
sumOfRelevance1 =
|
|
sumOfRelevance1 + Relevance(i, str, st, diag, alpha);
|
|
}
|
|
|
|
leftTotal =
|
|
sumOfRelevance1 / (double) numCoordinates1;
|
|
|
|
int numCoordinates2 = st.GetNumCoordinates();
|
|
double sumOfRelevance2 = 0;
|
|
double rightTotal = 0;
|
|
for (int i = 0; i < numCoordinates2; i++)
|
|
{
|
|
|
|
success = st.GetSemString(i, str);
|
|
|
|
assert(success);
|
|
sumOfRelevance2 =
|
|
sumOfRelevance2 + st.Relevance(
|
|
i, str, *this, diag, alpha);
|
|
}
|
|
rightTotal =
|
|
sumOfRelevance2 / (double) numCoordinates2;
|
|
|
|
|
|
double result = rightTotal + leftTotal;
|
|
|
|
return result;
|
|
}
|
|
/*
|
|
3.5.8 Placename Function
|
|
TODO
|
|
|
|
*/
|
|
double SemanticTrajectory::textualScoreTT(SemanticTrajectory& st2)
|
|
{
|
|
std::vector<std::string*>** hashTable;
|
|
std::vector<std::string*>** hashTable2;
|
|
const std::vector<std::string*>* bucket;
|
|
std::hash<std::string> str_hash;
|
|
unsigned int bucketnum = 100;
|
|
|
|
|
|
hashTable = new std::vector<std::string*>*[bucketnum];
|
|
for (unsigned int i = 0; i < bucketnum; i++)
|
|
{
|
|
hashTable[i] = 0;
|
|
}
|
|
|
|
hashTable2 = new std::vector<std::string*>*[bucketnum];
|
|
for (unsigned int i = 0; i < bucketnum; i++)
|
|
{
|
|
hashTable2[i] = 0;
|
|
}
|
|
for (int i = 0; i < GetNumWords(); i++)
|
|
{
|
|
std::string holdValue = "";
|
|
bool success = GetStringSum(i, holdValue);
|
|
if(success)
|
|
{
|
|
|
|
size_t hash = str_hash(holdValue) % bucketnum;
|
|
|
|
if (!hashTable[hash])
|
|
{
|
|
hashTable[hash] = new std::vector<std::string*>();
|
|
}
|
|
std::string* stn = new std::string(holdValue);
|
|
hashTable[hash]->push_back(stn);
|
|
}
|
|
|
|
}
|
|
|
|
for (int i = 0; i < st2.GetNumWords(); i++)
|
|
{
|
|
std::string holdValue = "";
|
|
bool success = st2.GetStringSum(i, holdValue);
|
|
if(success)
|
|
{
|
|
|
|
size_t hash = str_hash(holdValue) % bucketnum;
|
|
|
|
if (!hashTable2[hash])
|
|
{
|
|
hashTable2[hash] = new std::vector<std::string*>();
|
|
}
|
|
std::string* stn = new std::string(holdValue);
|
|
hashTable2[hash]->push_back(stn);
|
|
}
|
|
|
|
}
|
|
double TSim = 0.0;
|
|
unsigned int bucketpos = 0;
|
|
for(int i = 0; i < GetNumCoordinates(); i++)
|
|
{
|
|
std::string holdvalue;
|
|
GetSemString(i, holdvalue);
|
|
|
|
if (holdvalue.length() > 0)
|
|
{
|
|
stringutils::StringTokenizer parse_st1(holdvalue, " ");
|
|
while(parse_st1.hasNextToken())
|
|
{
|
|
std::string eval = parse_st1.nextToken();
|
|
stringutils::trim(eval);
|
|
size_t hash = str_hash(eval) % bucketnum;;
|
|
bucket = 0;
|
|
bucket = hashTable2[hash];
|
|
bucketpos = 0;
|
|
if(bucket)
|
|
{
|
|
while(bucketpos < bucket->size())
|
|
{
|
|
std::string* check = (*bucket)[bucketpos];
|
|
if ((check)->compare(eval) == 0)
|
|
{
|
|
TSim = TSim + ((double) 1/GetNumCoordinates());
|
|
break;
|
|
}
|
|
bucketpos++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for(int i = 0; i < st2.GetNumTextData(); i++)
|
|
{
|
|
|
|
std::string holdvalue;
|
|
st2.GetSemString(i, holdvalue);
|
|
if (holdvalue.length() > 0)
|
|
{
|
|
stringutils::StringTokenizer parse_st2(holdvalue, " ");
|
|
|
|
while(parse_st2.hasNextToken())
|
|
{
|
|
|
|
std::string eval = parse_st2.nextToken();
|
|
stringutils::trim(eval);
|
|
size_t hash = str_hash(eval) % bucketnum;
|
|
bucket = 0;
|
|
bucket = hashTable[hash];
|
|
bucketpos = 0;
|
|
if(bucket)
|
|
{
|
|
while(bucketpos < bucket->size())
|
|
{
|
|
|
|
std::string* check = (*bucket)[bucketpos];
|
|
if ((check)->compare(eval) == 0)
|
|
{
|
|
|
|
TSim = TSim + ((double) 1/st2.GetNumCoordinates());
|
|
break;
|
|
}
|
|
bucketpos++;
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
for (unsigned int i = 0; i< bucketnum; i++)
|
|
{
|
|
std::vector<std::string*>* v = hashTable[i];
|
|
if (v)
|
|
{
|
|
for(unsigned int j = 0; j < v->size(); j++)
|
|
{
|
|
std::string* stn = (*v)[j];
|
|
delete stn;
|
|
|
|
}
|
|
(v)->clear();
|
|
delete hashTable[i];
|
|
hashTable[i] = 0;
|
|
}
|
|
}
|
|
|
|
for (unsigned int i = 0; i< bucketnum; i++)
|
|
{
|
|
std::vector<std::string*>* v = hashTable2[i];
|
|
if (v)
|
|
{
|
|
for(unsigned int j = 0; j < v->size(); j++)
|
|
{
|
|
std::string* stn = (*v)[j];
|
|
delete stn;
|
|
|
|
}
|
|
(v)->clear();
|
|
delete hashTable2[i];
|
|
hashTable2[i] = 0;
|
|
}
|
|
}
|
|
delete hashTable; delete hashTable2;
|
|
return TSim;
|
|
}
|
|
/*
|
|
3.5.9 Placename Function
|
|
TODO
|
|
|
|
*/
|
|
double SemanticTrajectory::MinDistAux(
|
|
SemanticTrajectory& st2, double wx, double wy)
|
|
{
|
|
|
|
DbArray<Cell>* Ax = new DbArray<Cell>(0);
|
|
DbArray<Cell> valuesSt1 = GetCellList();
|
|
DbArray<Cell> valuesSt2 = st2.GetCellList();
|
|
Ax->Append(valuesSt1);
|
|
Ax->Append(valuesSt2);
|
|
DbArray<Cell>* Ay = new DbArray<Cell>(0);
|
|
Ay->Append(valuesSt1);
|
|
Ay->Append(valuesSt2);
|
|
|
|
Ax->Sort(SemanticTrajectory::CompareX);
|
|
Ay->Sort(SemanticTrajectory::CompareY);
|
|
int32_t m = Ax->Size();
|
|
double result = 0.0;
|
|
|
|
result = MinDistUtils(*Ax, *Ay, m, wx, wy);
|
|
delete Ay;
|
|
delete Ax;
|
|
return result;
|
|
}
|
|
/*
|
|
3.5.10 MinDistUtils Function
|
|
|
|
*/
|
|
double SemanticTrajectory::MinDistUtils(
|
|
DbArray<Cell>& Ax,
|
|
DbArray<Cell>& Ay, int32_t m, double wx, double wy)
|
|
{
|
|
|
|
double minD = DBL_MAX;
|
|
|
|
if (m > 3)
|
|
{
|
|
|
|
int n = m/2;
|
|
|
|
DbArray<Cell>* AxL = new DbArray<Cell>(0);
|
|
Ax.copyTo(*AxL, 0, n, 0);
|
|
DbArray<Cell>* AxR = new DbArray<Cell>(0);
|
|
Ax.copyTo(*AxR, n, m-n, 0);
|
|
DbArray<Cell>* AyL = new DbArray<Cell>(0);
|
|
DbArray<Cell>* AyR = new DbArray<Cell>(0);
|
|
|
|
double minDL = 0.0;
|
|
double minDR = 0.0;
|
|
|
|
|
|
for (int i = 0; i < Ay.Size(); i++)
|
|
{
|
|
Cell celly, cellx;
|
|
Ay.Get(i, celly);
|
|
Ax.Get(n, cellx);
|
|
|
|
if(celly.GetX() <= cellx.GetX())
|
|
{
|
|
AyL->Append(celly);
|
|
}
|
|
else
|
|
{
|
|
AyR->Append(celly);
|
|
}
|
|
}
|
|
|
|
/* Check to see if AyL has
|
|
cells from both C1 and C2 */
|
|
if (AyL->Size() != 0){
|
|
Cell cellAyL;
|
|
AyL->Get(0, cellAyL);
|
|
int32_t firstId = cellAyL.GetId();
|
|
bool both = false;
|
|
for (int i = 1; i < AyL->Size(); i++)
|
|
{
|
|
AyL->Get(i, cellAyL);
|
|
if (cellAyL.GetId() != firstId)
|
|
{
|
|
both = true;
|
|
break;
|
|
}
|
|
}
|
|
if (both == true)
|
|
{
|
|
|
|
minDL = MinDistUtils(*AxL, *AyL, n, wx, wy);
|
|
|
|
}
|
|
else
|
|
{
|
|
minDL = DBL_MAX;
|
|
}
|
|
} else {
|
|
minDL = DBL_MAX;
|
|
}
|
|
if (AyR->Size() != 0)
|
|
{
|
|
Cell cellAyR;
|
|
AyR->Get(0, cellAyR);
|
|
int32_t firstId = cellAyR.GetId();
|
|
bool both = false;
|
|
for (int i = 1; i < AyR->Size(); i++)
|
|
{
|
|
AyR->Get(i, cellAyR);
|
|
if (cellAyR.GetId() != firstId)
|
|
{
|
|
both = true;
|
|
break;
|
|
}
|
|
}
|
|
if (both == true)
|
|
{
|
|
|
|
minDR = MinDistUtils(*AxR, *AyR, m-n, wx, wy);
|
|
|
|
}
|
|
else
|
|
{
|
|
minDR = DBL_MAX;
|
|
}
|
|
}
|
|
else {
|
|
minDR = DBL_MAX;
|
|
}
|
|
|
|
minD = minDL > minDR ? minDR : minDL;
|
|
|
|
|
|
DbArray<Cell>* Am = new DbArray<Cell>(0);
|
|
for (int i = 0; i < Ay.Size(); i++)
|
|
{
|
|
Cell x;
|
|
Cell y;
|
|
|
|
Ax.Get(n, x);
|
|
Ay.Get(i, y);
|
|
if (fabs(y.GetX() - x.GetX()) < minD)
|
|
{
|
|
Am->Append(y);
|
|
}
|
|
}
|
|
|
|
|
|
for (int i = 0; i < Am->Size(); i++)
|
|
{
|
|
for (int j = i + 1; j < Am->Size(); j++)
|
|
{
|
|
Cell c1;
|
|
Cell c2;
|
|
Am->Get(i, c1);
|
|
Am->Get(j, c2);
|
|
if (c1.GetId() != c2.GetId())
|
|
{
|
|
|
|
double tempmin = GetCellDist(c1,c2, wx, wy);
|
|
|
|
if (tempmin < minD)
|
|
{
|
|
minD = tempmin;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//Don't forget to delete the DbArrays
|
|
// that were initialized here
|
|
delete Am;
|
|
delete AyR;
|
|
delete AyL;
|
|
delete AxR;
|
|
delete AxL;
|
|
}
|
|
else
|
|
{
|
|
minD = BruteForce(Ax, m, wx, wy);
|
|
|
|
}
|
|
return minD;
|
|
}
|
|
/*
|
|
3.5.11 GetCellDist Function
|
|
TODO
|
|
|
|
*/
|
|
double SemanticTrajectory::GetCellDist(
|
|
Cell& c1, Cell& c2, double wx, double wy)
|
|
{
|
|
|
|
double result;
|
|
//Are they the same cell
|
|
if (c1.GetX() == c2.GetX()
|
|
&& c1.GetY() == c2.GetY())
|
|
{
|
|
return 0.0;
|
|
}
|
|
|
|
//c1 and c2 on the same x Axis
|
|
if (c1.GetX() == c2.GetX())
|
|
{
|
|
// if c1 is above c2
|
|
// Take bottom corner of c1 and top corner of c2
|
|
if(c1.GetY() > c2.GetY())
|
|
{
|
|
int32_t y2 = (int32_t)(c2.GetY() + 1);
|
|
return
|
|
EuclidDist(c1.GetX(), c1.GetY(),
|
|
c2.GetX(), y2, wx, wy);
|
|
}
|
|
// if c1 is below c2
|
|
// Take top corner of c1 and bottom corner of c2
|
|
else
|
|
{
|
|
int32_t y1 = (int32_t)(c1.GetY() + 1);
|
|
return
|
|
EuclidDist(c1.GetX(),
|
|
y1,
|
|
c2.GetX(),
|
|
c2.GetY(), wx, wy);
|
|
}
|
|
}
|
|
//c1 and c2 on the same y axis
|
|
if (c1.GetY() == c2.GetY())
|
|
{
|
|
// if c1 is to the right of c2
|
|
if(c1.GetX() > c2.GetX())
|
|
{
|
|
int32_t x2 = (int32_t)(c2.GetX() + 1);
|
|
return
|
|
EuclidDist(c1.GetX(), c1.GetY(),
|
|
x2, c2.GetY(), wx, wy);
|
|
}
|
|
// if c1 is to the left of c2
|
|
else
|
|
{
|
|
int32_t x1 = (int32_t)(c1.GetX() + 1);
|
|
return
|
|
EuclidDist(x1,
|
|
c1.GetY(),
|
|
c2.GetX(), c2.GetY(), wx, wy);
|
|
}
|
|
}
|
|
// if c1 is above c2
|
|
if (c1.GetY() > c2.GetY())
|
|
{
|
|
// if c1 is to the right of c2
|
|
if (c1.GetX() > c2.GetX())
|
|
{
|
|
int32_t x2 = (int32_t)(c2.GetX() + 1);
|
|
int32_t y2 = (int32_t)(c2.GetY() + 1);
|
|
return
|
|
EuclidDist(c1.GetX(),
|
|
c1.GetY(),
|
|
x2,
|
|
y2, wx, wy);
|
|
}
|
|
// if c1 is to the left c2
|
|
//
|
|
else
|
|
{
|
|
|
|
int32_t x1 = (int32_t)(c1.GetX() + 1);
|
|
int32_t y2 = (int32_t)(c2.GetY() + 1);
|
|
return
|
|
EuclidDist(x1, c1.GetY(),
|
|
c2.GetX(), y2, wx, wy);
|
|
}
|
|
}
|
|
// if c1 is below c2
|
|
else
|
|
{
|
|
// if c1 is to the right of c2
|
|
if (c1.GetX() > c2.GetX())
|
|
{
|
|
int32_t x1 = (c1.GetX() + 1);
|
|
int32_t x2 = (c2.GetX() + 1);
|
|
return
|
|
EuclidDist(
|
|
x1,
|
|
c1.GetY(),
|
|
x2,
|
|
c2.GetY(), wx, wy);
|
|
}
|
|
// if c1 is to the left c2
|
|
else
|
|
{
|
|
int32_t x1 = (c1.GetX() + 1);
|
|
int32_t y1 = (c1.GetY() + 1);
|
|
return
|
|
EuclidDist(
|
|
x1,y1,
|
|
c2.GetX(),
|
|
c2.GetY(), wx, wy);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
/*
|
|
3.5.12 BruteForce Function
|
|
TODO
|
|
|
|
*/
|
|
double SemanticTrajectory::BruteForce(
|
|
DbArray<Cell>& Ax,
|
|
int32_t m, double wx, double wy)
|
|
{
|
|
|
|
double minD = DBL_MAX;
|
|
for (int i = 0; i < Ax.Size(); i++)
|
|
{
|
|
for (int j = i + 1; j < Ax.Size(); j++)
|
|
{
|
|
Cell c1;
|
|
Cell c2;
|
|
Ax.Get(i, c1);
|
|
Ax.Get(j, c2);
|
|
if (c1.GetId() != c2.GetId())
|
|
{
|
|
double tempmin = GetCellDist(c1,c2, wx, wy);
|
|
|
|
if (tempmin < minD)
|
|
{
|
|
minD = tempmin;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return minD;
|
|
}
|
|
/*
|
|
3.5.13 Placename Function
|
|
TODO
|
|
|
|
*/
|
|
double SemanticTrajectory::EuclidDist(int32_t x1,
|
|
int32_t y1,
|
|
int32_t x2,
|
|
int32_t y2, double wx, double wy) const
|
|
{
|
|
double x11 = (double) x1*wx;
|
|
double x21 = (double) x2*wx;
|
|
double y11 = (double) y1*wy;
|
|
double y21 = (double) y2*wy;
|
|
|
|
return sqrt(pow((x11 - x21),2) + pow((y11 - y21),2));
|
|
}
|
|
|
|
/*
|
|
4 Implementation of class Batch
|
|
|
|
4.1 Constructors and Destructor
|
|
|
|
*/
|
|
|
|
Batch::Batch(int dummy):
|
|
Attribute(true),
|
|
batchwords(0),
|
|
batchwords_Flob(0),
|
|
trips(0),
|
|
bcells(0),
|
|
bwords(0),
|
|
bwords_Flob(0),
|
|
bcoordinates(0),
|
|
bsemantics(0),
|
|
bsemantics_Flob(0),
|
|
bbox(false),
|
|
batchId(0)
|
|
{
|
|
|
|
}
|
|
|
|
Batch::
|
|
Batch(const Batch& b) :
|
|
Attribute(b.IsDefined()),
|
|
batchwords(b.batchwords.Size()),
|
|
batchwords_Flob(b.batchwords_Flob.getSize()),
|
|
trips(b.trips.Size()),
|
|
bcells(b.bcells.Size()),
|
|
bwords(b.bwords.Size()),
|
|
bwords_Flob(b.bwords_Flob.getSize()),
|
|
bcoordinates(b.bcoordinates.Size()),
|
|
bsemantics(b.bsemantics.Size()),
|
|
bsemantics_Flob(b.bsemantics_Flob.getSize()),
|
|
bbox(b.bbox),
|
|
batchId(b.batchId)
|
|
{
|
|
|
|
bool success = false;
|
|
success =
|
|
batchwords.Append(b.batchwords);
|
|
assert(success);
|
|
success =
|
|
batchwords_Flob.copyFrom(b.batchwords_Flob);
|
|
assert(success);
|
|
success = trips.Append(b.trips);
|
|
assert(success);
|
|
success = bcells.Append(b.bcells);
|
|
assert(success);
|
|
success = bwords.Append(b.bwords);
|
|
assert(success);
|
|
success =
|
|
bwords_Flob.copyFrom(b.bwords_Flob);
|
|
assert(success);
|
|
success =
|
|
bcoordinates.Append(b.bcoordinates);
|
|
assert(success);
|
|
success = bsemantics.Append(b.bsemantics);
|
|
assert(success);
|
|
success =
|
|
bsemantics_Flob.copyFrom(b.bsemantics_Flob);
|
|
bbox = b.bbox;
|
|
}
|
|
|
|
Batch::~Batch()
|
|
{
|
|
|
|
}
|
|
|
|
Batch& Batch::
|
|
operator=(const Batch& b)
|
|
{
|
|
SetDefined(b.IsDefined());
|
|
|
|
bool success = false;
|
|
success = batchwords.clean();
|
|
assert(success);
|
|
success =
|
|
batchwords.copyFrom(b.batchwords);
|
|
assert(success);
|
|
success = batchwords_Flob.clean();
|
|
assert(success);
|
|
success =
|
|
batchwords_Flob.copyFrom(b.batchwords_Flob);
|
|
assert(success);
|
|
success = trips.clean();
|
|
assert(success);
|
|
success = trips.copyFrom(b.trips);
|
|
assert(success);
|
|
success = bcells.clean();
|
|
assert(success);
|
|
success = bcells.copyFrom(b.bcells);
|
|
assert(success);
|
|
success = bwords.clean();
|
|
assert(success);
|
|
success = bwords.copyFrom(b.bwords);
|
|
assert(success);
|
|
success = bwords_Flob.clean();
|
|
assert(success);
|
|
success =
|
|
bwords_Flob.copyFrom(b.bwords_Flob);
|
|
assert(success);
|
|
success = bcoordinates.clean();
|
|
assert(success);
|
|
success =
|
|
bcoordinates.copyFrom(b.bcoordinates);
|
|
assert(success);
|
|
success = bsemantics.clean();
|
|
assert(success);
|
|
success =
|
|
bsemantics.copyFrom(b.bsemantics);
|
|
assert(success);
|
|
success = bsemantics_Flob.clean();
|
|
assert(success);
|
|
success =
|
|
bsemantics_Flob.copyFrom(b.bsemantics_Flob);
|
|
bbox = b.bbox;
|
|
batchId = b.batchId;
|
|
return *this;
|
|
}
|
|
|
|
/*
|
|
4.2 Implementation of virtual functions
|
|
|
|
*/
|
|
Flob *Batch::GetFLOB(const int i)
|
|
{
|
|
Flob* stFlob = 0;
|
|
if (i == 0) {
|
|
stFlob = &batchwords;
|
|
} else if (i == 1) {
|
|
stFlob = &batchwords_Flob;
|
|
} else if (i == 2) {
|
|
stFlob = &trips;
|
|
} else if (i == 3) {
|
|
stFlob = &bcells;
|
|
} else if (i == 4) {
|
|
stFlob = &bwords;
|
|
} else if (i == 5) {
|
|
stFlob = &bwords_Flob;
|
|
} else if (i == 6) {
|
|
stFlob = &bcoordinates;
|
|
} else if (i ==7) {
|
|
stFlob = &bsemantics;
|
|
} else if (i == 8) {
|
|
stFlob = &bsemantics_Flob;
|
|
}
|
|
return stFlob;
|
|
}
|
|
|
|
void Batch::CopyFrom(
|
|
const Attribute* right)
|
|
{
|
|
|
|
if(right != 0)
|
|
{
|
|
const Batch* b =
|
|
static_cast<
|
|
const Batch*>(right);
|
|
if(b != 0)
|
|
{
|
|
*this = *b;
|
|
}
|
|
}
|
|
}
|
|
|
|
Batch*
|
|
Batch::Clone() const
|
|
{
|
|
|
|
Batch *b =
|
|
new Batch(*this);
|
|
assert(b != 0);
|
|
return b;
|
|
|
|
}
|
|
|
|
/*
|
|
4.3 The mandatory set of algebra support functions
|
|
|
|
4.3.1 Placename holder
|
|
|
|
*/
|
|
|
|
ListExpr
|
|
Batch::Property()
|
|
{
|
|
return
|
|
(nl->TwoElemList(
|
|
nl->FiveElemList(
|
|
nl->StringAtom("Signature"),
|
|
nl->StringAtom("Example Type List"),
|
|
nl->StringAtom("List Rep"),
|
|
nl->StringAtom("Example List"),
|
|
nl->StringAtom("Remarks")),
|
|
nl->FiveElemList(nl->StringAtom(
|
|
"->" + Kind::DATA()
|
|
),
|
|
nl->StringAtom(
|
|
Batch::BasicType()
|
|
),
|
|
nl->TextAtom(
|
|
"((batchId)(minx miny maxx maxy)"
|
|
"((1 word1 ctn)"
|
|
"(2 word2 ctn)...)"
|
|
"((st1) (st2)...))"),
|
|
nl->TextAtom(
|
|
"((1)(3.2 15.4 6.34 15.4)"
|
|
"(1 diversity 2)(2 bear 3)"
|
|
"((st data type)"
|
|
"(st datatype)))"),
|
|
nl->TextAtom(
|
|
"batchid, mbr,"
|
|
" wordlist, "
|
|
"triplist.")
|
|
)));
|
|
}
|
|
|
|
/*
|
|
4.3.2 Placename holder
|
|
|
|
*/
|
|
bool
|
|
Batch::KindCheck(
|
|
ListExpr type,
|
|
ListExpr& errorInfo )
|
|
{
|
|
return (nl->IsEqual(
|
|
type,
|
|
Batch::BasicType() ));
|
|
}
|
|
|
|
/*
|
|
4.3.3 Placename holder
|
|
|
|
*/
|
|
Word Batch::Create(
|
|
const ListExpr typeInfo)
|
|
{
|
|
Batch* b = new Batch(0);
|
|
return (SetWord(b));
|
|
}
|
|
|
|
/*
|
|
4.3.4 Placename holder
|
|
|
|
*/
|
|
void Batch::Destroy()
|
|
{
|
|
batchwords.Destroy();
|
|
batchwords_Flob.destroy();
|
|
trips.Destroy();
|
|
bcells.Destroy();
|
|
bwords.Destroy();
|
|
bwords_Flob.destroy();
|
|
bcoordinates.Destroy(),
|
|
bsemantics.Destroy(),
|
|
bsemantics_Flob.destroy();
|
|
}
|
|
|
|
/*
|
|
4.3.5 Placename holder
|
|
|
|
*/
|
|
void Batch::Delete(
|
|
const ListExpr typeInfo,
|
|
Word& w)
|
|
{
|
|
|
|
Batch* b =
|
|
(Batch*)w.addr;
|
|
b->Destroy();
|
|
delete b;
|
|
}
|
|
|
|
/*
|
|
4.3.6 Placename holder
|
|
|
|
*/
|
|
bool
|
|
Batch::Open(
|
|
SmiRecord& valueRecord,
|
|
size_t& offset,
|
|
const ListExpr typeInfo,
|
|
Word& value )
|
|
{
|
|
|
|
Batch *b =
|
|
(Batch*)Attribute::Open(
|
|
valueRecord, offset, typeInfo );
|
|
value.setAddr( b );
|
|
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
4.3.7 Placename holder
|
|
|
|
*/
|
|
bool
|
|
Batch::Save( SmiRecord& valueRecord,
|
|
size_t& offset,
|
|
const ListExpr typeInfo,
|
|
Word& value )
|
|
{
|
|
|
|
Batch *b =
|
|
(Batch *)value.addr;
|
|
Attribute::Save( valueRecord, offset, typeInfo, b );
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
4.3.8 Placename holder
|
|
|
|
*/
|
|
void Batch::Close(
|
|
const ListExpr typeInfo,
|
|
Word& w)
|
|
{
|
|
|
|
Batch* b = (Batch*)w.addr;
|
|
delete b;
|
|
}
|
|
|
|
/*
|
|
4.3.9 Placename holder
|
|
|
|
*/
|
|
Word Batch::Clone(
|
|
const ListExpr typeInfo,
|
|
const Word& rWord)
|
|
{
|
|
|
|
Word word;
|
|
Batch* p =
|
|
static_cast<Batch*>(rWord.addr);
|
|
if (p != 0)
|
|
{
|
|
word.addr =
|
|
new Batch(*p);
|
|
assert(word.addr != 0);
|
|
}
|
|
return word;
|
|
}
|
|
|
|
|
|
/*
|
|
4.3.10 Placename holder
|
|
|
|
*/
|
|
int Batch::SizeOfObj()
|
|
{
|
|
return sizeof(Batch);
|
|
}
|
|
|
|
/*
|
|
4.3.11 Placename holder
|
|
|
|
*/
|
|
void* Batch::Cast(void* addr)
|
|
{
|
|
return (new (addr) Batch);
|
|
}
|
|
|
|
/*
|
|
4.3.12 Placename holder
|
|
|
|
*/
|
|
ListExpr
|
|
Batch::Out(
|
|
ListExpr typeInfo,
|
|
Word value )
|
|
{
|
|
|
|
// the addr pointer of value
|
|
Batch* b =
|
|
(Batch*)(value.addr);
|
|
if ( !b->IsDefined() ) {
|
|
return nl->SymbolAtom(Symbol::UNDEFINED());
|
|
}
|
|
if( b->IsEmpty() )
|
|
{
|
|
return (nl->TheEmptyList());
|
|
}
|
|
else
|
|
{
|
|
|
|
ListExpr textual = nl->Empty();
|
|
|
|
|
|
/* Need to retrieve equivalent of WordList */
|
|
if (!b->IsEmptyWordList())
|
|
{
|
|
|
|
std::string holdValue;
|
|
bool success = b->GetBSumString(0, holdValue);
|
|
if (success == false) {
|
|
holdValue = "";
|
|
}
|
|
textual =
|
|
nl->OneElemList(
|
|
nl->ThreeElemList(
|
|
nl->IntAtom(b->GetBSumWord(0).indexId),
|
|
nl->IntAtom(b->GetBSumWord(0).count),
|
|
nl->TextAtom(holdValue)
|
|
)
|
|
);
|
|
ListExpr textuallast = textual;
|
|
for( int i = 1; i < b->GetWordListSize(); i++ )
|
|
{
|
|
|
|
bool success = b->GetBSumString(i, holdValue);
|
|
|
|
if (success == false) {
|
|
holdValue = "";
|
|
}
|
|
textuallast = nl->Append(textuallast,
|
|
nl->ThreeElemList(
|
|
nl->IntAtom(b->GetBSumWord(i).indexId),
|
|
nl->IntAtom(b->GetBSumWord(i).count),
|
|
nl->TextAtom(holdValue)
|
|
)
|
|
);
|
|
}
|
|
|
|
}
|
|
/*
|
|
Retrive the tripList
|
|
|
|
*/
|
|
ListExpr result;
|
|
if (!b->IsEmptyTripList())
|
|
{
|
|
|
|
Trip t = b->GetTrip(0);
|
|
|
|
/* Retrieve cell information */
|
|
int getStartIdx = t.GetStartCellsIdx();
|
|
int count = getStartIdx;
|
|
int getEndIdx = t.GetEndCellsIdx();
|
|
ListExpr spatial = nl->Empty();
|
|
if (getStartIdx < getEndIdx)
|
|
{
|
|
spatial =
|
|
nl->OneElemList(
|
|
nl->ThreeElemList(
|
|
nl->IntAtom(b->GetBCell(count).tripId),
|
|
nl->IntAtom(b->GetBCell(count).origx),
|
|
nl->IntAtom(b->GetBCell(count).origy)
|
|
)
|
|
);
|
|
|
|
ListExpr spatiallast = spatial;
|
|
count++;
|
|
for( int i = count; i < getEndIdx; i++ )
|
|
{
|
|
spatiallast = nl->Append(spatiallast,
|
|
nl->ThreeElemList(
|
|
nl->IntAtom(b->GetBCell(i).tripId),
|
|
nl->IntAtom(b->GetBCell(i).origx),
|
|
nl->IntAtom(b->GetBCell(i).origy)
|
|
)
|
|
);
|
|
|
|
}
|
|
} // end of cell information
|
|
/* Retrieve Trip textual summary */
|
|
int getStartIdx1 = t.GetStartSumWordsIdx();
|
|
int getEndIdx1 = t.GetEndSumWordsIdx();
|
|
ListExpr tripsum = nl->Empty();
|
|
|
|
if (getStartIdx1 < getEndIdx1)
|
|
{
|
|
std::string holdValue;
|
|
// Equivalent of GetStingSum
|
|
bool success = b->GetBWord(getStartIdx1, holdValue);
|
|
|
|
if (success == false) {
|
|
holdValue = "";
|
|
}
|
|
|
|
|
|
tripsum =
|
|
nl->OneElemList(
|
|
nl->ThreeElemList(
|
|
nl->IntAtom(b->GetBWordInfo(getStartIdx1).indexId),
|
|
nl->IntAtom(b->GetBWordInfo(getStartIdx1).count),
|
|
nl->TextAtom(holdValue)
|
|
)
|
|
);
|
|
|
|
ListExpr tripsumlast = tripsum;
|
|
for( int i = getStartIdx1 + 1; i < getEndIdx1; i++ )
|
|
{
|
|
std::string holdValue;
|
|
// Equivalent of GetStingSum
|
|
bool success = b->GetBWord(i, holdValue);
|
|
if (success == false) {
|
|
holdValue = "";
|
|
}
|
|
|
|
tripsumlast = nl->Append(tripsumlast,
|
|
nl->ThreeElemList(
|
|
nl->IntAtom(b->GetBWordInfo(i).indexId),
|
|
nl->IntAtom(b->GetBWordInfo(i).count),
|
|
nl->TextAtom(holdValue)
|
|
)
|
|
);
|
|
}
|
|
} // End of Trip textsummary information
|
|
|
|
/* Retrive Trip coordinates and Semantics */
|
|
int getStartIdx2 = t.GetStartCoordsIdx();
|
|
int count2 = getStartIdx2;
|
|
int getEndIdx2 = t.GetEndCoordsIdx();
|
|
ListExpr tripdata = nl->Empty();
|
|
if (getStartIdx2 < getEndIdx2)
|
|
{
|
|
std::string holdValue;
|
|
bool success = b->GetBSemString(count2, holdValue);
|
|
if (success == false) {
|
|
holdValue = "";
|
|
}
|
|
tripdata = nl->OneElemList(
|
|
nl->ThreeElemList(
|
|
nl->RealAtom(b->GetBCoordinate(count2).x),
|
|
nl->RealAtom(b->GetBCoordinate(count2).y),
|
|
nl->TextAtom(holdValue)));
|
|
ListExpr tlast = tripdata;
|
|
|
|
count2++;
|
|
for( int i = count2; i < getEndIdx2; i++ )
|
|
{
|
|
std::string holdValue;
|
|
bool success = b->GetBSemString(i, holdValue);
|
|
|
|
if (success == false) {
|
|
holdValue = "";
|
|
}
|
|
tlast = nl->Append(tlast,
|
|
nl->ThreeElemList(
|
|
nl->RealAtom(b->GetBCoordinate(i).x),
|
|
nl->RealAtom(b->GetBCoordinate(i).y),
|
|
nl->TextAtom(holdValue)));
|
|
|
|
}
|
|
} // End of Trip data
|
|
result = nl->OneElemList(
|
|
nl->TwoElemList(
|
|
nl->OneElemList(
|
|
nl->IntAtom(t.GetId())),
|
|
nl->FourElemList(
|
|
nl->FourElemList(
|
|
nl->RealAtom(t.bbox.getMinX()),
|
|
nl->RealAtom(t.bbox.getMinY()),
|
|
nl->RealAtom(t.bbox.getMaxX()),
|
|
nl->RealAtom(t.bbox.getMaxY())
|
|
),
|
|
spatial,
|
|
tripsum,
|
|
tripdata
|
|
)
|
|
)
|
|
);
|
|
ListExpr last = result;
|
|
for (int i = 1; i < b->GetNumTrips(); i++)
|
|
{
|
|
Trip t = b->GetTrip(i);
|
|
|
|
/* Get Cell Information */
|
|
int getStartIdx = t.GetStartCellsIdx();
|
|
int count3 = getStartIdx;
|
|
int getEndIdx = t.GetEndCellsIdx();
|
|
ListExpr spatial = nl->Empty();
|
|
if (getStartIdx < getEndIdx)
|
|
{
|
|
spatial =
|
|
nl->OneElemList(
|
|
nl->ThreeElemList(
|
|
nl->IntAtom(b->GetBCell(count3).tripId),
|
|
nl->IntAtom(b->GetBCell(count3).origx),
|
|
nl->IntAtom(b->GetBCell(count3).origy)
|
|
)
|
|
);
|
|
ListExpr spatiallast = spatial;
|
|
count3++;
|
|
for( int i = count3; i < getEndIdx; i++ )
|
|
{
|
|
spatiallast = nl->Append(spatiallast,
|
|
nl->ThreeElemList(
|
|
nl->IntAtom(b->GetBCell(i).tripId),
|
|
nl->IntAtom(b->GetBCell(i).origx),
|
|
nl->IntAtom(b->GetBCell(i).origy)
|
|
)
|
|
);
|
|
}
|
|
} // End of getting cell informtion
|
|
|
|
int getStartIdx1 = t.GetStartSumWordsIdx();
|
|
int count1 = getStartIdx1;
|
|
int getEndIdx1 = t.GetEndSumWordsIdx();
|
|
ListExpr tripsum = nl->Empty();
|
|
if (getStartIdx1 < getEndIdx1)
|
|
{
|
|
std::string holdValue;
|
|
bool success = b->GetBWord(count1, holdValue);
|
|
|
|
if (success == false) {
|
|
holdValue = "";
|
|
}
|
|
|
|
tripsum =
|
|
nl->OneElemList(
|
|
nl->ThreeElemList(
|
|
nl->IntAtom(b->GetBWordInfo(count1).indexId),
|
|
nl->IntAtom(b->GetBWordInfo(count1).count),
|
|
nl->TextAtom(holdValue)
|
|
)
|
|
);
|
|
ListExpr tripsumlast = tripsum;
|
|
count1++;
|
|
for( int i = count1; i < getEndIdx1; i++ )
|
|
{
|
|
|
|
std::string holdValue;
|
|
// Equivalent of GetStingSum
|
|
bool success = b->GetBWord(i, holdValue);
|
|
if (success == false) {
|
|
holdValue = "";
|
|
}
|
|
|
|
tripsumlast = nl->Append(tripsumlast,
|
|
nl->ThreeElemList(
|
|
nl->IntAtom(b->GetBWordInfo(i).indexId),
|
|
nl->IntAtom(b->GetBWordInfo(i).count),
|
|
nl->TextAtom(holdValue)
|
|
)
|
|
);
|
|
}
|
|
} // End of Trip information
|
|
/* Retrive Trip coordinates and Semantics */
|
|
int getStartIdx2 = t.GetStartCoordsIdx();
|
|
int count2 = getStartIdx2;
|
|
int getEndIdx2 = t.GetEndCoordsIdx();
|
|
ListExpr tripdata = nl->Empty();
|
|
|
|
if (getStartIdx2 < getEndIdx2)
|
|
{
|
|
std::string holdValue;
|
|
bool success = b->GetBSemString(count2, holdValue);
|
|
|
|
|
|
|
|
if (success == false) {
|
|
holdValue = "";
|
|
}
|
|
tripdata =
|
|
nl->OneElemList(
|
|
nl->ThreeElemList(
|
|
nl->RealAtom(b->GetBCoordinate(count2).x),
|
|
nl->RealAtom(b->GetBCoordinate(count2).y),
|
|
nl->TextAtom(holdValue)));
|
|
|
|
ListExpr tlast = tripdata;
|
|
count2++;
|
|
for( int i = count2; i < getEndIdx2; i++ )
|
|
{
|
|
std::string holdValue;
|
|
bool success = b->GetBSemString(i, holdValue);
|
|
if (success == false) {
|
|
holdValue = "";
|
|
}
|
|
tlast = nl->Append(tlast,
|
|
nl->ThreeElemList(
|
|
nl->RealAtom(b->GetBCoordinate(i).x),
|
|
nl->RealAtom(b->GetBCoordinate(i).y),
|
|
nl->TextAtom(holdValue)));
|
|
|
|
}
|
|
} // End of Trip data
|
|
last = nl->Append(last,
|
|
nl->TwoElemList(
|
|
nl->OneElemList(
|
|
nl->IntAtom(t.GetId())),
|
|
nl->FourElemList(
|
|
nl->FourElemList(
|
|
nl->RealAtom(t.bbox.getMinX()),
|
|
nl->RealAtom(t.bbox.getMinY()),
|
|
nl->RealAtom(t.bbox.getMaxX()),
|
|
nl->RealAtom(t.bbox.getMaxY())
|
|
),
|
|
spatial,
|
|
tripsum,
|
|
tripdata
|
|
)
|
|
)
|
|
);
|
|
}
|
|
}
|
|
|
|
ListExpr final = nl->FourElemList(
|
|
nl->OneElemList(
|
|
nl->IntAtom(b->GetBatchId())),
|
|
nl->FourElemList(
|
|
nl->RealAtom(b->bbox.getMinX()),
|
|
nl->RealAtom(b->bbox.getMinY()),
|
|
nl->RealAtom(b->bbox.getMaxX()),
|
|
nl->RealAtom(b->bbox.getMaxY())
|
|
),
|
|
textual,
|
|
result
|
|
);
|
|
return final;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
4.3.13 Placename holder
|
|
|
|
*/
|
|
/*
|
|
List represenation
|
|
Nested list of 4:
|
|
first nl: Represents the batchId
|
|
second nested list: Represents bounding box which is a 4 coordinates
|
|
to represent a rectangle
|
|
third nested list: Represents the wordlist
|
|
fourth nested list: Represents the triplist
|
|
|
|
*/
|
|
|
|
Word
|
|
Batch::In( const ListExpr typeInfo,
|
|
const ListExpr instance,
|
|
const int errorPos,
|
|
ListExpr& errorInfo,
|
|
bool& correct )
|
|
{
|
|
|
|
Word word;
|
|
correct = false;
|
|
Batch* b = new Batch(0);
|
|
b->SetDefined(true);
|
|
|
|
// This is if list is undefined
|
|
// ~ setDefined to false
|
|
if(listutils::isSymbolUndefined( instance ))
|
|
{
|
|
b->SetDefined(false);
|
|
correct = true;
|
|
word.addr = b;
|
|
return word;
|
|
}
|
|
|
|
if (nl != 0)
|
|
{
|
|
|
|
int nListLength = nl->ListLength(instance);
|
|
// If list has 4 arguments
|
|
// and undefined content
|
|
//~ setDefined to false
|
|
if (nListLength == 4 &&
|
|
nl->IsAtom(nl->Fourth(instance)) &&
|
|
nl->AtomType(nl->Fourth(instance)) == SymbolType &&
|
|
listutils::isSymbolUndefined(nl->Fourth(instance)))
|
|
{
|
|
correct = true;
|
|
b->SetDefined(false);
|
|
correct = true;
|
|
word.addr = b;
|
|
return word;
|
|
}
|
|
|
|
if (nListLength == 4)
|
|
{
|
|
|
|
|
|
/* Collect BatchId */
|
|
if (!listutils::isSymbolUndefined(nl->First(instance)))
|
|
{
|
|
ListExpr first = nl->First(instance);
|
|
if( nl->ListLength(first) == 1 &&
|
|
nl->IsAtom(nl->First(first)) &&
|
|
nl->AtomType(nl->First(first))
|
|
== IntType)
|
|
{
|
|
b->batchId = nl->IntValue(nl->First(first));
|
|
|
|
}
|
|
}
|
|
/* Extract info for bbox */
|
|
if (!listutils::isSymbolUndefined(nl->Second(instance)))
|
|
{
|
|
ListExpr first = nl->Second(instance);
|
|
double mind[2];
|
|
double maxd[2];
|
|
if( nl->ListLength(first) == 4 &&
|
|
nl->IsAtom(nl->First(first)) &&
|
|
nl->AtomType(nl->First(first))
|
|
== RealType &&
|
|
nl->IsAtom(nl->Second(first)) &&
|
|
nl->AtomType(nl->Second(first))
|
|
== RealType &&
|
|
nl->IsAtom(nl->Third(first)) &&
|
|
nl->AtomType(nl->Third(first))
|
|
== RealType &&
|
|
nl->IsAtom(nl->Fourth(first)) &&
|
|
nl->AtomType(nl->Fourth(first))
|
|
== RealType
|
|
)
|
|
{
|
|
mind[0] = nl->RealValue(nl->First(first));
|
|
mind[1] = nl->RealValue(nl->Second(first));
|
|
maxd[0] = nl->RealValue(nl->Third(first));
|
|
maxd[1] = nl->RealValue(nl->Fourth(first));
|
|
b->bbox.Set(true, mind, maxd);
|
|
}
|
|
}
|
|
|
|
/* Extract info for textual summary if any */
|
|
if (!listutils::isSymbolUndefined(nl->Third(instance)))
|
|
{
|
|
ListExpr first = nl->Empty();
|
|
ListExpr rest = nl->Third(instance);
|
|
|
|
while (nl->IsEmpty(rest) == false)
|
|
{
|
|
first = nl->First( rest );
|
|
rest = nl->Rest( rest );
|
|
if( nl->ListLength(first) == 3 &&
|
|
nl->IsAtom(nl->First(first)) &&
|
|
nl->AtomType(nl->First(first))
|
|
== IntType &&
|
|
nl->IsAtom(nl->Second(first)) &&
|
|
nl->AtomType(nl->Second(first))
|
|
== IntType && nl->IsAtom(nl->Third(first))
|
|
)
|
|
{
|
|
|
|
bool typeString =
|
|
nl->AtomType(nl->Third(first)) == StringType;
|
|
|
|
std::string stringValue;
|
|
if (typeString == true)
|
|
{
|
|
stringValue =
|
|
nl->StringValue(nl->Third(first));
|
|
} else {
|
|
stringValue =
|
|
nl->TextValue(nl->Third(first));
|
|
}
|
|
|
|
b->AddBSumString(stringValue,
|
|
nl->IntValue(nl->First(first)),
|
|
nl->IntValue(nl->Second(first)));
|
|
|
|
}
|
|
else
|
|
{
|
|
correct = false;
|
|
delete b;
|
|
return SetWord( Address(0) );
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Extract info for TripList */
|
|
if (!listutils::isSymbolUndefined(nl->Fourth(instance)))
|
|
{
|
|
|
|
|
|
ListExpr first = nl->Empty();
|
|
ListExpr rest = nl->Fourth(instance);
|
|
int cellidxcounter = 0;
|
|
int tripsumidxcounter = 0;
|
|
int tripdataidxcounter = 0;
|
|
/* This is the while loop for each trip */
|
|
|
|
while (nl->IsEmpty(rest) == false)
|
|
{
|
|
|
|
|
|
first = nl->First( rest );
|
|
rest = nl->Rest( rest );
|
|
Trip t(0);
|
|
if(!listutils::isSymbolUndefined(nl->First(first)))
|
|
{
|
|
/* Get first part of two element list */
|
|
|
|
ListExpr ok = nl->First(first);
|
|
|
|
t.SetId(nl->IntValue(nl->First(ok)));
|
|
|
|
}
|
|
/*
|
|
Extract second part of two element list
|
|
Second part consists of 4 parts: BBox, Cell, TextSum, DayTrip
|
|
|
|
*/
|
|
if(!listutils::isSymbolUndefined(nl->Second(first)))
|
|
{
|
|
ListExpr ok = nl->Second(first);
|
|
if( nl->ListLength(ok) == 4)
|
|
{
|
|
|
|
/* Extract Bbox information */
|
|
if (!listutils::isSymbolUndefined(nl->First(ok)))
|
|
{
|
|
ListExpr box = nl->First(ok);
|
|
double mind[2];
|
|
double maxd[2];
|
|
if( nl->ListLength(box) == 4 &&
|
|
nl->IsAtom(nl->First(box)) &&
|
|
nl->AtomType(nl->First(box))
|
|
== RealType &&
|
|
nl->IsAtom(nl->Second(box)) &&
|
|
nl->AtomType(nl->Second(box))
|
|
== RealType &&
|
|
nl->IsAtom(nl->Third(box)) &&
|
|
nl->AtomType(nl->Third(box))
|
|
== RealType &&
|
|
nl->IsAtom(nl->Fourth(box)) &&
|
|
nl->AtomType(nl->Fourth(box))
|
|
== RealType
|
|
)
|
|
{
|
|
mind[0] = nl->RealValue(nl->First(box));
|
|
mind[1] = nl->RealValue(nl->Second(box));
|
|
maxd[0] = nl->RealValue(nl->Third(box));
|
|
maxd[1] = nl->RealValue(nl->Fourth(box));
|
|
|
|
t.SetBoundingBox(true, mind, maxd);
|
|
}
|
|
}
|
|
/* Extract the Cell info */
|
|
if (!listutils::isSymbolUndefined(
|
|
nl->Second(ok)))
|
|
{
|
|
|
|
ListExpr first1 = nl->Empty();
|
|
ListExpr rest1 = nl->Second(ok);
|
|
t.SetStartCellsIdx(cellidxcounter);
|
|
while (nl->IsEmpty(rest1) == false)
|
|
{
|
|
first1 = nl->First( rest1 );
|
|
rest1 = nl->Rest( rest1 );
|
|
if( nl->ListLength(first1) == 3 &&
|
|
nl->IsAtom(nl->First(first1)) &&
|
|
nl->AtomType(nl->First(first1))
|
|
== IntType &&
|
|
nl->IsAtom(nl->Second(first1)) &&
|
|
nl->AtomType(nl->Second(first1))
|
|
== IntType &&
|
|
nl->IsAtom(nl->Third(first1)) &&
|
|
nl->AtomType(nl->Third(first1))
|
|
== IntType
|
|
)
|
|
{
|
|
Cell c(nl->IntValue(nl->First(first1)),
|
|
nl->IntValue(nl->Second(first1)),
|
|
nl->IntValue(nl->Third(first1))
|
|
);
|
|
b->AddBCell(c);
|
|
cellidxcounter++;
|
|
}
|
|
else
|
|
{
|
|
correct = false;
|
|
delete b;
|
|
return SetWord( Address(0) );
|
|
}
|
|
|
|
|
|
} // end of while
|
|
t.SetEndCellsIdx(cellidxcounter);
|
|
} // end of if
|
|
/* Extract the Textual */
|
|
if (!listutils::isSymbolUndefined(
|
|
nl->Third(ok)))
|
|
{
|
|
|
|
ListExpr f1 = nl->Empty();
|
|
ListExpr r1 = nl->Third(ok);
|
|
t.SetStartSumWordsIdx(tripsumidxcounter);
|
|
while (nl->IsEmpty(r1) == false) {
|
|
f1 = nl->First( r1 );
|
|
r1 = nl->Rest( r1 );
|
|
|
|
if( nl->ListLength(f1) == 3 &&
|
|
nl->IsAtom(nl->First(f1)) &&
|
|
nl->AtomType(nl->First(f1))
|
|
== IntType &&
|
|
nl->IsAtom(nl->Second(f1)) &&
|
|
nl->AtomType(nl->Second(f1))
|
|
== IntType && nl->IsAtom(nl->Third(f1))
|
|
)
|
|
{
|
|
bool typeString =
|
|
nl->AtomType(nl->Third(f1)) == StringType;
|
|
|
|
std::string stringValue;
|
|
if (typeString == true)
|
|
{
|
|
stringValue =
|
|
nl->StringValue(nl->Third(f1));
|
|
} else {
|
|
stringValue =
|
|
nl->TextValue(nl->Third(f1));
|
|
}
|
|
|
|
b->AddBWord(stringValue,
|
|
nl->IntValue(nl->First(f1)),
|
|
nl->IntValue(nl->Second(f1)));
|
|
tripsumidxcounter++;
|
|
}
|
|
else
|
|
{
|
|
correct = false;
|
|
delete b;
|
|
return SetWord( Address(0) );
|
|
}
|
|
|
|
}
|
|
t.SetEndSumWordsIdx(tripsumidxcounter);
|
|
}
|
|
// /* Extract the DayTrip */
|
|
if (!listutils::isSymbolUndefined(
|
|
nl->Fourth(ok)))
|
|
{
|
|
ListExpr f2 = nl->Empty();
|
|
ListExpr r2 = nl->Fourth(ok);
|
|
t.SetStartCoordsIdx(tripdataidxcounter);
|
|
while (nl->IsEmpty(r2) == false)
|
|
{
|
|
f2 = nl->First( r2 );
|
|
r2 = nl->Rest( r2 );
|
|
|
|
if( nl->ListLength(f2) == 3 &&
|
|
nl->IsAtom(nl->First(f2)) &&
|
|
nl->AtomType(nl->First(f2))
|
|
== RealType &&
|
|
nl->IsAtom(nl->Second(f2)) &&
|
|
nl->AtomType(nl->Second(f2))
|
|
== RealType &&
|
|
nl->IsAtom(nl->Third(f2)))
|
|
{
|
|
|
|
double x1 = nl->RealValue(nl->First(f2));
|
|
double y1 = nl->RealValue(nl->Second(f2));
|
|
Coordinate c(x1, y1);
|
|
b->AddBCoordinate(c);
|
|
bool typeString =
|
|
nl->AtomType(nl->Third(f2)) == StringType;
|
|
bool typeText =
|
|
nl->AtomType(nl->Third(f2)) == TextType;
|
|
std::string stringValue;
|
|
if (typeString == true)
|
|
{
|
|
stringValue =
|
|
nl->StringValue(nl->Third(f2));
|
|
}
|
|
if (typeText == true)
|
|
{
|
|
stringValue =
|
|
nl->TextValue(nl->Third(f2));
|
|
}
|
|
|
|
b->AddBSemString(stringValue);
|
|
tripdataidxcounter++;
|
|
|
|
}
|
|
else
|
|
{
|
|
correct = false;
|
|
delete b;
|
|
return SetWord( Address(0) );
|
|
}
|
|
}
|
|
t.SetEndCoordsIdx(tripdataidxcounter);
|
|
}
|
|
}
|
|
b->AddTrip(t);
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
} // end of if n ===4
|
|
correct = true;
|
|
return SetWord(b);
|
|
} // end of n != 0
|
|
|
|
return word;
|
|
}
|
|
|
|
|
|
/*
|
|
4.4 Implementation of helper functions for class Batch
|
|
|
|
4.4.1 GetBSumString name
|
|
|
|
*/
|
|
|
|
bool Batch::
|
|
GetBSumString(int index, std::string& rString) const
|
|
{
|
|
|
|
bool success = false;
|
|
int numString = batchwords.Size();
|
|
if (index < numString)
|
|
{
|
|
BatchWord textData;
|
|
success = batchwords.Get(index, &textData);
|
|
if (success == true)
|
|
{
|
|
SmiSize bufferSize = textData.Length + 1;
|
|
char* pBuffer = new char[bufferSize];
|
|
if (pBuffer != 0)
|
|
{
|
|
memset(
|
|
pBuffer,
|
|
0,
|
|
bufferSize * sizeof(char));
|
|
success = batchwords_Flob.read(
|
|
pBuffer,
|
|
textData.Length,
|
|
textData.Offset);
|
|
}
|
|
if(success == true)
|
|
{
|
|
rString = pBuffer;
|
|
}
|
|
delete [] pBuffer;
|
|
}
|
|
}
|
|
return success;
|
|
}
|
|
|
|
/*
|
|
4.4.2 AddBSumString Function
|
|
|
|
*/
|
|
bool Batch::AddBSumString(
|
|
const std::string& stString, int id, int count)
|
|
{
|
|
if (!stString.empty()) {
|
|
BatchWord td;
|
|
td.Offset = batchwords_Flob.getSize();
|
|
td.Length = stString.length();
|
|
td.indexId = id;
|
|
td.count = count;
|
|
|
|
bool success = batchwords.Append(td);
|
|
assert(success);
|
|
success = batchwords_Flob.write(
|
|
stString.c_str(),
|
|
td.Length,
|
|
td.Offset);
|
|
assert(success);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
4.4.3 AddBWord Function
|
|
|
|
*/
|
|
bool Batch::AddBWord(
|
|
const std::string& stString, int id, int count)
|
|
{
|
|
if (!stString.empty()) {
|
|
WordST td;
|
|
td.Offset = bwords_Flob.getSize();
|
|
td.Length = stString.length();
|
|
td.indexId = id;
|
|
td.count = count;
|
|
bool success = bwords.Append(td);
|
|
assert(success);
|
|
bwords_Flob.write(
|
|
stString.c_str(),
|
|
td.Length,
|
|
td.Offset);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
4.4.4 GetBWord Function
|
|
|
|
*/
|
|
bool Batch::
|
|
GetBWord(int index, std::string& rString) const
|
|
{
|
|
|
|
bool success = false;
|
|
int numString = bwords.Size();
|
|
if (index < numString)
|
|
{
|
|
WordST textData;
|
|
success = bwords.Get(index, &textData);
|
|
|
|
if (success == true)
|
|
{
|
|
SmiSize bufferSize = textData.Length + 1;
|
|
char* pBuffer = new char[bufferSize];
|
|
if (pBuffer != 0)
|
|
{
|
|
memset(
|
|
pBuffer,
|
|
0,
|
|
bufferSize * sizeof(char));
|
|
success = bwords_Flob.read(
|
|
pBuffer,
|
|
textData.Length,
|
|
textData.Offset);
|
|
}
|
|
if(success == true)
|
|
{
|
|
rString = pBuffer;
|
|
}
|
|
delete [] pBuffer;
|
|
}
|
|
}
|
|
return success;
|
|
}
|
|
|
|
/*
|
|
4.4.5 AddBSemString Function
|
|
|
|
*/
|
|
bool Batch::AddBSemString(const std::string& str)
|
|
{
|
|
|
|
TextData td;
|
|
td.Offset = bsemantics_Flob.getSize();
|
|
td.Length = str.length();
|
|
bool success = bsemantics.Append(td);
|
|
assert(success);
|
|
if (!str.empty()) {
|
|
bsemantics_Flob.write(
|
|
str.c_str(),
|
|
td.Length,
|
|
td.Offset);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
4.4.6 GetBSemString Function
|
|
|
|
*/
|
|
bool Batch::GetBSemString(int index, std::string& str) const
|
|
{
|
|
|
|
bool success = false;
|
|
int numString = bsemantics.Size();
|
|
|
|
|
|
if (index < numString)
|
|
{
|
|
TextData textData;
|
|
success = bsemantics.Get(index, &textData);
|
|
if (success == true)
|
|
{
|
|
|
|
SmiSize bufferSize = textData.Length + 1;
|
|
char* pBuffer = new char[bufferSize];
|
|
if (pBuffer != 0)
|
|
{
|
|
memset(
|
|
pBuffer,
|
|
0,
|
|
bufferSize * sizeof(char));
|
|
success = bsemantics_Flob.read(
|
|
pBuffer,
|
|
textData.Length,
|
|
textData.Offset);
|
|
}
|
|
if(success == true)
|
|
{
|
|
str = pBuffer;
|
|
}
|
|
delete [] pBuffer;
|
|
}
|
|
}
|
|
return success;
|
|
}
|
|
|
|
/*
|
|
4.4.7 AddBCoordinate name
|
|
|
|
*/
|
|
void Batch::AddBCoordinate(const Coordinate& c)
|
|
{
|
|
bcoordinates.Append(c);
|
|
}
|
|
|
|
/*
|
|
4.5 Operator helper functions for Batch
|
|
|
|
4.5.1 RelevanceSumBT function
|
|
|
|
*/
|
|
double Batch::RelevanceSumBT(Rectangle<2>& mbr,
|
|
SemanticTrajectory& st,
|
|
double alpha,
|
|
double diag)
|
|
{
|
|
|
|
|
|
double relevancesum = 0.0;
|
|
double finalres = 0.0;
|
|
int sumWords = 0;
|
|
std::vector<std::string*>** hashTable;
|
|
const std::vector<std::string*>* bucket;
|
|
std::hash<std::string> str_hash;
|
|
unsigned int bucketPos = 0;
|
|
unsigned int bucketnum = 500;
|
|
|
|
hashTable = new std::vector<std::string*>*[bucketnum];
|
|
for (unsigned int i = 0; i < bucketnum; i++)
|
|
{
|
|
hashTable[i] = 0;
|
|
}
|
|
|
|
|
|
if (!IsEmptyWordList())
|
|
{
|
|
for (int i = 0; i < GetWordListSize(); i++)
|
|
{
|
|
|
|
std::string holdValue;
|
|
bool success = GetBSumString(i, holdValue);
|
|
assert(success);
|
|
std::string* stn = new std::string(holdValue);
|
|
size_t hash = str_hash(holdValue) % bucketnum;
|
|
|
|
if (!hashTable[hash])
|
|
{
|
|
hashTable[hash] = new std::vector<std::string*>();
|
|
}
|
|
hashTable[hash]->push_back(stn);
|
|
|
|
sumWords++;
|
|
}
|
|
}
|
|
|
|
for (int i = 0; i < st.GetNumCoordinates(); i++)
|
|
{
|
|
|
|
double LH = 0;
|
|
double RH = 0;
|
|
std::string holdvalue;
|
|
st.GetSemString(i, holdvalue);
|
|
if (holdvalue.length() > 0 && double (1-alpha) > 0)
|
|
{
|
|
// Do the textual stuff;
|
|
int numMatches = 0;
|
|
stringutils::StringTokenizer tokenizer(holdvalue, " ");
|
|
|
|
while(tokenizer.hasNextToken())
|
|
{
|
|
std::string eval = tokenizer.nextToken();
|
|
if (eval.length() > 0)
|
|
{
|
|
size_t hash = str_hash(eval) % bucketnum;
|
|
bucket = 0;
|
|
bucket = hashTable[hash];
|
|
bucketPos = 0;
|
|
// There is a match
|
|
if (bucket)
|
|
{
|
|
// Find the match
|
|
while(bucketPos < bucket->size())
|
|
{
|
|
std::string* p = (*bucket)[bucketPos];
|
|
|
|
if ((*p).compare(eval) == 0)
|
|
{
|
|
numMatches++;
|
|
break;
|
|
}
|
|
bucketPos++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
double textualscore = 0;
|
|
if (!numMatches == 0)
|
|
{
|
|
double uniquewords = (double)
|
|
(sumWords + holdvalue.length() - numMatches);
|
|
textualscore = (double) numMatches / uniquewords;
|
|
}
|
|
|
|
RH = double (1 - alpha) * textualscore;
|
|
}
|
|
if (alpha > 0)
|
|
{
|
|
double dist =
|
|
getDistanceBT(mbr, st.GetCoordinate(i).x, st.GetCoordinate(i).y);
|
|
double normalizedScore = 0.0;
|
|
if (dist == 0.0)
|
|
{
|
|
normalizedScore = 1;
|
|
}
|
|
else
|
|
{
|
|
normalizedScore = 1 - (double) (dist/diag);
|
|
}
|
|
LH = alpha * normalizedScore;
|
|
}
|
|
double localrel = LH + RH;
|
|
|
|
relevancesum = relevancesum + localrel;
|
|
}
|
|
if (relevancesum > 0)
|
|
{
|
|
finalres = relevancesum / st.GetNumCoordinates();
|
|
}
|
|
|
|
for (unsigned int i = 0; i< bucketnum; i++)
|
|
{
|
|
std::vector<std::string*>* v = hashTable[i];
|
|
if (v)
|
|
{
|
|
for(unsigned int j = 0; j < v->size(); j++)
|
|
{
|
|
delete (*v)[j];
|
|
|
|
}
|
|
delete hashTable[i];
|
|
hashTable[i] = 0;
|
|
}
|
|
}
|
|
delete hashTable;
|
|
return finalres;
|
|
|
|
}
|
|
|
|
/*
|
|
4.5.2 getDistanceBT function
|
|
|
|
*/
|
|
double Batch::getDistanceBT(Rectangle<2>& mbr, double x, double y)
|
|
{
|
|
double xmin = mbr.getMinX();
|
|
double ymin = mbr.getMinY();
|
|
double xmax = mbr.getMaxX();
|
|
double ymax = mbr.getMaxY();
|
|
if (xmin <= x && x <= xmax && ymin <= y && y <= ymax)
|
|
{
|
|
return 0.0;
|
|
}
|
|
// Upper quadrant
|
|
if (ymin > y)
|
|
{
|
|
//left
|
|
if (xmax < x) {
|
|
return EuclidDistRT(x, y, xmax ,ymin);
|
|
}
|
|
//Center
|
|
if (xmin <= x && x <= xmax) {
|
|
return EuclidDistRT(x, y, x ,ymin);
|
|
}
|
|
//Right
|
|
if(xmin > x)
|
|
{
|
|
return EuclidDistRT(x, y, xmin, ymin);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//left
|
|
if (xmax < x) {
|
|
return EuclidDistRT(x, y, xmax ,ymax);
|
|
}
|
|
//Center
|
|
if (xmin <= x && x <= xmax) {
|
|
return EuclidDistRT(x, y, x ,ymax);
|
|
}
|
|
//Right
|
|
if(xmin > x)
|
|
{
|
|
return EuclidDistRT(x, y, xmin, ymax);
|
|
}
|
|
}
|
|
|
|
if (ymin <= y && y <= ymax)
|
|
{
|
|
if (x < xmin)
|
|
{
|
|
return EuclidDistRT(x, y, xmin, y);
|
|
}
|
|
if (x > xmax)
|
|
{
|
|
return EuclidDistRT(x, y, xmax, y);
|
|
}
|
|
}
|
|
|
|
return 0.0;
|
|
}
|
|
|
|
/*
|
|
4.5.3 getDistanceBT function
|
|
|
|
*/
|
|
double Batch::EuclidDistRT(double x1,
|
|
double y1,
|
|
double x2,
|
|
double y2)
|
|
{
|
|
return sqrt(pow((x1 - x2),2) + pow((y1 - y2),2));
|
|
}
|
|
|
|
/*
|
|
5 Operators
|
|
|
|
5.1 Operator makesemtraj.
|
|
|
|
5.1.1 Type map for ~makesemtraj~
|
|
|
|
*/
|
|
|
|
ListExpr TypeMapMakeSemtraj(ListExpr args)
|
|
{
|
|
|
|
// Check to see if it's the right number of arguments
|
|
if (nl->HasLength(args, 4))
|
|
{
|
|
// Make sure each param is of right type
|
|
std::string err = "stream(tuple) x attr_1 x"
|
|
" attr_2 x attr_3 expected";
|
|
|
|
ListExpr stream = nl->First(args);
|
|
ListExpr attrname_longitude = nl->Second(args);
|
|
ListExpr attrname_latitude = nl->Third(args);
|
|
ListExpr attrname_semantics = nl->Fourth(args);
|
|
|
|
if(!listutils::isTupleStream(stream)){
|
|
return
|
|
listutils::typeError(
|
|
"first parameter must be a tuple stream");
|
|
}
|
|
|
|
if(!listutils::isSymbol(attrname_longitude)){
|
|
return
|
|
listutils::typeError("second parameter must"
|
|
"be an attribute name");
|
|
}
|
|
|
|
if(!listutils::isSymbol(attrname_latitude)){
|
|
return
|
|
listutils::typeError("third parameter must"
|
|
" be an attribute name");
|
|
}
|
|
|
|
if(!listutils::isSymbol(attrname_semantics)){
|
|
return
|
|
listutils::typeError("fourth parameter must"
|
|
"be an attribute name");
|
|
}
|
|
|
|
ListExpr type;
|
|
// extract the attribute list
|
|
ListExpr attrList = nl->Second(nl->Second(stream));
|
|
|
|
// Get the index for the longitude
|
|
std::string name =
|
|
nl->SymbolValue(attrname_longitude);
|
|
int index1 =
|
|
listutils::findAttribute(attrList, name, type);
|
|
if(index1==0){
|
|
return
|
|
listutils::typeError(
|
|
"attribute name " + name +
|
|
" unknown in tuple"
|
|
" stream");
|
|
}
|
|
if(!CcReal::checkType(type)){
|
|
return
|
|
listutils::typeError("attribute '" + name +
|
|
"' must be of type 'real'");
|
|
}
|
|
|
|
name = nl->SymbolValue(attrname_latitude);
|
|
|
|
int index2 =
|
|
listutils::findAttribute(attrList, name, type);
|
|
|
|
if(index2==0){
|
|
return
|
|
listutils::typeError("attribute name " + name +
|
|
" unknown in tuple stream");
|
|
}
|
|
if(!CcReal::checkType(type)){
|
|
return
|
|
listutils::typeError("attribute '" + name +
|
|
"' must be of type 'real'");
|
|
}
|
|
|
|
name = nl->SymbolValue(attrname_semantics);
|
|
int index3 =
|
|
listutils::findAttribute(attrList, name, type);
|
|
if(index3==0){
|
|
return
|
|
listutils::typeError("attribute name " + name +
|
|
" unknown in tuple stream");
|
|
}
|
|
if(!CcString::checkType(type) && !FText::checkType(type)){
|
|
return
|
|
listutils::typeError("attribute '" + name +
|
|
"' must be of type 'string'");
|
|
}
|
|
|
|
std::string restype =
|
|
SemanticTrajectory::BasicType();
|
|
|
|
|
|
ListExpr indexes = nl->ThreeElemList(
|
|
nl->IntAtom(index1-1),
|
|
nl->IntAtom(index2-1),
|
|
nl->IntAtom(index3-1));
|
|
|
|
return
|
|
nl->ThreeElemList(nl->SymbolAtom(Symbol::APPEND()),
|
|
indexes,
|
|
nl->SymbolAtom(restype));
|
|
}
|
|
return
|
|
listutils::typeError("Wrong number of arguments");
|
|
|
|
}
|
|
|
|
/*
|
|
5.1.2 Value map for ~makesemtraj~
|
|
|
|
*/
|
|
template <class T>
|
|
int MakeSemTrajMV(Word* args, Word& result,
|
|
int message, Word& local,
|
|
Supplier s)
|
|
{
|
|
|
|
result = qp->ResultStorage(s);
|
|
SemanticTrajectory* res =
|
|
static_cast<SemanticTrajectory*>(result.addr);
|
|
|
|
int noargs = qp->GetNoSons(s);
|
|
|
|
int idx1 = ((CcInt*)args[noargs-3].addr)->GetValue();
|
|
int idx2 = ((CcInt*)args[noargs-2].addr)->GetValue();
|
|
int idx3 = ((CcInt*)args[noargs-1].addr)->GetValue();
|
|
|
|
double c_x1;
|
|
double c_y1;
|
|
double c_x2;
|
|
double c_y2;
|
|
Stream<Tuple> stream(args[0]);
|
|
Tuple* tuple;
|
|
stream.open();
|
|
while((tuple = stream.request()))
|
|
{
|
|
CcReal* x = (CcReal*) tuple->GetAttribute(idx1);
|
|
CcReal* y = (CcReal*) tuple->GetAttribute(idx2);
|
|
T* sem = (T*)
|
|
tuple->GetAttribute(idx3);
|
|
double x1 = x->GetValue();
|
|
double y1 = y->GetValue();
|
|
|
|
Coordinate c(x1, y1);
|
|
res->AddCoordinate(c);
|
|
std::string str = sem->GetValue();
|
|
/*
|
|
This section here is to remove any special characters
|
|
|
|
*/
|
|
std::string resu = "";
|
|
for (size_t i = 0; i < str.size(); ++i)
|
|
{
|
|
if ((str[i] >= 'a' && str[i] <= 'z')
|
|
|| (str[i] >= 'A' && str[i] <= 'Z') || str[i] == ' ') {
|
|
resu = resu + str[i];
|
|
}
|
|
}
|
|
std::list<std::string> tokenlist;
|
|
stringutils::StringTokenizer st1(resu, " ");
|
|
while(st1.hasNextToken())
|
|
{
|
|
std::string eval = st1.nextToken();
|
|
stringutils::trim(eval);
|
|
stringutils::toLower(eval);
|
|
if (eval.length() > 1 )
|
|
{
|
|
tokenlist.push_back(eval);
|
|
}
|
|
}
|
|
std::string finalstr = "";
|
|
tokenlist.sort(SemanticTrajectory::compare_nocase);
|
|
tokenlist.unique();
|
|
|
|
int size = tokenlist.size();
|
|
int i = 0;
|
|
for (std::list<std::string>::iterator it =
|
|
tokenlist.begin();
|
|
it != tokenlist.end();
|
|
++it)
|
|
{
|
|
if (i < size - 1)
|
|
{
|
|
finalstr += *it + " ";
|
|
}
|
|
else
|
|
{
|
|
finalstr += *it;
|
|
}
|
|
i++;
|
|
}
|
|
/*
|
|
Double spaces in String seems to not be removed earlier on.
|
|
Extra trim needed at the end to remove extra space at the start
|
|
of the string.
|
|
|
|
*/
|
|
stringutils::trim(finalstr);
|
|
res->AddSemString(finalstr);
|
|
|
|
if (res->GetNumCoordinates() == 1)
|
|
{
|
|
c_x1 = x1;
|
|
c_y1 = y1;
|
|
c_x2 = x1;
|
|
c_y2 = y1;
|
|
}
|
|
else
|
|
{
|
|
c_x1 = std::min(c_x1, x1);
|
|
c_y1 = std::min(c_y1, y1);
|
|
c_x2 = std::max(c_x2, x1);
|
|
c_y2 = std::max(c_y2, y1);
|
|
|
|
}
|
|
|
|
tuple->DeleteIfAllowed();
|
|
}
|
|
if (c_x1 <= c_x2 && c_y1 <= c_y2)
|
|
{
|
|
double mind[2];
|
|
double maxd[2];
|
|
mind[0] = c_x1;
|
|
mind[1] = c_y1;
|
|
maxd[0] = c_x2;
|
|
maxd[1] = c_y2;
|
|
res->SetBoundingBox(true, mind, maxd);
|
|
}
|
|
stream.close();
|
|
return 0;
|
|
}
|
|
|
|
ValueMapping makesemtrajFuns[] =
|
|
{MakeSemTrajMV<FText>, MakeSemTrajMV<CcString>};
|
|
|
|
int makesemtrajSelect(ListExpr args)
|
|
{
|
|
ListExpr type;
|
|
ListExpr attrList = nl->Second(nl->Second(nl->First(args)));
|
|
std::string name = nl->SymbolValue(nl->Fourth(args));
|
|
listutils::findAttribute(attrList, name, type);
|
|
if(CcString::checkType(type))
|
|
{
|
|
return 1;
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
5.2 Operator ~makesemtraj2~
|
|
|
|
5.2.1 Type map for ~makesemtraj2~
|
|
|
|
*/
|
|
ListExpr TypeMapMakeSemtraj2(ListExpr args)
|
|
{
|
|
// Check to see if it's the right number of arguments
|
|
if (nl->HasLength(args, 6))
|
|
{
|
|
// Make sure each param is of right type
|
|
std::string err = "stream(tuple) x stream(tuple) x a1 x"
|
|
" a2 x a3 x a4 expected";
|
|
|
|
ListExpr stream = nl->First(args);
|
|
ListExpr stream2 = nl->Second(args);
|
|
ListExpr attrname_longitude = nl->Third(args);
|
|
ListExpr attrname_latitude = nl->Fourth(args);
|
|
ListExpr attrname_semantics = nl->Fifth(args);
|
|
ListExpr attrname_elem = nl->Sixth(args);
|
|
|
|
if(!listutils::isTupleStream(stream)){
|
|
return
|
|
listutils::typeError(
|
|
"first parameter must be a tuple stream");
|
|
}
|
|
if(!listutils::isTupleStream(stream2)){
|
|
return
|
|
listutils::typeError(
|
|
"first parameter must be a tuple stream");
|
|
}
|
|
if(!listutils::isSymbol(attrname_longitude)){
|
|
return
|
|
listutils::typeError("second parameter must"
|
|
"be an attribute name");
|
|
}
|
|
|
|
if(!listutils::isSymbol(attrname_latitude)){
|
|
return
|
|
listutils::typeError("third parameter must"
|
|
" be an attribute name");
|
|
}
|
|
|
|
if(!listutils::isSymbol(attrname_semantics)){
|
|
return
|
|
listutils::typeError("fourth parameter must"
|
|
"be an attribute name");
|
|
}
|
|
if(!listutils::isSymbol(attrname_elem)){
|
|
return
|
|
listutils::typeError("fourth parameter must"
|
|
"be an attribute name");
|
|
}
|
|
ListExpr type;
|
|
// extract the attribute list
|
|
ListExpr attrList = nl->Second(nl->Second(stream));
|
|
ListExpr attrList2 = nl->Second(nl->Second(stream2));
|
|
// Get the index for the longitude
|
|
std::string name =
|
|
nl->SymbolValue(attrname_longitude);
|
|
int index1 =
|
|
listutils::findAttribute(attrList, name, type);
|
|
if(index1==0){
|
|
return
|
|
listutils::typeError(
|
|
"attribute name " + name +
|
|
" unknown in tuple"
|
|
" stream");
|
|
}
|
|
if(!CcReal::checkType(type)){
|
|
return
|
|
listutils::typeError("attribute '" + name +
|
|
"' must be of type 'real'");
|
|
}
|
|
|
|
name = nl->SymbolValue(attrname_latitude);
|
|
|
|
int index2 =
|
|
listutils::findAttribute(attrList, name, type);
|
|
|
|
if(index2==0){
|
|
return
|
|
listutils::typeError("attribute name " + name +
|
|
" unknown in tuple stream");
|
|
}
|
|
if(!CcReal::checkType(type)){
|
|
return
|
|
listutils::typeError("attribute '" + name +
|
|
"' must be of type 'real'");
|
|
}
|
|
|
|
name = nl->SymbolValue(attrname_semantics);
|
|
int index3 =
|
|
listutils::findAttribute(attrList, name, type);
|
|
if(index3==0){
|
|
return
|
|
listutils::typeError("attribute name " + name +
|
|
" unknown in tuple stream");
|
|
}
|
|
if(!CcString::checkType(type) && !FText::checkType(type))
|
|
{
|
|
return
|
|
listutils::typeError("attribute '" + name +
|
|
"' must be of type 'string'");
|
|
}
|
|
|
|
name = nl->SymbolValue(attrname_elem);
|
|
int index4 =
|
|
listutils::findAttribute(attrList2, name, type);
|
|
if(index4==0){
|
|
return
|
|
listutils::typeError("attribute elem " + name +
|
|
" unknown in tuple stream");
|
|
}
|
|
if(!CcString::checkType(type)){
|
|
return
|
|
listutils::typeError("attribute '" + name +
|
|
"' must be of type 'string'");
|
|
}
|
|
std::string restype =
|
|
SemanticTrajectory::BasicType();
|
|
|
|
|
|
ListExpr indexes = nl->FourElemList(
|
|
nl->IntAtom(index1-1),
|
|
nl->IntAtom(index2-1),
|
|
nl->IntAtom(index3-1),
|
|
nl->IntAtom(index4-1));
|
|
|
|
return
|
|
nl->ThreeElemList(nl->SymbolAtom(Symbol::APPEND()),
|
|
indexes,
|
|
nl->SymbolAtom(restype));
|
|
}
|
|
return
|
|
listutils::typeError("Wrong number of arguments");
|
|
|
|
}
|
|
|
|
/*
|
|
5.1.3 Value map for ~makesemtraj2~
|
|
|
|
*/
|
|
int MakeSemTrajMV2(Word* args, Word& result,
|
|
int message, Word& local,
|
|
Supplier s)
|
|
{
|
|
|
|
|
|
result = qp->ResultStorage(s);
|
|
SemanticTrajectory* res =
|
|
static_cast<SemanticTrajectory*>(result.addr);
|
|
|
|
int noargs = qp->GetNoSons(s);
|
|
|
|
int idx1 = ((CcInt*)args[noargs-4].addr)->GetValue();
|
|
int idx2 = ((CcInt*)args[noargs-3].addr)->GetValue();
|
|
int idx3 = ((CcInt*)args[noargs-2].addr)->GetValue();
|
|
int idx4 = ((CcInt*)args[noargs-1].addr)->GetValue();
|
|
|
|
//Prepare stop list
|
|
Stream<Tuple> stream2(args[1]);
|
|
unsigned int bucketnum = 800;
|
|
std::hash<std::string> str_hash;
|
|
std::vector<std::string*>** hashTable;
|
|
hashTable = new std::vector<std::string*>*[bucketnum];
|
|
for (unsigned int i = 0; i < bucketnum; i++)
|
|
{
|
|
hashTable[i] = 0;
|
|
}
|
|
Tuple* tuple2;
|
|
stream2.open();
|
|
while((tuple2 = stream2.request()))
|
|
{
|
|
CcString* stopw = (CcString*)
|
|
tuple2->GetAttribute(idx4);
|
|
std::string stw = stopw->GetValue();
|
|
std::string resu = "";
|
|
for (size_t i = 0; i < stw.size(); ++i)
|
|
{
|
|
if ((stw[i] >= 'a' && stw[i] <= 'z') ||
|
|
(stw[i] >= 'A' && stw[i] <= 'Z')) {
|
|
resu = resu + stw[i];
|
|
}
|
|
}
|
|
stringutils::trim(resu);
|
|
stringutils::toLower(resu);
|
|
std::string* stn = new std::string(resu);
|
|
size_t hash = str_hash(resu) % bucketnum;
|
|
|
|
if (!hashTable[hash])
|
|
{
|
|
hashTable[hash] = new std::vector<std::string*>();
|
|
}
|
|
hashTable[hash]->push_back(stn);
|
|
tuple2->DeleteIfAllowed();
|
|
}
|
|
stream2.close();
|
|
|
|
double c_x1;
|
|
double c_y1;
|
|
double c_x2;
|
|
double c_y2;
|
|
Stream<Tuple> stream(args[0]);
|
|
Tuple* tuple;
|
|
stream.open();
|
|
unsigned int bucketpos = 0;
|
|
while((tuple = stream.request()))
|
|
{
|
|
CcReal* x = (CcReal*) tuple->GetAttribute(idx1);
|
|
CcReal* y = (CcReal*) tuple->GetAttribute(idx2);
|
|
CcString* sem = (CcString*)
|
|
tuple->GetAttribute(idx3);
|
|
if ((sem->GetValue()).length() > 0)
|
|
{
|
|
std::string str = sem->GetValue();
|
|
std::string resu = "";
|
|
for (size_t i = 0; i < str.size(); ++i)
|
|
{
|
|
if ((str[i] >= 'a' && str[i] <= 'z') ||
|
|
(str[i] >= 'A' && str[i] <= 'Z') || str[i] == ' ') {
|
|
resu = resu + str[i];
|
|
}
|
|
}
|
|
|
|
std::list<std::string> tokenlist;
|
|
stringutils::StringTokenizer st1(resu, " ");
|
|
const std::vector<std::string*>* bucket;
|
|
size_t hash = 0;
|
|
while(st1.hasNextToken())
|
|
{
|
|
std::string eval = st1.nextToken();
|
|
stringutils::trim(eval);
|
|
stringutils::toLower(eval);
|
|
if (eval.length() > 1)
|
|
{
|
|
bucket = 0;
|
|
hash = str_hash(eval) % bucketnum;
|
|
|
|
bucket = hashTable[hash];
|
|
bucketpos =0;
|
|
if(bucket)
|
|
{
|
|
bool flag = true;
|
|
while(bucketpos < bucket->size())
|
|
{
|
|
std::string* e = (*bucket)[bucketpos];
|
|
if ((e)->compare(eval) == 0)
|
|
{
|
|
flag = false;
|
|
break;
|
|
}
|
|
bucketpos++;
|
|
}
|
|
if (flag)
|
|
{
|
|
tokenlist.push_back(eval);
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
|
|
tokenlist.push_back(eval);
|
|
}
|
|
}
|
|
}
|
|
std::string finalstr = "";
|
|
tokenlist.sort(SemanticTrajectory::compare_nocase);
|
|
tokenlist.unique();
|
|
int size = tokenlist.size();
|
|
int i = 0;
|
|
for(const auto &word : tokenlist)
|
|
{
|
|
if (i != size - 1)
|
|
{
|
|
finalstr += word + " ";
|
|
}
|
|
else
|
|
{
|
|
finalstr += word;
|
|
}
|
|
i++;
|
|
}
|
|
|
|
res->AddSemString(finalstr);
|
|
}
|
|
else
|
|
{
|
|
res->AddSemString("");
|
|
}
|
|
double x1 = x->GetValue();
|
|
double y1 = y->GetValue();
|
|
|
|
Coordinate c(x1, y1);
|
|
res->AddCoordinate(c);
|
|
|
|
|
|
if (res->GetNumCoordinates() == 1)
|
|
{
|
|
c_x1 = x1;
|
|
c_y1 = y1;
|
|
c_x2 = x1;
|
|
c_y2 = y1;
|
|
}
|
|
else
|
|
{
|
|
c_x1 = std::min(c_x1, x1);
|
|
c_y1 = std::min(c_y1, y1);
|
|
c_x2 = std::max(c_x2, x1);
|
|
c_y2 = std::max(c_y2, y1);
|
|
|
|
}
|
|
|
|
tuple->DeleteIfAllowed();
|
|
}
|
|
if (c_x1 < c_x2 && c_y1 < c_y2)
|
|
{
|
|
double mind[2];
|
|
double maxd[2];
|
|
mind[0] = c_x1;
|
|
mind[1] = c_y1;
|
|
maxd[0] = c_x2;
|
|
maxd[1] = c_y2;
|
|
res->SetBoundingBox(true, mind, maxd);
|
|
}
|
|
|
|
for (unsigned int i = 0; i< bucketnum; i++)
|
|
{
|
|
std::vector<std::string*>* v = hashTable[i];
|
|
if (v)
|
|
{
|
|
for(unsigned int j = 0; j < v->size(); j++)
|
|
{
|
|
std::string* stn = (*v)[j];
|
|
delete stn;
|
|
|
|
}
|
|
(v)->clear();
|
|
delete hashTable[i];
|
|
hashTable[i] = 0;
|
|
}
|
|
}
|
|
delete hashTable;
|
|
stream.close();
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
5.3 Operator ~stbox~
|
|
|
|
5.3.1 Type map for ~stbox~
|
|
|
|
*/
|
|
ListExpr STboxTM(ListExpr args)
|
|
{
|
|
std::string errmsg =
|
|
"Expected datatype semanticTrajectory";
|
|
|
|
if(!SemanticTrajectory::checkType(nl->First(args)))
|
|
{
|
|
return listutils::typeError(errmsg);
|
|
}
|
|
|
|
return (nl->SymbolAtom( Rectangle<2>::BasicType()));
|
|
}
|
|
|
|
/*
|
|
5.3.2 Value map for ~stbox~
|
|
|
|
*/
|
|
int STbboxMapValue(Word* args, Word& result,
|
|
int message,
|
|
Word& local,
|
|
Supplier s)
|
|
{
|
|
result = qp->ResultStorage( s );
|
|
Rectangle<2> *box =
|
|
static_cast<Rectangle<2>*>(result.addr);
|
|
const SemanticTrajectory* st =
|
|
static_cast<SemanticTrajectory*>(args[0].addr);
|
|
(*box) = st->GetBoundingBox();
|
|
box->SetDefined(true);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
5.4 Operator ~extractkeywords~
|
|
|
|
5.4.1 Type map for ~extractkeywords~
|
|
|
|
*/
|
|
ListExpr
|
|
extractkeywordsTM( ListExpr args )
|
|
{
|
|
|
|
std::string err =
|
|
"must be of type uniquestringarray or semantic";
|
|
|
|
if ( nl->ListLength(args) == 1
|
|
&& (SemanticTrajectory::checkType(nl->First(args))))
|
|
{
|
|
return nl->TwoElemList( nl->SymbolAtom(Symbol::STREAM()),
|
|
nl->SymbolAtom(CcString::BasicType()));
|
|
}
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
|
}
|
|
|
|
|
|
/*
|
|
5.4.2 Value map for ~extractkeywords~
|
|
|
|
*/
|
|
int extractkeywordMapV(Word* args, Word& result,
|
|
int message,
|
|
Word& local,
|
|
Supplier s)
|
|
{
|
|
|
|
// An auxiliary type which keeps of
|
|
// which coordinate is being
|
|
// examine between requests
|
|
|
|
struct TheWords {
|
|
|
|
int visitedwords = 0;
|
|
std::list<std::string>::iterator it;
|
|
int numOfWords = 0;
|
|
std::list<std::string> wordList;
|
|
TheWords(std::list<std::string>& list)
|
|
{
|
|
wordList = list;
|
|
numOfWords = wordList.size();
|
|
it = wordList.begin();
|
|
}
|
|
|
|
bool getNextWord(std::string& el)
|
|
{
|
|
|
|
el = *it;
|
|
stringutils::trim(el);
|
|
it++;
|
|
visitedwords++;
|
|
return true;
|
|
}
|
|
|
|
};
|
|
TheWords* localword =
|
|
static_cast<TheWords*>(local.addr);
|
|
|
|
std::list<std::string> list;
|
|
switch(message)
|
|
{
|
|
|
|
case OPEN: // Initialize the local storage
|
|
{
|
|
// If localword already exists
|
|
// need to delete and restart
|
|
|
|
if(localword)
|
|
{
|
|
delete localword;
|
|
localword = 0;
|
|
}
|
|
|
|
SemanticTrajectory* strarr =
|
|
static_cast<SemanticTrajectory*>(args[0].addr);
|
|
list = strarr->GetStringArray();
|
|
localword =
|
|
new TheWords(list);
|
|
local.addr = localword;
|
|
return 0;
|
|
}
|
|
case REQUEST: // returnthe next stream element
|
|
{
|
|
if (localword->visitedwords <
|
|
localword->numOfWords)
|
|
{
|
|
|
|
std::string str;
|
|
bool success = localword->getNextWord(str);
|
|
if (success == true)
|
|
{
|
|
CcString* elem = new CcString(true, str);
|
|
result.addr = elem;
|
|
}
|
|
else
|
|
{
|
|
result.addr = 0;
|
|
}
|
|
|
|
return YIELD;
|
|
}
|
|
else
|
|
{
|
|
|
|
result.addr = 0;
|
|
return CANCEL;
|
|
}
|
|
}
|
|
case CLOSE:
|
|
{
|
|
if (localword != 0)
|
|
{
|
|
delete localword;
|
|
local.addr = 0;
|
|
list.clear();
|
|
}
|
|
return 0;
|
|
}
|
|
default:
|
|
{
|
|
// This should never happen
|
|
return -1;
|
|
}
|
|
}
|
|
return 0;
|
|
|
|
}
|
|
|
|
/*
|
|
5.5 Operator ~makesummaries~
|
|
|
|
5.5.1 Type map for ~makesummaries~
|
|
|
|
*/
|
|
ListExpr MakesummariesTM( ListExpr args )
|
|
{
|
|
if( (nl->ListLength(args) == 7)
|
|
&& listutils::isTupleStream(nl->First(args))
|
|
&& CcInt::checkType(nl->Second(args))
|
|
&& SemanticTrajectory::checkType(nl->Third(args))
|
|
&& CellGrid2D::checkType(nl->Fourth(args))
|
|
&& listutils::isSymbol(nl->Fifth(args))
|
|
&& listutils::isSymbol(nl->Sixth(args))
|
|
&& listutils::isSymbol(nl->Seventh(args))
|
|
)
|
|
{
|
|
|
|
ListExpr stream = nl->First(args);
|
|
ListExpr attrname_WiD = nl->Fifth(args);
|
|
ListExpr attrname_Ctn = nl->Sixth(args);
|
|
ListExpr attrname_word = nl->Seventh(args);
|
|
ListExpr attrList = nl->Second(nl->Second(stream));
|
|
ListExpr type;
|
|
std::string name =
|
|
nl->SymbolValue(attrname_WiD);
|
|
int index1 =
|
|
listutils::findAttribute(attrList, name, type);
|
|
|
|
if(index1==0){
|
|
return
|
|
listutils::typeError(
|
|
"attribute name " + name +
|
|
" unknown in tuple"
|
|
" stream");
|
|
}
|
|
if(!CcInt::checkType(type)){
|
|
return
|
|
listutils::typeError("attribute '" + name +
|
|
"' must be of type 'real'");
|
|
}
|
|
|
|
name = nl->SymbolValue(attrname_Ctn);
|
|
|
|
int index2 =
|
|
listutils::findAttribute(attrList, name, type);
|
|
|
|
if(index2==0){
|
|
return
|
|
listutils::typeError("attribute name " + name +
|
|
" unknown in tuple stream");
|
|
}
|
|
|
|
name = nl->SymbolValue(attrname_word);
|
|
int index3 =
|
|
listutils::findAttribute(attrList, name, type);
|
|
|
|
if(index3==0){
|
|
return
|
|
listutils::typeError("attribute name " + name +
|
|
" unknown in tuple stream");
|
|
}
|
|
|
|
ListExpr indexes = nl->ThreeElemList(
|
|
nl->IntAtom(index1-1),
|
|
nl->IntAtom(index2-1),
|
|
nl->IntAtom(index3-1));
|
|
|
|
return
|
|
nl->ThreeElemList(nl->SymbolAtom(Symbol::APPEND()),
|
|
indexes,
|
|
nl->SymbolAtom(SemanticTrajectory::BasicType()));
|
|
}
|
|
return
|
|
listutils::typeError("Expected "
|
|
"(stream(tuple) x int x semantictrajectory x "
|
|
"cellgrid2d x attr_WordId x attr_Ctn x attr_Word).");
|
|
}
|
|
|
|
/*
|
|
5.5.2 Value map for ~makesummaries~
|
|
|
|
*/
|
|
int MakesummariesMV(Word* args, Word& result,
|
|
int message,
|
|
Word& local,
|
|
Supplier s)
|
|
{
|
|
|
|
result = qp->ResultStorage(s);
|
|
int noargs = qp->GetNoSons(s);
|
|
int idx1 = ((CcInt*)args[noargs-3].addr)->GetValue();
|
|
int idx2 = ((CcInt*)args[noargs-2].addr)->GetValue();
|
|
int idx3 = ((CcInt*)args[noargs-1].addr)->GetValue();
|
|
Stream<Tuple> stream(args[0]);
|
|
Tuple* tuple;
|
|
stream.open();
|
|
|
|
|
|
CcInt* id = static_cast<CcInt*>( args[1].addr );
|
|
|
|
SemanticTrajectory* st =
|
|
static_cast<SemanticTrajectory*>(args[2].addr);
|
|
CellGrid2D* grid =
|
|
static_cast<CellGrid2D*>(args[3].addr);
|
|
SemanticTrajectory* res =
|
|
static_cast<SemanticTrajectory*>(result.addr);
|
|
|
|
|
|
res->Clear();
|
|
res->InitializeST();
|
|
|
|
/*
|
|
Create vector to hold already found cell numbers
|
|
|
|
*/
|
|
std::vector<std::pair<int, int>> cellsresult;
|
|
|
|
/*
|
|
Iterate over each coordinate in semantictrajectory
|
|
Find the cell and return origin of cell
|
|
See if that cell origin is already present
|
|
in if not add to spatialsummary
|
|
|
|
*/
|
|
|
|
for(int i = 0; i < st->GetNumCoordinates(); i++)
|
|
{
|
|
Coordinate c = st->GetCoordinate(i);
|
|
if(!grid->onGrid(c.x, c.y))
|
|
{
|
|
|
|
return listutils::typeError("Coordinate outside of grid"
|
|
", please enter a new grid dimension in operator");
|
|
}
|
|
int32_t cellIndexX = grid->getXIndex(c.x);
|
|
int32_t cellIndexY = grid->getYIndex(c.y);
|
|
|
|
if(std::find(
|
|
cellsresult.begin(),
|
|
cellsresult.end(),
|
|
std::make_pair(cellIndexX,cellIndexY))
|
|
== cellsresult.end())
|
|
{
|
|
Cell cell(id->GetValue(),
|
|
cellIndexX,
|
|
cellIndexY);
|
|
|
|
res->AddCell(cell);
|
|
cellsresult.push_back(std::make_pair(
|
|
cellIndexX,
|
|
cellIndexY));
|
|
}
|
|
}
|
|
|
|
|
|
while((tuple = stream.request()))
|
|
{
|
|
CcInt* id = (CcInt*) tuple->GetAttribute(idx1);
|
|
CcInt* ctn = (CcInt*) tuple->GetAttribute(idx2);
|
|
CcString* str = (CcString*) tuple->GetAttribute(idx3);
|
|
res->AddStringSum(str->GetValue(),id->GetIntval(), ctn->GetIntval());
|
|
tuple->DeleteIfAllowed();
|
|
}
|
|
|
|
res->EndST(*st);
|
|
|
|
res->Finalize();
|
|
stream.close();
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
5.6 Operator ~filtersim~
|
|
|
|
5.6.1 Type map for ~filtersim~
|
|
|
|
*/
|
|
ListExpr FilterSimTypeMap(ListExpr args)
|
|
{
|
|
|
|
std::string err = "stream(tuple) x attr1 x "
|
|
"attr2 x real x real x rect";
|
|
if(!nl->HasLength(args, 6))
|
|
{
|
|
return listutils::typeError(err);
|
|
}
|
|
ListExpr stream1 = nl->First(args);
|
|
ListExpr attr1 = nl->Second(args); // semtraj1
|
|
ListExpr attr2 = nl->Third(args); // semtraj2
|
|
ListExpr attr4 = nl->Fourth(args); // real
|
|
ListExpr attr5 = nl->Fifth(args); // Real
|
|
ListExpr attr6 = nl->Sixth(args); // Rect
|
|
if (!Stream<Tuple>::checkType(stream1))
|
|
{
|
|
return listutils::typeError(err + "(first arg is not a tuple sream)");
|
|
}
|
|
|
|
if(!listutils::isSymbol(attr1)){
|
|
return listutils::typeError(err + "(first attrname is not valid)");
|
|
}
|
|
if(!listutils::isSymbol(attr2)){
|
|
return listutils::typeError(err + "(second attrname is not valid)");
|
|
}
|
|
if (!CcReal::checkType(attr4))
|
|
{
|
|
return listutils::typeError(err + "4th arg must be a real");
|
|
}
|
|
if (!CcReal::checkType(attr5))
|
|
{
|
|
return listutils::typeError(err + "5th arg must be a real");
|
|
}
|
|
if (!Rectangle<2>::checkType(attr6))
|
|
{
|
|
return listutils::typeError(err + "6th arg must be a rectangle");
|
|
}
|
|
if(!listutils::isSymbol(attr1)){
|
|
return listutils::typeError(err + "(first attrname is not valid)");
|
|
}
|
|
if(!listutils::isSymbol(attr2)){
|
|
return listutils::typeError(err + "(second attrname is not valid)");
|
|
}
|
|
ListExpr attrList1 = nl->Second(nl->Second(stream1));
|
|
std::string attrname1 = nl->SymbolValue(attr1);
|
|
std::string attrname2 = nl->SymbolValue(attr2);
|
|
ListExpr attrType1;
|
|
|
|
|
|
int index1 = listutils::findAttribute(attrList1,attrname1,attrType1);
|
|
if(index1==0){
|
|
return listutils::typeError(attrname1+
|
|
" is not an attribute of the first stream");
|
|
}
|
|
|
|
int index2 = listutils::findAttribute(attrList1,attrname2,attrType1);
|
|
if(index2==0){
|
|
return listutils::typeError(attrname2+
|
|
" is not an attribute of the second stream");
|
|
}
|
|
|
|
|
|
|
|
|
|
ListExpr indexList = nl->TwoElemList(
|
|
nl->IntAtom(index1-1),
|
|
nl->IntAtom(index2-1));
|
|
|
|
/*
|
|
Last argument to this ThreeElemList
|
|
Return types Stream<Tuple>
|
|
Tuple Type and attribute List
|
|
*/
|
|
return nl->ThreeElemList( nl->SymbolAtom(Symbols::APPEND()),
|
|
indexList,
|
|
nl->TwoElemList(
|
|
nl->SymbolAtom(Stream<Tuple>::BasicType()),
|
|
nl->TwoElemList(
|
|
nl->SymbolAtom(Tuple::BasicType()),
|
|
attrList1)));
|
|
}
|
|
|
|
/*
|
|
5.6.2 Class for ~filtersim~
|
|
|
|
*/
|
|
class SIMData
|
|
{
|
|
public:
|
|
|
|
SIMData(Word& _stream1,
|
|
const ListExpr _resType,
|
|
const int _index1, const int _index2,
|
|
double _alpha, double _threshold, double _diag) :
|
|
stream1(_stream1),
|
|
tt(0),
|
|
index1(_index1), index2(_index2),
|
|
alpha(_alpha), threshold(_threshold),
|
|
diag(_diag)
|
|
{
|
|
tt = new TupleType(_resType);
|
|
stream1.open();
|
|
}
|
|
~SIMData()
|
|
{
|
|
stream1.close();
|
|
tt->DeleteIfAllowed();
|
|
}
|
|
Tuple* nextTuple()
|
|
{
|
|
|
|
Tuple* res = new Tuple(tt);
|
|
while((res = stream1.request()))
|
|
{
|
|
SemanticTrajectory* st1 =
|
|
(SemanticTrajectory*) res->GetAttribute(index1);
|
|
SemanticTrajectory* st2 =
|
|
(SemanticTrajectory*) res->GetAttribute(index2);
|
|
double result = st1->Similarity(*st2, diag, alpha);
|
|
|
|
if (result > threshold)
|
|
{
|
|
return res;
|
|
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
private:
|
|
Stream<Tuple> stream1;
|
|
TupleType* tt;
|
|
int index1;
|
|
int index2;
|
|
double alpha;
|
|
double threshold;
|
|
double diag;
|
|
|
|
|
|
};
|
|
|
|
/*
|
|
5.6.3 Value map for ~filtersim~
|
|
|
|
*/
|
|
int FilterSimMapValue( Word* args, Word& result,
|
|
int message, Word& local, Supplier s )
|
|
{
|
|
|
|
|
|
SIMData* li = (SIMData*) local.addr;
|
|
switch(message) {
|
|
case OPEN: { if(li){
|
|
delete li;
|
|
}
|
|
ListExpr ttype = nl->Second(GetTupleResultType(s));
|
|
int noargs = qp->GetNoSons(s);
|
|
int idx1 = ((CcInt*)args[noargs-2].addr)->GetValue();
|
|
int idx2 = ((CcInt*)args[noargs-1].addr)->GetValue();
|
|
CcReal * alpha = static_cast<CcReal*>(args[3].addr);
|
|
CcReal * thresh = static_cast<CcReal*>(args[4].addr);
|
|
Rectangle<2>* rec = static_cast<Rectangle<2>*>(args[5].addr);
|
|
double diagonal = GetDiag(*rec);
|
|
|
|
local.addr = new SIMData(
|
|
args[0],
|
|
ttype,
|
|
idx1,
|
|
idx2,
|
|
alpha->GetValue(),
|
|
thresh->GetValue(),
|
|
diagonal);
|
|
return 0;
|
|
}
|
|
case REQUEST: { if(!li){
|
|
return CANCEL;
|
|
}
|
|
result.addr = li->nextTuple();;
|
|
return result.addr ? YIELD:CANCEL;
|
|
}
|
|
case CLOSE : {
|
|
if(li){
|
|
delete li;
|
|
local.addr=0;
|
|
}
|
|
return 0;
|
|
}
|
|
}
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
5.7 Operator ~filterttsim~
|
|
|
|
5.7.1 Type map for ~filterttsim~
|
|
|
|
*/
|
|
ListExpr FilterTTSimTypeMap(ListExpr args)
|
|
{
|
|
|
|
|
|
std::string err = "stream(tuple) x attr1 x "
|
|
"attr2 x real x real x rect x Grid";
|
|
if(!nl->HasLength(args, 7))
|
|
{
|
|
return listutils::typeError(err);
|
|
}
|
|
ListExpr stream1 = nl->First(args);
|
|
ListExpr attr1 = nl->Second(args); // semtraj1
|
|
ListExpr attr2 = nl->Third(args); // semtraj2
|
|
ListExpr attr4 = nl->Fourth(args); // real
|
|
ListExpr attr5 = nl->Fifth(args); // Real
|
|
ListExpr attr6 = nl->Sixth(args); // Rect
|
|
ListExpr attr7 = nl->Seventh(args); // Grid
|
|
if (!Stream<Tuple>::checkType(stream1))
|
|
{
|
|
return listutils::typeError(err + "(first arg is not a tuple sream)");
|
|
}
|
|
|
|
if(!listutils::isSymbol(attr1)){
|
|
return listutils::typeError(err + "(first attrname is not valid)");
|
|
}
|
|
if(!listutils::isSymbol(attr2)){
|
|
return listutils::typeError(err + "(second attrname is not valid)");
|
|
}
|
|
if (!CcReal::checkType(attr4))
|
|
{
|
|
return listutils::typeError(err + "4th arg must be a real");
|
|
}
|
|
if (!CcReal::checkType(attr5))
|
|
{
|
|
return listutils::typeError(err + "5th arg must be a real");
|
|
}
|
|
if (!Rectangle<2>::checkType(attr6))
|
|
{
|
|
return listutils::typeError(err + "6th arg must be a rectangle");
|
|
}
|
|
if(!CellGrid2D::checkType(attr7))
|
|
{
|
|
return listutils::typeError(err + "(7th arg must be CellGrid2D");
|
|
}
|
|
if(!listutils::isSymbol(attr1)){
|
|
return listutils::typeError(err + "(first attrname is not valid)");
|
|
}
|
|
if(!listutils::isSymbol(attr2)){
|
|
return listutils::typeError(err + "(second attrname is not valid)");
|
|
}
|
|
ListExpr attrList1 = nl->Second(nl->Second(stream1));
|
|
std::string attrname1 = nl->SymbolValue(attr1);
|
|
std::string attrname2 = nl->SymbolValue(attr2);
|
|
ListExpr attrType1;
|
|
|
|
|
|
int index1 = listutils::findAttribute(attrList1,attrname1,attrType1);
|
|
if(index1==0){
|
|
return listutils::typeError(attrname1+
|
|
" is not an attribute of the first stream");
|
|
}
|
|
|
|
int index2 = listutils::findAttribute(attrList1,attrname2,attrType1);
|
|
if(index2==0){
|
|
return listutils::typeError(attrname2+
|
|
" is not an attribute of the second stream");
|
|
}
|
|
|
|
|
|
|
|
|
|
ListExpr indexList = nl->TwoElemList(
|
|
nl->IntAtom(index1-1),
|
|
nl->IntAtom(index2-1));
|
|
|
|
/*
|
|
Last argument to this ThreeElemList
|
|
Return types Stream<Tuple>
|
|
Tuple Type and attribute List
|
|
*/
|
|
return nl->ThreeElemList( nl->SymbolAtom(Symbols::APPEND()),
|
|
indexList,
|
|
nl->TwoElemList(
|
|
nl->SymbolAtom(Stream<Tuple>::BasicType()),
|
|
nl->TwoElemList(
|
|
nl->SymbolAtom(Tuple::BasicType()),
|
|
attrList1)));
|
|
}
|
|
|
|
/*
|
|
5.7.2 Class for ~filterttsim~
|
|
|
|
*/
|
|
class TTInfo
|
|
{
|
|
public:
|
|
|
|
TTInfo(unsigned int bucknum, Word& _stream1,
|
|
const ListExpr _resType,
|
|
const int _index1, const int _index2,
|
|
double _alpha, double _threshold, double _diag, double _wx, double _wy) :
|
|
hashTable(0), hashTable2(0), bucket(0),
|
|
bucketnum(bucknum),
|
|
stream1(_stream1),
|
|
tt(0),
|
|
index1(_index1), index2(_index2),
|
|
alpha(_alpha), threshold(_threshold),
|
|
diag(_diag), wx(_wx), wy(_wy)
|
|
{
|
|
tt = new TupleType(_resType);
|
|
stream1.open();
|
|
if (double (1-alpha) > 0)
|
|
{
|
|
InitializeTables();
|
|
}
|
|
}
|
|
~TTInfo()
|
|
{
|
|
stream1.close();
|
|
|
|
tt->DeleteIfAllowed();
|
|
}
|
|
size_t getBucket(std::string& str)
|
|
{
|
|
return str_hash(str) % bucketnum;
|
|
}
|
|
void InitializeTables()
|
|
{
|
|
if(!hashTable)
|
|
{
|
|
|
|
hashTable = new std::vector<std::string*>*[bucketnum];
|
|
for (unsigned int i = 0; i < bucketnum; i++)
|
|
{
|
|
hashTable[i] = 0;
|
|
}
|
|
}
|
|
|
|
if(!hashTable2)
|
|
{
|
|
hashTable2 = new std::vector<std::string*>*[bucketnum];
|
|
for (unsigned int i = 0; i < bucketnum; i++)
|
|
{
|
|
hashTable2[i] = 0;
|
|
}
|
|
}
|
|
}
|
|
void getTablesReady(SemanticTrajectory& st1, SemanticTrajectory& st2)
|
|
{
|
|
|
|
for (int i = 0; i < st1.GetNumWords(); i++)
|
|
{
|
|
std::string holdValue = "";
|
|
bool success = st1.GetStringSum(i, holdValue);
|
|
if(success)
|
|
{
|
|
|
|
size_t hash = getBucket(holdValue);
|
|
|
|
if (!hashTable[hash])
|
|
{
|
|
hashTable[hash] = new std::vector<std::string*>();
|
|
}
|
|
std::string* stn = new std::string(holdValue);
|
|
hashTable[hash]->push_back(stn);
|
|
}
|
|
|
|
}
|
|
|
|
for (int i = 0; i < st2.GetNumWords(); i++)
|
|
{
|
|
std::string holdValue = "";
|
|
bool success = st2.GetStringSum(i, holdValue);
|
|
if(success)
|
|
{
|
|
|
|
size_t hash = getBucket(holdValue);
|
|
|
|
if (!hashTable2[hash])
|
|
{
|
|
hashTable2[hash] = new std::vector<std::string*>();
|
|
}
|
|
std::string* stn = new std::string(holdValue);
|
|
hashTable2[hash]->push_back(stn);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
}
|
|
Tuple* nextTuple()
|
|
{
|
|
|
|
Tuple* res = new Tuple(tt);
|
|
while((res = stream1.request()))
|
|
{
|
|
|
|
SemanticTrajectory* st1 =
|
|
(SemanticTrajectory*) res->GetAttribute(index1);
|
|
SemanticTrajectory* st2 =
|
|
(SemanticTrajectory*) res->GetAttribute(index2);
|
|
|
|
|
|
double result1 = 0.0;
|
|
double result2 = 0.0;
|
|
double result = 0.0;
|
|
double ts = 0.0;
|
|
double textalpha = double (1 - alpha);
|
|
if (textalpha > 0)
|
|
{
|
|
getTablesReady(*st1, *st2);
|
|
ts = textualScore(*st1, *st2);
|
|
result2 = double (1 - alpha ) * ts;
|
|
}
|
|
|
|
|
|
double dist = 0.0;
|
|
if (alpha > 0)
|
|
{
|
|
dist =
|
|
MinDistAux(*st1, *st2, wx, wy);
|
|
}
|
|
|
|
|
|
double normalizedScore = 0.0;
|
|
if (dist != 0.0)
|
|
{
|
|
normalizedScore = 1 - (double)(dist/diag);
|
|
}
|
|
else {
|
|
normalizedScore = 1;
|
|
}
|
|
result1 = alpha * normalizedScore;
|
|
result = result1 + result2;
|
|
clearContent();
|
|
|
|
if (result > threshold)
|
|
{
|
|
return res;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void clearContent()
|
|
{
|
|
|
|
for (unsigned int i = 0; i< bucketnum; i++)
|
|
{
|
|
std::vector<std::string*>* v = hashTable[i];
|
|
if (v)
|
|
{
|
|
for(unsigned int j = 0; j < v->size(); j++)
|
|
{
|
|
std::string* stn = (*v)[j];
|
|
delete stn;
|
|
|
|
}
|
|
(v)->clear();
|
|
delete hashTable[i];
|
|
hashTable[i] = 0;
|
|
}
|
|
}
|
|
|
|
for (unsigned int i = 0; i< bucketnum; i++)
|
|
{
|
|
std::vector<std::string*>* v = hashTable2[i];
|
|
if (v)
|
|
{
|
|
for(unsigned int j = 0; j < v->size(); j++)
|
|
{
|
|
std::string* stn = (*v)[j];
|
|
delete stn;
|
|
|
|
}
|
|
(v)->clear();
|
|
delete hashTable2[i];
|
|
hashTable2[i] = 0;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
double MinDistAux(SemanticTrajectory& st1,
|
|
SemanticTrajectory& st2, double wx, double wy)
|
|
{
|
|
|
|
DbArray<Cell>* Ax = new DbArray<Cell>(0);
|
|
DbArray<Cell> valuesSt1 = st1.GetCellList();
|
|
DbArray<Cell> valuesSt2 = st2.GetCellList();
|
|
Ax->Append(valuesSt1);
|
|
Ax->Append(valuesSt2);
|
|
DbArray<Cell>* Ay = new DbArray<Cell>(0);
|
|
Ay->Append(valuesSt1);
|
|
Ay->Append(valuesSt2);
|
|
|
|
Ax->Sort(SemanticTrajectory::CompareX);
|
|
Ay->Sort(SemanticTrajectory::CompareY);
|
|
int32_t m = Ax->Size();
|
|
double result = 0.0;
|
|
for (int i = 0; i < Ax->Size(); i++)
|
|
{
|
|
Cell c;
|
|
Ax->Get(i, &c);
|
|
|
|
}
|
|
for (int i = 0; i < Ay->Size(); i++)
|
|
{
|
|
Cell c;
|
|
Ay->Get(i, &c);
|
|
|
|
}
|
|
result = MinDistUtils(*Ax, *Ay, m, wx, wy);
|
|
return result;
|
|
}
|
|
|
|
double MinDistUtils(
|
|
DbArray<Cell>& Ax,
|
|
DbArray<Cell>& Ay, int32_t m, double wx, double wy)
|
|
{
|
|
|
|
double minD = DBL_MAX;
|
|
|
|
if (m > 3)
|
|
{
|
|
|
|
int n = m/2;
|
|
|
|
DbArray<Cell>* AxL = new DbArray<Cell>(0);
|
|
Cell cell1;
|
|
Ax.Get(0,cell1);
|
|
Ax.copyTo(*AxL, 0, n, 0);
|
|
DbArray<Cell>* AxR = new DbArray<Cell>(0);
|
|
Ax.copyTo(*AxR, n, m-n, 0);
|
|
DbArray<Cell>* AyL = new DbArray<Cell>(0);
|
|
DbArray<Cell>* AyR = new DbArray<Cell>(0);
|
|
|
|
double minDL = 0.0;
|
|
double minDR = 0.0;
|
|
|
|
|
|
for (int i = 0; i < Ay.Size(); i++)
|
|
{
|
|
Cell celly, cellx;
|
|
Ay.Get(i, celly);
|
|
Ax.Get(n, cellx);
|
|
if(celly.GetX() <= cellx.GetX())
|
|
{
|
|
AyL->Append(celly);
|
|
}
|
|
else
|
|
{
|
|
AyR->Append(celly);
|
|
}
|
|
}
|
|
|
|
/* Check to see if AxL has
|
|
cells from both C1 and C2 */
|
|
if (AyL->Size() != 0){
|
|
Cell cellAyL;
|
|
AyL->Get(0, cellAyL);
|
|
int32_t firstId = cellAyL.GetId();
|
|
bool both = false;
|
|
for (int i = 1; i < AyL->Size(); i++)
|
|
{
|
|
AyL->Get(i, cellAyL);
|
|
if (cellAyL.GetId() != firstId)
|
|
{
|
|
both = true;
|
|
break;
|
|
}
|
|
}
|
|
if (both == true)
|
|
{
|
|
|
|
minDL = MinDistUtils(*AxL, *AyL, n, wx, wy);
|
|
|
|
}
|
|
else
|
|
{
|
|
minDL = DBL_MAX;
|
|
}
|
|
} else {
|
|
minDL = DBL_MAX;
|
|
}
|
|
if (AyR->Size() != 0)
|
|
{
|
|
Cell cellAyR;
|
|
AyR->Get(0, cellAyR);
|
|
int32_t firstId = cellAyR.GetId();
|
|
bool both = false;
|
|
for (int i = 1; i < AyR->Size(); i++)
|
|
{
|
|
AyR->Get(i, cellAyR);
|
|
if (cellAyR.GetId() != firstId)
|
|
{
|
|
both = true;
|
|
break;
|
|
}
|
|
}
|
|
if (both == true)
|
|
{
|
|
|
|
minDR = MinDistUtils(*AxR, *AyR, m-n, wx, wy);
|
|
|
|
}
|
|
else
|
|
{
|
|
minDR = DBL_MAX;
|
|
}
|
|
}
|
|
else {
|
|
minDR = DBL_MAX;
|
|
}
|
|
|
|
minD = minDL > minDR ? minDR : minDL;
|
|
|
|
|
|
DbArray<Cell>* Am = new DbArray<Cell>(0);
|
|
for (int i = 0; i < Ay.Size(); i++)
|
|
{
|
|
Cell x;
|
|
Cell y;
|
|
|
|
Ax.Get(n, x);
|
|
Ay.Get(i, y);
|
|
if (fabs(y.GetX() - x.GetX()) < minD)
|
|
{
|
|
Am->Append(y);
|
|
}
|
|
}
|
|
|
|
|
|
for (int i = 0; i < Am->Size(); i++)
|
|
{
|
|
for (int j = i + 1; j < Am->Size(); j++)
|
|
{
|
|
Cell c1;
|
|
Cell c2;
|
|
Am->Get(i, c1);
|
|
Am->Get(j, c2);
|
|
if (c1.GetId() != c2.GetId())
|
|
{
|
|
|
|
double tempmin = GetCellDist(c1,c2, wx, wy);
|
|
|
|
if (tempmin < minD)
|
|
{
|
|
minD = tempmin;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//Don't forget to delete the DbArrays
|
|
// that were initialized here
|
|
delete Am;
|
|
delete AyR;
|
|
delete AyL;
|
|
delete AxR;
|
|
delete AxL;
|
|
}
|
|
else
|
|
{
|
|
minD = BruteForce(Ax, m, wx, wy);
|
|
|
|
}
|
|
return minD;
|
|
}
|
|
|
|
double GetCellDist(
|
|
Cell& c1, Cell& c2, double wx, double wy)
|
|
{
|
|
double result;
|
|
//Are they the same cell
|
|
if (c1.GetX() == c2.GetX()
|
|
&& c1.GetY() == c2.GetY())
|
|
{
|
|
return 0.0;
|
|
}
|
|
|
|
//c1 and c2 on the same x Axis
|
|
if (c1.GetX() == c2.GetX())
|
|
{
|
|
// if c1 is above c2
|
|
// Take bottom corner of c1 and top corner of c2
|
|
if(c1.GetY() > c2.GetY())
|
|
{
|
|
int32_t y2 = (int32_t)(c2.GetY() + 1);
|
|
return
|
|
EuclidDist(c1.GetX(), c1.GetY(),
|
|
c2.GetX(), y2, wx, wy);
|
|
}
|
|
// if c1 is below c2
|
|
// Take top corner of c1 and bottom corner of c2
|
|
else
|
|
{
|
|
int32_t y1 = (int32_t)(c1.GetY() + 1);
|
|
return
|
|
EuclidDist(c1.GetX(),
|
|
y1,
|
|
c2.GetX(),
|
|
c2.GetY(), wx, wy);
|
|
}
|
|
}
|
|
//c1 and c2 on the same y axis
|
|
if (c1.GetY() == c2.GetY())
|
|
{
|
|
// if c1 is to the right of c2
|
|
if(c1.GetX() > c2.GetX())
|
|
{
|
|
int32_t x2 = (int32_t)(c2.GetX() + 1);
|
|
return
|
|
EuclidDist(c1.GetX(), c1.GetY(),
|
|
x2, c2.GetY(), wx, wy);
|
|
}
|
|
// if c1 is to the left of c2
|
|
else
|
|
{
|
|
int32_t x1 = (int32_t)(c1.GetX() + 1);
|
|
return
|
|
EuclidDist(x1,
|
|
c1.GetY(),
|
|
c2.GetX(), c2.GetY(), wx, wy);
|
|
}
|
|
}
|
|
// if c1 is above c2
|
|
if (c1.GetY() > c2.GetY())
|
|
{
|
|
// if c1 is to the right of c2
|
|
if (c1.GetX() > c2.GetX())
|
|
{
|
|
int32_t x2 = (int32_t)(c2.GetX() + 1);
|
|
int32_t y2 = (int32_t)(c2.GetY() + 1);
|
|
return
|
|
EuclidDist(c1.GetX(),
|
|
c1.GetY(),
|
|
x2,
|
|
y2, wx, wy);
|
|
}
|
|
// if c1 is to the left c2
|
|
//
|
|
else
|
|
{
|
|
|
|
int32_t x1 = (int32_t)(c1.GetX() + 1);
|
|
int32_t y2 = (int32_t)(c2.GetY() + 1);
|
|
return
|
|
EuclidDist(x1, c1.GetY(),
|
|
c2.GetX(), y2, wx, wy);
|
|
}
|
|
}
|
|
// if c1 is below c2
|
|
else
|
|
{
|
|
// if c1 is to the right of c2
|
|
if (c1.GetX() > c2.GetX())
|
|
{
|
|
int32_t x1 = (c1.GetX() + 1);
|
|
int32_t x2 = (c2.GetX() + 1);
|
|
return
|
|
EuclidDist(
|
|
x1,
|
|
c1.GetY(),
|
|
x2,
|
|
c2.GetY(), wx, wy);
|
|
}
|
|
// if c1 is to the left c2
|
|
else
|
|
{
|
|
int32_t x1 = (c1.GetX() + 1);
|
|
int32_t y1 = (c1.GetY() + 1);
|
|
return
|
|
EuclidDist(
|
|
x1,y1,
|
|
c2.GetX(),
|
|
c2.GetY(), wx, wy);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
double BruteForce(
|
|
DbArray<Cell>& Ax,
|
|
int32_t m, double wx, double wy)
|
|
{
|
|
|
|
double minD = DBL_MAX;
|
|
for (int i = 0; i < Ax.Size(); i++)
|
|
{
|
|
for (int j = i + 1; j < Ax.Size(); j++)
|
|
{
|
|
Cell c1;
|
|
Cell c2;
|
|
Ax.Get(i, c1);
|
|
Ax.Get(j, c2);
|
|
if (c1.GetId() != c2.GetId())
|
|
{
|
|
double tempmin = GetCellDist(c1,c2, wx, wy);
|
|
|
|
if (tempmin < minD)
|
|
{
|
|
minD = tempmin;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return minD;
|
|
}
|
|
double EuclidDist(int32_t x1,
|
|
int32_t y1,
|
|
int32_t x2,
|
|
int32_t y2, double wx, double wy) const
|
|
{
|
|
double x11 = (double) x1*wx;
|
|
double x21 = (double) x2*wx;
|
|
double y11 = (double) y1*wy;
|
|
double y21 = (double) y2*wy;
|
|
return sqrt(pow((x11 - x21),2) + pow((y11 - y21),2));
|
|
}
|
|
|
|
double textualScore(SemanticTrajectory& st1, SemanticTrajectory& st2)
|
|
{
|
|
|
|
double TSim = 0.0;
|
|
unsigned int bucketpos = 0;
|
|
for(int i = 0; i < st1.GetNumCoordinates(); i++)
|
|
{
|
|
std::string holdvalue;
|
|
st1.GetSemString(i, holdvalue);
|
|
|
|
if (holdvalue.length() > 0)
|
|
{
|
|
stringutils::StringTokenizer parse_st1(holdvalue, " ");
|
|
while(parse_st1.hasNextToken())
|
|
{
|
|
std::string eval = parse_st1.nextToken();
|
|
stringutils::trim(eval);
|
|
size_t hash = getBucket(eval);
|
|
bucket = 0;
|
|
bucket = hashTable2[hash];
|
|
bucketpos = 0;
|
|
if(bucket)
|
|
{
|
|
while(bucketpos < bucket->size())
|
|
{
|
|
std::string* check = (*bucket)[bucketpos];
|
|
if ((check)->compare(eval) == 0)
|
|
{
|
|
TSim = TSim + ((double) 1/st1.GetNumCoordinates());
|
|
break;
|
|
}
|
|
bucketpos++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for(int i = 0; i < st2.GetNumTextData(); i++)
|
|
{
|
|
|
|
std::string holdvalue;
|
|
st2.GetSemString(i, holdvalue);
|
|
if (holdvalue.length() > 0)
|
|
{
|
|
stringutils::StringTokenizer parse_st2(holdvalue, " ");
|
|
|
|
while(parse_st2.hasNextToken())
|
|
{
|
|
|
|
std::string eval = parse_st2.nextToken();
|
|
stringutils::trim(eval);
|
|
size_t hash = getBucket(eval);
|
|
bucket = 0;
|
|
bucket = hashTable[hash];
|
|
bucketpos = 0;
|
|
if(bucket)
|
|
{
|
|
while(bucketpos < bucket->size())
|
|
{
|
|
|
|
std::string* check = (*bucket)[bucketpos];
|
|
if ((check)->compare(eval) == 0)
|
|
{
|
|
|
|
TSim = TSim + ((double) 1/st2.GetNumCoordinates());
|
|
break;
|
|
}
|
|
bucketpos++;
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return TSim;
|
|
}
|
|
private:
|
|
|
|
std::vector<std::string*>** hashTable;
|
|
std::vector<std::string*>** hashTable2;
|
|
const std::vector<std::string*>* bucket;
|
|
unsigned int bucketnum;
|
|
Stream<Tuple> stream1;
|
|
TupleType* tt;
|
|
int index1;
|
|
int index2;
|
|
double alpha;
|
|
double threshold;
|
|
double diag;
|
|
std::hash<std::string> str_hash;
|
|
double wx;
|
|
double wy;
|
|
|
|
|
|
};
|
|
|
|
/*
|
|
5.7.3 Value map for ~filterttsim~
|
|
|
|
*/
|
|
int FilterTTSimMapValue( Word* args, Word& result,
|
|
int message, Word& local, Supplier s )
|
|
{
|
|
|
|
TTInfo* li = (TTInfo*) local.addr;
|
|
switch(message){
|
|
case OPEN: { if(li){
|
|
delete li;
|
|
}
|
|
ListExpr ttype = nl->Second(GetTupleResultType(s));
|
|
int noargs = qp->GetNoSons(s);
|
|
int idx1 = ((CcInt*)args[noargs-2].addr)->GetValue();
|
|
int idx2 = ((CcInt*)args[noargs-1].addr)->GetValue();
|
|
CellGrid2D* grid = static_cast<CellGrid2D*>(args[6].addr);
|
|
CcReal * alpha = static_cast<CcReal*>(args[3].addr);
|
|
CcReal * thresh = static_cast<CcReal*>(args[4].addr);
|
|
Rectangle<2>* rec = static_cast<Rectangle<2>*>(args[5].addr);
|
|
double diagonal = GetDiag(*rec);
|
|
double wx = grid->getXw();
|
|
double wy = grid->getYw();
|
|
|
|
local.addr = new TTInfo(
|
|
100,
|
|
args[0],
|
|
ttype,
|
|
idx1,
|
|
idx2,
|
|
alpha->GetValue(),
|
|
thresh->GetValue(),
|
|
diagonal,
|
|
wx,
|
|
wy);
|
|
return 0;
|
|
}
|
|
case REQUEST: { if(!li){
|
|
return CANCEL;
|
|
}
|
|
result.addr = li->nextTuple();;
|
|
return result.addr ? YIELD:CANCEL;
|
|
}
|
|
case CLOSE : {
|
|
if(li){
|
|
delete li;
|
|
local.addr=0;
|
|
}
|
|
return 0;
|
|
}
|
|
}
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
5.8 Operator ~filterbbsim~
|
|
|
|
5.8.1 Type map for ~filterbbsim~
|
|
|
|
*/
|
|
ListExpr FilterBBSimTypeMap(ListExpr args)
|
|
{
|
|
std::string err = "stream(tuple) x attr1 x "
|
|
"attr2 x attr3 x attr4 x CcReal";
|
|
if(!nl->HasLength(args, 8))
|
|
{
|
|
return listutils::typeError(err);
|
|
}
|
|
ListExpr stream1 = nl->First(args);
|
|
ListExpr attr1 = nl->Second(args); // batch 1 id
|
|
ListExpr attr2 = nl->Third(args); // batch 2 id
|
|
ListExpr attr3 = nl->Fourth(args); // batch mbr 1
|
|
ListExpr attr4 = nl->Fifth(args); // batch mbr2
|
|
if (!Stream<Tuple>::checkType(stream1))
|
|
{
|
|
return listutils::typeError(err + "(first arg is not a tuple sream)");
|
|
}
|
|
if (!CcReal::checkType(nl->Sixth(args)))
|
|
{
|
|
return listutils::typeError(err + "6th arg must be a real");
|
|
}
|
|
if (!CcReal::checkType(nl->Seventh(args)))
|
|
{
|
|
return listutils::typeError(err + "7th arg must be a real");
|
|
}
|
|
if (!Rectangle<2>::checkType(nl->Eigth(args)))
|
|
{
|
|
return listutils::typeError(err + "8th arg must be a rectangle");
|
|
}
|
|
if(!listutils::isSymbol(attr1)){
|
|
return listutils::typeError(err + "(first attrname is not valid)");
|
|
}
|
|
if(!listutils::isSymbol(attr2)){
|
|
return listutils::typeError(err + "(second attrname is not valid)");
|
|
}
|
|
if(!listutils::isSymbol(attr3)){
|
|
return listutils::typeError(err + "(first attrname is not valid)");
|
|
}
|
|
if(!listutils::isSymbol(attr4)){
|
|
return listutils::typeError(err + "(second attrname is not valid)");
|
|
}
|
|
ListExpr attrList1 = nl->Second(nl->Second(stream1));
|
|
std::string attrname1 = nl->SymbolValue(attr1);
|
|
std::string attrname2 = nl->SymbolValue(attr2);
|
|
std::string attrname3 = nl->SymbolValue(attr3);
|
|
std::string attrname4 = nl->SymbolValue(attr4);
|
|
ListExpr attrType1;
|
|
|
|
|
|
int index1 = listutils::findAttribute(attrList1,attrname1,attrType1);
|
|
if(index1==0){
|
|
return listutils::typeError(attrname1+
|
|
" is not an attribute of the first stream");
|
|
}
|
|
|
|
int index2 = listutils::findAttribute(attrList1,attrname2,attrType1);
|
|
if(index2==0){
|
|
return listutils::typeError(attrname2+
|
|
" is not an attribute of the second stream");
|
|
}
|
|
|
|
int index3 = listutils::findAttribute(attrList1,attrname3,attrType1);
|
|
if(index3==0){
|
|
return listutils::typeError(attrname3+
|
|
" is not an attribute of the first stream");
|
|
}
|
|
|
|
int index4 = listutils::findAttribute(attrList1,attrname4,attrType1);
|
|
if(index4==0){
|
|
return listutils::typeError(attrname4+
|
|
" is not an attribute of the second stream");
|
|
}
|
|
|
|
|
|
ListExpr indexList = nl->FourElemList(
|
|
nl->IntAtom(index1-1),
|
|
nl->IntAtom(index2-1),
|
|
nl->IntAtom(index3-1),
|
|
nl->IntAtom(index4-1));
|
|
|
|
/*
|
|
Last argument to this ThreeElemList
|
|
Return types Stream<Tuple>
|
|
Tuple Type and attribute List
|
|
*/
|
|
return nl->ThreeElemList( nl->SymbolAtom(Symbols::APPEND()),
|
|
indexList,
|
|
nl->TwoElemList(
|
|
nl->SymbolAtom(Stream<Tuple>::BasicType()),
|
|
nl->TwoElemList(
|
|
nl->SymbolAtom(Tuple::BasicType()),
|
|
attrList1)));
|
|
}
|
|
|
|
class BatchBatchInfo
|
|
{
|
|
public:
|
|
|
|
BatchBatchInfo(Word& _stream1,
|
|
const ListExpr _resType,
|
|
const int _index1, const int _index2,
|
|
const int _index3, const int _index4,
|
|
double _alpha, double _threshold, double _diag) :
|
|
stream1(_stream1),
|
|
tt(0),
|
|
index1(_index1), index2(_index2),
|
|
index3(_index3), index4(_index4),
|
|
alpha(_alpha), threshold(_threshold),
|
|
diag(_diag)
|
|
{
|
|
tt = new TupleType(_resType);
|
|
stream1.open();
|
|
}
|
|
~BatchBatchInfo()
|
|
{
|
|
stream1.close();
|
|
tt->DeleteIfAllowed();
|
|
}
|
|
Tuple* nextTuple()
|
|
{
|
|
|
|
Tuple* res = new Tuple(tt);
|
|
while((res = stream1.request()))
|
|
{
|
|
CcInt* id1 = (CcInt*) res->GetAttribute(index1);
|
|
CcInt* id2 = (CcInt*) res->GetAttribute(index2);
|
|
if(id1->GetIntval() < id2->GetIntval()
|
|
|| id1->GetIntval() == id2->GetIntval())
|
|
{
|
|
|
|
Rectangle<2>* r1 = (Rectangle<2>*) res->GetAttribute(index3);
|
|
Rectangle<2>* r2 = (Rectangle<2>*) res->GetAttribute(index4);
|
|
|
|
const Geoid* geoid = 0;
|
|
double distance = 0.0;
|
|
if (alpha > 0)
|
|
{
|
|
distance = r1->Distance(*r2, geoid);
|
|
}
|
|
double normalizedScore = 0.0;
|
|
if (distance == 0.0) {
|
|
normalizedScore = 1;
|
|
}
|
|
else
|
|
{
|
|
normalizedScore = 1 - (double)(distance/diag);
|
|
}
|
|
|
|
double result = alpha * normalizedScore * 2 + double (1-alpha) * 2;
|
|
|
|
if (result > threshold)
|
|
{
|
|
if (r1->Area() < r2->Area())
|
|
{
|
|
|
|
Tuple* t = reverseBatches(res);
|
|
res->DeleteIfAllowed();
|
|
return t;
|
|
} else {
|
|
return res;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
private:
|
|
Stream<Tuple> stream1;
|
|
TupleType* tt;
|
|
int index1;
|
|
int index2;
|
|
int index3;
|
|
int index4;
|
|
double alpha;
|
|
double threshold;
|
|
double diag;
|
|
|
|
|
|
|
|
Tuple* reverseBatches(Tuple* t1)
|
|
{
|
|
Tuple* res = new Tuple(tt);
|
|
int no1 = t1->GetNoAttributes();
|
|
|
|
int half = no1 / 2;
|
|
for (int i = 0; i < no1; i++)
|
|
{
|
|
if (i < half)
|
|
{
|
|
res->CopyAttribute(half+i, t1, i);
|
|
}
|
|
else
|
|
{
|
|
res->CopyAttribute(i-half, t1, i);
|
|
}
|
|
|
|
}
|
|
return res;
|
|
}
|
|
};
|
|
|
|
int FilterBBSimMapValue( Word* args, Word& result,
|
|
int message, Word& local, Supplier s )
|
|
{
|
|
|
|
BatchBatchInfo* li = (BatchBatchInfo*) local.addr;
|
|
switch(message){
|
|
case OPEN: { if(li){
|
|
delete li;
|
|
}
|
|
ListExpr ttype = nl->Second(GetTupleResultType(s));
|
|
int noargs = qp->GetNoSons(s);
|
|
int idx1 = ((CcInt*)args[noargs-4].addr)->GetValue();
|
|
int idx2 = ((CcInt*)args[noargs-3].addr)->GetValue();
|
|
int idx3 = ((CcInt*)args[noargs-2].addr)->GetValue();
|
|
int idx4 = ((CcInt*)args[noargs-1].addr)->GetValue();
|
|
CcReal * alpha = static_cast<CcReal*>(args[5].addr);
|
|
CcReal * thresh = static_cast<CcReal*>(args[6].addr);
|
|
Rectangle<2>* rec = static_cast<Rectangle<2>*>(args[7].addr);
|
|
double diagonal = GetDiag(*rec);
|
|
|
|
local.addr = new BatchBatchInfo(args[0], ttype,
|
|
idx1,
|
|
idx2,
|
|
idx3,
|
|
idx4,
|
|
alpha->GetValue(),
|
|
thresh->GetValue(),
|
|
diagonal);
|
|
return 0;
|
|
}
|
|
case REQUEST: { if(!li){
|
|
return CANCEL;
|
|
}
|
|
|
|
result.addr = li->nextTuple();;
|
|
return result.addr ? YIELD:CANCEL;
|
|
}
|
|
case CLOSE : {
|
|
if(li){
|
|
delete li;
|
|
local.addr=0;
|
|
}
|
|
return 0;
|
|
}
|
|
}
|
|
return 0;
|
|
|
|
}
|
|
|
|
/*
|
|
5.9 Operator ~batches~
|
|
|
|
5.9.1 Type map for ~batches~
|
|
|
|
*/
|
|
ListExpr BatchesTM(ListExpr args)
|
|
{
|
|
std::string err = "stream(tuple) x attr1 x "
|
|
"attr2";
|
|
if(!nl->HasLength(args, 4))
|
|
{
|
|
return listutils::typeError(err);
|
|
}
|
|
ListExpr stream1 = nl->First(args);
|
|
ListExpr attr1 = nl->Second(args);
|
|
ListExpr attr2 = nl->Third(args);
|
|
if (!Stream<Tuple>::checkType(stream1))
|
|
{
|
|
return listutils::typeError(err + "(first arg is not a tuple sream)");
|
|
}
|
|
if (!CcReal::checkType(nl->Fourth(args)))
|
|
{
|
|
return listutils::typeError(err + "4th arg must be a real");
|
|
}
|
|
if(!listutils::isSymbol(attr1)){
|
|
return listutils::typeError(err + "(first attrname is not valid)");
|
|
}
|
|
if(!listutils::isSymbol(attr2)){
|
|
return listutils::typeError(err + "(second attrname is not valid)");
|
|
}
|
|
ListExpr attrList1 = nl->Second(nl->Second(stream1));
|
|
std::string attrname1 = nl->SymbolValue(attr1);
|
|
std::string attrname2 = nl->SymbolValue(attr2);
|
|
ListExpr attrType1;
|
|
|
|
|
|
int index1 = listutils::findAttribute(attrList1,attrname1,attrType1);
|
|
if(index1==0){
|
|
return listutils::typeError(attrname1+
|
|
" is not an attribute of the first stream");
|
|
}
|
|
|
|
int index2 = listutils::findAttribute(attrList1,attrname2,attrType1);
|
|
if(index2==0){
|
|
return listutils::typeError(attrname2+
|
|
" is not an attribute of the second stream");
|
|
}
|
|
|
|
|
|
|
|
ListExpr indexList = nl->TwoElemList(
|
|
nl->IntAtom(index1-1),
|
|
nl->IntAtom(index2-1));
|
|
|
|
/*
|
|
Last argument to this ThreeElemList
|
|
Return types Stream<Tuple>
|
|
Tuple Type and attribute List
|
|
*/
|
|
return nl->ThreeElemList( nl->SymbolAtom(Symbols::APPEND()),
|
|
indexList,
|
|
nl->TwoElemList(
|
|
nl->SymbolAtom(Stream<Tuple>::BasicType()),
|
|
nl->TwoElemList(
|
|
nl->SymbolAtom(Tuple::BasicType()),
|
|
attrList1)));
|
|
}
|
|
|
|
class HoldBatchesInfo
|
|
{
|
|
public:
|
|
|
|
HoldBatchesInfo(Word& _stream1,
|
|
const ListExpr _resType,
|
|
const int _index1, const int _index2, double _threshold) :
|
|
stream1(_stream1),
|
|
tt(0), batchidcounter(0), currentBatches(0),
|
|
index1(_index1), index2(_index2), diathreshold(_threshold)
|
|
{
|
|
tt = new TupleType(_resType);
|
|
batchidcounter = 0;
|
|
stream1.open();
|
|
}
|
|
~HoldBatchesInfo()
|
|
{
|
|
stream1.close();
|
|
tt->DeleteIfAllowed();
|
|
}
|
|
Tuple* nextTuple()
|
|
{
|
|
|
|
std::vector<BatchGroup>::iterator it;
|
|
Tuple* res = new Tuple(tt);
|
|
int assignBatchId = -1;
|
|
if ((res = stream1.request()))
|
|
{
|
|
|
|
int bmin = -1;
|
|
double diagmin = DBL_MAX;
|
|
int i = 0;
|
|
SemanticTrajectory* st =
|
|
(SemanticTrajectory*) res->GetAttribute(index1);
|
|
for (it=currentBatches.begin(); it!=currentBatches.end(); ++it)
|
|
{
|
|
|
|
BatchGroup tempBatch(st->GetBoundingBox());
|
|
tempBatch.addnewMBR((*it).GetMBR());
|
|
Rectangle<2> mbr = tempBatch.GetMBR();
|
|
double x1 = mbr.getMinX();
|
|
double y1 = mbr.getMinY();
|
|
double x2 = mbr.getMaxX();
|
|
double y2 = mbr.getMaxY();
|
|
|
|
double dgbox = sqrt(pow((x1 - x2),2)
|
|
+ pow((y1 - y2),2));
|
|
|
|
if(dgbox < diagmin)
|
|
{
|
|
diagmin = dgbox;
|
|
|
|
bmin = i; // hold the index of
|
|
}
|
|
i++;
|
|
}
|
|
if (diagmin <= diathreshold)
|
|
{
|
|
|
|
it = currentBatches.begin();
|
|
std::advance(it, bmin);
|
|
(*it).addnewMBR(st->GetBoundingBox());
|
|
assignBatchId = bmin;
|
|
}
|
|
else
|
|
{
|
|
|
|
currentBatches.push_back(BatchGroup(st->GetBoundingBox()));
|
|
assignBatchId = batchidcounter;
|
|
batchidcounter++;
|
|
}
|
|
res->PutAttribute(index2, new CcInt(true, assignBatchId));
|
|
return res;
|
|
} else
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
|
|
return res;
|
|
}
|
|
private:
|
|
Stream<Tuple> stream1;
|
|
TupleType* tt;
|
|
int batchidcounter;
|
|
std::vector<BatchGroup> currentBatches;
|
|
int index1;
|
|
int index2;
|
|
double diathreshold;
|
|
};
|
|
|
|
int BatchesVM( Word* args, Word& result,
|
|
int message, Word& local, Supplier s )
|
|
{
|
|
|
|
HoldBatchesInfo* li = (HoldBatchesInfo*) local.addr;
|
|
switch(message){
|
|
case OPEN: { if(li){
|
|
delete li;
|
|
}
|
|
ListExpr ttype = nl->Second(GetTupleResultType(s));
|
|
int noargs = qp->GetNoSons(s);
|
|
int idx1 = ((CcInt*)args[noargs-2].addr)->GetValue();
|
|
int idx2 = ((CcInt*)args[noargs-1].addr)->GetValue();
|
|
CcReal * thresh = static_cast<CcReal*>(args[3].addr);
|
|
|
|
local.addr = new HoldBatchesInfo(args[0], ttype,
|
|
idx1,
|
|
idx2,
|
|
thresh->GetValue());
|
|
return 0;
|
|
}
|
|
case REQUEST: { if(!li){
|
|
return CANCEL;
|
|
}
|
|
|
|
result.addr = li->nextTuple();;
|
|
return result.addr ? YIELD:CANCEL;
|
|
}
|
|
case CLOSE : {
|
|
if(li){
|
|
delete li;
|
|
local.addr=0;
|
|
}
|
|
return 0;
|
|
}
|
|
}
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
5.10 Operator ~btsim~
|
|
|
|
5.10.1 Type map for ~btsim~
|
|
|
|
*/
|
|
ListExpr BTSimTypeMap(ListExpr args)
|
|
{
|
|
|
|
std::string err = "stream(tuple) x x "
|
|
"";
|
|
if(!nl->HasLength(args, 4))
|
|
{
|
|
return listutils::typeError(err);
|
|
}
|
|
if(!Batch::checkType(nl->First(args)))
|
|
{
|
|
return listutils::typeError("expecting one batch type");
|
|
}
|
|
if(!SemanticTrajectory::checkType(nl->Second(args)))
|
|
{
|
|
return listutils::typeError("expecting semanticTrajectory type");
|
|
}
|
|
if (!CcReal::checkType(nl->Third(args)) ||
|
|
!Rectangle<2>::checkType(nl->Fourth(args)))
|
|
{
|
|
return
|
|
listutils::typeError("3rd and 4th arg of real and rectangle");
|
|
}
|
|
|
|
return NList(CcReal::BasicType()).listExpr();
|
|
|
|
}
|
|
|
|
int BTSimMapValue( Word* args, Word& result,
|
|
int message, Word& local, Supplier s )
|
|
{
|
|
|
|
Batch* b = static_cast<Batch*>( args[0].addr );
|
|
SemanticTrajectory* st = static_cast<SemanticTrajectory*>( args[1].addr );
|
|
CcReal * alpha = static_cast<CcReal*>(args[2].addr);
|
|
Rectangle<2>* rec = static_cast<Rectangle<2>*>(args[3].addr);
|
|
|
|
double alpha1 = alpha->GetValue();
|
|
|
|
double diag = GetDiag(*rec);
|
|
const Geoid* geoid = 0;
|
|
Rectangle<2> bmbr = b->GetBoundingBox();
|
|
double distance = bmbr.Distance(st->GetBoundingBox(), geoid);
|
|
double normalizedScore = 1 - (double)(distance/diag);
|
|
double RH = alpha1 * normalizedScore + double (1-alpha1);
|
|
// double LH = 0.0;
|
|
double LH = b->RelevanceSumBT(bmbr, *st, alpha1, diag);
|
|
result = qp->ResultStorage(s);
|
|
double answer = LH + RH;
|
|
((CcReal*) result.addr)->Set(answer);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
5.11 Operator ~filterbtsim~
|
|
|
|
5.11.1 Type map for ~filterbtsim~
|
|
|
|
*/
|
|
ListExpr FilterBTSimTypeMap(ListExpr args)
|
|
{
|
|
|
|
std::string err = "stream(tuple) x x "
|
|
"";
|
|
if(!nl->HasLength(args, 9))
|
|
{
|
|
return listutils::typeError(err);
|
|
}
|
|
ListExpr stream1 = nl->First(args);
|
|
ListExpr stream2 = nl->Second(args);
|
|
ListExpr batchMBR = nl->Sixth(args);
|
|
ListExpr st1 = nl->Third(args);
|
|
ListExpr word = nl->Fourth(args);
|
|
ListExpr Ctn = nl->Fifth(args);
|
|
|
|
if (!Stream<Tuple>::checkType(stream1))
|
|
{
|
|
return listutils::typeError(err + "(first arg is not a tuple stream)");
|
|
}
|
|
if (!Stream<Tuple>::checkType(stream2))
|
|
{
|
|
return listutils::typeError(err + "(second arg is not a tuple stream)");
|
|
}
|
|
if(!listutils::isSymbol(st1)){
|
|
return listutils::typeError(err + "(first attrname is not valid)");
|
|
}
|
|
if(!listutils::isSymbol(word)){
|
|
return listutils::typeError(err + "(second attrname is not valid)");
|
|
}
|
|
if(!listutils::isSymbol(Ctn)){
|
|
return listutils::typeError(err + "(third attrname is not valid)");
|
|
}
|
|
if (!Rectangle<2>::checkType(batchMBR))
|
|
{
|
|
return listutils::typeError(err + "6th arg must be a rectangle");
|
|
}
|
|
// THE PARAMS FOR NORMALIZATION ~ ALPHA ~ _threshold
|
|
if (!CcReal::checkType(nl->Seventh(args)))
|
|
{
|
|
return listutils::typeError(err + "6th arg must be a real");
|
|
}
|
|
if (!CcReal::checkType(nl->Eigth(args)))
|
|
{
|
|
return listutils::typeError(err + "7th arg must be a real");
|
|
}
|
|
if (!Rectangle<2>::checkType(nl->Ninth(args)))
|
|
{
|
|
return listutils::typeError(err + "8th arg must be a rectangle");
|
|
}
|
|
std::string attrname1 = nl->SymbolValue(st1);
|
|
std::string attrname2 = nl->SymbolValue(word);
|
|
std::string attrname3 = nl->SymbolValue(Ctn);
|
|
ListExpr attrType1;
|
|
ListExpr attrList1 = nl->Second(nl->Second(stream1));
|
|
ListExpr attrList2 = nl->Second(nl->Second(stream2));
|
|
|
|
int index1 = listutils::findAttribute(attrList1, attrname1,attrType1);
|
|
if(index1==0)
|
|
{
|
|
return listutils::typeError(attrname1+
|
|
" is not an attribute of the first stream");
|
|
}
|
|
int index2 = listutils::findAttribute(attrList2, attrname2,attrType1);
|
|
if(index2==0)
|
|
{
|
|
return listutils::typeError(attrname2+
|
|
" is not an attribute of the first stream");
|
|
}
|
|
int index3 = listutils::findAttribute(attrList2, attrname3,attrType1);
|
|
if(index3==0)
|
|
{
|
|
return listutils::typeError(attrname3+
|
|
" is not an attribute of the first stream");
|
|
}
|
|
|
|
// Temporarily here because I will be adding more
|
|
ListExpr indexList = nl->ThreeElemList(
|
|
nl->IntAtom(index1-1),
|
|
nl->IntAtom(index2-1),
|
|
nl->IntAtom(index3-1)
|
|
);
|
|
|
|
|
|
/*
|
|
Last argument to this ThreeElemList
|
|
Return types Stream<Tuple>
|
|
Tuple Type and attribute List
|
|
*/
|
|
|
|
return nl->ThreeElemList( nl->SymbolAtom(Symbols::APPEND()),
|
|
indexList,
|
|
nl->TwoElemList(
|
|
nl->SymbolAtom(Stream<Tuple>::BasicType()),
|
|
nl->TwoElemList(
|
|
nl->SymbolAtom(Tuple::BasicType()),
|
|
attrList1)));
|
|
|
|
}
|
|
|
|
class BatchTrajInfo
|
|
{
|
|
struct WordInfo
|
|
{
|
|
|
|
CcString* str;
|
|
CcInt* count;
|
|
};
|
|
|
|
public:
|
|
|
|
BatchTrajInfo(unsigned int bucknum,
|
|
Rectangle<2>& _rect, Word& _stream1, Word& _stream2,
|
|
const ListExpr _resType,
|
|
const int _index1, const int _index2, const int _index3,
|
|
double _alpha, double _threshold, double _diag) :
|
|
hashTable(0), bucket(0), bucketPos(0), bucketnum(bucknum), bmbr(_rect),
|
|
stream1(_stream1),
|
|
stream2(_stream2),
|
|
tt(0),
|
|
index1(_index1), index2(_index2),
|
|
index3(_index3),
|
|
alpha(_alpha), threshold(_threshold),
|
|
diag(_diag), wordTuple(0), sumOfBoth(0)
|
|
{
|
|
// this->stream2 = stream2;
|
|
wordTuple =0;
|
|
tt = new TupleType(_resType);
|
|
|
|
stream1.open();
|
|
qp->Open(stream2.addr);
|
|
readBatchTSum();
|
|
}
|
|
~BatchTrajInfo()
|
|
{
|
|
stream1.close();
|
|
qp->Close(stream2.addr);
|
|
|
|
clearTable();
|
|
tt->DeleteIfAllowed();
|
|
}
|
|
|
|
void clearTable(){
|
|
for (unsigned int i = 0; i< bucketnum; i++)
|
|
{
|
|
std::vector<WordInfo*>* v = hashTable[i];
|
|
if (v)
|
|
{
|
|
for(unsigned int j = 0; j < v->size(); j++)
|
|
{
|
|
delete (*v)[j];
|
|
|
|
}
|
|
delete hashTable[i];
|
|
hashTable[i] = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
size_t getBucket(CcString* str)
|
|
{
|
|
return str->HashValue() % bucketnum;
|
|
}
|
|
void readBatchTSum()
|
|
{
|
|
|
|
if (!hashTable)
|
|
{
|
|
hashTable = new std::vector<WordInfo*>*[bucketnum];
|
|
for (unsigned int i = 0; i < bucketnum; i++)
|
|
{
|
|
hashTable[i] = 0;
|
|
}
|
|
}
|
|
|
|
|
|
Word tuple;
|
|
qp->Request(stream2.addr, tuple);
|
|
while (qp->Received(stream2.addr))
|
|
{
|
|
wordTuple = static_cast<Tuple*>(tuple.addr);
|
|
CcString* str1 = (CcString*) wordTuple->GetAttribute(index2);
|
|
CcInt* ctn = (CcInt*) wordTuple->GetAttribute(index3);
|
|
size_t hash = getBucket(str1);
|
|
|
|
if (!hashTable[hash])
|
|
{
|
|
hashTable[hash] = new std::vector<WordInfo*>();
|
|
}
|
|
WordInfo* rInfo = new WordInfo;
|
|
rInfo->count = ctn;
|
|
rInfo->str = str1;
|
|
hashTable[hash]->push_back(rInfo);
|
|
sumOfBoth = sumOfBoth + 1;
|
|
qp->Request(stream2.addr, tuple);
|
|
}
|
|
|
|
}
|
|
Tuple* nextTuple()
|
|
{
|
|
|
|
|
|
Tuple* res = new Tuple(tt);
|
|
while ((res = stream1.request()))
|
|
{
|
|
SemanticTrajectory* st =
|
|
(SemanticTrajectory*) res->GetAttribute(index1);
|
|
const Geoid* geoid = 0;
|
|
|
|
double distance = bmbr.Distance((st->GetBoundingBox()), geoid);
|
|
|
|
double normalizedScore = 1 - (double)(distance/diag);
|
|
|
|
double result1 = alpha * normalizedScore + double (1-alpha);
|
|
|
|
double result2 = 0.0;
|
|
double sum = 0.0;
|
|
for (int i = 0; i < st->GetNumCoordinates(); i++)
|
|
{
|
|
std::string holdvalue;
|
|
st->GetSemString(i, holdvalue);
|
|
|
|
double rel = RelevanceBT(bmbr, st->GetCoordinate(i).x,
|
|
st->GetCoordinate(i).y, holdvalue,alpha, diag);
|
|
|
|
sum = sum + rel;
|
|
}
|
|
if (sum > 0)
|
|
{
|
|
result2 = sum / st->GetNumCoordinates();
|
|
}
|
|
|
|
double result3 = result1 + result2;
|
|
|
|
if (result3 > threshold)
|
|
{
|
|
return res;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
private:
|
|
std::vector<WordInfo*>** hashTable;
|
|
const std::vector<WordInfo*>* bucket;
|
|
unsigned int bucketPos;
|
|
unsigned int bucketnum;
|
|
Rectangle<2> bmbr;
|
|
Stream<Tuple> stream1;
|
|
Word stream2;
|
|
TupleType* tt;
|
|
int index1;
|
|
int index2;
|
|
int index3;
|
|
double alpha;
|
|
double threshold;
|
|
double diag;
|
|
Tuple* wordTuple;
|
|
int sumOfBoth = 0;
|
|
|
|
double EuclidDistRT(double x1,
|
|
double y1,
|
|
double x2,
|
|
double y2)
|
|
{
|
|
return sqrt(pow((x1 - x2),2) + pow((y1 - y2),2));
|
|
}
|
|
|
|
double RelevanceBT(Rectangle<2>& mbr, double x,
|
|
double y,
|
|
std::string& objectwords, double alpha,
|
|
double diag)
|
|
{
|
|
double result1 = 0.0;
|
|
double result2 = 0.0;
|
|
double textscore = 0.0;
|
|
if (objectwords.length() > 0)
|
|
{
|
|
textscore = getTextualScoreBT(objectwords);
|
|
}
|
|
result2 = double (1 - alpha) * textscore;
|
|
double dist = getDistanceBT(mbr, x, y);
|
|
double normalizedScore = 0.0;
|
|
if (dist == 0.0)
|
|
{
|
|
normalizedScore = 1;
|
|
}
|
|
else
|
|
{
|
|
normalizedScore = 1 - (double) (dist/diag);
|
|
}
|
|
result1 = alpha * normalizedScore;
|
|
return result1 + result2;
|
|
|
|
}
|
|
|
|
double getTextualScoreBT(std::string& objectwords)
|
|
{
|
|
|
|
int numMatches = 0;
|
|
int count = objectwords.length();
|
|
|
|
stringutils::StringTokenizer parse1(objectwords, " ");
|
|
|
|
while(parse1.hasNextToken())
|
|
{
|
|
std::string eval = parse1.nextToken();
|
|
|
|
CcString* stn = new CcString(true, eval);
|
|
size_t hash = getBucket(stn);
|
|
bucket = 0;
|
|
bucket = hashTable[hash];
|
|
bucketPos = 0;
|
|
|
|
|
|
// There is a match
|
|
if (bucket)
|
|
{
|
|
// Find the match
|
|
while(bucketPos < bucket->size())
|
|
{
|
|
WordInfo* p = (*bucket)[bucketPos];
|
|
|
|
|
|
if (((p->str)->GetValue()).compare(eval) == 0)
|
|
{
|
|
numMatches++;
|
|
break;
|
|
}
|
|
bucketPos++;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
if (numMatches == 0)
|
|
{
|
|
return 0.0;
|
|
}
|
|
double uniquewords = (double)
|
|
(sumOfBoth + count - numMatches);
|
|
return (double) numMatches / uniquewords;
|
|
}
|
|
|
|
double getDistanceBT(Rectangle<2>& mbr, double x, double y)
|
|
{
|
|
double xmin = mbr.getMinX();
|
|
double ymin = mbr.getMinY();
|
|
double xmax = mbr.getMaxX();
|
|
double ymax = mbr.getMaxY();
|
|
if (xmin <= x && x <= xmax && ymin <= y && y <= ymax)
|
|
{
|
|
return 0.0;
|
|
}
|
|
// Upper quadrant
|
|
if (ymin > y)
|
|
{
|
|
//left
|
|
if (xmax < x) {
|
|
return EuclidDistRT(x, y, xmax ,ymin);
|
|
}
|
|
//Center
|
|
if (xmin <= x && x <= xmax) {
|
|
return EuclidDistRT(x, y, x ,ymin);
|
|
}
|
|
//Right
|
|
if(xmin > x)
|
|
{
|
|
return EuclidDistRT(x, y, xmin, ymin);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//left
|
|
if (xmax < x) {
|
|
return EuclidDistRT(x, y, xmax ,ymax);
|
|
}
|
|
//Center
|
|
if (xmin <= x && x <= xmax) {
|
|
return EuclidDistRT(x, y, x ,ymax);
|
|
}
|
|
//Right
|
|
if(xmin > x)
|
|
{
|
|
return EuclidDistRT(x, y, xmin, ymax);
|
|
}
|
|
}
|
|
|
|
if (ymin <= y && y <= ymax)
|
|
{
|
|
if (x < xmin)
|
|
{
|
|
return EuclidDistRT(x, y, xmin, y);
|
|
}
|
|
if (x > xmax)
|
|
{
|
|
return EuclidDistRT(x, y, xmax, y);
|
|
}
|
|
}
|
|
|
|
return 0.0;
|
|
}
|
|
};
|
|
|
|
int FilterBTSimMapValue( Word* args, Word& result,
|
|
int message, Word& local, Supplier s )
|
|
{
|
|
|
|
BatchTrajInfo* li = (BatchTrajInfo*) local.addr;
|
|
switch(message){
|
|
case OPEN: { if(li){
|
|
delete li;
|
|
}
|
|
ListExpr ttype = nl->Second(GetTupleResultType(s));
|
|
|
|
int noargs = qp->GetNoSons(s);
|
|
int idx1 = ((CcInt*)args[noargs-3].addr)->GetValue();
|
|
int idx2 = ((CcInt*)args[noargs-2].addr)->GetValue();
|
|
int idx3 = ((CcInt*)args[noargs-1].addr)->GetValue();
|
|
Rectangle<2> * mbr = static_cast<Rectangle<2>*>(args[5].addr);
|
|
CcReal * alpha = static_cast<CcReal*>(args[6].addr);
|
|
CcReal * thresh = static_cast<CcReal*>(args[7].addr);
|
|
Rectangle<2>* rec = static_cast<Rectangle<2>*>(args[8].addr);
|
|
double diagonal = GetDiag(*rec);
|
|
|
|
local.addr = new BatchTrajInfo(
|
|
9999,
|
|
*(mbr),
|
|
args[0],
|
|
args[1],
|
|
ttype,
|
|
idx1,
|
|
idx2,
|
|
idx3,
|
|
alpha->GetValue(),
|
|
thresh->GetValue(),
|
|
diagonal);
|
|
return 0;
|
|
}
|
|
case REQUEST: { if(!li){
|
|
return CANCEL;
|
|
}
|
|
|
|
result.addr = li->nextTuple();
|
|
|
|
return result.addr ? YIELD:CANCEL;
|
|
}
|
|
case CLOSE : {
|
|
if(li){
|
|
delete li;
|
|
local.addr=0;
|
|
}
|
|
return 0;
|
|
}
|
|
}
|
|
return 0;
|
|
|
|
}
|
|
|
|
/*
|
|
5.12 Operator ~sim~
|
|
|
|
5.12.1 Type map for ~sim~
|
|
|
|
*/
|
|
ListExpr SimTypeMap(ListExpr args)
|
|
{
|
|
|
|
NList type(args);
|
|
if(type != NList(SemanticTrajectory::BasicType(),
|
|
SemanticTrajectory::BasicType(),
|
|
Rectangle<2>::BasicType(),
|
|
CcReal::BasicType()))
|
|
{
|
|
return NList::typeError("Expecting two semantic"
|
|
"trajectories, a rectangle<2> and a real value for the alpha");
|
|
}
|
|
return NList(CcReal::BasicType()).listExpr();
|
|
}
|
|
|
|
int SimMapValue(Word* args,
|
|
Word& result,
|
|
int message,
|
|
Word& local,
|
|
Supplier s)
|
|
{
|
|
|
|
SemanticTrajectory* st1 = static_cast<SemanticTrajectory*>(args[0].addr);
|
|
SemanticTrajectory* st2 = static_cast<SemanticTrajectory*>(args[1].addr);
|
|
Rectangle<2>* rec = static_cast<Rectangle<2>*>(args[2].addr);
|
|
CcReal * alpha = static_cast<CcReal*>(args[3].addr);
|
|
|
|
result = qp->ResultStorage(s);
|
|
double diag = st1->GetDiagonal(*rec);
|
|
|
|
double answer = st1->Similarity(*st2, diag, alpha->GetValue());
|
|
|
|
((CcReal*) result.addr)->Set(answer);
|
|
// cout << answer << endl;
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
5.13 Operator ~bbsim~
|
|
|
|
5.13.1 Type map for ~bbsim~
|
|
|
|
*/
|
|
ListExpr BBSimTypeMap(ListExpr args)
|
|
{
|
|
|
|
if(!Batch::checkType(nl->First(args))
|
|
&& !Batch::checkType(nl->Second(args)))
|
|
{
|
|
return listutils::
|
|
typeError("expecting two tuples for first and second arguments");
|
|
}
|
|
if (!CcReal::checkType(nl->Third(args)) ||
|
|
!Rectangle<2>::checkType(nl->Fourth(args))){
|
|
return listutils::
|
|
typeError("third and fourth argument of real and rectangle");
|
|
}
|
|
|
|
return NList(CcReal::BasicType()).listExpr();
|
|
}
|
|
|
|
int BBSimMapValue(Word* args,
|
|
Word& result,
|
|
int message,
|
|
Word& local,
|
|
Supplier s)
|
|
{
|
|
|
|
Batch* t1 = static_cast<Batch*>( args[0].addr );
|
|
Batch* t2 = static_cast<Batch*>( args[1].addr );
|
|
CcReal * alpha = static_cast<CcReal*>(args[2].addr);
|
|
Rectangle<2>* rec = static_cast<Rectangle<2>*>(args[3].addr);
|
|
|
|
|
|
result = qp->ResultStorage(s);
|
|
double diag = GetDiag(*rec);
|
|
const Rectangle<2> r1 = t1->GetBoundingBox();
|
|
const Rectangle<2> r2 = t2->GetBoundingBox();
|
|
const Geoid* geoid = 0;
|
|
double distance = 0.0;
|
|
double alpha1 = alpha->GetValue();
|
|
if (alpha1 > 0)
|
|
{
|
|
distance = r1.Distance(r2, geoid);
|
|
}
|
|
double normalizedScore = 0.0;
|
|
if (distance == 0.0) {
|
|
normalizedScore = 1;
|
|
}
|
|
else
|
|
{
|
|
normalizedScore = 1 - (double)(distance/diag);
|
|
}
|
|
|
|
double answer = alpha1 * normalizedScore * 2 + double (1-alpha1) * 2;
|
|
|
|
((CcReal*) result.addr)->Set(answer);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
5.14 Operator ~ttsim~
|
|
|
|
5.14.1 Type map for ~ttsim~
|
|
|
|
*/
|
|
ListExpr TTSimTypeMap(ListExpr args)
|
|
{
|
|
|
|
std::string err = "Should have 5 arguments";
|
|
if(!nl->HasLength(args, 5))
|
|
{
|
|
return listutils::typeError(err);
|
|
}
|
|
|
|
if(!SemanticTrajectory::checkType(nl->First(args))
|
|
&& !SemanticTrajectory::checkType(nl->Second(args)))
|
|
{
|
|
return listutils::
|
|
typeError("expecting two first arguments to first"
|
|
"arguments to be semantictrajectory");
|
|
}
|
|
if (!CcReal::checkType(nl->Third(args))){
|
|
return listutils::
|
|
typeError("third argument should be a real");
|
|
}
|
|
if (!Rectangle<2>::checkType(nl->Fourth(args)))
|
|
{
|
|
return listutils::
|
|
typeError("fourth argument should be a rectangle");
|
|
}
|
|
if(!CellGrid2D::checkType(nl->Fifth(args)))
|
|
{
|
|
return listutils::
|
|
typeError(err + "(5th arg must be CellGrid2D");
|
|
}
|
|
|
|
return NList(CcReal::BasicType()).listExpr();
|
|
}
|
|
|
|
int TTSimMapValue(Word* args,
|
|
Word& result,
|
|
int message,
|
|
Word& local,
|
|
Supplier s)
|
|
{
|
|
|
|
result = qp->ResultStorage(s);
|
|
CcReal* res = static_cast<CcReal*>(result.addr);
|
|
SemanticTrajectory* s1 = static_cast<SemanticTrajectory*>( args[0].addr );
|
|
SemanticTrajectory* s2 = static_cast<SemanticTrajectory*>( args[1].addr );
|
|
CcReal * alpha = static_cast<CcReal*>(args[2].addr);
|
|
Rectangle<2>* rec = static_cast<Rectangle<2>*>(args[3].addr);
|
|
CellGrid2D* grid = static_cast<CellGrid2D*>(args[4].addr);
|
|
double LH = 0.0;
|
|
double RH = 0.0;
|
|
double textualscore = 0.0;
|
|
double distancescore = 0.0;
|
|
double alpha1 = alpha->GetValue();
|
|
double textalpha = 1.0 - alpha1;
|
|
if (textalpha > 0)
|
|
{
|
|
textualscore = s1->textualScoreTT(*s2);
|
|
RH = (1.0 - textalpha) * textualscore;
|
|
}
|
|
|
|
if (alpha1 > 0)
|
|
{
|
|
|
|
double wx = grid->getXw();
|
|
double wy = grid->getYw();
|
|
distancescore = s1->MinDistAux(*s2, wx, wy);
|
|
|
|
}
|
|
double normalizedScore = 0.0;
|
|
if (distancescore != 0.0)
|
|
{
|
|
double diag = s1->GetDiagonal(*rec);
|
|
normalizedScore = 1 - (double)(distancescore/diag);
|
|
}
|
|
else {
|
|
normalizedScore = 1;
|
|
}
|
|
LH = alpha1 * normalizedScore;
|
|
double answer = LH + RH;
|
|
|
|
res->Set(true, answer);
|
|
|
|
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
5.15 Operator ~buildbatch~
|
|
|
|
5.15.1 Type map for ~buildbatch~
|
|
|
|
*/
|
|
ListExpr BuildBatchTypeMap(ListExpr args)
|
|
{
|
|
|
|
// Check to see if it's the right number of arguments
|
|
if (nl->HasLength(args, 8))
|
|
{
|
|
// Make sure each param is of right type
|
|
std::string err = "stream(tuple) x stream(tuple) x Ccint x"
|
|
" attr_2 x attr_3 x attr_4 x attr_5 x rect expected";
|
|
|
|
ListExpr stream = nl->First(args);
|
|
ListExpr stream2 = nl->Second(args);
|
|
ListExpr BatchId = nl->Third(args);
|
|
ListExpr attrname_word = nl->Fourth(args);
|
|
ListExpr attrname_ctn = nl->Fifth(args);
|
|
ListExpr attrname_tripid = nl->Sixth(args);
|
|
ListExpr attrname_st = nl->Seventh(args);
|
|
ListExpr r1 = nl->Eigth(args);
|
|
|
|
if(!listutils::isTupleStream(stream)){
|
|
return
|
|
listutils::typeError(
|
|
"first parameter must be a tuple stream");
|
|
}
|
|
if(!listutils::isTupleStream(stream2)){
|
|
return
|
|
listutils::typeError(
|
|
"second parameter must be a tuple stream");
|
|
}
|
|
if (!CcInt::checkType(BatchId))
|
|
{
|
|
return listutils::typeError(err + "3rd arg must be a int");
|
|
}
|
|
if(!listutils::isSymbol(attrname_word)){
|
|
return
|
|
listutils::typeError("4th parameter must"
|
|
"be an attribute name");
|
|
}
|
|
|
|
if(!listutils::isSymbol(attrname_ctn)){
|
|
return
|
|
listutils::typeError("5th parameter must"
|
|
" be an attribute name");
|
|
}
|
|
if(!listutils::isSymbol(attrname_tripid)){
|
|
return
|
|
listutils::typeError("5th parameter must"
|
|
"be an attribute name");
|
|
}
|
|
|
|
if(!listutils::isSymbol(attrname_st)){
|
|
return
|
|
listutils::typeError("6th parameter must"
|
|
" be an attribute name");
|
|
}
|
|
if (!Rectangle<2>::checkType(r1))
|
|
{
|
|
return listutils::typeError(err + "6th arg must be a rectangle");
|
|
}
|
|
|
|
ListExpr type;
|
|
// extract the attribute list
|
|
ListExpr attrList = nl->Second(nl->Second(stream));
|
|
ListExpr attrList2 = nl->Second(nl->Second(stream2));
|
|
// Get the index for the longitude
|
|
std::string name =
|
|
nl->SymbolValue(attrname_word);
|
|
int index1 =
|
|
listutils::findAttribute(attrList, name, type);
|
|
if(index1==0)
|
|
{
|
|
return
|
|
listutils::typeError(
|
|
"attribute name " + name +
|
|
" unknown in tuple"
|
|
" stream");
|
|
}
|
|
if(!CcString::checkType(type))
|
|
{
|
|
return
|
|
listutils::typeError("attribute "
|
|
+ name +
|
|
" must be of type real");
|
|
}
|
|
|
|
name = nl->SymbolValue(attrname_ctn);
|
|
|
|
int index2 =
|
|
listutils::findAttribute(attrList, name, type);
|
|
|
|
if(index2==0){
|
|
return
|
|
listutils::typeError("attribute name " + name +
|
|
" unknown in tuple stream");
|
|
}
|
|
if(!CcInt::checkType(type)){
|
|
return
|
|
listutils::typeError("attribute '" + name +
|
|
"' must be of type 'real'");
|
|
}
|
|
name = nl->SymbolValue(attrname_tripid);
|
|
int index3 =
|
|
listutils::findAttribute(attrList2, name, type);
|
|
|
|
if(index3==0){
|
|
return
|
|
listutils::typeError("attribute name " + name +
|
|
" unknown in tuple stream");
|
|
}
|
|
if(!CcInt::checkType(type)){
|
|
return
|
|
listutils::typeError("attribute '" + name +
|
|
"' must be of type 'real'");
|
|
}
|
|
name = nl->SymbolValue(attrname_st);
|
|
int index4 =
|
|
listutils::findAttribute(attrList2, name, type);
|
|
|
|
if(index4==0){
|
|
return
|
|
listutils::typeError("attribute name " + name +
|
|
" unknown in tuple stream");
|
|
}
|
|
if(!SemanticTrajectory::checkType(type)){
|
|
return
|
|
listutils::typeError("attribute '" + name +
|
|
"' must be of type 'real'");
|
|
}
|
|
std::string restype =
|
|
Batch::BasicType();
|
|
|
|
|
|
ListExpr indexes = nl->FourElemList(
|
|
nl->IntAtom(index1-1),
|
|
nl->IntAtom(index2-1),
|
|
nl->IntAtom(index3-1),
|
|
nl->IntAtom(index4-1)
|
|
);
|
|
|
|
return
|
|
nl->ThreeElemList(nl->SymbolAtom(Symbol::APPEND()),
|
|
indexes,
|
|
nl->SymbolAtom(restype));
|
|
}
|
|
return
|
|
listutils::typeError("Wrong number of arguments");
|
|
|
|
}
|
|
|
|
int BuildBatchMapValue(Word* args, Word& result,
|
|
int message, Word& local,
|
|
Supplier s)
|
|
{
|
|
|
|
result = qp->ResultStorage(s);
|
|
Batch* b =
|
|
static_cast<Batch*>(result.addr);
|
|
b->Clear();
|
|
int noargs = qp->GetNoSons(s);
|
|
|
|
int idx1 = ((CcInt*)args[noargs-4].addr)->GetValue();
|
|
int idx2 = ((CcInt*)args[noargs-3].addr)->GetValue();
|
|
int idx3 = ((CcInt*)args[noargs-2].addr)->GetValue();
|
|
int idx4 = ((CcInt*)args[noargs-1].addr)->GetValue();
|
|
|
|
Stream<Tuple> stream(args[0]);
|
|
Stream<Tuple> stream2(args[1]);
|
|
CcInt * batchId = static_cast<CcInt*>(args[2].addr);
|
|
Rectangle<2>* rec = static_cast<Rectangle<2>*>(args[7].addr);
|
|
b->SetBatchId(batchId->GetValue());
|
|
Tuple* tuple;
|
|
stream.open();
|
|
while((tuple = stream.request()))
|
|
{
|
|
CcString* x = (CcString*) tuple->GetAttribute(idx1);
|
|
CcInt* y = (CcInt*) tuple->GetAttribute(idx2);
|
|
|
|
b->AddBSumString(x->GetValue(), -1, y->GetValue());
|
|
tuple->DeleteIfAllowed();
|
|
}
|
|
|
|
double mind[2];
|
|
double maxd[2];
|
|
mind[0] = rec->getMinX();
|
|
mind[1] = rec->getMinY();
|
|
maxd[0] = rec->getMaxX();
|
|
maxd[1] = rec->getMaxY();
|
|
b->SetBoundingBox(true, mind, maxd);
|
|
/*
|
|
Retrieval of Trip information for batch starts here
|
|
|
|
*/
|
|
stream2.open();
|
|
int coordcounters = 0;
|
|
int cellcounters = 0;
|
|
int sumwordscounter = 0;
|
|
|
|
while((tuple = stream2.request()))
|
|
{
|
|
|
|
SemanticTrajectory* st = (SemanticTrajectory*) tuple->GetAttribute(idx4);
|
|
CcInt* id = (CcInt*) tuple->GetAttribute(idx3);
|
|
Trip t;
|
|
double mind[2];
|
|
double maxd[2];
|
|
const Rectangle<2> r = st->GetBoundingBox();
|
|
mind[0] = r.getMinX();
|
|
mind[1] = r.getMinY();
|
|
maxd[0] = r.getMaxX();
|
|
maxd[1] = r.getMaxY();
|
|
t.SetBoundingBox(true, mind, maxd);
|
|
t.SetId(id->GetValue());
|
|
|
|
/* TODO Collect the Coordinate information */
|
|
t.SetStartCoordsIdx(coordcounters);
|
|
|
|
for (int i = 0; i < st->GetNumCoordinates(); i++)
|
|
{
|
|
|
|
Coordinate c = st->GetCoordinate(i);
|
|
b->AddBCoordinate(c);
|
|
std::string holdValue = "";
|
|
st->GetSemString(i, holdValue);
|
|
|
|
|
|
b->AddBSemString(holdValue);
|
|
|
|
coordcounters++;
|
|
}
|
|
t.SetEndCoordsIdx(coordcounters);
|
|
|
|
/* TODO Collect the Cell information */
|
|
t.SetStartCellsIdx(cellcounters);
|
|
for (int i = 0; i < st->GetNumCells(); i++)
|
|
{
|
|
|
|
Cell c = st->GetCell(i);
|
|
b->AddBCell(c);
|
|
cellcounters++;
|
|
}
|
|
t.SetEndCellsIdx(cellcounters);
|
|
|
|
|
|
/* TODO Collect the Summary Information */
|
|
t.SetStartSumWordsIdx(sumwordscounter);
|
|
for (int i = 0; i < st->GetNumWords(); i++)
|
|
{
|
|
std::string holdValue = "";
|
|
bool success = st->GetStringSum(i, holdValue);
|
|
assert(success);
|
|
int id = st->GetWord(i).indexId;
|
|
int count = st->GetWord(i).count;
|
|
b->AddBWord(holdValue, id, count);
|
|
sumwordscounter++;
|
|
}
|
|
t.SetEndSumWordsIdx(sumwordscounter);
|
|
|
|
b->AddTrip(t);
|
|
|
|
|
|
tuple->DeleteIfAllowed();
|
|
}
|
|
|
|
stream.close();
|
|
stream2.close();
|
|
return 0;
|
|
}
|
|
/*
|
|
5.16 Operator ~getTrips~
|
|
|
|
5.16.1 Type map for ~getTrips~
|
|
|
|
*/
|
|
ListExpr GetTripsTypeMap(ListExpr args)
|
|
{
|
|
if (!nl->HasLength(args, 1)) {
|
|
return listutils::typeError("Only takes one argument");
|
|
}
|
|
if (!Batch::checkType(nl->First(args))) {
|
|
return listutils::typeError("Needs a batch");
|
|
}
|
|
return nl->TwoElemList(
|
|
nl->SymbolAtom(Symbol::STREAM()),
|
|
nl->TwoElemList(
|
|
nl->SymbolAtom(Tuple::BasicType()),
|
|
nl->TwoElemList(
|
|
nl->TwoElemList(nl->SymbolAtom("TripId"),
|
|
nl->SymbolAtom(CcInt::BasicType())
|
|
),
|
|
nl->TwoElemList(nl->SymbolAtom("Trip"),
|
|
nl->SymbolAtom(SemanticTrajectory::BasicType())
|
|
)
|
|
|
|
)
|
|
));
|
|
}
|
|
|
|
class TripInfo
|
|
{
|
|
|
|
public:
|
|
TripInfo(const ListExpr _resType,
|
|
int numTrips, Batch& bt) :
|
|
tt(0),visitedtrip(0),
|
|
numOfTrips(numTrips),
|
|
curidx(0), b(bt)
|
|
{
|
|
tt = new TupleType(_resType);
|
|
}
|
|
~TripInfo() {
|
|
tt->DeleteIfAllowed();
|
|
}
|
|
int getIndex()
|
|
{
|
|
if (visitedtrip < numOfTrips)
|
|
{
|
|
curidx = visitedtrip;
|
|
visitedtrip++;
|
|
return curidx;
|
|
}
|
|
return -1;
|
|
}
|
|
int getTripId() {
|
|
Trip t = b.GetTrip(curidx);
|
|
return t.GetId();
|
|
}
|
|
Tuple* nextTuple()
|
|
{
|
|
Tuple* res = new Tuple(tt);
|
|
/* Create ST */
|
|
Trip t = b.GetTrip(curidx);
|
|
int id = t.GetId();
|
|
|
|
res->PutAttribute(0, new CcInt(true, id));
|
|
|
|
SemanticTrajectory* st = new SemanticTrajectory(0);
|
|
double mind[2];
|
|
double maxd[2];
|
|
Rectangle<2> bbox = b.GetBoundingBox();
|
|
mind[0] = bbox.getMinX();
|
|
mind[1] = bbox.getMinY();
|
|
maxd[0] = bbox.getMaxX();
|
|
maxd[1] = bbox.getMaxY();
|
|
st->SetBoundingBox(true, mind, maxd);
|
|
int startCellIdx = t.GetStartCellsIdx();
|
|
int endCellIdx = t.GetEndCellsIdx();
|
|
if (startCellIdx < endCellIdx)
|
|
{
|
|
for (int i = startCellIdx; i < endCellIdx; i++)
|
|
{
|
|
Cell c = b.GetBCell(i);
|
|
st->AddCell(c);
|
|
}
|
|
}
|
|
int startTSumIdx = t.GetStartSumWordsIdx();
|
|
int endTSumIdx = t.GetEndSumWordsIdx();
|
|
if (startTSumIdx < endTSumIdx)
|
|
{
|
|
for (int i = startTSumIdx; i < endTSumIdx; i++)
|
|
{
|
|
WordST wordInfo = b.GetBWordInfo(i);
|
|
std::string holdValue = "";
|
|
b.GetBWord(i, holdValue);
|
|
st->AddStringSum(holdValue, wordInfo.indexId, wordInfo.count);
|
|
}
|
|
}
|
|
int startCoordsIdx = t.GetStartCoordsIdx();
|
|
int endCoordsIdx = t.GetEndCoordsIdx();
|
|
if (startCoordsIdx < endCoordsIdx)
|
|
{
|
|
for (int i = startCoordsIdx; i < endCoordsIdx; i++)
|
|
{
|
|
std::string holdvalue = "";
|
|
b.GetBSemString(i, holdvalue);
|
|
Coordinate c = b.GetBCoordinate(i);
|
|
st->AddCoordinate(c);
|
|
st->AddSemString(holdvalue);
|
|
}
|
|
}
|
|
|
|
res->PutAttribute(1, st);
|
|
return res;
|
|
}
|
|
Rectangle<2> getBoundingBox() {
|
|
return b.GetBoundingBox();
|
|
}
|
|
private:
|
|
TupleType* tt;
|
|
int visitedtrip;
|
|
int numOfTrips;
|
|
int curidx;
|
|
Batch b;
|
|
|
|
};
|
|
|
|
int GetTripsValueMap(Word* args, Word& result,
|
|
int message,
|
|
Word& local,
|
|
Supplier s)
|
|
{
|
|
|
|
TripInfo* localtrip =
|
|
(TripInfo*) local.addr;
|
|
|
|
switch(message)
|
|
{
|
|
|
|
case OPEN: // Initialize the local storage
|
|
{
|
|
|
|
if(localtrip)
|
|
{
|
|
delete localtrip;
|
|
localtrip = 0;
|
|
}
|
|
|
|
Batch* b =
|
|
static_cast<Batch*>(args[0].addr);
|
|
int numoftrips = b->GetNumTrips();
|
|
local.addr =
|
|
new TripInfo(nl->Second(GetTupleResultType(s)), numoftrips, *b);
|
|
|
|
|
|
return 0;
|
|
}
|
|
case REQUEST: // returnthe next stream element
|
|
{
|
|
int localidx = localtrip->getIndex();
|
|
|
|
if (localidx >= 0)
|
|
{
|
|
result.addr = localtrip->nextTuple();
|
|
return YIELD;
|
|
}
|
|
else
|
|
{
|
|
result.addr = 0;
|
|
return CANCEL;
|
|
}
|
|
}
|
|
case CLOSE:
|
|
{
|
|
if (localtrip != 0)
|
|
{
|
|
delete localtrip;
|
|
local.addr = 0;
|
|
}
|
|
return 0;
|
|
}
|
|
default:
|
|
{
|
|
// This should never happen
|
|
return -1;
|
|
}
|
|
}
|
|
return 0;
|
|
|
|
}
|
|
|
|
/*
|
|
5.17 Operator ~largerbatch~
|
|
|
|
5.17.1 Type map for ~largerbatch~
|
|
|
|
*/
|
|
ListExpr LargerBatchTypeMap(ListExpr args)
|
|
{
|
|
if (!nl->HasLength(args, 2)) {
|
|
return listutils::typeError("Only takes one argument");
|
|
}
|
|
if (!Batch::checkType(nl->First(args)) &&
|
|
!Batch::checkType(nl->Second(args))) {
|
|
return listutils::typeError("Needs a batch");
|
|
}
|
|
return NList(CcBool::BasicType()).listExpr();
|
|
}
|
|
|
|
int LargerBatchValueMap(Word* args, Word& result,
|
|
int message,
|
|
Word& local,
|
|
Supplier s)
|
|
{
|
|
Batch *b1 = static_cast<Batch*>( args[0].addr );
|
|
Batch *b2 = static_cast<Batch*>( args[1].addr );
|
|
Rectangle<2> r1 = b1->GetBoundingBox();
|
|
Rectangle<2> r2 = b2->GetBoundingBox();
|
|
|
|
result = qp->ResultStorage(s);
|
|
|
|
CcBool* b = static_cast<CcBool*>( result.addr );
|
|
b->Set(true, r1.Area() > r2.Area());
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
6 Operator Info
|
|
|
|
*/
|
|
struct LargerBatchInfo : OperatorInfo
|
|
{
|
|
LargerBatchInfo()
|
|
{
|
|
name = "largerbatch";
|
|
signature = "batch x batch -> bool";
|
|
syntax = "largerbatch(_,_)";
|
|
meaning =
|
|
"Compares area of two batches and"
|
|
"returns true if first param is the largest batch";
|
|
}
|
|
};
|
|
|
|
struct GetTripsInfo : OperatorInfo
|
|
{
|
|
GetTripsInfo()
|
|
{
|
|
name = "getTrips";
|
|
signature = "batch -> Stream(x)"
|
|
"batch -> Stream(x)";
|
|
syntax = "_ getTrips";
|
|
meaning =
|
|
"Get all trips data from a batch as a tuple with id and semantictrajectory";
|
|
}
|
|
};
|
|
|
|
struct BuildBatchInfo : OperatorInfo
|
|
{
|
|
BuildBatchInfo()
|
|
{
|
|
name = "buildbatch";
|
|
signature = "stream(tulple(X)) x stream(tuple(y))"
|
|
"int x a1 x a2 x a3 x a4 x rectangle -> batch";
|
|
syntax = "_ _ buildbatch[_,_,_,_,_,_]";
|
|
meaning =
|
|
"Pass a tuple stream to convert object into Batch Datatype";
|
|
}
|
|
};
|
|
|
|
struct BatchesInfo : OperatorInfo
|
|
{
|
|
BatchesInfo()
|
|
{
|
|
name = "batches";
|
|
signature = "stream(tulple(X)) x "
|
|
"a1 x a2 x real -> Stream (tuple(X))";
|
|
syntax = "_ batches[_,_,_]";
|
|
meaning =
|
|
"Assigns batchid to a list of semantictrajectory "
|
|
"~attribute a1 should be the ST"
|
|
"attribute a2 should batchId field"
|
|
" and attribute a3 should be the diagonal threshold value";
|
|
}
|
|
};
|
|
|
|
struct BBSimInfo : OperatorInfo
|
|
{
|
|
BBSimInfo()
|
|
{
|
|
name = "bbsim";
|
|
signature = "Batch x Batch x CcReal x Rectangle"
|
|
" -> CcReal";
|
|
syntax = "bbsim(_,_,_,_)";
|
|
meaning = "Evaluates two batch type"
|
|
"in order to calculate the spatial-textual distance and returns score";
|
|
}
|
|
};
|
|
|
|
struct BTSimInfo : OperatorInfo
|
|
{
|
|
BTSimInfo()
|
|
{
|
|
name = "btsim";
|
|
signature = "Batch x SemanticTrajectory "
|
|
"x CcReal x Rectangle"
|
|
" -> CcReal";
|
|
syntax = "btsim(_,_,_,_)";
|
|
meaning = "Evaluates trajectory-batch pair"
|
|
"using an uppberbound evaluation and returns score";
|
|
}
|
|
};
|
|
|
|
struct FilterBBSimInfo : OperatorInfo
|
|
{
|
|
FilterBBSimInfo()
|
|
{
|
|
name = "filterbbsim";
|
|
signature = "Stream(Tuple(x)) x id1 x id2"
|
|
"x MBR1 x MBR2 x CcReal x CcReal x Rectangle"
|
|
" -> Stream(Tuple(x))";
|
|
syntax = "_ filterbbsim[_,_,_,_,_,_,_]";
|
|
meaning = "Filters out batch-batch pair that are below the threshold"
|
|
"using an uppberbound evaluation"
|
|
"and return the batch pair tuple"
|
|
"with the batch with the largest Area 1st in tuple";
|
|
}
|
|
};
|
|
|
|
struct FilterBTSimInfo : OperatorInfo
|
|
{
|
|
FilterBTSimInfo()
|
|
{
|
|
name = "filterbtsim";
|
|
signature = "Stream(Tuple(x)) x Stream(Tuple(x)) "
|
|
"x attr x attr x attr x rect x real x real x rect"
|
|
" -> Stream(Tuple(x))";
|
|
syntax = "_ _ filterbtsim[_,_,_,_,_,_,_]";
|
|
meaning = "Filters out trajectory-batch pair"
|
|
"that are below the threshold"
|
|
"using an uppberbound evaluation";
|
|
}
|
|
};
|
|
|
|
struct FilterTTSimInfo : OperatorInfo
|
|
{
|
|
FilterTTSimInfo()
|
|
{
|
|
name = "filterttsim";
|
|
signature = "Stream(Tuple(x)) x attr x attr"
|
|
" x real x real x rect x CellGrid2D"
|
|
" -> Stream(Tuple(x))";
|
|
syntax = "_ filterttsim[_,_,_,_,_,_]";
|
|
meaning = "Filters out trajectory-trajectory pair"
|
|
" that are below the threshold"
|
|
"using an uppberbound evaluation";
|
|
}
|
|
};
|
|
|
|
struct FilterSimInfo : OperatorInfo
|
|
{
|
|
FilterSimInfo()
|
|
{
|
|
name = "filtersim";
|
|
signature = "Stream(Tuple(x)) x attr x attr x "
|
|
" real x real x rect"
|
|
" -> Stream(Tuple(x))";
|
|
syntax = "_ filtersim[_,_,_,_,_]";
|
|
meaning =
|
|
"Filter out trajectory-trajectory pair that are below threshold"
|
|
"by evaluating all the points";
|
|
}
|
|
};
|
|
|
|
struct TTSimInfo : OperatorInfo
|
|
{
|
|
TTSimInfo()
|
|
{
|
|
name = "ttsim";
|
|
signature = "semantictrajectory x semantictrajectory x real x "
|
|
" rectangle x CellGrid2D -> real";
|
|
syntax = "ttsim (_,_,_,_,_)";
|
|
meaning = "Returns the upperbound score between"
|
|
"two values semantictrajectory";
|
|
}
|
|
};
|
|
|
|
struct SimInfo : OperatorInfo
|
|
{
|
|
SimInfo()
|
|
{
|
|
name = "sim";
|
|
signature = SemanticTrajectory::BasicType() + " x "
|
|
+ SemanticTrajectory::BasicType()
|
|
+ " x " + Rectangle<2>::BasicType() + " x "
|
|
+ CcReal::BasicType() + " -> " + CcReal::BasicType();
|
|
syntax = "sim(_,_,_,_)";
|
|
meaning = "Get similarity score of two semantic Trajectories";
|
|
}
|
|
};
|
|
|
|
struct STBboxInfo : OperatorInfo
|
|
{
|
|
STBboxInfo()
|
|
{
|
|
name = "stbox";
|
|
signature = SemanticTrajectory::BasicType()
|
|
+ " -> " + Rectangle<2>::BasicType();
|
|
syntax = "stbox(_)";
|
|
meaning = "Returns the bounding box"
|
|
"of a semantic trajectory";
|
|
}
|
|
};
|
|
|
|
struct MakeSemTrajInfo : OperatorInfo
|
|
{
|
|
MakeSemTrajInfo()
|
|
{
|
|
name = "makesemtraj";
|
|
signature =
|
|
"stream(tuple(a1 t1) ...(an tn) ) "
|
|
" x ai x aj x ak-> semantictrajectory";
|
|
syntax = "_ makesemtraj [_,_,_]";
|
|
meaning =
|
|
"Convert stream of tuples"
|
|
" into a semantictrajectory datatype";
|
|
}
|
|
};
|
|
|
|
struct MakeSemTrajInfo2 : OperatorInfo
|
|
{
|
|
MakeSemTrajInfo2()
|
|
{
|
|
name = "makesemtraj2";
|
|
signature =
|
|
"stream(tuple(a1 t1) ...(an tn) ) "
|
|
" x ai x aj x ak-> semantictrajectory";
|
|
syntax = "_ _ makesemtraj2 [_,_,_,_]";
|
|
meaning =
|
|
"Convert stream of tuples"
|
|
" into a semantictrajectory datatype"
|
|
" + removes stopwords";
|
|
}
|
|
};
|
|
|
|
struct MakeSummariesInfo : OperatorInfo
|
|
{
|
|
MakeSummariesInfo()
|
|
{
|
|
name = "makesum";
|
|
signature =
|
|
"stream(tuple) x int x semantictrajectory x "
|
|
"cellgrid2d x attr x attr x attr"
|
|
" -> semantictrajectory";
|
|
syntax = "_ makesum [_,_,_,_,_,_]";
|
|
meaning =
|
|
"Retrieves cell origin coordinates from"
|
|
"a semantictrajectory to create spatial and textual summary";
|
|
}
|
|
};
|
|
|
|
struct ExtractKeywordsInfo : OperatorInfo
|
|
{
|
|
ExtractKeywordsInfo()
|
|
{
|
|
name = "extractkeywords";
|
|
signature =
|
|
"semantictrajectory -> stream(string)";
|
|
syntax = "_ extractkeywords";
|
|
meaning =
|
|
"Extracts semanticTrajectory string and"
|
|
" converts it into a"
|
|
"a stream of words";
|
|
}
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
7 Type Constructor for SemanticTrajectory
|
|
|
|
*/
|
|
TypeConstructor semantictrajectory (
|
|
SemanticTrajectory::BasicType(),
|
|
//name
|
|
SemanticTrajectory::Property,
|
|
//property function
|
|
SemanticTrajectory::Out,
|
|
SemanticTrajectory::In,
|
|
//Out and In functions
|
|
0,
|
|
0,
|
|
//SaveTo and RestoreFrom functions
|
|
SemanticTrajectory::Create,
|
|
SemanticTrajectory::Delete,
|
|
//object creation and deletion
|
|
SemanticTrajectory::Open,
|
|
SemanticTrajectory::Save,
|
|
//object open and save
|
|
SemanticTrajectory::Close,
|
|
SemanticTrajectory::Clone,
|
|
//object close and clone
|
|
SemanticTrajectory::Cast,
|
|
//cast function
|
|
SemanticTrajectory::SizeOfObj,
|
|
//sizeof function
|
|
SemanticTrajectory::KindCheck);
|
|
//kind checking function
|
|
|
|
|
|
|
|
|
|
/*
|
|
8 Type Constructor for Batch
|
|
|
|
*/
|
|
TypeConstructor batch (
|
|
Batch::BasicType(),
|
|
//name
|
|
Batch::Property,
|
|
//property function
|
|
Batch::Out,
|
|
Batch::In,
|
|
//Out and In functions
|
|
0,
|
|
0,
|
|
//SaveTo and RestoreFrom functions
|
|
Batch::Create,
|
|
Batch::Delete,
|
|
//object creation and deletion
|
|
Batch::Open,
|
|
Batch::Save,
|
|
//object open and save
|
|
Batch::Close,
|
|
Batch::Clone,
|
|
//object close and clone
|
|
Batch::Cast,
|
|
//cast function
|
|
Batch::SizeOfObj,
|
|
//sizeof function
|
|
Batch::KindCheck);
|
|
//kind checking function
|
|
|
|
|
|
/*
|
|
9 SemanticTrajectoryAlgebra
|
|
|
|
*/
|
|
class SemanticTrajectoryAlgebra : public Algebra
|
|
{
|
|
public:
|
|
SemanticTrajectoryAlgebra() : Algebra()
|
|
{
|
|
AddTypeConstructor(&semantictrajectory);
|
|
semantictrajectory.AssociateKind(Kind::DATA());
|
|
|
|
AddTypeConstructor(&batch);
|
|
batch.AssociateKind(Kind::DATA());
|
|
|
|
AddOperator(
|
|
BuildBatchInfo(),
|
|
BuildBatchMapValue,
|
|
BuildBatchTypeMap);
|
|
|
|
AddOperator(
|
|
LargerBatchInfo(),
|
|
LargerBatchValueMap,
|
|
LargerBatchTypeMap
|
|
);
|
|
|
|
AddOperator(
|
|
GetTripsInfo(),
|
|
GetTripsValueMap,
|
|
GetTripsTypeMap
|
|
);
|
|
|
|
AddOperator(
|
|
FilterBBSimInfo(),
|
|
FilterBBSimMapValue,
|
|
FilterBBSimTypeMap
|
|
);
|
|
|
|
AddOperator(
|
|
BBSimInfo(),
|
|
BBSimMapValue,
|
|
BBSimTypeMap
|
|
);
|
|
|
|
AddOperator(
|
|
FilterBTSimInfo(),
|
|
FilterBTSimMapValue,
|
|
FilterBTSimTypeMap
|
|
);
|
|
|
|
AddOperator(
|
|
BTSimInfo(),
|
|
BTSimMapValue,
|
|
BTSimTypeMap
|
|
);
|
|
|
|
AddOperator(
|
|
FilterTTSimInfo(),
|
|
FilterTTSimMapValue,
|
|
FilterTTSimTypeMap
|
|
);
|
|
|
|
AddOperator(
|
|
TTSimInfo(),
|
|
TTSimMapValue,
|
|
TTSimTypeMap
|
|
);
|
|
|
|
AddOperator(
|
|
FilterSimInfo(),
|
|
FilterSimMapValue,
|
|
FilterSimTypeMap);
|
|
|
|
AddOperator(
|
|
SimInfo(),
|
|
SimMapValue,
|
|
SimTypeMap);
|
|
|
|
AddOperator(
|
|
MakeSemTrajInfo(),
|
|
makesemtrajFuns,
|
|
makesemtrajSelect,
|
|
TypeMapMakeSemtraj);
|
|
|
|
AddOperator(
|
|
MakeSemTrajInfo2(),
|
|
MakeSemTrajMV2,
|
|
TypeMapMakeSemtraj2);
|
|
|
|
AddOperator(
|
|
STBboxInfo(),
|
|
STbboxMapValue,
|
|
STboxTM);
|
|
|
|
AddOperator(
|
|
MakeSummariesInfo(),
|
|
MakesummariesMV,
|
|
MakesummariesTM );
|
|
|
|
AddOperator(
|
|
ExtractKeywordsInfo(),
|
|
extractkeywordMapV,
|
|
extractkeywordsTM);
|
|
|
|
AddOperator (
|
|
BatchesInfo(),
|
|
BatchesVM,
|
|
BatchesTM);
|
|
|
|
}
|
|
~SemanticTrajectoryAlgebra() {};
|
|
|
|
};
|
|
|
|
|
|
/*
|
|
10 Initialization
|
|
|
|
*/
|
|
|
|
extern "C"
|
|
Algebra*
|
|
InitializeSemanticTrajectoryAlgebra(NestedList *nlRef,
|
|
QueryProcessor *qpRef)
|
|
{
|
|
nl = nlRef;
|
|
qp = qpRef;
|
|
return (new SemanticTrajectoryAlgebra());
|
|
}
|
|
} // end of namespace
|