Files
secondo/Algebras/PMRegion/PMRegionAlgebra.cpp
2026-01-23 17:03:45 +08:00

1450 lines
38 KiB
C++

/*
----
This file is part of SECONDO.
Copyright (C) 2004, University in Hagen, Department of Computer Science,
Database Systems for New Applications.
SECONDO is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
SECONDO is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with SECONDO; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
----
//paragraph [1] Title: [{\Large \bf \begin {center}] [\end {center}}]
//[TOC] [\tableofcontents]
[1] Implementation of the Polyhedral Moving Region Algebra (PMRegionAlgebra)
June, 2018. Florian Heinz <fh@sysv.de>
[TOC]
1 Overview
This Algebra defines a new datatype:
1.1 PMRegion
The ~pmregion~ represents a polyhedral moving region.
Operations are ~atinstant~, ~inside~ (of a moving point), ~traversedarea~,
which calculates the exact area, which is traversed during the time interval,
~area~ and ~perimeter~, which calculates an mreal value for the requested
parameter, the set operations ~union~, ~intersection~ and ~minus~ as well as
~intersects~. Furthermore, ~pmreg2mreg~ and ~mreg2pmreg~ can be used to
convert the pmregion to a mregion and vice versa.
*/
#include "Algebra.h"
#include "NestedList.h"
#include "QueryProcessor.h"
#include "Algebras/Spatial/SpatialAlgebra.h"
#include "Algebras/Temporal/TemporalAlgebra.h"
#include "Algebras/MovingRegion/MovingRegionAlgebra.h"
#include "StandardTypes.h"
#include "Algebras/Relation-C++/RelationAlgebra.h"
#include "ListUtils.h"
#include "PMRegionAlgebra.h"
#include <math.h>
using namespace temporalalgebra;
using namespace pmregion;
using namespace pmr;
using namespace std;
Region* buildRegion(vector< vector<Point> >& cycles);
namespace temporalalgebra {
Word InUReal( const ListExpr typeInfo, const ListExpr instance,
const int errorPos, ListExpr& errorInfo, bool& correct );
Word InMRegion(const ListExpr typeInfo,
const ListExpr instance,
const int errorPos,
ListExpr& errorInfo,
bool& correct);
ListExpr OutMRegion(ListExpr typeInfo, Word instance);
}
namespace pmregion {
/*
2 PMRegion type definition
An ~pmregion~ is defined by one or more polyhedra.
2.1 List definition
((<Point3D>*)(<Triangle>*))
<Point3D>: (x y z) with x, y, z : coordinate (real value)
<Triangle>: (idx1 idx2 idx3) with idxn being the index of
the point in the first list.
Example:
(
( __! Vertices !__
( 1392 438 0 )
( 1683 758 1000 )
( 1098 917 1000 )
( 1392 438 1000 ) )
( __! Surfaces !__
( 1 2 3 )
( 3 2 0 )
( 0 2 1 )
( 3 0 1 ) ) )
2.2 ~PMRegionProperty~
Describes the signature of the type constructor
*/
ListExpr PMRegionProperty() {
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("-> Data"),
nl->StringAtom(PMRegion::BasicType()),
nl->StringAtom("((<points>)(<faces>))"),
nl->StringAtom("<example too long>"),
nl->StringAtom("Type representing a polyhedral moving region")
)
)
);
}
/*
2.3 ~OutPMRegion~
Converts the ~pmregion~ into a list representation.
(See 2.1 for the definition of the list representation)
*/
ListExpr OutPMRegion(ListExpr typeInfo, Word value) {
PMRegion *pmr = (PMRegion *) value.addr;
// RList is the interal format of the libpmregion
RList rl = pmr->pmr()->toRList();
// RList2NL converts RList to a Secondo NestedList
ListExpr ret = RList2NL(rl.items[4]);
return ret;
}
/*
2.4 ~InPMRegion~
Converts a list representation of a ~pmregion~ into a PMRegion object.
(See 2.1 for the definition of the list representation)
*/
Word InPMRegion(const ListExpr typeInfo, const ListExpr instance,
const int errorPos, ListExpr& errorInfo, bool& correct) {
PMRegion *pmr = new PMRegion(true);
// Convert a Secondo NestedList to the libpmregion RList
RList rl = NL2RList(instance);
pmr->UpdateFLOBs(rl);
// Construct a native libpmregion object from the RList
correct = true;
return pmr;
}
/*
2.5 ~CreatePMRegion~
Creates an empty PMRegion instance
*/
Word CreatePMRegion(const ListExpr typeInfo) {
PMRegion* pmr = new PMRegion(true);
return SetWord(pmr);
}
/*
2.6 ~DeletePMRegion~
Deletes a PMRegion object
*/
void DeletePMRegion(const ListExpr typeInfo, Word& w) {
PMRegion* pmr = (PMRegion*) w.addr;
w.addr = 0;
delete pmr;
}
/*
2.7 ~ClosePMRegion~
Removes a PMRegion object from memory
*/
void ClosePMRegion(const ListExpr typeInfo, Word& w) {
PMRegion* pmr = (PMRegion*) w.addr;
w.addr = 0;
delete pmr;
}
/*
2.8 ~ClonePMRegion~
Creates a deep copy of a PMRegion object
*/
Word ClonePMRegion(const ListExpr typeInfo, const Word& w) {
return SetWord(((PMRegion*) w.addr)->Clone());
}
/*
2.9 ~SizeOfPMRegion~
Returns the size of a PMRegion object
*/
int SizeOfPMRegion() {
return sizeof (PMRegion);
}
/*
2.10 ~CastPMRegion~
Casts a pointer to an PMRegion object
*/
void* CastPMRegion(void* addr) {
return (new (addr) PMRegion);
}
/*
2.11 ~CheckPMRegion~
Returns ~true~ iff a type list represents an pmregion object
*/
bool CheckPMRegion(ListExpr type, ListExpr& errorInfo) {
return (nl->IsEqual(type, PMRegion::BasicType()));
}
TypeConstructor pmregion(
PMRegion::BasicType(),
PMRegionProperty,
OutPMRegion, InPMRegion,
0, 0,
CreatePMRegion, DeletePMRegion,
0, 0,
// OpenAttribute<PMRegion>, SaveAttribute<PMRegion>,
ClosePMRegion,
ClonePMRegion, CastPMRegion,
SizeOfPMRegion, CheckPMRegion
);
/*
2.12 ~Clone~
Clone this PMRegion object, i.e. creates a deep copy
*/
PMRegion* PMRegion::Clone() const {
PMRegion *pmr = new PMRegion(true);
*pmr = *this;
pmr->pmr(NULL);
return pmr;
}
/*
2.13 ~PMRegion~ constructor
Creates an empty PMRegion object
*/
PMRegion::PMRegion(bool dummy) : points(10000), faces(10000), _pmr(NULL) {
}
/*
2.14 ~PMRegion~ destructor
Destruct a PMRegion object and the underlying libpmregion object
*/
PMRegion::~PMRegion() {
if (_pmr) delete _pmr;
}
/*
3 ~Operators~
Some operators for handling ~pmregion~s
3.1 ~atinstant~
Calculates the projection of a ~pmregion~ to an ~iregion~ for a given instant.
Signature: pmregion x instant -> iregion
Example: query pmregion1 atinstant [const instant value "2000-01-01-01:00"]
3.1.1 ~Type mapping~
Maps the source types to the result type. Only one variant is supported here.
*/
ListExpr atinstanttypemap(ListExpr args) {
std::string err = "pmregion x instant expected";
int len = nl->ListLength(args);
if (len != 2) {
return listutils::typeError(err + " (wrong number of arguments)");
}
if (!PMRegion::checkType(nl->First(args))) {
return listutils::typeError(err + " (first arg wrong)");
}
if (!Instant::checkType(nl->Second(args))) {
return listutils::typeError(err + " (second arg wrong)");
}
return nl->SymbolAtom(temporalalgebra::IRegion::BasicType());
}
/*
3.1.2 ~Value mapping~
Maps a result value to the given arguments.
*/
int atinstantvalmap(Word *args, Word& result,
int message, Word& local, Supplier s) {
result = qp->ResultStorage(s);
PMRegion *pmr = static_cast<PMRegion*> (args[0].addr);
Instant *it = static_cast<Instant*> (args[1].addr);
// Convert secondo instant to ms since unix epoch
double instant = (it->ToDouble()+10959)*86400000;
cout << "Calculating atinstant" << endl;
// Calculate the projected region in libpmregion
RList region = pmr->pmr()->atinstant2(instant);
cout << "Building region..." << endl;
#if 0
// and convert the result to a Secondo nested list
ListExpr regle = RList2NL(region.items[4]);
// Create an IRegion from the result and return it
bool correct;
ListExpr errorInfo;
cout << "Calling InRegion..." << endl;
Word regp = InRegion(nl->Empty(), regle, 0, errorInfo, correct);
Region *reg = static_cast<Region*> (regp.addr);
#else
Region reg(10);
cout << "StartBulkLoad()" << endl;
reg.StartBulkLoad();
int partnerno = 0;
RList faces = region.items[4];
for (unsigned int i = 0; i < faces.items.size(); i++) {
RList cycles = faces.items[i];
for (unsigned int j = 0; j < cycles.items.size(); j++) {
vector<Point> c;
RList points = cycles.items[j];
unsigned int ps = points.items.size();
Point prev;
vector<HalfSegment> hss;
for (unsigned int k = 0; k <= ps; k++) {
RList rp = points.items[k%ps];
Point p(true, rp.items[0].getNr(), rp.items[1].getNr());
if (k > 0) {
if (AlmostEqual(prev, p))
continue;
HalfSegment hs(true, prev, p);
hs.attr.faceno = 0;
hs.attr.cycleno = 0;
hs.attr.edgeno = partnerno;
hs.attr.partnerno = partnerno;
hs.attr.insideAbove = prev < p;
hss.push_back(hs);
hs.SetLeftDomPoint(false);
hss.push_back(hs);
partnerno++;
}
prev = p;
}
if (hss.size() >= 6) {
for (unsigned int k = 0; k < hss.size(); k++) {
reg += hss[k];
}
}
}
}
cout << "EndBulkLoad()" << endl;
reg.EndBulkLoad();
#endif
cout << "Done" << endl;
result.setAddr(new temporalalgebra::IRegion(*it, reg));
return 0;
}
static const std::string atinstantspec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
" (<text>pmregion x instant -> iregion</text--->"
"<text>_ atinstant _</text--->"
"<text>Shows the pmregion at some instant</text--->"
"<text>pmregion atinstant instant1</text---> ) )";
Operator atinstant("atinstant",
atinstantspec,
atinstantvalmap,
Operator::SimpleSelect,
atinstanttypemap
);
/*
3.2 ~perimeter~
Calculates the perimeter of a ~pmregion~ to an ~mreal~ value
Signature: pmregion -> mreal
Example: query perimeter(pmregion1)
3.2.1 ~Type mapping~
Maps the source types to the result type. Only one variant is supported here.
*/
ListExpr perimetertypemap(ListExpr args) {
std::string err = "pmregion expected";
int len = nl->ListLength(args);
if (len != 1) {
return listutils::typeError(err + " (wrong number of arguments)");
}
if (!PMRegion::checkType(nl->First(args))) {
return listutils::typeError(err + " (first arg wrong)");
}
return nl->SymbolAtom(temporalalgebra::MReal::BasicType());
}
/*
3.2.2 ~Value mapping~
Maps a result value to the given arguments.
*/
int perimetervalmap(Word *args, Word& result,
int message, Word& local, Supplier s) {
result = qp->ResultStorage(s);
PMRegion *pmr = static_cast<PMRegion*> (args[0].addr);
// Calculate the perimeter in libpmregion
pmr::MReal mreal = pmr->pmr()->perimeter();
// and convert the result to a Secondo nested list
ListExpr le = RList2NL(mreal.rl.items[4]);
// Create an MReal from the result and return it
bool correct;
ListExpr errorInfo;
result = InMapping<temporalalgebra::MReal, UReal, InUReal>
(nl->Empty(), le, 0, errorInfo, correct);
return 0;
}
static const std::string perimeterspec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
" (<text>pmregion -> mreal</text--->"
"<text>perimeter ( _ )</text--->"
"<text>Calculates the perimeter of a pmregion</text--->"
"<text>perimeter pmregion</text---> ) )";
Operator perimeter("perimeter",
perimeterspec,
perimetervalmap,
Operator::SimpleSelect,
perimetertypemap
);
/*
3.3 ~area~
Calculates the area of a ~pmregion~ to an ~iregion~ for a given instant.
Signature: pmregion -> mreal
Example: query area(pmregion)
3.3.1 ~Type mapping~
Maps the source types to the result type. Only one variant is supported here.
*/
ListExpr areatypemap(ListExpr args) {
std::string err = "pmregion expected";
int len = nl->ListLength(args);
if (len != 1) {
return listutils::typeError(err + " (wrong number of arguments)");
}
if (!PMRegion::checkType(nl->First(args))) {
return listutils::typeError(err + " (first arg wrong)");
}
return nl->SymbolAtom(temporalalgebra::MReal::BasicType());
}
/*
3.3.2 ~Value mapping~
Maps a result value to the given arguments.
*/
int areavalmap(Word *args, Word& result,
int message, Word& local, Supplier s) {
result = qp->ResultStorage(s);
PMRegion *pmr = static_cast<PMRegion*> (args[0].addr);
// Calculate the area in libpmregion
pmr::MReal mreal = pmr->pmr()->area();
// and convert the result to a Secondo nested list
ListExpr le = RList2NL(mreal.rl.items[4]);
// Create an MReal from the result and return it
bool correct;
ListExpr errorInfo;
result = InMapping<temporalalgebra::MReal, UReal, InUReal>
(nl->Empty(), le, 0, errorInfo, correct);
return 0;
}
static const std::string areaspec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
" (<text>pmregion -> mreal</text--->"
"<text>perimeter ( _ )</text--->"
"<text>Calculates the area of a pmregion</text--->"
"<text>perimeter pmregion</text---> ) )";
Operator area("area",
areaspec,
areavalmap,
Operator::SimpleSelect,
areatypemap
);
/*
3.4 ~traversedarea~
Calculates the traversed area of a ~pmregion~
Signature: pmregion -> region
Example: query traversedarea(pmregion1)
3.4.1 ~Type mapping~
Maps the source types to the result type. Only one variant is supported here.
*/
ListExpr traversedareatypemap(ListExpr args) {
std::string err = "pmregion expected";
int len = nl->ListLength(args);
if (len != 1) {
return listutils::typeError(err + " (wrong number of arguments)");
}
if (!PMRegion::checkType(nl->First(args))) {
return listutils::typeError(err + " (first arg wrong)");
}
return nl->SymbolAtom(Region::BasicType());
}
/*
3.4.2 ~Value mapping~
Maps a result value to the given arguments.
*/
int traversedareavalmap(Word *args, Word& result,
int message, Word& local, Supplier s) {
result = qp->ResultStorage(s);
PMRegion *pmr = static_cast<PMRegion*> (args[0].addr);
// Calculate the traversed area in libpmregion
RList region = pmr->pmr()->traversedarea();
// and convert the result to a Secondo nested list
ListExpr le = RList2NL(region.items[4]);
// Create an region from the result and return it
bool correct;
ListExpr errorInfo;
result = InRegion(nl->Empty(), le, 0, errorInfo, correct);
return 0;
}
static const std::string traversedareaspec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
" (<text>pmregion -> region</text--->"
"<text>traversedarea ( _ )</text--->"
"<text>Calculates the traversed area of a pmregion</text--->"
"<text>traversedarea pmregion</text---> ) )";
Operator traversedarea("traversedarea",
traversedareaspec,
traversedareavalmap,
Operator::SimpleSelect,
traversedareatypemap
);
/* #if CGAL_VERSION_NR >= 1041400000 */
#ifndef PMREGION_DISABLE_COVERDURATION
/*
3.4 ~coverduration~
Calculates the coverduration of a ~pmregion~
Signature: pmregion -> pmregion
Example: query coverduration(pmregion1)
3.4.1 ~Type mapping~
Maps the source types to the result type. Only one variant is supported here.
*/
ListExpr coverdurationtypemap(ListExpr args) {
std::string err = "pmregion expected";
int len = nl->ListLength(args);
if (len != 1) {
return listutils::typeError(err + " (wrong number of arguments)");
}
if (!PMRegion::checkType(nl->First(args))) {
return listutils::typeError(err + " (first arg wrong)");
}
return nl->SymbolAtom(PMRegion::BasicType());
}
/*
3.4.2 ~Value mapping~
Maps a result value to the given arguments.
*/
int coverdurationvalmap(Word *args, Word& result,
int message, Word& local, Supplier s) {
result = qp->ResultStorage(s);
PMRegion *pmr1 = static_cast<PMRegion*> (args[0].addr);
PMRegion *pmr = new PMRegion(true);
// Calculate the coverduration in libpmregion
pmr::PMRegion tmp = pmr1->pmr()->createcdpoly();
pmr->pmr(tmp);
result = pmr;
return 0;
}
static const std::string coverdurationspec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
" (<text>pmregion -> pmregion</text--->"
"<text>coverduration ( _ )</text--->"
"<text>Calculates the coverduration of a pmregion</text--->"
"<text>coverduration pmregion</text---> ) )";
Operator coverduration("coverduration",
coverdurationspec,
coverdurationvalmap,
Operator::SimpleSelect,
coverdurationtypemap
);
#endif
/*
3.5 ~inside~
Calculates the times, when a moving point is inside the pmregion.
Signature: mpoint x pmregion -> mbool
Example: query mpoint1 inside pmregion1
3.5.1 ~Type mapping~
Maps the source types to the result type. Only one variant is supported here.
*/
ListExpr mpointinsidetypemap(ListExpr args) {
std::string err = "mpoint x pmregion expected";
int len = nl->ListLength(args);
if (len != 2) {
return listutils::typeError(err + " (wrong number of arguments)");
}
if (!temporalalgebra::MPoint::checkType(nl->First(args))) {
return listutils::typeError(err + " (first arg wrong)");
}
if (!PMRegion::checkType(nl->Second(args))) {
return listutils::typeError(err + " (second arg wrong)");
}
return nl->SymbolAtom(temporalalgebra::MBool::BasicType());
}
/*
3.5.2 ~Value mapping~
Maps a result value to the given arguments.
*/
int mpointinsidevalmap(Word *args, Word& result,
int message, Word& local, Supplier s) {
result = qp->ResultStorage(s);
RList mprl = NL2RList(OutMapping<MPoint, UPoint, OutUPoint>
(nl->Empty(), args[0])).obj("mpoint", "mpoint");
PMRegion *pmr = static_cast<PMRegion*> (args[1].addr);
// Calculate the inside operation in libpmregion
pmr::MBool mbool = pmr->pmr()->mpointinside(mprl);
// and convert the result to a Secondo nested list
ListExpr le = RList2NL(mbool.rl.items[4]);
// Create an MBool from the result and return it
bool correct;
ListExpr errorInfo;
result = InMapping<temporalalgebra::MBool, UBool,
InConstTemporalUnit<CcBool, InCcBool> >
(nl->Empty(), le, 0, errorInfo, correct);
return 0;
}
static const std::string mpointinsidespec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
" (<text>mpoint x pmregion -> region</text--->"
"<text>_ inside _</text--->"
"<text>Calculates times when mpoint is inside the pmregion</text--->"
"<text>mpoint1 inside pmregion1</text---> ) )";
Operator mpointinside("inside",
mpointinsidespec,
mpointinsidevalmap,
Operator::SimpleSelect,
mpointinsidetypemap
);
/*
3.6 ~union~
Calculates the union of two ~pmregion~s
Signature: pmregion x pmregion -> pmregion
Example: query pmregion1 union pmregion2
3.6.1 ~Type mapping~
Maps the source types to the result type. Only one variant is supported here.
*/
ListExpr uniontypemap(ListExpr args) {
std::string err = "pmregion x pmregion expected";
int len = nl->ListLength(args);
if (len != 2) {
return listutils::typeError(err + " (wrong number of arguments)");
}
if (!PMRegion::checkType(nl->First(args))) {
return listutils::typeError(err + " (first arg wrong)");
}
if (!PMRegion::checkType(nl->Second(args))) {
return listutils::typeError(err + " (second arg wrong)");
}
return nl->SymbolAtom(PMRegion::BasicType());
}
/*
3.6.2 ~Value mapping~
Maps a result value to the given arguments.
*/
int unionvalmap(Word *args, Word& result,
int message, Word& local, Supplier s) {
result = qp->ResultStorage(s);
PMRegion *pmr1 = static_cast<PMRegion*> (args[0].addr);
PMRegion *pmr2 = static_cast<PMRegion*> (args[1].addr);
// Create the result object
PMRegion *pmr = new PMRegion(true);
// Calculate the union of the two pmregions
pmr::PMRegion u = *pmr1->pmr() + *pmr2->pmr();
pmr->pmr(u);
result = pmr;
return 0;
}
static const std::string unionspec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
" (<text>pmregion x pmregion -> pmregion</text--->"
"<text>_ union _</text--->"
"<text>Calculates the union of two pmregions</text--->"
"<text>pmreg1 union pmreg2</text---> ) )";
Operator do_union("union",
unionspec,
unionvalmap,
Operator::SimpleSelect,
uniontypemap
);
/*
3.7 ~minus~
Calculates the difference of two ~pmregion~s
Signature: pmregion x pmregion -> pmregion
Example: query pmregion1 minus pmregion2
3.7.1 ~Type mapping~
Maps the source types to the result type. Only one variant is supported here.
*/
ListExpr minustypemap(ListExpr args) {
std::string err = "pmregion x pmregion expected";
int len = nl->ListLength(args);
if (len != 2) {
return listutils::typeError(err + " (wrong number of arguments)");
}
if (!PMRegion::checkType(nl->First(args))) {
return listutils::typeError(err + " (first arg wrong)");
}
if (!PMRegion::checkType(nl->Second(args))) {
return listutils::typeError(err + " (second arg wrong)");
}
return nl->SymbolAtom(PMRegion::BasicType());
}
/*
3.7.2 ~Value mapping~
Maps a result value to the given arguments.
*/
int minusvalmap(Word *args, Word& result,
int message, Word& local, Supplier s) {
result = qp->ResultStorage(s);
PMRegion *pmr1 = static_cast<PMRegion*> (args[0].addr);
PMRegion *pmr2 = static_cast<PMRegion*> (args[1].addr);
// Create the result object
PMRegion *pmr = new PMRegion(true);
// Calculate the difference of the two pmregions
pmr::PMRegion diff = *pmr1->pmr() - *pmr2->pmr();
pmr->pmr(diff);
result = pmr;
return 0;
}
static const std::string minusspec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
" (<text>pmregion x pmregion -> pmregion</text--->"
"<text>_ union _</text--->"
"<text>Calculates the difference of two pmregions</text--->"
"<text>pmreg1 minus pmreg2</text---> ) )";
Operator do_minus("minus",
minusspec,
minusvalmap,
Operator::SimpleSelect,
minustypemap
);
/*
3.8 ~intersection~
Calculates the union of two ~pmregion~s
Signature: pmregion x pmregion -> pmregion
Example: query intersection(pmregion1, pmregion2)
3.8.1 ~Type mapping~
Maps the source types to the result type. Only one variant is supported here.
*/
ListExpr intersectiontypemap(ListExpr args) {
std::string err = "pmregion x pmregion expected";
int len = nl->ListLength(args);
if (len != 2) {
return listutils::typeError(err + " (wrong number of arguments)");
}
if (!PMRegion::checkType(nl->First(args))) {
return listutils::typeError(err + " (first arg wrong)");
}
if (!PMRegion::checkType(nl->Second(args))) {
return listutils::typeError(err + " (second arg wrong)");
}
return nl->SymbolAtom(PMRegion::BasicType());
}
/*
3.8.2 ~Value mapping~
Maps a result value to the given arguments.
*/
int intersectionvalmap(Word *args, Word& result,
int message, Word& local, Supplier s) {
result = qp->ResultStorage(s);
PMRegion *pmr1 = static_cast<PMRegion*> (args[0].addr);
PMRegion *pmr2 = static_cast<PMRegion*> (args[1].addr);
// Create the result object
PMRegion *pmr = new PMRegion(true);
// Calculate the intersection of the two pmregions
pmr::PMRegion is = *pmr1->pmr() * *pmr2->pmr();
pmr->pmr(is);
result = pmr;
return 0;
}
static const std::string intersectionspec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
" (<text>pmregion x pmregion -> pmregion</text--->"
"<text>_ union _</text--->"
"<text>Calculates the intersection of two pmregions</text--->"
"<text>intersection(pmreg1, pmreg2)</text---> ) )";
Operator do_intersection("intersection",
intersectionspec,
intersectionvalmap,
Operator::SimpleSelect,
intersectiontypemap
);
/*
3.9 ~intersects~
Calculates the times, during which two ~pmregion~s intersect.
Signature: pmregion x pmregion -> mbool
Example: query pmregion1 intersects pmregion2
3.9.1 ~Type mapping~
Maps the source types to the result type. Only one variant is supported here.
*/
ListExpr intersectstypemap(ListExpr args) {
std::string err = "pmregion x pmregion expected";
int len = nl->ListLength(args);
if (len != 2) {
return listutils::typeError(err + " (wrong number of arguments)");
}
if (!PMRegion::checkType(nl->First(args))) {
return listutils::typeError(err + " (first arg wrong)");
}
if (!PMRegion::checkType(nl->Second(args))) {
return listutils::typeError(err + " (second arg wrong)");
}
return nl->SymbolAtom(temporalalgebra::MBool::BasicType());
}
/*
3.9.2 ~Value mapping~
Maps a result value to the given arguments.
*/
int intersectsvalmap(Word *args, Word& result,
int message, Word& local, Supplier s) {
result = qp->ResultStorage(s);
PMRegion *pmr1 = static_cast<PMRegion*> (args[0].addr);
PMRegion *pmr2 = static_cast<PMRegion*> (args[1].addr);
// Perform the "intersects" operation
pmr::MBool mbool = pmr1->pmr()->intersects(*(pmr2->pmr()));
// Convert the result to a Secondo nested list
ListExpr le = RList2NL(mbool.rl.items[4]);
// Create an MBool from the result
bool correct;
ListExpr errorInfo;
result = InMapping<temporalalgebra::MBool, UBool,
InConstTemporalUnit<CcBool, InCcBool> >
(nl->Empty(), le, 0, errorInfo, correct);
return 0;
}
static const std::string intersectsspec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
" (<text>pmregion x pmregion -> pmregion</text--->"
"<text>_ union _</text--->"
"<text>Calculates the intersection of two pmregions</text--->"
"<text>pmreg1 intersects pmreg2</text---> ) )";
Operator intersects("intersects",
intersectsspec,
intersectsvalmap,
Operator::SimpleSelect,
intersectstypemap
);
/*
3.10 ~pmreg2mreg~
Converts a pmregion to an mregion
Signature: pmregion -> mregion
Example: query pmreg2mreg(pmregion1)
3.10.1 ~Type mapping~
Maps the source types to the result type. Only one variant is supported here.
*/
ListExpr pmreg2mregtypemap(ListExpr args) {
std::string err = "pmregion expected";
int len = nl->ListLength(args);
if (len != 1) {
return listutils::typeError(err + " (wrong number of arguments)");
}
if (!PMRegion::checkType(nl->First(args))) {
return listutils::typeError(err + " (first arg wrong)");
}
return nl->SymbolAtom(temporalalgebra::MRegion::BasicType());
}
/*
3.10.2 ~Value mapping~
Maps a result value to the given arguments.
*/
int pmreg2mregvalmap(Word *args, Word& result,
int message, Word& local, Supplier s) {
result = qp->ResultStorage(s);
PMRegion *pmr = static_cast<PMRegion*> (args[0].addr);
// Perform the conversion to an mregion
RList mregion = pmr->pmr()->toMRegion2();
// Create a Secondo nested list from the result
ListExpr le = RList2NL(mregion.items[4]);
// Create an mregion object from the nested list
bool correct;
ListExpr errorInfo;
result = InMRegion(nl->Empty(), le, 0, errorInfo, correct);
return 0;
}
static const std::string pmreg2mregspec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
" (<text>pmregion -> mregion</text--->"
"<text>pmreg2mreg(_)</text--->"
"<text>Converts a pmregion to an mregion</text--->"
"<text>pmreg2mreg(pmreg1)</text---> ) )";
Operator pmreg2mreg("pmreg2mreg",
pmreg2mregspec,
pmreg2mregvalmap,
Operator::SimpleSelect,
pmreg2mregtypemap
);
/*
3.11 ~mreg2pmreg~
Converts an mregion to a pmregion
Signature: mregion -> pmregion
Example: query mreg2pmreg(pmregion1)
3.11.1 ~Type mapping~
Maps the source types to the result type. Only one variant is supported here.
*/
ListExpr mreg2pmregtypemap(ListExpr args) {
std::string err = "mregion expected";
int len = nl->ListLength(args);
if (len != 1) {
return listutils::typeError(err + " (wrong number of arguments)");
}
if (!temporalalgebra::MRegion::checkType(nl->First(args))) {
return listutils::typeError(err + " (first arg wrong)");
}
return nl->SymbolAtom(PMRegion::BasicType());
}
/*
3.11.2 ~Value mapping~
Maps a result value to the given arguments.
*/
int mreg2pmregvalmap(Word *args, Word& result,
int message, Word& local, Supplier s) {
result = qp->ResultStorage(s);
MRegion *mr = static_cast<MRegion*> (args[0].addr);
// Convert the mregion object to a libpmregion RList
RList mregion = NL2RList(OutMRegion(nl->Empty(), mr));
// Create the result object
PMRegion *pmr = new PMRegion(true);
// Create a pmregion from the mregion
pmr::PMRegion c = pmr::PMRegion::fromMRegion(
mregion.obj("mregion", "mregion"));
pmr->pmr(c);
result = pmr;
return 0;
}
static const std::string mreg2pmregspec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
" (<text>mregion -> pmregion</text--->"
"<text>mreg2pmreg(_)</text--->"
"<text>Converts an mregion to a pmregion</text--->"
"<text>mreg2pmreg(mreg1)</text---> ) )";
Operator mreg2pmreg("mreg2pmreg",
mreg2pmregspec,
mreg2pmregvalmap,
Operator::SimpleSelect,
mreg2pmregtypemap
);
/*
3.12 ~translate~
Translates a pmregion
Signature: pmregion x real x real x real -> pmregion
Example: query pmregion1 translate [100,100,0]
3.11.1 ~Type mapping~
Maps the source types to the result type. Only one variant is supported here.
*/
ListExpr translatetypemap(ListExpr args) {
std::string err = "mregion expected";
int len = nl->ListLength(args);
if (len != 2) {
return listutils::typeError(err + " (wrong number of arguments)");
}
if (!PMRegion::checkType(nl->First(args))) {
return listutils::typeError(err + " (first arg wrong)");
}
ListExpr coords = nl->Second(args);
if (nl->ListLength(coords) != 3) {
return listutils::typeError(err + " (need three coordinates)");
}
if (!nl->IsEqual(nl->First(coords), CcReal::BasicType()) ||
!nl->IsEqual(nl->Second(coords), CcReal::BasicType()) ||
!nl->IsEqual(nl->Third(coords), CcReal::BasicType())) {
return listutils::typeError(err + " (wrong type of coordinates)");
}
return nl->SymbolAtom(PMRegion::BasicType());
}
/*
3.11.2 ~Value mapping~
Maps a result value to the given arguments.
*/
int translatevalmap(Word *args, Word& result,
int message, Word& local, Supplier s) {
result = qp->ResultStorage(s);
PMRegion *pmr = static_cast<PMRegion*> (args[0].addr);
Word t;
Supplier son = qp->GetSupplier( args[1].addr, 0 );
qp->Request( son, t );
const CcReal *tx = ((CcReal *)t.addr);
son = qp->GetSupplier( args[1].addr, 1 );
qp->Request( son, t );
const CcReal *ty = ((CcReal *)t.addr);
son = qp->GetSupplier( args[1].addr, 2 );
qp->Request( son, t );
const CcReal *tz = ((CcReal *)t.addr);
// Create the result object
PMRegion *pmr2 = new PMRegion(true);
pmr::PMRegion *pmt = new pmr::PMRegion();
*pmt = *pmr->pmr();
pmt->translate(tx->GetRealval(),
ty->GetRealval(),
tz->GetRealval());
pmr2->pmr(pmt);
result = pmr2;
return 0;
}
static const std::string translatespec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
" (<text>pmregion x real x real x real -> pmregion</text--->"
"<text>_ translate [ _, _, _ ]</text--->"
"<text>translate the object by the given vector.</text--->"
"<text>query pmregion1 translate [100, 200, 0]</text--->"
") )";
Operator translate("translate",
translatespec,
translatevalmap,
Operator::SimpleSelect,
translatetypemap
);
/*
4 ~PMRegionAlgebra~
Instantiation of the FixedMRegionAlgebra.
Adds the types ~pmregion~
Adds the operators ~atinstant~, ~perimeter~, ~area~, ~traversedarea~
~inside~, ~union~, ~minus~, ~intersection~, ~intersects~
~pmreg2mreg~ and ~mreg2pmreg~
*/
PMRegionAlgebra::PMRegionAlgebra() : Algebra() {
AddTypeConstructor(&pmregion);
// pmregion.AssociateKind(Kind::SPATIAL3D());
pmregion.AssociateKind(Kind::DATA());
AddOperator(&atinstant);
AddOperator(&translate);
AddOperator(&perimeter);
AddOperator(&area);
AddOperator(&traversedarea);
AddOperator(&mpointinside);
AddOperator(&do_union);
AddOperator(&do_minus);
AddOperator(&do_intersection);
AddOperator(&intersects);
AddOperator(&pmreg2mreg);
AddOperator(&mreg2pmreg);
#if CGAL_VERSION_NR >= 1041400000
AddOperator(&coverduration);
#endif
}
extern "C"
Algebra *
InitializePMRegionAlgebra(NestedList *nlRef, QueryProcessor *qpRef) {
nl = nlRef;
qp = qpRef;
return new PMRegionAlgebra();
}
}
/*
5 Conversion functions
These functions convert between Secondo NestedLists and libpmregion RLists.
Supported types are: List, String, Double, Bool and Symbol, which are all
existing RList types. NestedList Integers are converted to double.
Unknown types are dropped.
5.1 ~RList2NL~
Convert a libpmregion RList to a Secondo NestedList.
*/
ListExpr RList2NL(RList r) {
ListExpr ret = nl->Empty();
ListExpr cur = ret;
switch (r.getType()) {
case NL_LIST:
for (unsigned int i = 0; i < r.items.size(); i++) {
if (i == 0)
ret = cur = nl->OneElemList(RList2NL(r.items[i]));
else
cur = nl->Append(cur, RList2NL(r.items[i]));
}
break;
case NL_STRING:
ret = nl->StringAtom(r.getString());
break;
case NL_DOUBLE:
ret = nl->RealAtom(r.getNr());
break;
case NL_FT:
ret = nl->RealAtom(r.getNr());
break;
case NL_BOOL:
ret = nl->BoolAtom(r.getBool());
break;
case NL_SYM:
ret = nl->SymbolAtom(r.getSym());
break;
}
return ret;
}
/*
5.2 ~NL2RList~
Convert a Secondo NestedList to a libpmregion RList.
*/
RList NL2RList(ListExpr l) {
RList ret;
while (l != nl->Empty()) {
ListExpr i = nl->First(l);
if (nl->IsNodeType(NoAtom, i)) {
ret.append(NL2RList(i));
} else if (nl->IsNodeType(IntType, i)) {
// Convert integer to double, since there is no separate
// RList type for it
ret.append(Kernel::FT((double)nl->IntValue(i)));
} else if (nl->IsNodeType(RealType, i)) {
ret.append(Kernel::FT(nl->RealValue(i)));
} else if (nl->IsNodeType(BoolType, i)) {
ret.append(nl->BoolValue(i));
} else if (nl->IsNodeType(StringType, i)) {
ret.append(nl->StringValue(i));
} else if (nl->IsNodeType(SymbolType, i)) {
ret.appendsym(nl->SymbolValue(i));
}
l = nl->Rest(l);
}
return ret;
}
void pmregion::PMRegion::UpdateFLOBs() {
RList rl = pmr()->toRList().items[4];
UpdateFLOBs(rl);
}
void pmregion::PMRegion::UpdateFLOBs(RList& _rl) {
RList rl = _rl.items[0];
points.clean();
points.resize(rl.items.size());
for (unsigned int j = 0; j < rl.items.size(); j++) {
RList point = rl.items[j];
PMPoint p(point.items[0].getNr(),
point.items[1].getNr(),
point.items[2].getNr());
points.Append(p);
}
rl = _rl.items[1];
faces.clean();
faces.resize(rl.items.size());
for (unsigned int j = 0; j < rl.items.size(); j++) {
RList face = rl.items[j];
PMFace f(face.items[0].getNr(),
face.items[1].getNr(),
face.items[2].getNr());
faces.Append(f);
}
}
pmr::PMRegion* pmregion::PMRegion::pmr() {
if (_pmr == NULL) {
RList rpoints, rfaces;
for (int i = 0; i < points.Size(); i++) {
RList point;
PMPoint p(0, 0, 0);
points.Get(i, p);
point.append(p.x);
point.append(p.y);
point.append(p.z);
rpoints.append(point);
}
for (int i = 0; i < faces.Size(); i++) {
RList face;
PMFace p(0, 0, 0);
faces.Get(i, p);
face.append((double)p.p1);
face.append((double)p.p2);
face.append((double)p.p3);
rfaces.append(face);
}
RList pmrlist;
pmrlist.append(rpoints);
pmrlist.append(rfaces);
_pmr = new pmr::PMRegion();
RList tmp2 = pmrlist.obj("pmregion", "pmregion");
*_pmr = pmr::PMRegion::fromRList(tmp2);
}
return _pmr;
}
Flob *pmregion::PMRegion::GetFLOB(const int i) {
if (i == 0) {
return &points;
} else if (i == 1) {
return &faces;
}
return NULL;
}