Files
secondo/Algebras/RegionInterpolation2/RegionInterpolation2Algebra.cpp

230 lines
6.6 KiB
C++
Raw Normal View History

2026-01-23 17:03:45 +08:00
/*
1 RegionInterpolation2Algebra
Specifies a new Secondo-algebra for interpolating two regions.
This algebra defines a new operator ~interpolate2~, which takes two regions
and instants and interpolates an mregion from them.
*/
#include "Algebra.h"
#include "Algebras/MovingRegion/MovingRegionAlgebra.h"
#include <librip/include/librip.h>
namespace temporalalgebra{
// InMRegion is defined in the MovingRegionAlgebra and converts a NestedList-
// expression to an mregion
Word InMRegion(const ListExpr typeInfo,
const ListExpr instance,
const int errorPos,
ListExpr& errorInfo,
bool& correct);
}
using namespace temporalalgebra;
static const std::string interpolate2spec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
" (<text>region x instant x region x instant [ x string ] -> mregion</text--->"
"<text>interpolate2( _ , _ , _ , _ [ , _ ] )</text--->"
"<text>Interpolates two regions to a moving region. The optional "
"string argument determines the matching strategy. Possible values are:\n "
"overlap \n distance \n null \n simple \n mw \n lowerleft \n "
"If the RegionInterpolation2Algebra is compiled without lua support, "
" overlap will be the default strategy. Otherwise a specialized 'lua' "
"strategy is used."
"</text--->"
"<text>interpolate2( region1, instant1, region2, instant2, args )</text--->) )";
static ListExpr Rl2ListExpr (RList l);
static RList ListExpr2Rl (ListExpr l);
// Configure the fallbacks with their arguments here, in case the interpolation
// failed for some reason.
std::string fallbacks[] = {
"mw",
"null",
"FALLBACK"
};
#define nrfallbacks (sizeof(fallbacks)/sizeof(fallbacks[0]))
/*
1.1 interpolate2typemap checks, if the number and type of arguments is
correct. The function takes exactly two region-objects and two instants and
an optional parameter-string.
*/
ListExpr interpolate2typemap(ListExpr args) {
std::string err = "region x instant x region x instant [x string] expected";
int len = nl->ListLength(args);
if ((len != 4) && (len != 5)) {
return listutils::typeError(err + " (wrong number of arguments)");
}
if (!Region::checkType(nl->First(args))) {
return listutils::typeError(err);
}
if (!Instant::checkType(nl->Second(args))) {
return listutils::typeError(err);
}
if (!Region::checkType(nl->Third(args))) {
return listutils::typeError(err);
}
if (!Instant::checkType(nl->Fourth(args))) {
return listutils::typeError(err);
}
if (len == 4) { // By default, the parameter string is empty
return nl->ThreeElemList(nl->SymbolAtom(Symbol::APPEND()),
nl->OneElemList(nl->StringAtom("", true)),
nl->SymbolAtom(MRegion::BasicType()));
}
if (!CcString::checkType(nl->Fifth(args))) {
return listutils::typeError(err);
}
return nl->SymbolAtom(MRegion::BasicType());
}
/*
1.2 interpolate2valmap is the interface to the Secondo-Algebra
RegionInterpolation2Algebra and called for the database function interpolate2.
The result is an mregion.
*/
int interpolate2valmap(Word* args,
Word& result,
int message,
Word& local,
Supplier s) {
result = qp->ResultStorage(s);
Instant* ti1 = static_cast<Instant*> (args[1].addr);
Instant* ti2 = static_cast<Instant*> (args[3].addr);
CcString* arg = static_cast<CcString*> (args[4].addr);
Interval<Instant> iv(*ti1, *ti2, true, true);
// We create the Face-objects from the RList-representation of the
// regions, this interface seems most stable.
ListExpr _sregs = OutRegion(nl->Empty(), args[0]);
ListExpr _dregs = OutRegion(nl->Empty(), args[2]);
RList sr = ListExpr2Rl(_sregs);
RList dr = ListExpr2Rl(_dregs);
// Create the interpolation from the lists of faces
RList res = regioninterpolate(sr, dr, ti1->ToString(),
ti2->ToString(), arg->GetValue());
bool correct = false;
ListExpr err;
Word w = InMRegion(nl->Empty(), Rl2ListExpr(res), 0, err, correct);
for (unsigned int i = 0; !correct && (i < nrfallbacks); i++) {
// Import failed, try the configured fallbacks...
RList res = regioninterpolate(sr, dr, ti1->ToString(),
ti2->ToString(), fallbacks[i]);
w = InMRegion(nl->Empty(), Rl2ListExpr(res), 0, err, correct);
}
if (correct)
result.setAddr(w.addr);
else {
// Yield an error message here.
ErrorReporter::ReportError("interpolate2 internal error");
MRegion *res = new MRegion(0);
result.setAddr(res);
}
return 0;
}
Operator interpolate2("interpolate2",
interpolate2spec,
interpolate2valmap,
Operator::SimpleSelect,
interpolate2typemap);
class RegionInterpolation2Algebra : public Algebra {
public:
RegionInterpolation2Algebra() : Algebra() {
AddOperator(&interpolate2);
}
~RegionInterpolation2Algebra() {}
};
extern "C"
Algebra* InitializeRegionInterpolation2Algebra(NestedList* nlRef,
QueryProcessor *qpRef) {
nl = nlRef;
qp = qpRef;
return new RegionInterpolation2Algebra();
}
/* Functions to convert Secondo-NestedLists to librip-RLists and vice-versa */
static RList ListExpr2Rl (ListExpr le) {
RList r;
while (le != nl->Empty()) {
ListExpr l = nl->First(le);
if (nl->IsAtom(l)) {
if (nl->AtomType(l) == IntType) {
r.append((double)nl->IntValue(l));
} else if (nl->AtomType(l) == RealType) {
r.append((double)nl->RealValue(l));
} else if (nl->AtomType(l) == StringType) {
r.append(nl->StringValue(l));
} else if (nl->AtomType(l) == BoolType) {
r.append(nl->BoolValue(l));
} else {
r.append("UNDEF");
}
} else {
r.append(ListExpr2Rl(l));
}
le = nl->Rest(le);
}
return r;
}
// Helper function, which appends a list-item to the end of a list.
static void Append(ListExpr &head, ListExpr l) {
if (l == nl->Empty())
return;
if (head == nl->Empty()) {
head = nl->OneElemList(l);
} else {
nl->Append(nl->End(head), l);
}
}
static ListExpr Rl2ListExpr (RList l) {
ListExpr r = nl->Empty();
for (unsigned int i = 0; i < l.items.size(); i++) {
if (l.items[i].getType() == NL_DOUBLE) {
Append(r, nl->RealAtom(l.items[i].getNr()));
} else if (l.items[i].getType() == NL_STRING) {
Append(r, nl->StringAtom(l.items[i].getString()));
} else if (l.items[i].getType() == NL_BOOL) {
Append(r, nl->BoolAtom(l.items[i].getBool()));
} else {
Append(r, Rl2ListExpr(l.items[i]));
}
}
return r;
}