9943 lines
286 KiB
C++
9943 lines
286 KiB
C++
|
|
/*
|
||
|
|
|
||
|
|
//paragraph [1] Title: [{\Large \bf \begin {center}] [\end {center}}]
|
||
|
|
//[TOC] [\tableofcontents]
|
||
|
|
//[ue] [\"u]
|
||
|
|
//[ae] [\"a]
|
||
|
|
//[oe] [\"o]
|
||
|
|
|
||
|
|
\setcounter{tocdepth}{4}
|
||
|
|
|
||
|
|
[1] The ~MovingRegionAlgebra~
|
||
|
|
|
||
|
|
December 2005, initial version created by Holger M[ue]nx for bachelor
|
||
|
|
thesis with Prof. Dr. G[ue]ting, Fachbereich Informatik,
|
||
|
|
Fernuniversit[ae]t Hagen.
|
||
|
|
|
||
|
|
December 2005, Victor Almeida deleted the deprecated algebra levels
|
||
|
|
(~executable~, ~descriptive~, and ~hibrid~). Only the executable
|
||
|
|
level remains. Models are also removed from type constructors.
|
||
|
|
|
||
|
|
January-June 2006, various bugfixes and improvements by Holger M[ue]nx,
|
||
|
|
with the help of Victor Almeida and Thomas Behr.
|
||
|
|
|
||
|
|
November 2006, Christian D[ue]ntgen added operator ~units~.
|
||
|
|
To this end, an additional creator for URegion and assignment operators
|
||
|
|
have been intoduced.
|
||
|
|
|
||
|
|
[TOC]
|
||
|
|
|
||
|
|
1 Introduction
|
||
|
|
|
||
|
|
The ~MovingRegionAlgebra~ provides datatypes and operators relating to
|
||
|
|
moving regions.
|
||
|
|
|
||
|
|
To keep the ~TemporalAlgebra~ stable during development, the
|
||
|
|
~MovingRegionAlgebra~ has been developed as an ~independent~ algebra. Once
|
||
|
|
it is sufficiently stable, it is planned to merge its code into the
|
||
|
|
~TemporalAlgebra~. Due to the deadline of the bachelor's thesis and the
|
||
|
|
complexity of the ~MovingRegionAlgebra~, the current version should be
|
||
|
|
considered as prototype or proof of concept only, and needs to be finalised
|
||
|
|
before production usage.
|
||
|
|
|
||
|
|
The class definitions of ~MSegmentData~,
|
||
|
|
~TrapeziumSegmentIntersection~, ~RefinementPartition~,
|
||
|
|
~URegion~ and ~MRegion~, which
|
||
|
|
are implemented in ~MovingRegionAlgebra.cpp~, have been moved to
|
||
|
|
the header file ~MovingRegionAlgebra.h~ to facilitate development work on
|
||
|
|
top of the ~MovingRegionAlgebra~ without modifying the ~MovingRegionAlgebra~
|
||
|
|
itself. This file contains detailed descriptions for the usage of the methods
|
||
|
|
of these classes too.
|
||
|
|
|
||
|
|
The MovingRegionAlgebra has been developed for the bachelor thesis of
|
||
|
|
Holger M[ue]nx together with Prof. Dr. G[ue]ting, Fachbereich Informatik,
|
||
|
|
Fernuniversit[ae]t Hagen.
|
||
|
|
|
||
|
|
1 Known bugs, issues and missing features
|
||
|
|
|
||
|
|
Open:
|
||
|
|
|
||
|
|
* Bug: List representation checks incorrect for
|
||
|
|
~(update mv := ((mregion)((0.0 0.0 true true)(0.0 0.0 1.0 1.0))));~.
|
||
|
|
Aleksej Struk found this issue.
|
||
|
|
|
||
|
|
Update: Debug output at the beginning on ~InMRegion()~ indicated that
|
||
|
|
this problem actually occurs before ~InMRegion()~ is called. The problem
|
||
|
|
is not caused by the ~MovingRegionAlgebra~.
|
||
|
|
|
||
|
|
* Feature: Calculations with values of datatype $Instant$ are done with
|
||
|
|
double precision only and not with the datatypes own calculation
|
||
|
|
operations.
|
||
|
|
|
||
|
|
* Feature: Operator ~traversed~ is not yet implemented. All code which
|
||
|
|
has been prepared for this operator so far is enclosed with
|
||
|
|
~\#ifdef MRA\_TRAVERSED ... \#endif // MRA\_TRAVERSED~.
|
||
|
|
|
||
|
|
* Feature: Debug bug output is very verbose. Due to its verbosity, it
|
||
|
|
has impact on the algebra's performance, when enabled. It would be useful
|
||
|
|
to have different debug levels.
|
||
|
|
|
||
|
|
Closed:
|
||
|
|
|
||
|
|
* Bug: Lets consider two units ~up~ of type ~upoint~ and ~ur~ of type
|
||
|
|
~uregion~ with the same interval. If ~val(initial(up))~ is within
|
||
|
|
~val(initial(ur))~ and ~val(initial(up))~ is not within
|
||
|
|
~val(final(ur))~, the operators ~intersection~ and ~inside~ correctly
|
||
|
|
recognize the intersection with the edge of the region but do not
|
||
|
|
correctly calculate the intervals when the point is within and outside
|
||
|
|
the region. If ~val(initial(up))~ is within ~val(final(ur))~, everything
|
||
|
|
works. Please note that this bug is causing two failed unit tests.
|
||
|
|
|
||
|
|
Resolved: Simplifying ~URegion::RestrictedIntersectionFindNormal()~
|
||
|
|
fixed the issue.
|
||
|
|
|
||
|
|
* Bug: The ~URegion~ constructor, which constructs the instance from a
|
||
|
|
~Region~ instance, does not work properly if the region contains half
|
||
|
|
segments, where the two end points have been swapped during half segment
|
||
|
|
created. J[ue]rgen Schmidt spotted this problem.
|
||
|
|
|
||
|
|
Resolved: Half segments with swapped end points are now being correctly
|
||
|
|
handled.
|
||
|
|
|
||
|
|
* Bug: There is a number of assertions, which can be triggered by input
|
||
|
|
data. This is caused by rounding errors, which render assumptions
|
||
|
|
verified before inapplicable later.
|
||
|
|
|
||
|
|
Resolved: Failed asserts replaced by proper error handling. Additionally,
|
||
|
|
some method stubs have been replaced by proper code. If the remaining
|
||
|
|
asserts fail, this will be caused by bugs in the algebra logic or by
|
||
|
|
calls to non-implemented functions or methods, where stubs had to be
|
||
|
|
provided.
|
||
|
|
|
||
|
|
* Bug: J[oe]rg Schmidt thinks there is an issue in the
|
||
|
|
generation of the refinement partition if two intervals start or
|
||
|
|
end at the same instant.
|
||
|
|
|
||
|
|
Resolved: Bugfix implemented, storing end instant of previously
|
||
|
|
created interval was incorrect.
|
||
|
|
|
||
|
|
* Bug: Sorting units at the beginning of RefinementPartition() is missing.
|
||
|
|
Constructor only works if units appear in ~mr~ and ~mp~ in proper order!
|
||
|
|
|
||
|
|
Rejected: ~InMRegion()~ and ~InMapping()~ sort units by using the
|
||
|
|
~StartBulkLoad()~ and ~EndBulkLoad()~ methods (the latter with parameter
|
||
|
|
~true~, of course).
|
||
|
|
|
||
|
|
* Bug: ~initial~ and ~final~ resulting in failed ~assert()~ when unit's
|
||
|
|
interval is open in the respective instant.
|
||
|
|
|
||
|
|
Resolved: Added the required checks.
|
||
|
|
|
||
|
|
* Bug: Objects created in the server version of SECONDO are not
|
||
|
|
compatible with the stand-alone version of SECONDO (and vice versa).
|
||
|
|
|
||
|
|
Resolved: Replaced weird implementation of ~OpenMRegion()~ and
|
||
|
|
~SaveMRegion()~ with code based on functions ~Open()~ and ~Save()~
|
||
|
|
from ~Attribute~. Thomas Behr contributed this valuable hint!
|
||
|
|
|
||
|
|
* Bug: ~URegion::AddSegment()~ checks for moving segment intersections
|
||
|
|
outside current region unit, which is incorrect.
|
||
|
|
|
||
|
|
Resolved: Offset ~segmentsStartPos~ in ~URegion::AddSegment()~ was
|
||
|
|
missing.
|
||
|
|
|
||
|
|
* Bug: Awkward memory leak at the end of ~URegion::TemporalFunction()~.
|
||
|
|
|
||
|
|
Resolved: Freeing memory now. Resulting code may not be compatible
|
||
|
|
with other compilers than gcc.
|
||
|
|
|
||
|
|
* Bug: References to ~URegion~ and ~UPoint~ instead of ~Unit1~ and ~Unit2~
|
||
|
|
in ~RefinementPartition()~. Victor Almeida found this one!
|
||
|
|
|
||
|
|
Resolved: Replaced references.
|
||
|
|
|
||
|
|
* Bug: ~iregion~ object creation via ~const iregion
|
||
|
|
value ...~ results in a failed assertion.
|
||
|
|
|
||
|
|
Resolved: Various modifications outside the MovingRegionAlgebra fixed
|
||
|
|
this without any modifications required for the MovingRegionAlgebra
|
||
|
|
itself.
|
||
|
|
|
||
|
|
* Bug: Rounding issues have been observed and could be traced back to the
|
||
|
|
value of constant ~eps~ in section \ref{defines}.
|
||
|
|
|
||
|
|
Resolved: Implemented operator ~mraprec~ which allows to set precision
|
||
|
|
without re-compiling the algreba.
|
||
|
|
|
||
|
|
* Bug: ~MRegion~ objects cannot be imported into SECONDO according
|
||
|
|
to Thomas Behr.
|
||
|
|
|
||
|
|
Resolved: Implemented operator ~mraprec~ which allows to set precision
|
||
|
|
without re-compiling the algreba.
|
||
|
|
|
||
|
|
1 Unit testing
|
||
|
|
|
||
|
|
To facilitate automated unit testing, a large number of test cases is provided
|
||
|
|
together with a ~Makefile~ to execute them. These are located in the directory
|
||
|
|
~Tests~. See the file ~Tests/README~ on running the test cases.
|
||
|
|
|
||
|
|
Special SECONDO operators have been implemented to make internal
|
||
|
|
functionality of the ~MovingRegionAlgebra~ available for unit testing.
|
||
|
|
These operators are included in the list of test cases below.
|
||
|
|
|
||
|
|
Please note that you have to compile this algebra with the ~MRA\_UNITTEST~
|
||
|
|
symbol defined so that the specific unit testing operators are available.
|
||
|
|
Even though this is rendering unit testing slightly more complicated,
|
||
|
|
this approach has been chosen to avoid puzzling users with operators, which
|
||
|
|
are not required for the production version of this algebra. The best place
|
||
|
|
to define this symbol is the ~makefile~, where the proper preparations have
|
||
|
|
been already done at the head of the file.
|
||
|
|
|
||
|
|
The following groups of test cases are available:
|
||
|
|
|
||
|
|
* ~Tests/trapeziumintersection.tests~: Checks the functions to calculate
|
||
|
|
the intersection of two trapeziums. These functions are required to
|
||
|
|
check the segments of moving regions for validity. The special operator
|
||
|
|
~unittest1~ allows unit testing to directly access these functions.
|
||
|
|
|
||
|
|
* ~Tests/insideabove.tests~: Verifies the ~insideAbove~ attribute of
|
||
|
|
segments in moving regions. The special operator ~unittest2~ provides
|
||
|
|
direct access to the value of this attribute for a specific segment.
|
||
|
|
|
||
|
|
* ~Tests/refinementpartition.tests~: Assures that the calculation of
|
||
|
|
refinement partitions is correct. The special operator ~unittest3~
|
||
|
|
provides the refinement partition of two ~mpoint~ values.
|
||
|
|
|
||
|
|
* ~Tests/basic.tests~: Checks operators ~bbox~, ~inst~, ~val~, ~deftime~
|
||
|
|
and present.
|
||
|
|
|
||
|
|
* ~Tests/atinstant.tests~: Checks operators ~atinstant~, ~initial~ and
|
||
|
|
~final~.
|
||
|
|
|
||
|
|
* ~Tests/intersection.tests~: Checks operators ~intersection~, ~inside~
|
||
|
|
and ~at~.
|
||
|
|
|
||
|
|
* ~Tests/relation.tests~: Checks moving regions as tuple attributes of
|
||
|
|
relations.
|
||
|
|
|
||
|
|
1 Defines and includes
|
||
|
|
\label{defines}
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
#include <string.h>
|
||
|
|
#include <queue>
|
||
|
|
#include <stdexcept>
|
||
|
|
|
||
|
|
#include "Algebra.h"
|
||
|
|
#include "NestedList.h"
|
||
|
|
#include "QueryProcessor.h"
|
||
|
|
#include "StandardTypes.h"
|
||
|
|
#include "Algebras/Temporal/TemporalAlgebra.h"
|
||
|
|
#include "MovingRegionAlgebra.h"
|
||
|
|
#include "DateTime.h"
|
||
|
|
#include "Symbols.h"
|
||
|
|
|
||
|
|
extern NestedList* nl;
|
||
|
|
extern QueryProcessor* qp;
|
||
|
|
|
||
|
|
|
||
|
|
using namespace std;
|
||
|
|
using namespace datetime;
|
||
|
|
namespace temporalalgebra{
|
||
|
|
|
||
|
|
/*
|
||
|
|
Set ~MRA\_DEBUG~ to ~true~ for debug output. Please note that debug output is
|
||
|
|
very verbose and has significant negative input on the algebra's performance.
|
||
|
|
Only enable debug output if you know what you are doing!
|
||
|
|
|
||
|
|
*/
|
||
|
|
const bool MRA_DEBUG = false;
|
||
|
|
|
||
|
|
#define SWITCH_OFF_TRAPEZIUM_INTERSECTS
|
||
|
|
|
||
|
|
|
||
|
|
//const bool MRA_DEBUG = true;
|
||
|
|
|
||
|
|
//#define MRA_TRACE cerr << __PRETTY_FUNCTION__ << " called " << endl;
|
||
|
|
#define MRA_TRACE
|
||
|
|
|
||
|
|
|
||
|
|
/*
|
||
|
|
Two floating point numbers are considered equal if their difference is
|
||
|
|
less than the constant ~eps~.
|
||
|
|
|
||
|
|
Please note that issues have been observed with both too large and too small
|
||
|
|
values of ~eps~. Prof. Dr. G[ue]ting reported an example with incorrect
|
||
|
|
behaviour of operator ~at~ for the value $0.00001$. Thomas Behr reported that
|
||
|
|
correct moving regions have been rejected for value $0.00000001$.
|
||
|
|
|
||
|
|
The operator ~mraprec~ can be used to set ~eps~, ie. to adjust the
|
||
|
|
precision of double
|
||
|
|
comparisons. Please note that the symbol ~MRA\_PREC~ has to be defined to
|
||
|
|
include this operator in the algebra. The best place to do this is the
|
||
|
|
~makefile~, and this has been already prepared at the top of the file.
|
||
|
|
|
||
|
|
A special behaviour has been implemented for the check whether a moving
|
||
|
|
segment is collinear with itself in its initial and ifnal instant (see
|
||
|
|
section \ref{collinear}. Since this check is very prone to rounding errors,
|
||
|
|
the additional constant ~epsRelaxFactor~ has been introduced. During this
|
||
|
|
check, two floating point numbers are considered equal if their difference
|
||
|
|
is less than the constant $eps\cdot\ epsRelaxFactor$. ~epsRelaxFactor~
|
||
|
|
can be set with the operator ~mraprec~ too.
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
//const double eps = 0.0001;
|
||
|
|
//const double eps = 0.00000001;
|
||
|
|
double eps = 0.00001;
|
||
|
|
double epsRelaxFactor = 10;
|
||
|
|
//double epsRelaxFactor = 1000;
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
/*
|
||
|
|
1 Helper functions
|
||
|
|
|
||
|
|
1.1 Function ~simpleSelect()~
|
||
|
|
|
||
|
|
Simple selection function for non-overloaded operators.
|
||
|
|
|
||
|
|
*/
|
||
|
|
static int simpleSelect(ListExpr args) {
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1 Comparison functions for ~double~
|
||
|
|
|
||
|
|
To avoid rounding issues, comparisons for equality are done using constant
|
||
|
|
~eps~.
|
||
|
|
|
||
|
|
1.1.1 Function ~nearlyEqual()~
|
||
|
|
|
||
|
|
Returns ~true~ if $-eps \le a-b \le eps$.
|
||
|
|
|
||
|
|
*/
|
||
|
|
static bool nearlyEqual(double a, double b) {
|
||
|
|
return abs(a-b) <= eps;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1 Function ~lowerOrNearlyEqual()~
|
||
|
|
|
||
|
|
Returns ~true~ if $a \le b+eps$.
|
||
|
|
|
||
|
|
*/
|
||
|
|
static bool lowerOrNearlyEqual(double a, double b) {
|
||
|
|
return a < b || nearlyEqual(a, b);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1 Function ~lower()~
|
||
|
|
|
||
|
|
Returns ~true~ if $a < b-eps$.
|
||
|
|
|
||
|
|
*/
|
||
|
|
static bool lower(double a, double b) {
|
||
|
|
return a < b-eps;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1 Function ~greaterOrNearlyEqual()~
|
||
|
|
|
||
|
|
Returns ~true~ if $a \ge b-eps$.
|
||
|
|
|
||
|
|
*/
|
||
|
|
static bool greaterOrNearlyEqual(double a, double b) {
|
||
|
|
return a > b || nearlyEqual(a, b);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1 Function ~between()~
|
||
|
|
|
||
|
|
Returns ~true~ if $a-eps \le x \le b+eps$ or $b-eps \le x \le a+eps$.
|
||
|
|
|
||
|
|
*/
|
||
|
|
static bool between(double a, double x, double b) {
|
||
|
|
return
|
||
|
|
(lowerOrNearlyEqual(a, x) && lowerOrNearlyEqual(x, b))
|
||
|
|
|| (lowerOrNearlyEqual(b, x) && lowerOrNearlyEqual(x, a));
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1 Function ~minmax4()~
|
||
|
|
|
||
|
|
Returns the minimum and maximum value of $a$, $b$, $c$ and $d$ in $min$
|
||
|
|
and $max$.
|
||
|
|
|
||
|
|
*/
|
||
|
|
static void minmax4(double a,
|
||
|
|
double b,
|
||
|
|
double c,
|
||
|
|
double d,
|
||
|
|
double& min,
|
||
|
|
double& max) {
|
||
|
|
if (MRA_DEBUG) cerr << "minmax4() called" << endl;
|
||
|
|
|
||
|
|
min = a;
|
||
|
|
max = a;
|
||
|
|
|
||
|
|
if (b < min) min = b;
|
||
|
|
if (b > max) max = b;
|
||
|
|
if (c < min) min = c;
|
||
|
|
if (c > max) max = c;
|
||
|
|
if (d < min) min = d;
|
||
|
|
if (d > max) max = d;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1 Mathematical and geometrical functions
|
||
|
|
|
||
|
|
1.1 Function ~GausTransform()~
|
||
|
|
|
||
|
|
Apply the Gauss transformation to system of equations. The left hand sides
|
||
|
|
of the equations are in matrix $a$ with $n$ rows and $m$ columns and the
|
||
|
|
right hand sides are in vector $b$ with $n$ rows.
|
||
|
|
|
||
|
|
The transformed matrix and vector are returned in $a$ and $b$.
|
||
|
|
|
||
|
|
*/
|
||
|
|
static void GaussTransform(const unsigned int n,
|
||
|
|
const unsigned int m,
|
||
|
|
double** a,
|
||
|
|
double* b) {
|
||
|
|
if (MRA_DEBUG) {
|
||
|
|
cerr << "GaussTransform() called, n="
|
||
|
|
<< n << " m=" << m << endl;
|
||
|
|
|
||
|
|
for (unsigned int j = 0; j < n; j++) {
|
||
|
|
for (unsigned int k = 0; k < m; k++)
|
||
|
|
fprintf(stderr, "%7.3f ", a[j][k]);
|
||
|
|
fprintf(stderr, "| %7.3f\n", b[j]);
|
||
|
|
}
|
||
|
|
cerr << "============================="
|
||
|
|
<< "============================="
|
||
|
|
<< endl;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/*
|
||
|
|
For each row...
|
||
|
|
|
||
|
|
*/
|
||
|
|
for (unsigned int i = 0; i < n-1; i++) {
|
||
|
|
/*
|
||
|
|
Check for non-zero element in column $i$ below and including row $i$, which
|
||
|
|
can be used as pivot.
|
||
|
|
|
||
|
|
*/
|
||
|
|
if (MRA_DEBUG) cerr << "i=" << i << endl;
|
||
|
|
unsigned int j;
|
||
|
|
for (j = i; j < n && a[j][i] == 0; j++)
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << " failed as pivot: a["
|
||
|
|
<< j
|
||
|
|
<< "]["
|
||
|
|
<< i
|
||
|
|
<< "]="
|
||
|
|
<< a[j][i]
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
/*
|
||
|
|
If we found a pivot, apply it to the rows below row $i$. If we did not find
|
||
|
|
a pivot, column $i$ is already zero below and including row $i$ and we do
|
||
|
|
not have to do anything.
|
||
|
|
|
||
|
|
*/
|
||
|
|
if (j != n) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << " pivot: a["
|
||
|
|
<< j
|
||
|
|
<< "]["
|
||
|
|
<< i
|
||
|
|
<< "]="
|
||
|
|
<< a[j][i]
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
/*
|
||
|
|
The pivot is in row $j$. If $j\ne i$, the pivot is in another row than row $i$.
|
||
|
|
Swap rows $i$ and $j$ in this case.
|
||
|
|
|
||
|
|
*/
|
||
|
|
if (j != i) {
|
||
|
|
double dummy = b[i];
|
||
|
|
b[i] = b[j];
|
||
|
|
b[j] = dummy;
|
||
|
|
for (unsigned int k = 0; k < m; k++) {
|
||
|
|
dummy = a[i][k];
|
||
|
|
a[i][k] = a[j][k];
|
||
|
|
a[j][k] = dummy;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
Subtract row $i$ from each row below row $i$, multiplied with factor $f$,
|
||
|
|
which is calculated so that it sets the element in column $i$ of each row
|
||
|
|
to $0$ during the substraction.
|
||
|
|
|
||
|
|
*/
|
||
|
|
for (j = i+1; j < n; j++) {
|
||
|
|
double f = a[j][i]/a[i][i];
|
||
|
|
if (MRA_DEBUG) {
|
||
|
|
cerr << " j=" << j << endl;
|
||
|
|
cerr << " f=" << f << endl;
|
||
|
|
}
|
||
|
|
a[j][i] = 0;
|
||
|
|
for (unsigned int k = i+1; k < m; k++)
|
||
|
|
a[j][k] -= a[i][k]*f;
|
||
|
|
b[j] -= b[i]*f;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (MRA_DEBUG) {
|
||
|
|
for (j = 0; j < n; j++) {
|
||
|
|
for (unsigned int k = 0; k < m; k++)
|
||
|
|
fprintf(stderr, "%7.3f ", a[j][k]);
|
||
|
|
fprintf(stderr, "| %7.3f\n", b[j]);
|
||
|
|
}
|
||
|
|
cerr
|
||
|
|
<< "-----------------------------"
|
||
|
|
<< "-----------------------------"
|
||
|
|
<< endl;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1 Intersections between two segments
|
||
|
|
|
||
|
|
1.1.1 Function ~specialSegmentIntersects2()~
|
||
|
|
|
||
|
|
Returns ~true~ if the specified segment and line intersect
|
||
|
|
in three-dimensional space $(x, y, t)$.
|
||
|
|
It is not considered as intersection if they touch in their end points.
|
||
|
|
|
||
|
|
The segment connects the points $(l1p1x, l1p1y, z)$ and $(l1p2x, l1p2y, z)$,
|
||
|
|
ie.\ segment 1 is parallel to the $(x, y)$-plane.
|
||
|
|
|
||
|
|
The line is $P+Q\cdot t$. The line must not be parallel to the $(x, y)-plane$.
|
||
|
|
|
||
|
|
*/
|
||
|
|
static bool specialSegmentIntersects2(double z,
|
||
|
|
double l1p1x,
|
||
|
|
double l1p1y,
|
||
|
|
double l1p2x,
|
||
|
|
double l1p2y,
|
||
|
|
double* P,
|
||
|
|
double* Q) {
|
||
|
|
if (MRA_DEBUG) {
|
||
|
|
cerr << "specialSegmentIntersects2() called"
|
||
|
|
<< endl;
|
||
|
|
cerr << "specialSegmentIntersects2() line 1: ("
|
||
|
|
<< l1p1x
|
||
|
|
<< ", "
|
||
|
|
<< l1p1y
|
||
|
|
<< ", "
|
||
|
|
<< z
|
||
|
|
<< ")-("
|
||
|
|
<< l1p2x
|
||
|
|
<< ", "
|
||
|
|
<< l1p2y
|
||
|
|
<< ", "
|
||
|
|
<< z
|
||
|
|
<< ")"
|
||
|
|
<< endl;
|
||
|
|
cerr << "specialSegmentIntersects2() line 2: ("
|
||
|
|
<< P[0]
|
||
|
|
<< ", "
|
||
|
|
<< P[1]
|
||
|
|
<< ", "
|
||
|
|
<< P[2]
|
||
|
|
<< ")-("
|
||
|
|
<< Q[0]
|
||
|
|
<< ", "
|
||
|
|
<< Q[1]
|
||
|
|
<< ", "
|
||
|
|
<< Q[2]
|
||
|
|
<< ")*t"
|
||
|
|
<< endl;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
Calculate point $(x, y)$ where the line intersects the plane parallel to the
|
||
|
|
$(x, y)$-plane with distance z from the $(x, y)$-plane.
|
||
|
|
|
||
|
|
*/
|
||
|
|
double t2 = (z-P[2])/Q[2];
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "specialSegmentIntersects2() t="
|
||
|
|
<< t2
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
double x = P[0]+Q[0]*t2;
|
||
|
|
double y = P[1]+Q[1]*t2;
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "specialSegmentIntersects2() x="
|
||
|
|
<< x
|
||
|
|
<< " y="
|
||
|
|
<< y
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
double l1MinX = l1p1x < l1p2x ? l1p1x : l1p2x;
|
||
|
|
double l1MaxX = l1p1x > l1p2x ? l1p1x : l1p2x;
|
||
|
|
double l1MinY = l1p1y < l1p2y ? l1p1y : l1p2y;
|
||
|
|
double l1MaxY = l1p1y > l1p2y ? l1p1y : l1p2y;
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "specialSegmentIntersects2() l1MinX="
|
||
|
|
<< l1MinX
|
||
|
|
<< " l1MaxX="
|
||
|
|
<< l1MaxX
|
||
|
|
<< " l1MinY="
|
||
|
|
<< l1MinY
|
||
|
|
<< " l1MaxY="
|
||
|
|
<< l1MaxY
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
if (nearlyEqual(l1p1x, l1p2x) && nearlyEqual(l1p1y, l1p2y)) {
|
||
|
|
/*
|
||
|
|
The segment is actually a point.
|
||
|
|
|
||
|
|
*/
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr
|
||
|
|
<< "specialSegmentIntersects2() "
|
||
|
|
<< "no intersection #1" << endl;
|
||
|
|
|
||
|
|
return false;
|
||
|
|
} else if (nearlyEqual(l1p1x, l1p2x)) {
|
||
|
|
/*
|
||
|
|
The segment is vertical in the $(x, y)$-plane.
|
||
|
|
|
||
|
|
*/
|
||
|
|
if (nearlyEqual(x, l1p1x)
|
||
|
|
&& lower(l1MinY, y)
|
||
|
|
&& lower(y, l1MaxY)) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr
|
||
|
|
<< "specialSegmentIntersects2() "
|
||
|
|
<< "intersects #2" << endl;
|
||
|
|
|
||
|
|
return true;
|
||
|
|
} else {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr
|
||
|
|
<< "specialSegmentIntersects2() "
|
||
|
|
<< "no intersection #2" << endl;
|
||
|
|
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
} else if (nearlyEqual(l1p1y, l1p2y)) {
|
||
|
|
/*
|
||
|
|
The segment is horizontal in the $(x, y)$-plane.
|
||
|
|
|
||
|
|
*/
|
||
|
|
if (nearlyEqual(y, l1p1y)
|
||
|
|
&& lower(l1MinX, x)
|
||
|
|
&& lower(x, l1MaxX)) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr
|
||
|
|
<< "specialSegmentIntersects2() "
|
||
|
|
<< "intersects #3" << endl;
|
||
|
|
|
||
|
|
return true;
|
||
|
|
} else {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr
|
||
|
|
<< "specialSegmentIntersects2() "
|
||
|
|
<< "no intersection #3" << endl;
|
||
|
|
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
/*
|
||
|
|
Otherwise, $l1p1x\ne l1p2x$ and $l1p1y\ne l1p2y$ so that we can happily
|
||
|
|
use the quotients below.
|
||
|
|
|
||
|
|
First, check whether $(x, y)$ is on the line through the segment.
|
||
|
|
|
||
|
|
*/
|
||
|
|
double t1 = (x-l1p1x)/(l1p2x-l1p1x);
|
||
|
|
|
||
|
|
if (!nearlyEqual(t1, (y-l1p1y)/(l1p2y-l1p1y))) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr
|
||
|
|
<< "specialSegmentIntersects2() "
|
||
|
|
<< "no intersection #4a" << endl;
|
||
|
|
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
Verify that $(x, y)$ is actually on the segment: As we already know that
|
||
|
|
it is on the line through the segment, we just have to check its bounding
|
||
|
|
box parallel to the $(x, y)$-plane.
|
||
|
|
|
||
|
|
*/
|
||
|
|
if (lowerOrNearlyEqual(x, l1MinX)
|
||
|
|
|| lowerOrNearlyEqual(l1MaxX, x)
|
||
|
|
|| lowerOrNearlyEqual(y, l1MinY)
|
||
|
|
|| lowerOrNearlyEqual(l1MaxY, y)) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "specialSegmentIntersects2() "
|
||
|
|
<< "no intersection #4b" << endl;
|
||
|
|
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "specialSegmentIntersects2() "
|
||
|
|
<< "intersects" << endl;
|
||
|
|
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1 Function ~specialSegmentIntersects1()~ (with $z$)
|
||
|
|
\label{ssi}
|
||
|
|
|
||
|
|
Returns ~true~ if the two specified segments intersect
|
||
|
|
in three-dimensional space $(x, y, t)$.
|
||
|
|
It is not considered as intersection if they touch in their end points.
|
||
|
|
|
||
|
|
The two lines must meet the following conditions.
|
||
|
|
|
||
|
|
Segment 1 connects the points $(l1p1x, l1p1y, 0)$ and $(l1p2x, l1p2y, dt)$.
|
||
|
|
|
||
|
|
Segment 2 connects the points $(l2p1x, l2p1y, 0)$ and $(l2p2x, l2p2y, dt)$.
|
||
|
|
|
||
|
|
$z$ will contain the $z$-coordinate of the intersection point, if it
|
||
|
|
exists.
|
||
|
|
|
||
|
|
*/
|
||
|
|
static bool specialSegmentIntersects1(double dt,
|
||
|
|
double l1p1x,
|
||
|
|
double l1p1y,
|
||
|
|
double l1p2x,
|
||
|
|
double l1p2y,
|
||
|
|
double l2p1x,
|
||
|
|
double l2p1y,
|
||
|
|
double l2p2x,
|
||
|
|
double l2p2y,
|
||
|
|
double& z) {
|
||
|
|
if (MRA_DEBUG) {
|
||
|
|
cerr << "specialSegmentIntersects1() w/ z component called"
|
||
|
|
<< endl;
|
||
|
|
cerr << "specialSegmentIntersects1() line 1: ("
|
||
|
|
<< l1p1x
|
||
|
|
<< ", "
|
||
|
|
<< l1p1y
|
||
|
|
<< ", 0.0)-("
|
||
|
|
<< l1p2x
|
||
|
|
<< ", "
|
||
|
|
<< l1p2y
|
||
|
|
<< ", "
|
||
|
|
<< dt
|
||
|
|
<< ")"
|
||
|
|
<< endl;
|
||
|
|
cerr << "specialSegmentIntersects1() line 2: ("
|
||
|
|
<< l2p1x
|
||
|
|
<< ", "
|
||
|
|
<< l2p1y
|
||
|
|
<< ", 0.0)-("
|
||
|
|
<< l2p2x
|
||
|
|
<< ", "
|
||
|
|
<< l2p2y
|
||
|
|
<< ", "
|
||
|
|
<< dt
|
||
|
|
<< ")"
|
||
|
|
<< endl;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
Check if both segments are identical or touch in their endpoints.
|
||
|
|
|
||
|
|
*/
|
||
|
|
if (nearlyEqual(l1p1x, l2p1x)
|
||
|
|
&& nearlyEqual(l1p1y, l2p1y)) {
|
||
|
|
if (nearlyEqual(l1p2x, l2p2x)
|
||
|
|
&& nearlyEqual(l1p2y, l2p2y)) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "specialSegmentIntersects1() same segment"
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
return false;
|
||
|
|
} else {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "specialSegmentIntersects1() "
|
||
|
|
<< "segments touch in ("
|
||
|
|
<< l1p1x << ", " << l1p1y << ")"
|
||
|
|
<< endl;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
} else if (nearlyEqual(l1p2x, l2p2x)
|
||
|
|
&& nearlyEqual(l1p2y, l2p2y)) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "specialSegmentIntersects1() "
|
||
|
|
<< "segments touch in ("
|
||
|
|
<< l1p2x << ", " << l1p2y << ")"
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
The line through segment 1 is
|
||
|
|
$(l1p1x, l1p1y, 0)+(l1p2x-l1p1x, l1p2y-l1p2y, dt)\cdot s$.
|
||
|
|
The line through segment 2 is
|
||
|
|
$(l2p1x, l2p1y, 0)+(l2p2x-l1p1x, l2p2y-l2p2y, dt)\cdot t$.
|
||
|
|
|
||
|
|
The intersection of the two lines is the solution of the following
|
||
|
|
linear system of equations:
|
||
|
|
\begin{eqnarray}
|
||
|
|
\begin{array}{ccc}
|
||
|
|
\begin{array}{cc}
|
||
|
|
l1p2x-l1p1x & l2p1x-l2p2x \\
|
||
|
|
l1p2y-l1p1y & l2p1y-l2p2y \\
|
||
|
|
dt & -dt
|
||
|
|
\end{array} & \left| \begin{array}{c}
|
||
|
|
l2p1x-l1p1x \\
|
||
|
|
l2p1y-l1p1y \\
|
||
|
|
0
|
||
|
|
\end{array} \right.
|
||
|
|
\end{array}
|
||
|
|
\nonumber\end{eqnarray}
|
||
|
|
|
||
|
|
We put the left handed sides of the equations in matrix $a$ and the right
|
||
|
|
handed sides into array $b$ and are applying the Gaussian elimination to these:
|
||
|
|
|
||
|
|
*/
|
||
|
|
double A[3][2] =
|
||
|
|
{{ l1p2x-l1p1x, l2p1x-l2p2x },
|
||
|
|
{ l1p2y-l1p1y, l2p1y-l2p2y },
|
||
|
|
{ dt, -dt }};
|
||
|
|
double B[3] =
|
||
|
|
{ l2p1x-l1p1x, l2p1y-l1p1y, 0 };
|
||
|
|
|
||
|
|
double* Ap[] = { A[0], A[1], A[2] };
|
||
|
|
|
||
|
|
GaussTransform(3, 2, Ap, B);
|
||
|
|
|
||
|
|
/*
|
||
|
|
Now, we will determine the solution $t$ from the transformed system.
|
||
|
|
We examine each row from the bottom to the top:
|
||
|
|
|
||
|
|
*/
|
||
|
|
for (int i = 2; i >= 0; i--) {
|
||
|
|
if (!nearlyEqual(Ap[i][0], 0.0)) break;
|
||
|
|
|
||
|
|
/*
|
||
|
|
Row is in format $0 c \left| b \right.$.
|
||
|
|
|
||
|
|
*/
|
||
|
|
if (nearlyEqual(Ap[i][1], 0.0)) {
|
||
|
|
/*
|
||
|
|
Row is in format $0 0 \left| b \right.$. Check if there is a contradiction
|
||
|
|
indicating that there are no solutions.
|
||
|
|
|
||
|
|
*/
|
||
|
|
if (nearlyEqual(B[i], 0.0))
|
||
|
|
continue;
|
||
|
|
else {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "specialSegmentIntersects1() "
|
||
|
|
<< "do not intersect #1"
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
z = dt*B[i]/Ap[i][1];
|
||
|
|
|
||
|
|
/*
|
||
|
|
Row is in format $0 c \left| b \right.$ with $c\ne 0$. All rows below are
|
||
|
|
entirely 0.
|
||
|
|
Inserting $t=b/c$ into the equation of line 2 yields the value $z=dt\cdot b/c$
|
||
|
|
for the third component. If $0\le z \le dt$, the two segments intersect. If
|
||
|
|
$z=0$ or $z=dt$, they touch at one of their end points, which is not considered
|
||
|
|
as intersection.
|
||
|
|
|
||
|
|
*/
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "specialSegmentIntersects1() z="
|
||
|
|
<< z << endl;
|
||
|
|
|
||
|
|
if (lowerOrNearlyEqual(0.0, z)
|
||
|
|
&& lowerOrNearlyEqual(z, dt)) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "specialSegmentIntersects1() "
|
||
|
|
<< "intersect"
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
return true;
|
||
|
|
} else {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "specialSegmentIntersects1() "
|
||
|
|
<< "do not intersect #2"
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
Both segments are located on the same line. We have to check whether they
|
||
|
|
are overlapping.
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
if ((between(l1p1x, l2p1x, l1p2x)
|
||
|
|
&& between(l1p1y, l2p1y, l1p2y))
|
||
|
|
|| (between(l1p1x, l2p2x, l1p2x)
|
||
|
|
&& between(l1p1y, l2p2y, l1p2y))
|
||
|
|
|| (between(l2p1x, l1p1x, l2p2x)
|
||
|
|
&& between(l2p1y, l1p1y, l2p2y))
|
||
|
|
|| (between(l2p1x, l1p2x, l2p2x)
|
||
|
|
&& between(l2p1y, l1p2y, l2p2y)))
|
||
|
|
return true;
|
||
|
|
else
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1 Function ~specialSegmentIntersects1()~ (without $z$)
|
||
|
|
|
||
|
|
Same as function in section \ref{ssi}, but not returning the $z$-coordinate
|
||
|
|
of the intersection point.
|
||
|
|
|
||
|
|
*/
|
||
|
|
static bool specialSegmentIntersects1(double dt,
|
||
|
|
double l1p1x,
|
||
|
|
double l1p1y,
|
||
|
|
double l1p2x,
|
||
|
|
double l1p2y,
|
||
|
|
double l2p1x,
|
||
|
|
double l2p1y,
|
||
|
|
double l2p2x,
|
||
|
|
double l2p2y) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "specialSegmentIntersects1() w/o z-component called"
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
double dummy;
|
||
|
|
|
||
|
|
return
|
||
|
|
specialSegmentIntersects1(dt,
|
||
|
|
l1p1x, l1p1y, l1p2x, l1p2y,
|
||
|
|
l2p1x, l2p1y, l2p2x, l2p2y,
|
||
|
|
dummy);
|
||
|
|
}
|
||
|
|
|
||
|
|
static int getNearestExpOf2(uint64_t src) {
|
||
|
|
if (src == 0) {
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
int exp = 0;
|
||
|
|
while (((uint64_t(1 << exp)) <= src) && (exp < 30)) {
|
||
|
|
exp++;
|
||
|
|
}
|
||
|
|
exp--;
|
||
|
|
if ((exp > 0) && (((1 << (exp - 1)) & src) > 0)) {
|
||
|
|
exp++;
|
||
|
|
}
|
||
|
|
return exp;
|
||
|
|
}
|
||
|
|
|
||
|
|
static uint64_t getScaleFactor(double dsrc) {
|
||
|
|
uint64_t isrc = (uint64_t)dsrc;
|
||
|
|
if (isrc <= (1 << 30)) {
|
||
|
|
int exp = getNearestExpOf2(isrc);
|
||
|
|
if (exp > 30) {
|
||
|
|
exp = 30;
|
||
|
|
}
|
||
|
|
return (1 << (30 - exp));
|
||
|
|
}
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1 Intersections between two trapeziums
|
||
|
|
|
||
|
|
1.1.1 Function ~specialTrapeziumIntersects()~
|
||
|
|
\label{stinu}
|
||
|
|
|
||
|
|
Returns ~true~ if and only if the two specified special trapeziums intersect
|
||
|
|
in three-dimensional space $(x, y, t)$.
|
||
|
|
|
||
|
|
The two trapeziums must meet the following conditions. These conditions are
|
||
|
|
not checked in the function. If the conditions are not met, the function will
|
||
|
|
deliver incorrect results.
|
||
|
|
|
||
|
|
Trapezium 1 is spanned by segments ~(t1p1x, t1p1y, 0)~ to ~(t1p2x, t1p2y, 0)~,
|
||
|
|
~(t1p1x, t1p1y, 0)~ to ~(t1p3x, t1p3y, dt)~, ~(t1p3x, t1p3y, dt)~ to
|
||
|
|
~(t1p4x, t1p4x, dt)~ and ~(t1p2x, t1p2y, 0)~ to ~(t1p4x, t1p4x, dt)~.
|
||
|
|
Allowed are either ~(t1p1x, t1p1y, 0)=(t1p2x, t1p2y, 0)~ or
|
||
|
|
~(t1p3x, t1p3y, dt)=(t1p4x, t1p4x, dt)~ but not both. Segments
|
||
|
|
~(t1p1x, t1p1y, 0)~ to ~(t1p2x, t1p2y, 0)~ and
|
||
|
|
~(t1p3x, t1p3y, dt)~ to ~(t1p4x, t1p4x, dt)~ are collinear.
|
||
|
|
|
||
|
|
Trapezium 2 is spanned by segments ~(t2p1x, t2p1y, 0)~ to ~(t2p2x, t2p2y, 0)~,
|
||
|
|
~(t2p1x, t2p1y, 0)~ to ~(t2p3x, t2p3y, dt)~, ~(t2p3x, t2p3y, dt)~ to
|
||
|
|
~(t2p4x, t2p4x, dt)~ and ~(t2p2x, t2p2y, 0)~ to ~(t2p4x, t2p4x, dt)~.
|
||
|
|
Allowed are either ~(t2p1x, t2p1y, 0)=(t2p2x, t2p2y, 0)~ or
|
||
|
|
~(t2p3x, t2p3y, dt)=(t2p4x, t2p4x, dt)~ but not both. Segments
|
||
|
|
~(t2p1x, t2p1y, 0)~ to ~(t2p2x, t2p2y, 0)~ and
|
||
|
|
~(t2p3x, t2p3y, dt)~ to ~(t2p4x, t2p4x, dt)~ are collinear.
|
||
|
|
|
||
|
|
$dt$ must be greater than $0$.
|
||
|
|
|
||
|
|
~detailedResult~ which will contain a numeric representation of the specific
|
||
|
|
case
|
||
|
|
responsible for the return value of the function. (Full description of
|
||
|
|
~detailedResult~ should be added here.)
|
||
|
|
|
||
|
|
*/
|
||
|
|
bool specialTrapeziumIntersects(
|
||
|
|
double dt,
|
||
|
|
double t1p1x,
|
||
|
|
double t1p1y,
|
||
|
|
double t1p2x,
|
||
|
|
double t1p2y,
|
||
|
|
double t1p3x,
|
||
|
|
double t1p3y,
|
||
|
|
double t1p4x,
|
||
|
|
double t1p4y,
|
||
|
|
double t2p1x,
|
||
|
|
double t2p1y,
|
||
|
|
double t2p2x,
|
||
|
|
double t2p2y,
|
||
|
|
double t2p3x,
|
||
|
|
double t2p3y,
|
||
|
|
double t2p4x,
|
||
|
|
double t2p4y,
|
||
|
|
unsigned int& detailedResult) {
|
||
|
|
|
||
|
|
#ifdef SWITCH_OFF_TRAPEZIUM_INTERSECTS
|
||
|
|
return false;
|
||
|
|
#endif
|
||
|
|
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "specialTrapeziumIntersects() "
|
||
|
|
<< "(w/ detailedResult) called"
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
detailedResult = 0;
|
||
|
|
|
||
|
|
if (MRA_DEBUG) {
|
||
|
|
cerr << "specialTrapeziumIntersects() trapezium 1: ("
|
||
|
|
<< t1p1x << ", " << t1p1y
|
||
|
|
<< "), (" << t1p2x << ", " << t1p2y
|
||
|
|
<< "), (" << t1p3x << ", " << t1p3y
|
||
|
|
<< "), (" << t1p4x << ", " << t1p4y
|
||
|
|
<< ")"
|
||
|
|
<< endl;
|
||
|
|
cerr << "specialTrapeziumIntersects() trapezium 2: ("
|
||
|
|
<< t2p1x << ", " << t2p1y
|
||
|
|
<< "), (" << t2p2x << ", " << t2p2y
|
||
|
|
<< "), (" << t2p3x << ", " << t2p3y
|
||
|
|
<< "), (" << t2p4x << ", " << t2p4y
|
||
|
|
<< ")"
|
||
|
|
<< endl;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
First, lets check the bounding boxes in the $(x, y)$-plane of the two
|
||
|
|
trapeziums.
|
||
|
|
|
||
|
|
*/
|
||
|
|
double t1MinX;
|
||
|
|
double t1MaxX;
|
||
|
|
double t1MinY;
|
||
|
|
double t1MaxY;
|
||
|
|
|
||
|
|
minmax4(t1p1x, t1p2x, t1p3x, t1p4x, t1MinX, t1MaxX);
|
||
|
|
minmax4(t1p1y, t1p2y, t1p3y, t1p4y, t1MinY, t1MaxY);
|
||
|
|
|
||
|
|
double t2MinX;
|
||
|
|
double t2MaxX;
|
||
|
|
double t2MinY;
|
||
|
|
double t2MaxY;
|
||
|
|
|
||
|
|
minmax4(t2p1x, t2p2x, t2p3x, t2p4x, t2MinX, t2MaxX);
|
||
|
|
minmax4(t2p1y, t2p2y, t2p3y, t2p4y, t2MinY, t2MaxY);
|
||
|
|
|
||
|
|
if (MRA_DEBUG) {
|
||
|
|
cerr << "specialTrapeziumIntersects() t1MinX=" << t1MinX
|
||
|
|
<< " t1MaxX=" << t1MaxX
|
||
|
|
<< " t1MinY=" << t1MinY
|
||
|
|
<< " t1MaxY=" << t1MaxY
|
||
|
|
<< endl;
|
||
|
|
cerr << "specialTrapeziumIntersects() t2MinX=" << t2MinX
|
||
|
|
<< " t2MaxX=" << t2MaxX
|
||
|
|
<< " t2MinY=" << t2MinY
|
||
|
|
<< " t2MaxY=" << t2MaxY
|
||
|
|
<< endl;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
// cout << "specialTrapeziumIntersects() trapezium 1: (" << t1p1x << ", "
|
||
|
|
// << t1p1y << "), (" << t1p2x << ", " << t1p2y << "), (" << t1p3x << ", "
|
||
|
|
// << t1p3y << "), (" << t1p4x << ", " << t1p4y << ")" << endl;
|
||
|
|
// cout << "specialTrapeziumIntersects() trapezium 2: (" << t2p1x << ", "
|
||
|
|
// << t2p1y << "), (" << t2p2x << ", " << t2p2y << "), (" << t2p3x << ", "
|
||
|
|
// << t2p3y << "), (" << t2p4x << ", " << t2p4y << ")" << endl;
|
||
|
|
|
||
|
|
double minX, minY, maxX, maxY;
|
||
|
|
minmax4(t1MinX, t1MaxX, t2MinX, t2MaxX, minX, maxX);
|
||
|
|
minmax4(t1MinY, t1MaxY, t2MinY, t2MaxY, minY, maxY);
|
||
|
|
|
||
|
|
// cout << "distX = " << maxX - minX << "distY = " << maxY - minY
|
||
|
|
// << "dt = " << dt << endl;
|
||
|
|
|
||
|
|
uint64_t sx = getScaleFactor(maxX - minX);
|
||
|
|
uint64_t sy = getScaleFactor(maxY - minY);
|
||
|
|
uint64_t st = getScaleFactor(dt);
|
||
|
|
|
||
|
|
// cout << "sx = " << sx << ", sy = " << sy << ", st = " << st << endl;
|
||
|
|
|
||
|
|
uint64_t tx = 1 << getNearestExpOf2((maxX + minX) / 2);
|
||
|
|
uint64_t ty = 1 << getNearestExpOf2((maxY + minY) / 2);
|
||
|
|
uint64_t tt = 1 << getNearestExpOf2(dt);
|
||
|
|
|
||
|
|
t1p1x = (t1p1x - tx) * sx; t1p1y = (t1p1y - ty) * sy;
|
||
|
|
t1p2x = (t1p2x - tx) * sx; t1p2y = (t1p2y - ty) * sy;
|
||
|
|
t1p3x = (t1p3x - tx) * sx; t1p3y = (t1p3y - ty) * sy;
|
||
|
|
t1p4x = (t1p4x - tx) * sx; t1p4y = (t1p4y - ty) * sy;
|
||
|
|
t2p1x = (t2p1x - tx) * sx; t2p1y = (t2p1y - ty) * sy;
|
||
|
|
t2p2x = (t2p2x - tx) * sx; t2p2y = (t2p2y - ty) * sy;
|
||
|
|
t2p3x = (t2p3x - tx) * sx; t2p3y = (t2p3y - ty) * sy;
|
||
|
|
t2p4x = (t2p4x - tx) * sx; t2p4y = (t2p4y - ty) * sy;
|
||
|
|
dt = (dt - tt) * st;
|
||
|
|
|
||
|
|
// cout << "specialTrapeziumIntersects() trapezium 1: (" << t1p1x << ", "
|
||
|
|
// << t1p1y << "), (" << t1p2x << ", " << t1p2y << "), (" << t1p3x << ", "
|
||
|
|
// << t1p3y << "), (" << t1p4x << ", " << t1p4y << ")" << endl;
|
||
|
|
// cout << "specialTrapeziumIntersects() trapezium 2: (" << t2p1x << ", "
|
||
|
|
// << t2p1y << "), (" << t2p2x << ", " << t2p2y << "), (" << t2p3x << ", "
|
||
|
|
// << t2p3y << "), (" << t2p4x << ", " << t2p4y << ")" << endl;
|
||
|
|
|
||
|
|
if (lower(t1MaxX, t2MinX)
|
||
|
|
|| lower(t2MaxX, t1MinX)
|
||
|
|
|| lower(t1MaxY, t2MinY)
|
||
|
|
|| lower(t2MaxY, t1MinY)) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "specialTrapeziumIntersects() no bbox overlap"
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
detailedResult = 1;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
Now, lets see if the trapeziums touch in one segment.
|
||
|
|
|
||
|
|
*/
|
||
|
|
if ((nearlyEqual(t1p1x, t2p1x)
|
||
|
|
&& nearlyEqual(t1p1y, t2p1y)
|
||
|
|
&& nearlyEqual(t1p3x, t2p3x)
|
||
|
|
&& nearlyEqual(t1p3y, t2p3y))
|
||
|
|
|| (nearlyEqual(t1p1x, t2p2x)
|
||
|
|
&& nearlyEqual(t1p1y, t2p2y)
|
||
|
|
&& nearlyEqual(t1p3x, t2p4x)
|
||
|
|
&& nearlyEqual(t1p3y, t2p4y))
|
||
|
|
|| (nearlyEqual(t1p2x, t2p1x)
|
||
|
|
&& nearlyEqual(t1p2y, t2p1y)
|
||
|
|
&& nearlyEqual(t1p4x, t2p3x)
|
||
|
|
&& nearlyEqual(t1p4y, t2p3y))
|
||
|
|
|| (nearlyEqual(t1p2x, t2p2x)
|
||
|
|
&& nearlyEqual(t1p2y, t2p2y)
|
||
|
|
&& nearlyEqual(t1p4x, t2p4x)
|
||
|
|
&& nearlyEqual(t1p4y, t2p4y))) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "specialTrapeziumIntersects() touching"
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
detailedResult = 2;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
The bounding boxes of the trapeziums overlap but they do not touch in one
|
||
|
|
segment. To determine if they actually intersect, we first calculate the
|
||
|
|
intersection of the two planes spanned by the trapezium.
|
||
|
|
|
||
|
|
Create equations for the two planes spanned by the trapeziums,
|
||
|
|
considering that one edge of
|
||
|
|
each trapezium may be a single point: Plane 1 is
|
||
|
|
$T1B+T1A\cdot (s, t)$ and Plane 2 is $T2B+T1A\cdot (s', t')$.
|
||
|
|
|
||
|
|
*/
|
||
|
|
double T1A[3][2];
|
||
|
|
double T1B[3];
|
||
|
|
|
||
|
|
if (nearlyEqual(t1p1x, t1p2x) && nearlyEqual(t1p1y, t1p2y)) {
|
||
|
|
if (MRA_DEBUG) cerr << "#1a" << endl;
|
||
|
|
|
||
|
|
T1A[0][0] = t1p4x-t1p3x;
|
||
|
|
T1A[1][0] = t1p4y-t1p3y;
|
||
|
|
T1A[2][0] = 0;
|
||
|
|
|
||
|
|
T1A[0][1] = t1p1x-t1p3x;
|
||
|
|
T1A[1][1] = t1p1y-t1p3y;
|
||
|
|
T1A[2][1] = -dt;
|
||
|
|
|
||
|
|
T1B[0] = t1p3x;
|
||
|
|
T1B[1] = t1p3y;
|
||
|
|
T1B[2] = dt;
|
||
|
|
} else {
|
||
|
|
if (MRA_DEBUG) cerr << "#1b" << endl;
|
||
|
|
|
||
|
|
T1A[0][0] = t1p2x-t1p1x;
|
||
|
|
T1A[1][0] = t1p2y-t1p1y;
|
||
|
|
T1A[2][0] = 0;
|
||
|
|
|
||
|
|
T1A[0][1] = t1p3x-t1p1x;
|
||
|
|
T1A[1][1] = t1p3y-t1p1y;
|
||
|
|
T1A[2][1] = dt;
|
||
|
|
|
||
|
|
T1B[0] = t1p1x;
|
||
|
|
T1B[1] = t1p1y;
|
||
|
|
T1B[2] = 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
double T2A[3][2];
|
||
|
|
double T2B[3];
|
||
|
|
|
||
|
|
if (nearlyEqual(t2p1x, t2p2x) && nearlyEqual(t2p1y, t2p2y)) {
|
||
|
|
if (MRA_DEBUG) cerr << "#2a" << endl;
|
||
|
|
|
||
|
|
T2A[0][0] = t2p4x-t2p3x;
|
||
|
|
T2A[1][0] = t2p4y-t2p3y;
|
||
|
|
T2A[2][0] = 0;
|
||
|
|
|
||
|
|
T2A[0][1] = t2p1x-t2p3x;
|
||
|
|
T2A[1][1] = t2p1y-t2p3y;
|
||
|
|
T2A[2][1] = -dt;
|
||
|
|
|
||
|
|
T2B[0] = t2p3x;
|
||
|
|
T2B[1] = t2p3y;
|
||
|
|
T2B[2] = dt;
|
||
|
|
} else {
|
||
|
|
if (MRA_DEBUG) cerr << "#2b" << endl;
|
||
|
|
|
||
|
|
T2A[0][0] = t2p2x-t2p1x;
|
||
|
|
T2A[1][0] = t2p2y-t2p1y;
|
||
|
|
T2A[2][0] = 0;
|
||
|
|
|
||
|
|
T2A[0][1] = t2p3x-t2p1x;
|
||
|
|
T2A[1][1] = t2p3y-t2p1y;
|
||
|
|
T2A[2][1] = dt;
|
||
|
|
|
||
|
|
T2B[0] = t2p1x;
|
||
|
|
T2B[1] = t2p1y;
|
||
|
|
T2B[2] = 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (MRA_DEBUG) {
|
||
|
|
cerr << "T1B T1A "
|
||
|
|
<< "T2B T2A"
|
||
|
|
<< endl;
|
||
|
|
cerr << "------- --------------- "
|
||
|
|
<< "------- ---------------"
|
||
|
|
<< endl;
|
||
|
|
for (unsigned int i = 0; i < 3; i++)
|
||
|
|
fprintf(stderr,
|
||
|
|
"%7.3f %7.3f %7.3f %7.3f %7.3f %7.3f\n",
|
||
|
|
T1B[i],
|
||
|
|
T1A[i][0],
|
||
|
|
T1A[i][1],
|
||
|
|
T2B[i],
|
||
|
|
T2A[i][0],
|
||
|
|
T2A[i][1]);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
Create a linear system of equations $A$ and $B$, which represents
|
||
|
|
$T1B+T1A\cdot (s, t)=T2B+T2A\cdot (s', t')$. Apply Gaussian elimination to
|
||
|
|
$A$ and $B$.
|
||
|
|
|
||
|
|
*/
|
||
|
|
double A[3][4];
|
||
|
|
double B[3];
|
||
|
|
double* Ap[3];
|
||
|
|
|
||
|
|
for (unsigned int i = 0; i < 3; i++) {
|
||
|
|
A[i][0] = T1A[i][0];
|
||
|
|
A[i][1] = T1A[i][1];
|
||
|
|
A[i][2] = -T2A[i][0];
|
||
|
|
A[i][3] = -T2A[i][1];
|
||
|
|
B[i] = T2B[i]-T1B[i];
|
||
|
|
Ap[i] = A[i];
|
||
|
|
}
|
||
|
|
|
||
|
|
GaussTransform(3, 4, Ap, B);
|
||
|
|
|
||
|
|
/*
|
||
|
|
Now, the linear system of equation has the following format
|
||
|
|
\begin{eqnarray}
|
||
|
|
\begin{array}{ccc}
|
||
|
|
\begin{array}{cccc}
|
||
|
|
\ast & \ast & \ast & \ast \\
|
||
|
|
0 & \ast & \ast & \ast \\
|
||
|
|
0 & 0 & c1 & c2
|
||
|
|
\end{array} & \left| \begin{array}{c}
|
||
|
|
\ast \\
|
||
|
|
\ast \\
|
||
|
|
b
|
||
|
|
\end{array} \right.
|
||
|
|
\end{array}
|
||
|
|
\nonumber\end{eqnarray}
|
||
|
|
The asterisk denotes arbitrary values.
|
||
|
|
|
||
|
|
If $c1=0$, $c2=0$ and $b\ne0$, the two planes are parallel and not identical:
|
||
|
|
They do not intersect. If $c1=0$, $c2=0$ and $b=0$, the two planes are
|
||
|
|
identical and we have to check if the two trapeziums overlap.
|
||
|
|
|
||
|
|
*/
|
||
|
|
if (nearlyEqual(Ap[2][2], 0.0) && nearlyEqual(Ap[2][3], 0.0)) {
|
||
|
|
if (nearlyEqual(B[2], 0.0)) {
|
||
|
|
/*
|
||
|
|
They overlap if one of the segments of each trapezium, which are not
|
||
|
|
parallel to the $(x, y)$-plane, intersect with another of such segments
|
||
|
|
of the other trapezium.
|
||
|
|
|
||
|
|
*/
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "specialTrapeziumIntersects() "
|
||
|
|
<< "identical plane"
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
if (specialSegmentIntersects1(
|
||
|
|
dt,
|
||
|
|
t1p1x, t1p1y, t1p3x, t1p3y,
|
||
|
|
t2p1x, t2p1y, t2p3x, t2p3y)
|
||
|
|
|| specialSegmentIntersects1(
|
||
|
|
dt,
|
||
|
|
t1p1x, t1p1y, t1p3x, t1p3y,
|
||
|
|
t2p2x, t2p2y, t2p4x, t2p4y)
|
||
|
|
|| specialSegmentIntersects1(
|
||
|
|
dt,
|
||
|
|
t1p2x, t1p2y, t1p4x, t1p4y,
|
||
|
|
t2p1x, t2p1y, t2p3x, t2p3y)
|
||
|
|
|| specialSegmentIntersects1(
|
||
|
|
dt,
|
||
|
|
t1p2x, t1p2y, t1p4x, t1p4y,
|
||
|
|
t2p2x, t2p2y, t2p4x, t2p4y)) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "specialTrapeziumIntersects() intersects"
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
if (MRA_DEBUG) {
|
||
|
|
cerr << ::std::fixed
|
||
|
|
<< ::std::setprecision(6);
|
||
|
|
for (unsigned int i = 0; i < 3; i++)
|
||
|
|
cerr <<Ap[i][0]<<" "
|
||
|
|
<<Ap[i][1]<<" "
|
||
|
|
<<Ap[i][2]<<" "
|
||
|
|
<<Ap[i][3]
|
||
|
|
<<"|"
|
||
|
|
<<B[i]
|
||
|
|
<<endl;
|
||
|
|
}
|
||
|
|
|
||
|
|
detailedResult = 3;
|
||
|
|
return true;
|
||
|
|
} else {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "specialTrapeziumIntersects() "
|
||
|
|
<< "do not intersect"
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
detailedResult = 4;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "specialTrapeziumIntersects() parallel"
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
detailedResult = 5;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
Otherwise, the two planes intersect in a line, which we need to
|
||
|
|
calculate now. We have to consider the following cases: For $c1=0$, it
|
||
|
|
follows that $t'=b/c2$ with $s'$ arbitrary; for $c2=0$, it follows that
|
||
|
|
$s'=b/c1$ with $t'$ arbitrary; otherwise, it follows that
|
||
|
|
$s'=(b-c2\cdot t')/c1$ with $t'$ arbitrary.
|
||
|
|
|
||
|
|
Inserting $s'$ and $t'$ into the equation of the plane spanned by
|
||
|
|
trapezium 2 provides the equation of the intersection line, which we
|
||
|
|
will use in notation $P+Q\cdot u$.
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "specialTrapeziumIntersects() intersect"
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
double P[3];
|
||
|
|
double Q[3];
|
||
|
|
|
||
|
|
if (nearlyEqual(Ap[2][2], 0.0)) {
|
||
|
|
/*
|
||
|
|
Case 1: $c1=0$.
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
double f = B[2]/Ap[2][3]; // = b/c2
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "specialTrapeziumIntersects() c1=0 f="
|
||
|
|
<< f
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
for (unsigned int i = 0; i < 3; i++) {
|
||
|
|
P[i] = T2B[i]+T2A[i][1]*f;
|
||
|
|
Q[i] = T2A[i][0];
|
||
|
|
}
|
||
|
|
} else if (nearlyEqual(Ap[2][3], 0.0)) {
|
||
|
|
/*
|
||
|
|
Case 2: $c2=0$.
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
double f = B[2]/Ap[2][2]; // = b/c1
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "specialTrapeziumIntersects() c2=0 f="
|
||
|
|
<< f
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
for (unsigned int i = 0; i < 3; i++) {
|
||
|
|
P[i] = T2B[i]+T2A[i][0]*f;
|
||
|
|
Q[i] = T2A[i][1];
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
/*
|
||
|
|
Case 3: $c1\ne 0$ and $c2\ne 0$.
|
||
|
|
|
||
|
|
Inserting $s'=(b-c2\cdot t')/c1$ into $T2B+T2A\cdot (s', t')$ yields
|
||
|
|
\begin{eqnarray}
|
||
|
|
\left(
|
||
|
|
\begin{array}{c}
|
||
|
|
T2B[0] \\
|
||
|
|
T2B[1] \\
|
||
|
|
T2B[2]
|
||
|
|
\end{array}
|
||
|
|
\right)+\left(
|
||
|
|
\begin{array}{c}
|
||
|
|
T2A[0][0] \\
|
||
|
|
T2A[1][0] \\
|
||
|
|
T2A[2][0]
|
||
|
|
\end{array}
|
||
|
|
\right)\cdot (b-c2\cdot t')/c1+\left(
|
||
|
|
\begin{array}{c}
|
||
|
|
T2A[0][1] \\
|
||
|
|
T2A[1][1] \\
|
||
|
|
T2A[2][1]
|
||
|
|
\end{array}
|
||
|
|
\right)\cdot t'
|
||
|
|
\nonumber\end{eqnarray}
|
||
|
|
and
|
||
|
|
\begin{eqnarray}
|
||
|
|
\left(
|
||
|
|
\begin{array}{c}
|
||
|
|
T2B[0]+T2A[0][0]\cdot b/c1 \\
|
||
|
|
T2B[1]+T2A[1][0]\cdot b/c1 \\
|
||
|
|
T2B[2]+T2A[2][0]\cdot b/c1
|
||
|
|
\end{array}
|
||
|
|
\right)+
|
||
|
|
\left(
|
||
|
|
\begin{array}{c}
|
||
|
|
T2A[0][1]-T2A[0][0]\cdot c2/c1 \\
|
||
|
|
T2A[1][1]-T2A[1][0]\cdot c2/c1 \\
|
||
|
|
T2A[2][1]-T2A[2][0]\cdot c2/c1
|
||
|
|
\end{array}
|
||
|
|
\right)\cdot t'
|
||
|
|
\nonumber\end{eqnarray}
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
double f1 = B[2]/Ap[2][2]; // = b/c1
|
||
|
|
double f2 = A[2][3]/Ap[2][2]; // = c2/c1
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "specialTrapeziumIntersects() f1="
|
||
|
|
<< f1
|
||
|
|
<< " f2="
|
||
|
|
<< f2
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
for (unsigned int i = 0; i < 3; i++) {
|
||
|
|
P[i] = T2B[i]+T2A[i][0]*f1;
|
||
|
|
Q[i] = T2A[i][1]-T2A[i][0]*f2;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "specialTrapeziumIntersects() ("
|
||
|
|
<< P[0]
|
||
|
|
<< ", "
|
||
|
|
<< P[1]
|
||
|
|
<< ", "
|
||
|
|
<< P[2]
|
||
|
|
<< ")+("
|
||
|
|
<< Q[0]
|
||
|
|
<< ", "
|
||
|
|
<< Q[1]
|
||
|
|
<< ", "
|
||
|
|
<< Q[2]
|
||
|
|
<< ")*u"
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
/*
|
||
|
|
Now, we have to check whether the intersection line intersects at least one
|
||
|
|
of the segments of each trapezium.
|
||
|
|
|
||
|
|
If $Q[2]=0$, the intersection line is parallel to the $(x, y)$-plane.
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
if (nearlyEqual(Q[2], 0.0)) {
|
||
|
|
/*
|
||
|
|
Check whether the intersection line is within the z-Range covered by the two
|
||
|
|
trapeziums.
|
||
|
|
|
||
|
|
*/
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "specialTrapeziumIntersects() intersection line "
|
||
|
|
<< "parallel to (x, y)-plane"
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
if (lowerOrNearlyEqual(P[2], 0)
|
||
|
|
|| lowerOrNearlyEqual(dt, P[2])) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "specialTrapeziumIntersects() "
|
||
|
|
<< "no intersection"
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
detailedResult = 6;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
Calculate the points where the trapeziums' segments intersect with the
|
||
|
|
intersection line.
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
double ip1x = t1p1x+(t1p3x-t1p1x)*P[2]/dt;
|
||
|
|
double ip1y = t1p1y+(t1p3y-t1p1y)*P[2]/dt;
|
||
|
|
|
||
|
|
double ip2x = t1p2x+(t1p4x-t1p2x)*P[2]/dt;
|
||
|
|
double ip2y = t1p2y+(t1p4y-t1p2y)*P[2]/dt;
|
||
|
|
|
||
|
|
double ip3x = t2p1x+(t2p3x-t2p1x)*P[2]/dt;
|
||
|
|
double ip3y = t2p1y+(t2p3y-t2p1y)*P[2]/dt;
|
||
|
|
|
||
|
|
double ip4x = t2p2x+(t2p4x-t2p2x)*P[2]/dt;
|
||
|
|
double ip4y = t2p2y+(t2p4y-t2p2y)*P[2]/dt;
|
||
|
|
|
||
|
|
|
||
|
|
/*
|
||
|
|
Check for overlaps of the bounding boxes of the two intersection segments.
|
||
|
|
If they overlap, the sections intersect.
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
double ip1ip2MinX = ip1x < ip2x ? ip1x : ip2x;
|
||
|
|
double ip1ip2MaxX = ip1x > ip2x ? ip1x : ip2x;
|
||
|
|
|
||
|
|
double ip1ip2MinY = ip1y < ip2y ? ip1y : ip2y;
|
||
|
|
double ip1ip2MaxY = ip1y > ip2y ? ip1y : ip2y;
|
||
|
|
|
||
|
|
double ip3ip4MinX = ip3x < ip4x ? ip3x : ip4x;
|
||
|
|
double ip3ip4MaxX = ip3x > ip4x ? ip3x : ip4x;
|
||
|
|
|
||
|
|
double ip3ip4MinY = ip3y < ip4y ? ip3y : ip4y;
|
||
|
|
double ip3ip4MaxY = ip3y > ip4y ? ip3y : ip4y;
|
||
|
|
|
||
|
|
if (lower(ip1ip2MaxX, ip3ip4MinX)
|
||
|
|
|| lower(ip3ip4MaxX, ip1ip2MinX)
|
||
|
|
|| lower(ip1ip2MaxY, ip3ip4MinY)
|
||
|
|
|| lower(ip3ip4MaxY, ip1ip2MinY)) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "specialTrapeziumIntersects() "
|
||
|
|
<< "no intersection"
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
detailedResult = 10;
|
||
|
|
return false;
|
||
|
|
} else {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "specialTrapeziumIntersects() intersection"
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
detailedResult = 7;
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
/*
|
||
|
|
Intersection line hits $(x, y)$-plane in $(P[0], P[1], 0)$ and the
|
||
|
|
plane parallel to $(x, y)$-plane in distance $dt$ in
|
||
|
|
$(P[0]+Q[0], P[1]+Q[1], dt)$ as we have handled the case $Q[2]=0$
|
||
|
|
separately.
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
double z;
|
||
|
|
|
||
|
|
double t1zMin = dt;
|
||
|
|
double t1zMax = 0;
|
||
|
|
bool t1Intersects = false;
|
||
|
|
|
||
|
|
if (specialSegmentIntersects2(
|
||
|
|
0, t1p1x, t1p1y, t1p2x, t1p2y, P, Q)) {
|
||
|
|
if (MRA_DEBUG) cerr << "#3a" << endl;
|
||
|
|
t1zMin = t1zMin > 0 ? 0 : t1zMin;
|
||
|
|
t1zMax = t1zMax < 0 ? 0 : t1zMax;
|
||
|
|
t1Intersects = true;
|
||
|
|
}
|
||
|
|
if (specialSegmentIntersects2(
|
||
|
|
dt, t1p3x, t1p3y, t1p4x, t1p4y, P, Q)) {
|
||
|
|
if (MRA_DEBUG) cerr << "#3b" << endl;
|
||
|
|
t1zMin = t1zMin > dt ? dt : t1zMin;
|
||
|
|
t1zMax = t1zMax < dt ? dt : t1zMax;
|
||
|
|
t1Intersects = true;
|
||
|
|
}
|
||
|
|
if (specialSegmentIntersects1(
|
||
|
|
dt,
|
||
|
|
t1p1x, t1p1y, t1p3x, t1p3y,
|
||
|
|
P[0], P[1], P[0]+Q[0], P[1]+Q[1], z)) {
|
||
|
|
if (MRA_DEBUG) cerr << "#3c" << endl;
|
||
|
|
t1zMin = t1zMin > z ? z : t1zMin;
|
||
|
|
t1zMax = t1zMax < z ? z : t1zMax;
|
||
|
|
t1Intersects = true;
|
||
|
|
}
|
||
|
|
if (specialSegmentIntersects1(
|
||
|
|
dt,
|
||
|
|
t1p2x, t1p2y, t1p4x, t1p4y,
|
||
|
|
P[0], P[1], P[0]+Q[0], P[1]+Q[1], z)) {
|
||
|
|
if (MRA_DEBUG) cerr << "#3d" << endl;
|
||
|
|
t1zMin = t1zMin > z ? z : t1zMin;
|
||
|
|
t1zMax = t1zMax < z ? z : t1zMax;
|
||
|
|
t1Intersects = true;
|
||
|
|
}
|
||
|
|
|
||
|
|
double t2zMin = dt;
|
||
|
|
double t2zMax = 0;
|
||
|
|
|
||
|
|
bool t2Intersects = false;
|
||
|
|
|
||
|
|
if (specialSegmentIntersects2(
|
||
|
|
0, t2p1x, t2p1y, t2p2x, t2p2y, P, Q)) {
|
||
|
|
if (MRA_DEBUG) cerr << "#4a" << endl;
|
||
|
|
t2zMin = t2zMin > 0 ? 0 : t2zMin;
|
||
|
|
t2zMax = t2zMax < 0 ? 0 : t2zMax;
|
||
|
|
t2Intersects = true;
|
||
|
|
}
|
||
|
|
if (specialSegmentIntersects2(
|
||
|
|
dt, t2p3x, t2p3y, t2p4x, t2p4y, P, Q)) {
|
||
|
|
if (MRA_DEBUG) cerr << "#4b" << endl;
|
||
|
|
t2zMin = t2zMin > dt ? dt : t2zMin;
|
||
|
|
t2zMax = t2zMax < dt ? dt : t2zMax;
|
||
|
|
t2Intersects = true;
|
||
|
|
}
|
||
|
|
if (specialSegmentIntersects1(
|
||
|
|
dt,
|
||
|
|
t2p1x, t2p1y, t2p3x, t2p3y,
|
||
|
|
P[0], P[1], P[0]+Q[0], P[1]+Q[1], z)) {
|
||
|
|
if (MRA_DEBUG) cerr << "#4c" << endl;
|
||
|
|
t2zMin = t2zMin > z ? z : t2zMin;
|
||
|
|
t2zMax = t2zMax < z ? z : t2zMax;
|
||
|
|
t2Intersects = true;
|
||
|
|
}
|
||
|
|
if (specialSegmentIntersects1(
|
||
|
|
dt,
|
||
|
|
t2p2x, t2p2y, t2p4x, t2p4y,
|
||
|
|
P[0], P[1], P[0]+Q[0], P[1]+Q[1], z)) {
|
||
|
|
if (MRA_DEBUG) cerr << "#4d" << endl;
|
||
|
|
t2zMin = t2zMin > z ? z : t2zMin;
|
||
|
|
t2zMax = t2zMax < z ? z : t2zMax;
|
||
|
|
t2Intersects = true;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (MRA_DEBUG) {
|
||
|
|
cerr << "specialTrapeziumIntersects() dt="
|
||
|
|
<< dt
|
||
|
|
<< endl;
|
||
|
|
cerr << "specialTrapeziumIntersects() t1Intersects="
|
||
|
|
<< t1Intersects
|
||
|
|
<< endl;
|
||
|
|
if (t1Intersects)
|
||
|
|
cerr << "specialTrapeziumIntersects() t1zMin="
|
||
|
|
<< t1zMin
|
||
|
|
<< " t1zMax="
|
||
|
|
<< t1zMax
|
||
|
|
<< endl;
|
||
|
|
cerr << "specialTrapeziumIntersects() t2Intersects="
|
||
|
|
<< t2Intersects
|
||
|
|
<< endl;
|
||
|
|
if (t2Intersects)
|
||
|
|
cerr << "specialTrapeziumIntersects() t2zMin="
|
||
|
|
<< t2zMin
|
||
|
|
<< " t2zMax="
|
||
|
|
<< t2zMax
|
||
|
|
<< endl;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (t1Intersects
|
||
|
|
&& t2Intersects
|
||
|
|
&& !(lower(t1zMax, t2zMin) || lower(t2zMax, t1zMin))
|
||
|
|
&& !(nearlyEqual(t1zMax, 0.0)
|
||
|
|
&& nearlyEqual(t1zMin, 0.0)
|
||
|
|
&& nearlyEqual(t2zMax, 0.0)
|
||
|
|
&& nearlyEqual(t2zMin, 0.0))
|
||
|
|
&& !(nearlyEqual(t1zMax, dt)
|
||
|
|
&& nearlyEqual(t1zMin, dt)
|
||
|
|
&& nearlyEqual(t2zMax, dt)
|
||
|
|
&& nearlyEqual(t2zMin, dt))) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "specialTrapeziumIntersects() intersect"
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
detailedResult = 8;
|
||
|
|
return true;
|
||
|
|
} else {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "specialTrapeziumIntersects() "
|
||
|
|
<< "no intersection"
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
detailedResult = 9;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1 Other intersections
|
||
|
|
|
||
|
|
This section contains functions which examine the intersection between two
|
||
|
|
different object types (such as trapezium and segment).
|
||
|
|
|
||
|
|
1.1.1 Function ~specialInsidePointTrapezium()~
|
||
|
|
|
||
|
|
Return ~true~ if the point $(x, y, t)$ is within the trapezium spanned by the
|
||
|
|
segments $(l1p1x, l1p1y, t1)$ to $(l1p2x, l1p2y, t1)$ and
|
||
|
|
$(l2p1x, l2p1y, t2)$ to $(l2p2x, l2p2y, t2)$.
|
||
|
|
|
||
|
|
*/
|
||
|
|
bool specialInsidePointTrapezium(double t,
|
||
|
|
double x,
|
||
|
|
double y,
|
||
|
|
double t1,
|
||
|
|
double l1p1x,
|
||
|
|
double l1p1y,
|
||
|
|
double l1p2x,
|
||
|
|
double l1p2y,
|
||
|
|
double t2,
|
||
|
|
double l2p1x,
|
||
|
|
double l2p1y,
|
||
|
|
double l2p2x,
|
||
|
|
double l2p2y) {
|
||
|
|
if (MRA_DEBUG) cerr << "sIPT() called" << endl;
|
||
|
|
|
||
|
|
/*
|
||
|
|
Check if $t1 <= t <= t2$ or $t2 <= t < t1$ holds. If not, no intersection
|
||
|
|
can occur.
|
||
|
|
|
||
|
|
*/
|
||
|
|
if (!(lowerOrNearlyEqual(t1, t)
|
||
|
|
&& lowerOrNearlyEqual(t, t2))
|
||
|
|
&& !(lowerOrNearlyEqual(t2, t)
|
||
|
|
&& lowerOrNearlyEqual(t, t1))) {
|
||
|
|
if (MRA_DEBUG) cerr << "sIPT() t check failed" << endl;
|
||
|
|
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (MRA_DEBUG) cerr << "sIPT() t check succeeded" << endl;
|
||
|
|
|
||
|
|
/*
|
||
|
|
Calculate the points $(x1, y1, t)$ and $(x2, y2, t)$, which are the end
|
||
|
|
points of a segment parallel to $(l1p1x, l1p1y, t1)$ to $(l1p2x, l1p2y, t1)$
|
||
|
|
and ($l2p1x, l2p1y, t2$ to $(l2p2x, l2p2y, t2)$ and which is located between
|
||
|
|
these two segments.
|
||
|
|
|
||
|
|
*/
|
||
|
|
double x1;
|
||
|
|
double y1;
|
||
|
|
double x2;
|
||
|
|
double y2;
|
||
|
|
|
||
|
|
if (nearlyEqual(t1, t2)) {
|
||
|
|
x1 = l1p1x;
|
||
|
|
y1 = l1p1y;
|
||
|
|
x2 = l1p2x;
|
||
|
|
y2 = l1p2y;
|
||
|
|
} else {
|
||
|
|
double f = (t-t1)/(t2-t1);
|
||
|
|
|
||
|
|
if (MRA_DEBUG) cerr << "sIPT() f=" << f << endl;
|
||
|
|
|
||
|
|
x1 = l1p1x+(l2p1x-l1p1x)*f;
|
||
|
|
y1 = l1p1y+(l2p1y-l1p1y)*f;
|
||
|
|
x2 = l1p2x+(l2p2x-l1p2x)*f;
|
||
|
|
y2 = l1p2y+(l2p2y-l1p2y)*f;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "sIPT() x1=" << x1
|
||
|
|
<< " y1=" << y1
|
||
|
|
<< " x2=" << x2
|
||
|
|
<< " y2=" << y2
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
/*
|
||
|
|
If $(x, y, t)$ is located on segment $(x1, y1, t)$ and $(x2, y2, t)$, the
|
||
|
|
point is inside the trapezium, and outside otherwise.
|
||
|
|
|
||
|
|
*/
|
||
|
|
if (((lowerOrNearlyEqual(x1, x)
|
||
|
|
&& lowerOrNearlyEqual(x, x2))
|
||
|
|
|| (lowerOrNearlyEqual(x2, x)
|
||
|
|
&& lowerOrNearlyEqual(x, x1)))
|
||
|
|
&& ((lowerOrNearlyEqual(y1, y)
|
||
|
|
&& lowerOrNearlyEqual(y, y2))
|
||
|
|
|| (lowerOrNearlyEqual(y2, y)
|
||
|
|
&& lowerOrNearlyEqual(y, y1)))) {
|
||
|
|
if (MRA_DEBUG) cerr << "sIPT() inside" << endl;
|
||
|
|
|
||
|
|
return true;
|
||
|
|
} else {
|
||
|
|
if (MRA_DEBUG) cerr << "sIPT() not inside" << endl;
|
||
|
|
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1 Function ~specialIntersectionTrapeziumSegment()~
|
||
|
|
|
||
|
|
Calculates the intersection of a trapezium and a segment
|
||
|
|
in three-dimensional space $(x, y, t)$.
|
||
|
|
|
||
|
|
The trapezium is spanned by the points ~(l1p1x, l1p1y, t1)~,
|
||
|
|
~(l1p2x, l1p2y, t1)~, ~(l2p1x, l2p1y, t2)~ and
|
||
|
|
~(l2p2x, l2p2y, t2)~. ~(l1p1x, l1p1y, t1)=(l1p2x, l1p2y, t1)~ or
|
||
|
|
~(l2p1x, l2p1y, t2)=(l2p2x, l2p2y, t2)~ is allowed but not both.
|
||
|
|
~l1t=l2t~ is allowed.
|
||
|
|
|
||
|
|
The segment is spanned by the points ~(p1x, p1y, t1)~ and ~(p2x, p2y, t2)~.
|
||
|
|
~(p1x, p1y, t1)=(p2x, p2y, t1)~ is allowed.
|
||
|
|
|
||
|
|
~t1=t2~ is allowed.
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
void specialIntersectionTrapeziumSegment(double t1,
|
||
|
|
double t2,
|
||
|
|
double l1p1x,
|
||
|
|
double l1p1y,
|
||
|
|
double l1p2x,
|
||
|
|
double l1p2y,
|
||
|
|
double l2p1x,
|
||
|
|
double l2p1y,
|
||
|
|
double l2p2x,
|
||
|
|
double l2p2y,
|
||
|
|
double p1x,
|
||
|
|
double p1y,
|
||
|
|
double p2x,
|
||
|
|
double p2y,
|
||
|
|
bool& ip1present,
|
||
|
|
double& ip1x,
|
||
|
|
double& ip1y,
|
||
|
|
double& ip1t, // sometimes not set!
|
||
|
|
bool& ip2present,
|
||
|
|
double& ip2x,
|
||
|
|
double& ip2y,
|
||
|
|
double& ip2t // sometimes not set!
|
||
|
|
)
|
||
|
|
{
|
||
|
|
if (MRA_DEBUG) {
|
||
|
|
cerr << "sITS() called" << endl;
|
||
|
|
cerr << "sITS() t1=" << t1
|
||
|
|
<< " t2=" << t2
|
||
|
|
<< " l1=[" << l1p1x << " " << l1p1y
|
||
|
|
<< " " << l1p2x << " " << l1p2y
|
||
|
|
<< "] l2=[" << l2p1x << " " << l2p1y
|
||
|
|
<< " " << l2p2x << " " << l2p2y
|
||
|
|
<< "] p=(" << p1x << " " << p1y
|
||
|
|
<< " " << p2x << " " << p2y << ")"
|
||
|
|
<< endl;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/*
|
||
|
|
Check bounding boxes in $(x, y)$-plane of trapzium and segment. If they
|
||
|
|
do not overlap, trapezium and segment do not intersect.
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
double tMinX;
|
||
|
|
double tMaxX;
|
||
|
|
double tMinY;
|
||
|
|
double tMaxY;
|
||
|
|
|
||
|
|
minmax4(l1p1x, l1p2x, l2p1x, l2p2x, tMinX, tMaxX);
|
||
|
|
minmax4(l1p1y, l1p2y, l2p1y, l2p2y, tMinY, tMaxY);
|
||
|
|
|
||
|
|
double lMinX = p1x < p2x ? p1x : p2x;
|
||
|
|
double lMaxX = p1x > p2x ? p1x : p2x;
|
||
|
|
double lMinY = p1y < p2y ? p1y : p2y;
|
||
|
|
double lMaxY = p1y > p2y ? p1y : p2y;
|
||
|
|
|
||
|
|
if (lower(tMaxX, lMinX)
|
||
|
|
|| lower(lMaxX, tMinX)
|
||
|
|
|| lower(tMaxY, lMinY)
|
||
|
|
|| lower(lMaxY, tMinY)) {
|
||
|
|
if (MRA_DEBUG) cerr << "sITS() no bbox overlap" << endl;
|
||
|
|
|
||
|
|
ip1present = false;
|
||
|
|
ip2present = false;
|
||
|
|
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
Create equations for the plane spanned by the trapezium and the line
|
||
|
|
through the segment. Keep in mind that the trapezium might be a triangle
|
||
|
|
and that the line might be point only.
|
||
|
|
|
||
|
|
The plane is $P1+P2\cdot (s, t)$, where $T1$ is a vector with three elements
|
||
|
|
and $T2$ a matrix with three rows and two columns, and the line is
|
||
|
|
$L1+L2\cdot u$, where both $L1$ and $L2$ are vectors with three elements.
|
||
|
|
|
||
|
|
The interesection between plane and line is the solution of the equation
|
||
|
|
$P2\cdot (s, t)-L2\cdot u=L1-T1$. Present the left handed side by the
|
||
|
|
matrix $A$ with three rows and three colums and the right handed side by
|
||
|
|
the verctor $B$ with three elements.
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
double A[3][3];
|
||
|
|
double B[3];
|
||
|
|
|
||
|
|
if (nearlyEqual(l1p1x, l1p2x) && nearlyEqual(l1p1y, l1p2y)) {
|
||
|
|
B[0] = -l2p1x;
|
||
|
|
B[1] = -l2p1y;
|
||
|
|
B[2] = -t2;
|
||
|
|
|
||
|
|
A[0][0] = l2p2x-l2p1x;
|
||
|
|
A[1][0] = l2p2y-l2p1y;
|
||
|
|
A[2][0] = 0;
|
||
|
|
A[0][1] = l1p1x-l2p1x;
|
||
|
|
A[1][1] = l1p1y-l2p1y;
|
||
|
|
A[2][1] = t1-t2;
|
||
|
|
} else {
|
||
|
|
B[0] = -l1p1x;
|
||
|
|
B[1] = -l1p1y;
|
||
|
|
B[2] = -t1;
|
||
|
|
|
||
|
|
A[0][0] = l1p2x-l1p1x;
|
||
|
|
A[1][0] = l1p2y-l1p1y;
|
||
|
|
A[2][0] = 0;
|
||
|
|
A[0][1] = l2p1x-l1p1x;
|
||
|
|
A[1][1] = l2p1y-l1p1y;
|
||
|
|
A[2][1] = t2-t1;
|
||
|
|
}
|
||
|
|
|
||
|
|
B[0] += p1x;
|
||
|
|
B[1] += p1y;
|
||
|
|
B[2] += t1;
|
||
|
|
|
||
|
|
A[0][2] = p1x-p2x;
|
||
|
|
A[1][2] = p1y-p2y;
|
||
|
|
A[2][2] = t1-t2;
|
||
|
|
|
||
|
|
/*
|
||
|
|
Apply Gauss elimination.
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
double* Ap[3];
|
||
|
|
for (unsigned int i = 0; i < 3; i++) Ap[i] = A[i];
|
||
|
|
|
||
|
|
GaussTransform(3, 3, Ap, B);
|
||
|
|
|
||
|
|
/*
|
||
|
|
Analyse solutions.
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
if (nearlyEqual(A[2][2], 0.0)) {
|
||
|
|
if (nearlyEqual(B[2], 0.0)) {
|
||
|
|
/*
|
||
|
|
Segment in same plane as trapezium.
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
if (MRA_DEBUG) cerr << "sITS() in same plane" << endl;
|
||
|
|
/*
|
||
|
|
The following cases have to be considered: Segment entirely outside
|
||
|
|
trapezium, segment entirely inside trapezium, $(p1x, p1y, t1)$ inside
|
||
|
|
trapezium, $(p2x, p2y, t2)$ inside trapezium and $(p1x, p1y, t1)$ and
|
||
|
|
$(p2x, p2y, t2)$ outside trapezium but still intersecting with trapezium.
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
bool p1in =
|
||
|
|
between(l1p1x, p1x, l1p2x)
|
||
|
|
&& between(l1p1y, p1y, l1p2y);
|
||
|
|
bool p2in =
|
||
|
|
between(l2p1x, p2x, l2p2x)
|
||
|
|
&& between(l2p1y, p2y, l2p2y);
|
||
|
|
|
||
|
|
if (p1in && p2in) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "sITS() entirely in trapezium"
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
ip1present = true;
|
||
|
|
ip2present = true;
|
||
|
|
|
||
|
|
ip1x = p1x;
|
||
|
|
ip1y = p1y;
|
||
|
|
ip1t = t1;
|
||
|
|
|
||
|
|
ip2x = p2x;
|
||
|
|
ip2y = p2y;
|
||
|
|
ip2t = t2;
|
||
|
|
|
||
|
|
return;
|
||
|
|
} else {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "sITS() not entirely in trapezium"
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
double l1p1t = 0.0;
|
||
|
|
bool l1p1is =
|
||
|
|
specialSegmentIntersects1(
|
||
|
|
t2-t1,
|
||
|
|
l1p1x, l1p1y, l2p1x, l2p1y,
|
||
|
|
p1x, p1y, p2x, p2y,
|
||
|
|
l1p1t);
|
||
|
|
|
||
|
|
double l1p2t = 0.0;
|
||
|
|
bool l1p2is =
|
||
|
|
specialSegmentIntersects1(
|
||
|
|
t2-t1,
|
||
|
|
l1p2x, l1p2y, l2p2x, l2p2y,
|
||
|
|
p1x, p1y, p2x, p2y,
|
||
|
|
l1p2t);
|
||
|
|
|
||
|
|
if (p1in) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "sITS() p1 in trapezium"
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
// assert(l1p1is || l1p2is);
|
||
|
|
if (!l1p1is && !l1p2is) {
|
||
|
|
stringstream msg;
|
||
|
|
msg << "Contradicting results for intersection"
|
||
|
|
<< endl
|
||
|
|
<< " between trapezium and segment (#1)."
|
||
|
|
<< endl
|
||
|
|
<< "Trapezium is: ("
|
||
|
|
<< l1p1x << " " << l1p1y
|
||
|
|
<< ") ("
|
||
|
|
<< l1p2x << " " << l1p2y
|
||
|
|
<< ") ("
|
||
|
|
<< l2p1x << " " << l2p1y
|
||
|
|
<< ") ("
|
||
|
|
<< l2p2x << " " << l2p2y
|
||
|
|
<< ")"
|
||
|
|
<< endl
|
||
|
|
<< "Segment is: ("
|
||
|
|
<< p1x << " " << p1y
|
||
|
|
<< ") ("
|
||
|
|
<< p2x << " " << p2y
|
||
|
|
<< ")"
|
||
|
|
<< endl
|
||
|
|
<< "It is very likely that this has been"
|
||
|
|
<< " caused by rounding errors."
|
||
|
|
<< endl
|
||
|
|
<< "Try adjusting the precision with the "
|
||
|
|
<< " mraprec operator (if available in this"
|
||
|
|
<< " build of the MovingRegionAlgebra)."
|
||
|
|
<< endl;
|
||
|
|
throw invalid_argument(msg.str());
|
||
|
|
}
|
||
|
|
|
||
|
|
ip1present = true;
|
||
|
|
ip2present = true;
|
||
|
|
|
||
|
|
ip1x = p1x;
|
||
|
|
ip1y = p1y;
|
||
|
|
ip1t = t1;
|
||
|
|
|
||
|
|
if (l1p1is) {
|
||
|
|
ip2x = p1x+(p2x-p1x)*l1p1t/(t2-t1);
|
||
|
|
ip2y = p1y+(p2y-p1y)*l1p1t/(t2-t1);
|
||
|
|
ip2t = l1p1t;
|
||
|
|
} else {
|
||
|
|
ip2x = p1x+(p2x-p1x)*l1p2t/(t2-t1);
|
||
|
|
ip2y = p1y+(p2y-p1y)*l1p2t/(t2-t1);
|
||
|
|
ip2t = l1p2t;
|
||
|
|
}
|
||
|
|
|
||
|
|
return;
|
||
|
|
} else if (p2in) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "sITS() p2 in trapezium"
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
// assert(l1p1is || l1p2is);
|
||
|
|
if (!l1p1is && !l1p2is) {
|
||
|
|
stringstream msg;
|
||
|
|
msg << "Contradicting results for intersection"
|
||
|
|
<< endl
|
||
|
|
<< " between trapezium and segment (#2)."
|
||
|
|
<< endl
|
||
|
|
<< "Trapezium is: ("
|
||
|
|
<< l1p1x << " " << l1p1y
|
||
|
|
<< ") ("
|
||
|
|
<< l1p2x << " " << l1p2y
|
||
|
|
<< ") ("
|
||
|
|
<< l2p1x << " " << l2p1y
|
||
|
|
<< ") ("
|
||
|
|
<< l2p2x << " " << l2p2y
|
||
|
|
<< ")"
|
||
|
|
<< endl
|
||
|
|
<< "Segment is: ("
|
||
|
|
<< p1x << " " << p1y
|
||
|
|
<< ") ("
|
||
|
|
<< p2x << " " << p2y
|
||
|
|
<< ")"
|
||
|
|
<< endl
|
||
|
|
<< "It is very likely that this has been"
|
||
|
|
<< " caused by rounding errors."
|
||
|
|
<< endl
|
||
|
|
<< "Try adjusting the precision with the "
|
||
|
|
<< " mraprec operator (if available in this"
|
||
|
|
<< " build of the MovingRegionAlgebra)."
|
||
|
|
<< endl;
|
||
|
|
throw invalid_argument(msg.str());
|
||
|
|
}
|
||
|
|
|
||
|
|
ip1present = true;
|
||
|
|
ip2present = true;
|
||
|
|
|
||
|
|
ip2x = p2x;
|
||
|
|
ip2y = p2y;
|
||
|
|
ip2t = t2;
|
||
|
|
|
||
|
|
if (l1p1is) {
|
||
|
|
ip1x = p1x+(p2x-p1x)*l1p1t/(t2-t1);
|
||
|
|
ip1y = p1y+(p2y-p1y)*l1p1t/(t2-t1);
|
||
|
|
ip1t = l1p1t;
|
||
|
|
} else {
|
||
|
|
ip1x = p1x+(p2x-p1x)*l1p2t/(t2-t1);
|
||
|
|
ip1y = p1y+(p2y-p1y)*l1p2t/(t2-t1);
|
||
|
|
ip1t = l1p2t;
|
||
|
|
}
|
||
|
|
|
||
|
|
return;
|
||
|
|
} else {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "sITS() neither p1 nor p2 in "
|
||
|
|
<< "trapezium"
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
if (l1p1is && l1p2is) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "sITS() intersects trapezium"
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
ip1present = true;
|
||
|
|
ip2present = true;
|
||
|
|
|
||
|
|
if (l1p1t < l1p2t) {
|
||
|
|
ip1x = p1x+(p2x-p1x)*l1p1t/(t2-t1);
|
||
|
|
ip1y = p1y+(p2y-p1y)*l1p1t/(t2-t1);
|
||
|
|
ip1t = l1p1t;
|
||
|
|
|
||
|
|
ip2x = p1x+(p2x-p1x)*l1p2t/(t2-t1);
|
||
|
|
ip2y = p1y+(p2y-p1y)*l1p2t/(t2-t1);
|
||
|
|
ip2t = l1p2t;
|
||
|
|
} else {
|
||
|
|
ip1x = p1x+(p2x-p1x)*l1p2t/(t2-t1);
|
||
|
|
ip1y = p1y+(p2y-p1y)*l1p2t/(t2-t1);
|
||
|
|
ip1t = l1p2t;
|
||
|
|
|
||
|
|
ip2x = p1x+(p2x-p1x)*l1p1t/(t2-t1);
|
||
|
|
ip2y = p1y+(p2y-p1y)*l1p1t/(t2-t1);
|
||
|
|
ip2t = l1p1t;
|
||
|
|
}
|
||
|
|
|
||
|
|
return;
|
||
|
|
} else {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "sITS() entirely outside "
|
||
|
|
<< "trapezium"
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
// assert(!l1p1is && !l1p2is);
|
||
|
|
if (l1p1is || l1p2is) {
|
||
|
|
stringstream msg;
|
||
|
|
msg << "Contradicting results for intersection"
|
||
|
|
<< endl
|
||
|
|
<< " between trapezium and segment (#2)."
|
||
|
|
<< endl
|
||
|
|
<< "Trapezium is: ("
|
||
|
|
<< l1p1x << " " << l1p1y
|
||
|
|
<< ") ("
|
||
|
|
<< l1p2x << " " << l1p2y
|
||
|
|
<< ") ("
|
||
|
|
<< l2p1x << " " << l2p1y
|
||
|
|
<< ") ("
|
||
|
|
<< l2p2x << " " << l2p2y
|
||
|
|
<< ")"
|
||
|
|
<< endl
|
||
|
|
<< "Segment is: ("
|
||
|
|
<< p1x << " " << p1y
|
||
|
|
<< ") ("
|
||
|
|
<< p2x << " " << p2y
|
||
|
|
<< ")"
|
||
|
|
<< endl
|
||
|
|
<< "It is very likely that this has been"
|
||
|
|
<< " caused by rounding errors."
|
||
|
|
<< endl
|
||
|
|
<< "Try adjusting the precision with the "
|
||
|
|
<< " mraprec operator (if available in this"
|
||
|
|
<< " build of the MovingRegionAlgebra)."
|
||
|
|
<< endl;
|
||
|
|
throw invalid_argument(msg.str());
|
||
|
|
}
|
||
|
|
|
||
|
|
ip1present = false;
|
||
|
|
ip2present = false;
|
||
|
|
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
} else {
|
||
|
|
/*
|
||
|
|
Segment in different plane as trapezium but parallel to trapezium.
|
||
|
|
|
||
|
|
*/
|
||
|
|
if (MRA_DEBUG) cerr << "sITS() no solution" << endl;
|
||
|
|
|
||
|
|
ip1present = false;
|
||
|
|
ip2present = false;
|
||
|
|
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
/*
|
||
|
|
Segment not parallel to trapezium.
|
||
|
|
|
||
|
|
*/
|
||
|
|
double u = B[2]/A[2][2];
|
||
|
|
double x = p1x+(p2x-p1x)*u;
|
||
|
|
double y = p1y+(p2y-p1y)*u;
|
||
|
|
double t = t1+(t2-t1)*u;
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "sITS() intersection with u="
|
||
|
|
<< u
|
||
|
|
<< " (" << x << " " << y << " " << t << ")"
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
ip2present = false;
|
||
|
|
|
||
|
|
if (specialInsidePointTrapezium(
|
||
|
|
t, x, y,
|
||
|
|
t1, l1p1x, l1p1y, l1p2x, l1p2y,
|
||
|
|
t2, l2p1x, l2p1y, l2p2x, l2p2y)) {
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "sITS() intersection is inside" << endl;
|
||
|
|
|
||
|
|
ip1present = true;
|
||
|
|
|
||
|
|
ip1x = x;
|
||
|
|
ip1y = y;
|
||
|
|
ip1t = t;
|
||
|
|
} else {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "sITS() intersection is not inside" << endl;
|
||
|
|
|
||
|
|
ip1present = false;
|
||
|
|
}
|
||
|
|
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1 Relative positions of points and segments
|
||
|
|
|
||
|
|
1.1.1 Function ~pointAboveSegment()~
|
||
|
|
|
||
|
|
Returns ~true~ if point $(x, y)$ is located left or above or on segment
|
||
|
|
spanned by the points $(p1x, p1y)$ and $(p2x, p2y)$. This matches the
|
||
|
|
definition of the ~insideAbove~ attribute in ~Region~ and ~URegion~
|
||
|
|
instances.
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
static bool pointAboveSegment(double x,
|
||
|
|
double y,
|
||
|
|
double p1x,
|
||
|
|
double p1y,
|
||
|
|
double p2x,
|
||
|
|
double p2y) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "pointAboveSegment() called p=(" << x << " " << y
|
||
|
|
<< ") p1=(" << p1x << " " << p1y
|
||
|
|
<< ") p2=(" << p2x << " " << p2y << ")"
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
if (nearlyEqual(p1x, p2x)) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "pointAboveSegment() p1x=p2x" << endl;
|
||
|
|
|
||
|
|
return x <= p1x;
|
||
|
|
} else if (nearlyEqual(p1y, p2y)) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "pointAboveSegment() p1y=p2y" << endl;
|
||
|
|
|
||
|
|
return y >= p1y;
|
||
|
|
} else {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "pointAboveSegment() other" << endl;
|
||
|
|
|
||
|
|
double t = (x-p1x)/(p2x-p1x);
|
||
|
|
double py = p1y+(p2y-p1y)*t;
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "pointAboveSegment() py=" << py << endl;
|
||
|
|
|
||
|
|
return y >= py;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1 Function ~restrictUPointToInterval()~
|
||
|
|
|
||
|
|
Create new ~UPoint~ instance in ~rUp~ from ~up~, which is restricted to
|
||
|
|
interval ~iv~.
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
static void restrictUPointToInterval(const UPoint& up,
|
||
|
|
const Interval<Instant> iv,
|
||
|
|
UPoint& rUp) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "restrictUPointToInterval() called" << endl;
|
||
|
|
|
||
|
|
if (nearlyEqual(iv.start.ToDouble(), iv.end.ToDouble()))
|
||
|
|
rUp = up;
|
||
|
|
else {
|
||
|
|
double ti =
|
||
|
|
(iv.start.ToDouble()
|
||
|
|
-up.timeInterval.start.ToDouble())
|
||
|
|
/(up.timeInterval.end.ToDouble()
|
||
|
|
-up.timeInterval.start.ToDouble());
|
||
|
|
double tf =
|
||
|
|
(iv.end.ToDouble()
|
||
|
|
-up.timeInterval.start.ToDouble())
|
||
|
|
/(up.timeInterval.end.ToDouble()
|
||
|
|
-up.timeInterval.start.ToDouble());
|
||
|
|
|
||
|
|
UPoint dummy(
|
||
|
|
iv,
|
||
|
|
up.p0.GetX()+(up.p1.GetX()-up.p0.GetX())*ti,
|
||
|
|
up.p0.GetY()+(up.p1.GetY()-up.p0.GetY())*ti,
|
||
|
|
up.p0.GetX()+(up.p1.GetX()-up.p0.GetX())*tf,
|
||
|
|
up.p0.GetY()+(up.p1.GetY()-up.p0.GetY())*tf);
|
||
|
|
|
||
|
|
rUp = dummy;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1 Supporting classes and class template
|
||
|
|
|
||
|
|
Supporting classes are those, which are not registered as SECONDO datatypes
|
||
|
|
but are used to implement the SECONDO datatypes ~iregion~, ~uregion~ and
|
||
|
|
~mregion~.
|
||
|
|
|
||
|
|
1.1 Class ~MSegmentData~
|
||
|
|
|
||
|
|
This class is used to represent the segments, which are used to represent
|
||
|
|
region units in section \ref{uregion}.
|
||
|
|
|
||
|
|
1.1.1 Class definition
|
||
|
|
|
||
|
|
The class definition has been moved to ~MovingRegionAlgebra.h~.
|
||
|
|
|
||
|
|
1.1.1 Constructor
|
||
|
|
\label{collinear}
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
MSegmentData::MSegmentData(
|
||
|
|
unsigned int fno,
|
||
|
|
unsigned int cno,
|
||
|
|
unsigned int sno,
|
||
|
|
bool ia,
|
||
|
|
double isx,
|
||
|
|
double isy,
|
||
|
|
double iex,
|
||
|
|
double iey,
|
||
|
|
double fsx,
|
||
|
|
double fsy,
|
||
|
|
double fex,
|
||
|
|
double fey) :
|
||
|
|
faceno(fno),
|
||
|
|
cycleno(cno),
|
||
|
|
segmentno(sno),
|
||
|
|
insideAbove(ia),
|
||
|
|
degeneratedInitialNext(-1),
|
||
|
|
degeneratedFinalNext(-1),
|
||
|
|
degeneratedInitial(DGM_UNKNOWN),
|
||
|
|
degeneratedFinal(DGM_UNKNOWN),
|
||
|
|
initialStartX(isx),
|
||
|
|
initialStartY(isy),
|
||
|
|
initialEndX(iex),
|
||
|
|
initialEndY(iey),
|
||
|
|
finalStartX(fsx),
|
||
|
|
finalStartY(fsy),
|
||
|
|
finalEndX(fex),
|
||
|
|
finalEndY(fey) {
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "MSegmentData::MSegmentData() #2 "
|
||
|
|
<< "called counter=["
|
||
|
|
<< faceno << " " << cycleno << " " << segmentno
|
||
|
|
<< "] flags=["
|
||
|
|
<< insideAbove
|
||
|
|
<< " " << degeneratedInitialNext
|
||
|
|
<< " " << degeneratedFinalNext
|
||
|
|
<< "] initial=["
|
||
|
|
<< initialStartX << " " << initialStartY
|
||
|
|
<< " "
|
||
|
|
<< initialEndX << " " << initialEndY
|
||
|
|
<< "] final=["
|
||
|
|
<< finalStartX << " " << finalStartY
|
||
|
|
<< " "
|
||
|
|
<< finalEndX << " " << finalEndY
|
||
|
|
<< "]"
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
/*
|
||
|
|
Calculate whether segment is point in initial or final instant.
|
||
|
|
|
||
|
|
*/
|
||
|
|
pointInitial =
|
||
|
|
nearlyEqual(isx, iex) && nearlyEqual(isy, iey);
|
||
|
|
pointFinal =
|
||
|
|
nearlyEqual(fsx, fex) && nearlyEqual(fsy, fey);
|
||
|
|
|
||
|
|
/*
|
||
|
|
Check whether initial and final segment are collinear,
|
||
|
|
|
||
|
|
*/
|
||
|
|
bool collinear;
|
||
|
|
|
||
|
|
if (pointInitial && pointFinal) {
|
||
|
|
/*
|
||
|
|
Error: A segment may not be reduced to a point both in initial and final
|
||
|
|
instant.
|
||
|
|
|
||
|
|
*/
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "MSegmentData::MSegmentData() both reduced"
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
throw invalid_argument("both initial and final segment "
|
||
|
|
"reduced to point, which is not "
|
||
|
|
"allowed");
|
||
|
|
} else if (pointInitial) {
|
||
|
|
/*
|
||
|
|
Only initial segment reduced to point. Initial and final segment are trivially
|
||
|
|
collinear.
|
||
|
|
|
||
|
|
*/
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "MSegmentData::MSegmentData() "
|
||
|
|
<< "initial reduced"
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
collinear = true;
|
||
|
|
} else if (pointFinal) {
|
||
|
|
/*
|
||
|
|
Only final segment reduced to point. Initial and final segment are trivially
|
||
|
|
collinear.
|
||
|
|
|
||
|
|
*/
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "MSegmentData::MSegmentData() "
|
||
|
|
<< "final reduced"
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
collinear = true;
|
||
|
|
} else if (nearlyEqual(isx, iex) && nearlyEqual(fsx, fex)) {
|
||
|
|
/*
|
||
|
|
Both segments are vertical. Check if both segments have the same
|
||
|
|
orientation.
|
||
|
|
|
||
|
|
*/
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "MSegmentData::MSegmentData() "
|
||
|
|
<< "both vertical"
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
collinear =
|
||
|
|
(lowerOrNearlyEqual(isy, iey)
|
||
|
|
&& lowerOrNearlyEqual(fsy, fey))
|
||
|
|
|| (greaterOrNearlyEqual(isy, iey)
|
||
|
|
&& greaterOrNearlyEqual(fsy, fey));
|
||
|
|
} else if (nearlyEqual(isx, iex) || nearlyEqual(fsx, fex)) {
|
||
|
|
/*
|
||
|
|
Only initial or final segment is vertical but not both.
|
||
|
|
|
||
|
|
*/
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "MSegmentData::MSegmentData() "
|
||
|
|
<< "one vertical" << endl;
|
||
|
|
|
||
|
|
collinear = false;
|
||
|
|
} else {
|
||
|
|
/*
|
||
|
|
Both segments are not vertical.
|
||
|
|
|
||
|
|
*/
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "MSegmentData::MSegmentData() "
|
||
|
|
<< "none vertical"
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
collinear =
|
||
|
|
abs((iey-isy)/(iex-isx)-(fey-fsy)/(fex-fsx))
|
||
|
|
<= eps*epsRelaxFactor
|
||
|
|
|| abs((iey-isy)*(fex-fsx)-(fey-fsy)*(iex-isx))
|
||
|
|
<= eps*epsRelaxFactor;
|
||
|
|
|
||
|
|
if (!collinear) {
|
||
|
|
cerr << setprecision(10)
|
||
|
|
<< "parameters for segment orientation comparison:"
|
||
|
|
<< endl
|
||
|
|
<< " 1. (iey-isy)/(iex-isx) = "
|
||
|
|
<< (iey-isy)/(iex-isx)
|
||
|
|
<< endl
|
||
|
|
<< " 2. (fey-fsy)/(fex-fsx) = "
|
||
|
|
<< (fey-fsy)/(fex-fsx)
|
||
|
|
<< endl
|
||
|
|
<< " 3. (iey-isy)*(fex-fsx) = "
|
||
|
|
<< (iey-isy)*(fex-fsx)
|
||
|
|
<< endl
|
||
|
|
<< " 4. (fey-fsy)*(iex-isx) = "
|
||
|
|
<< (fey-fsy)*(iex-isx)
|
||
|
|
<< endl
|
||
|
|
<< "1. and 2. or 3. and 4. should be equal."
|
||
|
|
<<"("<<isx<<";"<<isy<<")"
|
||
|
|
<<"("<<iex<<";"<<iey<<")"
|
||
|
|
<<"("<<fsx<<";"<<fsy<<")"
|
||
|
|
<<"("<<fex<<";"<<fey<<")"
|
||
|
|
<<fno<<" "
|
||
|
|
<<cno<<" "
|
||
|
|
<<sno
|
||
|
|
<< endl;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (MRA_DEBUG) {
|
||
|
|
cerr << ::std::fixed << ::std::setprecision(6);
|
||
|
|
cerr << "MSegmentData::MSegmentData() isx=" << isx
|
||
|
|
<< " isy=" << isy
|
||
|
|
<< " iex=" << iex
|
||
|
|
<< " iey=" << iey
|
||
|
|
<< " fsx=" << fsx
|
||
|
|
<< " fsy=" << fsy
|
||
|
|
<< " fex=" << fex
|
||
|
|
<< " fey=" << fey
|
||
|
|
<< endl;
|
||
|
|
cerr << "MSegmentData::MSegmentData() (iey-isy)/(iex-isx)="
|
||
|
|
<< (iey-isy)/(iex-isx) << endl;
|
||
|
|
cerr << "MSegmentData::MSegmentData() (fey-fsy)/(fex-fsx)="
|
||
|
|
<< (fey-fsy)/(fex-fsx) << endl;
|
||
|
|
cerr << "MSegmentData::MSegmentData() (iey-isy)*(fex-fsx)="
|
||
|
|
<< (iey-isy)*(fex-fsx) << endl;
|
||
|
|
cerr << "MSegmentData::MSegmentData() (fey-fsy)*(iex-isx)="
|
||
|
|
<< (fey-fsy)*(iex-isx) << endl;
|
||
|
|
cerr << "MSegmentData::MSegmentData() collinear="
|
||
|
|
<< collinear << endl;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!collinear)
|
||
|
|
throw
|
||
|
|
invalid_argument(
|
||
|
|
"initial and final segment not collinear");
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1 Other methods
|
||
|
|
|
||
|
|
1.1.1.1 Method ~restrictToInterval()~
|
||
|
|
|
||
|
|
*/
|
||
|
|
void MSegmentData::restrictToInterval(Interval<Instant> origIv,
|
||
|
|
Interval<Instant> restrIv,
|
||
|
|
MSegmentData& rDms) const {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "MSegmentData::restrictToInterval() called" << endl;
|
||
|
|
|
||
|
|
/*
|
||
|
|
Implementation is straightforward: Copy the attributes, which do not need to
|
||
|
|
be adjusted, and calculate the new initial and final end points.
|
||
|
|
|
||
|
|
*/
|
||
|
|
rDms.faceno = faceno;
|
||
|
|
rDms.cycleno = cycleno;
|
||
|
|
rDms.segmentno = segmentno;
|
||
|
|
|
||
|
|
rDms.insideAbove = insideAbove;
|
||
|
|
|
||
|
|
rDms.degeneratedInitialNext = degeneratedInitialNext;
|
||
|
|
rDms.degeneratedFinalNext = degeneratedFinalNext;
|
||
|
|
rDms.degeneratedInitial = degeneratedInitial;
|
||
|
|
rDms.degeneratedFinal = degeneratedFinal;
|
||
|
|
|
||
|
|
rDms.pointInitial = pointInitial;
|
||
|
|
rDms.pointFinal = pointFinal;
|
||
|
|
|
||
|
|
if (nearlyEqual(origIv.end.ToDouble(),
|
||
|
|
origIv.start.ToDouble())) {
|
||
|
|
rDms.initialStartX = initialStartX;
|
||
|
|
rDms.initialStartY = initialStartY;
|
||
|
|
rDms.initialEndX = initialEndX;
|
||
|
|
rDms.initialEndY = initialEndY;
|
||
|
|
rDms.finalStartX = finalStartX;
|
||
|
|
rDms.finalStartY = finalStartY;
|
||
|
|
rDms.finalEndX = finalEndX;
|
||
|
|
rDms.finalEndY = finalEndY;
|
||
|
|
} else {
|
||
|
|
double ti =
|
||
|
|
(restrIv.start.ToDouble()-origIv.start.ToDouble())
|
||
|
|
/(origIv.end.ToDouble()-origIv.start.ToDouble());
|
||
|
|
double tf =
|
||
|
|
(restrIv.end.ToDouble()-origIv.start.ToDouble())
|
||
|
|
/(origIv.end.ToDouble()-origIv.start.ToDouble());
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "MSegmentData::restrictToInterval() ti="
|
||
|
|
<< ti << " tf=" << tf
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
rDms.initialStartX =
|
||
|
|
initialStartX+(finalStartX-initialStartX)*ti;
|
||
|
|
rDms.initialStartY =
|
||
|
|
initialStartY+(finalStartY-initialStartY)*ti;
|
||
|
|
rDms.initialEndX =
|
||
|
|
initialEndX+(finalEndX-initialEndX)*ti;
|
||
|
|
rDms.initialEndY =
|
||
|
|
initialEndY+(finalEndY-initialEndY)*ti;
|
||
|
|
rDms.finalStartX =
|
||
|
|
initialStartX+(finalStartX-initialStartX)*tf;
|
||
|
|
rDms.finalStartY =
|
||
|
|
initialStartY+(finalStartY-initialStartY)*tf;
|
||
|
|
rDms.finalEndX =
|
||
|
|
initialEndX+(finalEndX-initialEndX)*tf;
|
||
|
|
rDms.finalEndY =
|
||
|
|
initialEndY+(finalEndY-initialEndY)*tf;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1.1 Method ~ToString()~
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
string MSegmentData::ToString(void) const {
|
||
|
|
ostringstream tmp;
|
||
|
|
|
||
|
|
tmp << "f/c/s=" << faceno
|
||
|
|
<< "/" << cycleno
|
||
|
|
<< "/" << segmentno
|
||
|
|
<< " initial: p/d/dn=" << pointInitial
|
||
|
|
<< "/" << degeneratedInitial
|
||
|
|
<< "/" << degeneratedInitialNext
|
||
|
|
<< " (" << initialStartX
|
||
|
|
<< ", " << initialStartY
|
||
|
|
<< ")-(" << initialEndX
|
||
|
|
<< ", " << initialEndY
|
||
|
|
<< ") final: p/d/dn=" << pointFinal
|
||
|
|
<< "/" << degeneratedFinal
|
||
|
|
<< "/" << degeneratedFinalNext
|
||
|
|
<< " (" << finalStartX
|
||
|
|
<< ", " << finalStartY
|
||
|
|
<< ")-(" << finalEndX
|
||
|
|
<< ", " << finalEndY
|
||
|
|
<< ")";
|
||
|
|
|
||
|
|
return tmp.str();
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1 Class ~TrapeziumSegmentIntersection~
|
||
|
|
|
||
|
|
1.1.1 Class definition
|
||
|
|
|
||
|
|
The class definition has been moved to ~MovingRegionAlgebra.h~.
|
||
|
|
|
||
|
|
1.1.1 Operator ~<~
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
bool TrapeziumSegmentIntersection::operator<(
|
||
|
|
const TrapeziumSegmentIntersection& tsi) const {
|
||
|
|
|
||
|
|
if (nearlyEqual(t, tsi.t)) {
|
||
|
|
return type < tsi.type;
|
||
|
|
} else
|
||
|
|
return t < tsi.t;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1 Class template ~RefinementPartition~
|
||
|
|
|
||
|
|
Moved to ~TemporalAlgbra.h~
|
||
|
|
|
||
|
|
|
||
|
|
1 Data type ~iregion~
|
||
|
|
|
||
|
|
1.1 Class ~IRegion~
|
||
|
|
|
||
|
|
1.1.1 Class definition
|
||
|
|
|
||
|
|
The class definition has been moved to ~MovingRegionAlgebra.h~.
|
||
|
|
|
||
|
|
1.1.1 Constructors
|
||
|
|
|
||
|
|
*/
|
||
|
|
IRegion::IRegion(bool dummy): Intime<Region>(0) {
|
||
|
|
MRA_TRACE;
|
||
|
|
|
||
|
|
/*
|
||
|
|
This is quite ugly and may not work with other compilers than gcc.
|
||
|
|
Since the ~Intime<Alpha>()~ constructors do not properly initialise their
|
||
|
|
~value~ attribute (which if of type ~Region~ in this case), there is
|
||
|
|
no better solution right now to assure that ~value~ has a valid DBArray.
|
||
|
|
|
||
|
|
*/
|
||
|
|
/*Region* tmp = new Region(0);
|
||
|
|
memcpy(&value, tmp, sizeof(*tmp));
|
||
|
|
delete(tmp);*/
|
||
|
|
value.SetEmpty();
|
||
|
|
value.SetDefined(true);
|
||
|
|
SetDefined(true);
|
||
|
|
}
|
||
|
|
|
||
|
|
IRegion::IRegion(const IRegion& ir) :
|
||
|
|
Intime<Region>(ir.instant, ir.value) {
|
||
|
|
MRA_TRACE;
|
||
|
|
if(!ir.IsDefined()){
|
||
|
|
SetDefined(false);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
IRegion::IRegion(const Instant& instant, const Region& region):
|
||
|
|
Intime<Region>(instant,region){}
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1 Methods for algebra integration
|
||
|
|
|
||
|
|
1.1.1.1 Method ~Clone()~
|
||
|
|
|
||
|
|
*/
|
||
|
|
IRegion* IRegion::Clone(void) const {
|
||
|
|
MRA_TRACE;
|
||
|
|
return new IRegion(*this);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1.1 ~DBArray~ access
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
int IRegion::NumOfFLOBs() const{
|
||
|
|
MRA_TRACE;
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
Flob* IRegion::GetFLOB(const int i) {
|
||
|
|
MRA_TRACE;
|
||
|
|
assert(i == 0);
|
||
|
|
return value.GetFLOB(0);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1 Algebra integration
|
||
|
|
|
||
|
|
1.1.1 Function ~IRegionProperty()~
|
||
|
|
|
||
|
|
*/
|
||
|
|
static ListExpr IRegionProperty() {
|
||
|
|
MRA_TRACE;
|
||
|
|
|
||
|
|
ListExpr example = nl->TextAtom();
|
||
|
|
nl->AppendText(example,
|
||
|
|
"(\"2003-01-10\" ((((1.0 3.5)(2.0 5.5)(3.0 6.5)(4.0 6.5)"
|
||
|
|
"(4.0 5.5)(5.0 4.5)(5.0 2.5)(4.0 1.5)(3.0 1.5))"
|
||
|
|
"((2.0 3.0)(2.0 4.0)(3.0 4.0)(3.0 3.0)))))");
|
||
|
|
return
|
||
|
|
nl->TwoElemList(
|
||
|
|
nl->FourElemList(
|
||
|
|
nl->StringAtom("Signature"),
|
||
|
|
nl->StringAtom("Example Type List"),
|
||
|
|
nl->StringAtom("List Rep"),
|
||
|
|
nl->StringAtom("Example List")),
|
||
|
|
nl->FourElemList(
|
||
|
|
nl->StringAtom("-> UNIT"),
|
||
|
|
nl->StringAtom("(iregion)"),
|
||
|
|
nl->StringAtom("(<instant> <region>)"),
|
||
|
|
example));
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1 Function ~CheckIRegion()~
|
||
|
|
|
||
|
|
*/
|
||
|
|
static bool CheckIRegion(ListExpr type, ListExpr& errorInfo) {
|
||
|
|
MRA_TRACE;
|
||
|
|
|
||
|
|
return nl->IsEqual(type, IRegion::BasicType())
|
||
|
|
|| nl->IsEqual(type, "intimeregion"); // backward-compatibility!
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1 Function ~CreateIRegion()~
|
||
|
|
|
||
|
|
*/
|
||
|
|
static Word CreateIRegion(const ListExpr typeInfo) {
|
||
|
|
if (MRA_DEBUG) cerr << "CreateIRegion() called" << endl;
|
||
|
|
|
||
|
|
return SetWord(new IRegion(false));
|
||
|
|
}
|
||
|
|
|
||
|
|
void*
|
||
|
|
CastIRegion( void* addr )
|
||
|
|
{
|
||
|
|
return (new (addr) IRegion);
|
||
|
|
}
|
||
|
|
|
||
|
|
int
|
||
|
|
SizeOfIRegion()
|
||
|
|
{
|
||
|
|
return sizeof(IRegion);
|
||
|
|
}
|
||
|
|
|
||
|
|
void DeleteIRegion(const ListExpr typeInfo, Word &w){
|
||
|
|
IRegion* ir = (IRegion*) w.addr;
|
||
|
|
delete ir;
|
||
|
|
w.addr=0;
|
||
|
|
}
|
||
|
|
|
||
|
|
void CloseIRegion(const ListExpr typeInfo, Word &w){
|
||
|
|
IRegion* ir = (IRegion*) w.addr;
|
||
|
|
delete ir;
|
||
|
|
w.addr=0;
|
||
|
|
}
|
||
|
|
|
||
|
|
Word CloneIRegion( const ListExpr typeInfo, const Word& w )
|
||
|
|
{
|
||
|
|
return SetWord( new IRegion( * ((IRegion*)w.addr)));
|
||
|
|
}
|
||
|
|
|
||
|
|
Word InIRegion(
|
||
|
|
const ListExpr typeInfo, const ListExpr instance,
|
||
|
|
const int errorPos, ListExpr& errorInfo, bool& correct ){
|
||
|
|
|
||
|
|
if(listutils::isSymbolUndefined( instance ) ){
|
||
|
|
IRegion* res = new IRegion(false);
|
||
|
|
res->SetDefined(false);
|
||
|
|
correct = true;
|
||
|
|
return SetWord(res);
|
||
|
|
}
|
||
|
|
if(!nl->HasLength(instance,2)){
|
||
|
|
correct = false;
|
||
|
|
return SetWord((void*)0);
|
||
|
|
}
|
||
|
|
ListExpr inst = nl->First(instance);
|
||
|
|
ListExpr reg = nl->Second(instance);
|
||
|
|
Instant* instant = (Instant *)InInstant( nl->TheEmptyList(),
|
||
|
|
inst,
|
||
|
|
errorPos,
|
||
|
|
errorInfo,
|
||
|
|
correct ).addr;
|
||
|
|
if(!correct){
|
||
|
|
if(instant){
|
||
|
|
delete instant;
|
||
|
|
}
|
||
|
|
return SetWord((void*)0);
|
||
|
|
}
|
||
|
|
Region* region = (Region*)InRegion(
|
||
|
|
nl->TheEmptyList(),
|
||
|
|
reg,
|
||
|
|
errorPos,
|
||
|
|
errorInfo,
|
||
|
|
correct).addr;
|
||
|
|
if(!correct){
|
||
|
|
if(region){
|
||
|
|
delete region;
|
||
|
|
}
|
||
|
|
delete instant;
|
||
|
|
return SetWord((void*)0);
|
||
|
|
}
|
||
|
|
IRegion* res = new IRegion(*instant, *region);
|
||
|
|
delete instant;
|
||
|
|
delete region;
|
||
|
|
correct = true;
|
||
|
|
return SetWord(res);
|
||
|
|
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1 Type constructor ~intimeregion~
|
||
|
|
|
||
|
|
*/
|
||
|
|
static TypeConstructor intimeregion(
|
||
|
|
IRegion::BasicType(),
|
||
|
|
IRegionProperty,
|
||
|
|
OutIntime<Region, OutRegion>,
|
||
|
|
InIRegion,
|
||
|
|
0, 0, // SaveToList, RestoreFromList
|
||
|
|
CreateIRegion,
|
||
|
|
DeleteIRegion,
|
||
|
|
OpenAttribute<IRegion>,
|
||
|
|
SaveAttribute<IRegion>, // object open and save
|
||
|
|
CloseIRegion,
|
||
|
|
CloneIRegion,
|
||
|
|
CastIRegion,
|
||
|
|
SizeOfIRegion,
|
||
|
|
CheckIRegion );
|
||
|
|
|
||
|
|
/*
|
||
|
|
1 Class ~URegionEmb~
|
||
|
|
|
||
|
|
1.1 Class definition
|
||
|
|
|
||
|
|
The class definition has been moved to ~MovingRegionAlgebra.h~.
|
||
|
|
|
||
|
|
1.1 Constructors
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
URegionEmb::URegionEmb( const bool Defined ) :
|
||
|
|
segmentsStartPos(0),
|
||
|
|
segmentsNum(0),
|
||
|
|
bbox(false)
|
||
|
|
{
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::URegionEmb(bool) called"
|
||
|
|
<< endl;
|
||
|
|
}
|
||
|
|
|
||
|
|
URegionEmb::URegionEmb(const Interval<Instant>& tiv,
|
||
|
|
unsigned int pos) :
|
||
|
|
segmentsStartPos(pos),
|
||
|
|
segmentsNum(0),
|
||
|
|
bbox(false),
|
||
|
|
timeInterval(tiv) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::URegionEmb() #2 called"
|
||
|
|
<< endl;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
URegionEmb::URegionEmb(
|
||
|
|
DbArray<MSegmentData>* segments,
|
||
|
|
const Interval<Instant>& tiv,
|
||
|
|
const Region& region,
|
||
|
|
unsigned int pos) :
|
||
|
|
segmentsStartPos(pos),
|
||
|
|
segmentsNum(0),
|
||
|
|
timeInterval(tiv) {
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::URegionEmb() #4 called" << endl;
|
||
|
|
|
||
|
|
/*
|
||
|
|
The following code adds each segment of the region as constant moving segment
|
||
|
|
to the region unit. Since region units do not use half segments, only one
|
||
|
|
half segment of each segment is considered. Each considered half segment may
|
||
|
|
need to be reversed before it is added to the region unit so that clockwise
|
||
|
|
or counter-clockwise order is maintained within the region unit.
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
int cycleStart = 0;
|
||
|
|
|
||
|
|
for (int i = 0; i < region.Size(); i += 2) {
|
||
|
|
HalfSegment thisHs;
|
||
|
|
region.Get(i, thisHs);
|
||
|
|
|
||
|
|
HalfSegment nextHs;
|
||
|
|
region.Get(i+2 == region.Size() ? 0 : i+2, nextHs);
|
||
|
|
|
||
|
|
if (thisHs.GetAttr().cycleno != nextHs.GetAttr().cycleno) {
|
||
|
|
region.Get(cycleStart, nextHs);
|
||
|
|
cycleStart = i+2;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (MRA_DEBUG) {
|
||
|
|
cerr << "URegionEmb::URegionEmb() i=" << i << endl;
|
||
|
|
cerr << "URegionEmb::URegionEmb() cycleStart="
|
||
|
|
<< cycleStart
|
||
|
|
<< endl;
|
||
|
|
cerr << "URegionEmb::URegionEmb() thisHs=" << thisHs << endl;
|
||
|
|
cerr << "URegionEmb::URegionEmb() nextHs=" << nextHs << endl;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (thisHs.GetRightPoint() == nextHs.GetLeftPoint()
|
||
|
|
|| thisHs.GetRightPoint() == nextHs.GetRightPoint()) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::URegionEmb() not swapping" << endl;
|
||
|
|
|
||
|
|
MSegmentData dms(thisHs.GetAttr().faceno,
|
||
|
|
thisHs.GetAttr().cycleno,
|
||
|
|
thisHs.GetAttr().edgeno,
|
||
|
|
thisHs.GetAttr().insideAbove,
|
||
|
|
thisHs.GetLeftPoint().GetX(),
|
||
|
|
thisHs.GetLeftPoint().GetY(),
|
||
|
|
thisHs.GetRightPoint().GetX(),
|
||
|
|
thisHs.GetRightPoint().GetY(),
|
||
|
|
thisHs.GetLeftPoint().GetX(),
|
||
|
|
thisHs.GetLeftPoint().GetY(),
|
||
|
|
thisHs.GetRightPoint().GetX(),
|
||
|
|
thisHs.GetRightPoint().GetY());
|
||
|
|
|
||
|
|
dms.SetDegeneratedInitial(DGM_NONE);
|
||
|
|
dms.SetDegeneratedFinal(DGM_NONE);
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::URegionEmb() adding "
|
||
|
|
<< dms.ToString()
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
segments->Put(segmentsStartPos+segmentsNum, dms);
|
||
|
|
} else {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::URegionEmb() swapping" << endl;
|
||
|
|
|
||
|
|
MSegmentData dms(thisHs.GetAttr().faceno,
|
||
|
|
thisHs.GetAttr().cycleno,
|
||
|
|
thisHs.GetAttr().edgeno,
|
||
|
|
thisHs.GetAttr().insideAbove,
|
||
|
|
thisHs.GetRightPoint().GetX(),
|
||
|
|
thisHs.GetRightPoint().GetY(),
|
||
|
|
thisHs.GetLeftPoint().GetX(),
|
||
|
|
thisHs.GetLeftPoint().GetY(),
|
||
|
|
thisHs.GetRightPoint().GetX(),
|
||
|
|
thisHs.GetRightPoint().GetY(),
|
||
|
|
thisHs.GetLeftPoint().GetX(),
|
||
|
|
thisHs.GetLeftPoint().GetY());
|
||
|
|
|
||
|
|
dms.SetDegeneratedInitial(DGM_NONE);
|
||
|
|
dms.SetDegeneratedFinal(DGM_NONE);
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::URegionEmb() adding "
|
||
|
|
<< dms.ToString()
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
segments->Put(segmentsStartPos+segmentsNum, dms);
|
||
|
|
}
|
||
|
|
|
||
|
|
segmentsNum++;
|
||
|
|
}
|
||
|
|
|
||
|
|
Rectangle<2> rbb = region.BoundingBox();
|
||
|
|
double min[3] = { rbb.MinD(0),
|
||
|
|
rbb.MinD(1),
|
||
|
|
timeInterval.start.ToDouble() };
|
||
|
|
double max[3] = { rbb.MaxD(0),
|
||
|
|
rbb.MaxD(1),
|
||
|
|
timeInterval.end.ToDouble() };
|
||
|
|
bbox.Set(true, min, max);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
void URegionEmb::SetSegmentsNum(int i){
|
||
|
|
segmentsNum=i;
|
||
|
|
}
|
||
|
|
|
||
|
|
void URegionEmb::SetStartPos(int i){
|
||
|
|
segmentsStartPos=i;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1 Methods required to act as unit in ~Mapping~ template
|
||
|
|
|
||
|
|
1.1.1 Method ~IsValid()~
|
||
|
|
|
||
|
|
*/
|
||
|
|
bool URegionEmb::IsValid(void) const {
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1 Method ~Disjoint()~
|
||
|
|
|
||
|
|
*/
|
||
|
|
bool URegionEmb::Disjoint(const URegionEmb& ur) const {
|
||
|
|
return
|
||
|
|
timeInterval.R_Disjoint(ur.timeInterval)
|
||
|
|
|| ur.timeInterval.R_Disjoint(timeInterval);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1 Method ~TU\_Adjacent()~
|
||
|
|
|
||
|
|
*/
|
||
|
|
bool URegionEmb::TU_Adjacent(const URegionEmb& ur) const {
|
||
|
|
return
|
||
|
|
timeInterval.R_Adjacent(ur.timeInterval)
|
||
|
|
|| ur.timeInterval.R_Adjacent(timeInterval);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1 Operator ~==~
|
||
|
|
|
||
|
|
*/
|
||
|
|
bool URegionEmb::operator==(const URegionEmb& ur) const {
|
||
|
|
return (timeInterval == ur.timeInterval);
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1 Method ~Before()~
|
||
|
|
|
||
|
|
*/
|
||
|
|
bool URegionEmb::Before(const URegionEmb& ur) const {
|
||
|
|
return timeInterval.Before(ur.timeInterval);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1 Method ~Compare()~
|
||
|
|
|
||
|
|
*/
|
||
|
|
bool URegionEmb::Compare(const URegionEmb* ur) const {
|
||
|
|
assert(false);
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1 Moving segment access methods
|
||
|
|
|
||
|
|
1.1.1 Method ~GetSegmentsNum()~
|
||
|
|
|
||
|
|
*/
|
||
|
|
int URegionEmb::GetSegmentsNum(void) const {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::GetSegmentsNum() called, num="
|
||
|
|
<< segmentsNum
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
return segmentsNum;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.2 Method ~GetStartPos()~
|
||
|
|
|
||
|
|
*/
|
||
|
|
const int URegionEmb::GetStartPos() const{
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::GetStartPos() called, sp="
|
||
|
|
<< segmentsStartPos
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
return segmentsStartPos;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1 Method ~GetSegment()~
|
||
|
|
|
||
|
|
*/
|
||
|
|
void URegionEmb::GetSegment(
|
||
|
|
const DbArray<MSegmentData>* segments,
|
||
|
|
int pos,
|
||
|
|
MSegmentData& dms) const {
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::GetSegment() called, pos=" << pos
|
||
|
|
<< ", segments="
|
||
|
|
<< segments
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
segments->Get(segmentsStartPos+pos, &dms);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1 Method ~PutSegment()~
|
||
|
|
|
||
|
|
*/
|
||
|
|
void URegionEmb::PutSegment(
|
||
|
|
DbArray<MSegmentData>* segments,
|
||
|
|
int pos,
|
||
|
|
const MSegmentData& dms,
|
||
|
|
const bool isNew) {
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::PutSegment() called, pos=" << pos <<
|
||
|
|
" "<<segmentsStartPos<<dms.ToString()<< endl;
|
||
|
|
segments->Put(segmentsStartPos+pos, dms);
|
||
|
|
if(isNew){
|
||
|
|
segmentsNum++;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1 Method ~SetSegmentInsideAbove()~
|
||
|
|
|
||
|
|
*/
|
||
|
|
void URegionEmb::SetSegmentInsideAbove(
|
||
|
|
DbArray<MSegmentData>* segments,
|
||
|
|
int pos,
|
||
|
|
bool insideAbove) {
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::GetSegmentLeftOrAbove() called, segments="
|
||
|
|
<< segments
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
MSegmentData auxDms;
|
||
|
|
segments->Get(segmentsStartPos+pos, &auxDms);
|
||
|
|
MSegmentData dms( auxDms );
|
||
|
|
dms.SetInsideAbove(insideAbove);
|
||
|
|
segments->Put(segmentsStartPos+pos, dms);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1 Method ~AddSegment()~
|
||
|
|
|
||
|
|
*/
|
||
|
|
bool URegionEmb::AddSegment(
|
||
|
|
DbArray<MSegmentData>* segments,
|
||
|
|
Region& cr,
|
||
|
|
Region& rDir,
|
||
|
|
unsigned int faceno,
|
||
|
|
unsigned int cycleno,
|
||
|
|
unsigned int segmentno,
|
||
|
|
unsigned int partnerno,
|
||
|
|
DateTime& intervalLen,
|
||
|
|
ListExpr start,
|
||
|
|
ListExpr end) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::AddSegment() called "
|
||
|
|
<< faceno
|
||
|
|
<< " "
|
||
|
|
<< cycleno
|
||
|
|
<< " "
|
||
|
|
<< segmentno
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
/*
|
||
|
|
To avoid awkward return value handling, we throw an exception if we find
|
||
|
|
a mistake. This is caught and converted into a proper error message and
|
||
|
|
return value.
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
try {
|
||
|
|
/*
|
||
|
|
Check list representation.
|
||
|
|
|
||
|
|
*/
|
||
|
|
if (nl->ListLength(start) != 4
|
||
|
|
|| !nl->IsAtom(nl->First(start))
|
||
|
|
|| (nl->AtomType(nl->First(start)) != RealType
|
||
|
|
&& nl->AtomType(nl->First(start)) != IntType)
|
||
|
|
|| !nl->IsAtom(nl->Second(start))
|
||
|
|
|| (nl->AtomType(nl->Second(start)) != RealType
|
||
|
|
&& nl->AtomType(nl->Second(start)) != IntType)
|
||
|
|
|| !nl->IsAtom(nl->Third(start))
|
||
|
|
|| (nl->AtomType(nl->Third(start)) != RealType
|
||
|
|
&& nl->AtomType(nl->Third(start)) != IntType)
|
||
|
|
|| !nl->IsAtom(nl->Fourth(start))
|
||
|
|
|| (nl->AtomType(nl->Fourth(start)) != RealType
|
||
|
|
&& nl->AtomType(nl->Fourth(start)) != IntType))
|
||
|
|
throw invalid_argument(
|
||
|
|
" Start point "
|
||
|
|
+nl->ToString(start)
|
||
|
|
+" not in format (<number> <number> <number> <number>).");
|
||
|
|
|
||
|
|
if (nl->ListLength(end) != 4
|
||
|
|
|
||
|
|
|| !nl->IsAtom(nl->First(end))
|
||
|
|
|| (nl->AtomType(nl->First(end)) != RealType
|
||
|
|
&& nl->AtomType(nl->First(end)) != IntType)
|
||
|
|
|| !nl->IsAtom(nl->Second(end))
|
||
|
|
|| (nl->AtomType(nl->Second(end)) != RealType
|
||
|
|
&& nl->AtomType(nl->Second(end)) != IntType)
|
||
|
|
|| !nl->IsAtom(nl->Third(end))
|
||
|
|
|| (nl->AtomType(nl->Third(end)) != RealType
|
||
|
|
&& nl->AtomType(nl->Third(end)) != IntType)
|
||
|
|
|| !nl->IsAtom(nl->Fourth(end))
|
||
|
|
|| (nl->AtomType(nl->Fourth(end)) != RealType
|
||
|
|
&& nl->AtomType(nl->Fourth(end)) != IntType))
|
||
|
|
throw invalid_argument(
|
||
|
|
" End point "
|
||
|
|
+nl->ToString(end)
|
||
|
|
+" not in format (<number> <number> <number> <number>).");
|
||
|
|
|
||
|
|
/*
|
||
|
|
Create segment from list representation.
|
||
|
|
|
||
|
|
*/
|
||
|
|
MSegmentData dms(faceno,
|
||
|
|
cycleno,
|
||
|
|
segmentno,
|
||
|
|
false,
|
||
|
|
nl->AtomType(nl->First(start)) == RealType
|
||
|
|
? nl->RealValue(nl->First(start))
|
||
|
|
: (double) nl->IntValue(nl->First(start)),
|
||
|
|
nl->AtomType(nl->Second(start)) == RealType
|
||
|
|
? nl->RealValue(nl->Second(start))
|
||
|
|
: (double) nl->IntValue(nl->Second(start)),
|
||
|
|
nl->AtomType(nl->First(end)) == RealType
|
||
|
|
? nl->RealValue(nl->First(end))
|
||
|
|
: (double) nl->IntValue(nl->First(end)),
|
||
|
|
nl->AtomType(nl->Second(end)) == RealType
|
||
|
|
? nl->RealValue(nl->Second(end))
|
||
|
|
: (double) nl->IntValue(nl->Second(end)),
|
||
|
|
nl->AtomType(nl->Third(start)) == RealType
|
||
|
|
? nl->RealValue(nl->Third(start))
|
||
|
|
: (double) nl->IntValue(nl->Third(start)),
|
||
|
|
nl->AtomType(nl->Fourth(start)) == RealType
|
||
|
|
? nl->RealValue(nl->Fourth(start))
|
||
|
|
: (double) nl->IntValue(nl->Fourth(start)),
|
||
|
|
nl->AtomType(nl->Third(end)) == RealType
|
||
|
|
? nl->RealValue(nl->Third(end))
|
||
|
|
: (double) nl->IntValue(nl->Third(end)),
|
||
|
|
nl->AtomType(nl->Fourth(end)) == RealType
|
||
|
|
? nl->RealValue(nl->Fourth(end))
|
||
|
|
: (double) nl->IntValue(nl->Fourth(end)));
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::AddSegment() segmentsNum="
|
||
|
|
<< segmentsNum
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
/*
|
||
|
|
For each of the already existing segments:
|
||
|
|
|
||
|
|
*/
|
||
|
|
for (int i = segmentsNum-1; i >= 0; i--) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::AddSegment() i=" << i << endl;
|
||
|
|
|
||
|
|
MSegmentData auxExistingDms;
|
||
|
|
|
||
|
|
segments->Get(segmentsStartPos+i, &auxExistingDms);
|
||
|
|
MSegmentData existingDms( auxExistingDms );
|
||
|
|
|
||
|
|
/*
|
||
|
|
Check whether the current segment degenerates with this segment in the
|
||
|
|
initial instant. Note that segments reduced to points are excluded from
|
||
|
|
this.
|
||
|
|
|
||
|
|
All segments, which degenerate into each other, are collected in a list
|
||
|
|
using the ~degeneratedInitialNext~ attribute.
|
||
|
|
|
||
|
|
*/
|
||
|
|
if (dms.GetDegeneratedInitialNext() < 0
|
||
|
|
&& !dms.GetPointInitial()
|
||
|
|
&& !existingDms.GetPointInitial()
|
||
|
|
&& ((nearlyEqual(
|
||
|
|
dms.GetInitialStartX(),
|
||
|
|
existingDms.GetInitialStartX())
|
||
|
|
&& nearlyEqual(
|
||
|
|
dms.GetInitialStartY(),
|
||
|
|
existingDms.GetInitialStartY())
|
||
|
|
&& nearlyEqual(
|
||
|
|
dms.GetInitialEndX(),
|
||
|
|
existingDms.GetInitialEndX())
|
||
|
|
&& nearlyEqual(
|
||
|
|
dms.GetInitialEndY(),
|
||
|
|
existingDms.GetInitialEndY()))
|
||
|
|
|| (nearlyEqual(
|
||
|
|
dms.GetInitialStartX(),
|
||
|
|
existingDms.GetInitialEndX())
|
||
|
|
&& nearlyEqual(
|
||
|
|
dms.GetInitialStartY(),
|
||
|
|
existingDms.GetInitialEndY())
|
||
|
|
&& nearlyEqual(
|
||
|
|
dms.GetInitialEndX(),
|
||
|
|
existingDms.GetInitialStartX())
|
||
|
|
&& nearlyEqual(
|
||
|
|
dms.GetInitialEndY(),
|
||
|
|
existingDms.GetInitialStartY()))))
|
||
|
|
{
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::AddSegment() "
|
||
|
|
<< "degen'ed initial in " << i
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
dms.SetDegeneratedInitialNext(0);
|
||
|
|
existingDms.SetDegeneratedInitialNext(segmentsNum+1);
|
||
|
|
|
||
|
|
segments->Put(segmentsStartPos+i, existingDms);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
Same for the final instant.
|
||
|
|
|
||
|
|
*/
|
||
|
|
if (dms.GetDegeneratedFinalNext() < 0
|
||
|
|
&& !dms.GetPointFinal()
|
||
|
|
&& !existingDms.GetPointFinal()
|
||
|
|
&& ((nearlyEqual(
|
||
|
|
dms.GetFinalStartX(),
|
||
|
|
existingDms.GetFinalStartX())
|
||
|
|
&& nearlyEqual(
|
||
|
|
dms.GetFinalStartY(),
|
||
|
|
existingDms.GetFinalStartY())
|
||
|
|
&& nearlyEqual(
|
||
|
|
dms.GetFinalEndX(),
|
||
|
|
existingDms.GetFinalEndX())
|
||
|
|
&& nearlyEqual(
|
||
|
|
dms.GetFinalEndY(),
|
||
|
|
existingDms.GetFinalEndY()))
|
||
|
|
|| (nearlyEqual(
|
||
|
|
dms.GetFinalStartX(),
|
||
|
|
existingDms.GetFinalEndX())
|
||
|
|
&& nearlyEqual(
|
||
|
|
dms.GetFinalStartY(),
|
||
|
|
existingDms.GetFinalEndY())
|
||
|
|
&& nearlyEqual(
|
||
|
|
dms.GetFinalEndX(),
|
||
|
|
existingDms.GetFinalStartX())
|
||
|
|
&& nearlyEqual(
|
||
|
|
dms.GetFinalEndY(),
|
||
|
|
existingDms.GetFinalStartY())))) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::AddSegment() "
|
||
|
|
<< "degen'ed final in " << i
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
dms.SetDegeneratedFinalNext(0);
|
||
|
|
existingDms.SetDegeneratedFinalNext(segmentsNum+1);
|
||
|
|
|
||
|
|
segments->Put(segmentsStartPos+i, existingDms);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
If we have a point time interval, degeneration is not allowed.
|
||
|
|
|
||
|
|
*/
|
||
|
|
if (intervalLen.IsZero()
|
||
|
|
&& (dms.GetDegeneratedInitialNext() >= 0
|
||
|
|
|| dms.GetDegeneratedFinalNext() >= 0)) {
|
||
|
|
stringstream msg;
|
||
|
|
msg << " Units with zero length time interval must not"
|
||
|
|
<< " be degenerated." << endl
|
||
|
|
<< " New segment:" << endl
|
||
|
|
<< " Initial: ("
|
||
|
|
<< dms.GetInitialStartX()
|
||
|
|
<< " "
|
||
|
|
<< dms.GetInitialStartY()
|
||
|
|
<< ") - ("
|
||
|
|
<< dms.GetInitialEndX()
|
||
|
|
<< " "
|
||
|
|
<< dms.GetInitialEndY()
|
||
|
|
<< ")" << endl
|
||
|
|
<< " Final: ("
|
||
|
|
<< dms.GetFinalStartX()
|
||
|
|
<< " "
|
||
|
|
<< dms.GetFinalStartY()
|
||
|
|
<< ") - ("
|
||
|
|
<< dms.GetFinalEndX()
|
||
|
|
<< " "
|
||
|
|
<< dms.GetFinalEndY();
|
||
|
|
throw invalid_argument(msg.str());
|
||
|
|
} else if (!intervalLen.IsZero()
|
||
|
|
&& dms.GetDegeneratedInitialNext() >= 0
|
||
|
|
&& dms.GetDegeneratedFinalNext() >= 0) {
|
||
|
|
stringstream msg;
|
||
|
|
msg << " Units must not degenerate both in initial and"
|
||
|
|
<< " final instant." << endl
|
||
|
|
<< " New segment:" << endl
|
||
|
|
<< " Initial: ("
|
||
|
|
<< dms.GetInitialStartX()
|
||
|
|
<< " "
|
||
|
|
<< dms.GetInitialStartY()
|
||
|
|
<< ") - ("
|
||
|
|
<< dms.GetInitialEndX()
|
||
|
|
<< " "
|
||
|
|
<< dms.GetInitialEndY()
|
||
|
|
<< ")" << endl
|
||
|
|
<< " Final: ("
|
||
|
|
<< dms.GetFinalStartX()
|
||
|
|
<< " "
|
||
|
|
<< dms.GetFinalStartY()
|
||
|
|
<< ") - ("
|
||
|
|
<< dms.GetFinalEndX()
|
||
|
|
<< " "
|
||
|
|
<< dms.GetFinalEndY();
|
||
|
|
throw invalid_argument(msg.str());
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
Check if the current segment intersects with the existing segment.
|
||
|
|
Since both a moving segments and are spanning a trapezium in 3d space
|
||
|
|
$(x, y, t)$, this is equivalent to the intersection of two trapeziums.
|
||
|
|
|
||
|
|
*/
|
||
|
|
unsigned int detailedResult;
|
||
|
|
|
||
|
|
if ( specialTrapeziumIntersects(intervalLen.ToDouble(),
|
||
|
|
existingDms.GetInitialStartX(),
|
||
|
|
existingDms.GetInitialStartY(),
|
||
|
|
existingDms.GetInitialEndX(),
|
||
|
|
existingDms.GetInitialEndY(),
|
||
|
|
existingDms.GetFinalStartX(),
|
||
|
|
existingDms.GetFinalStartY(),
|
||
|
|
existingDms.GetFinalEndX(),
|
||
|
|
existingDms.GetFinalEndY(),
|
||
|
|
dms.GetInitialStartX(),
|
||
|
|
dms.GetInitialStartY(),
|
||
|
|
dms.GetInitialEndX(),
|
||
|
|
dms.GetInitialEndY(),
|
||
|
|
dms.GetFinalStartX(),
|
||
|
|
dms.GetFinalStartY(),
|
||
|
|
dms.GetFinalEndX(),
|
||
|
|
dms.GetFinalEndY(),
|
||
|
|
detailedResult)) {
|
||
|
|
|
||
|
|
stringstream msg;
|
||
|
|
msg << " Moving segments intersect (code "
|
||
|
|
<< detailedResult
|
||
|
|
<< ")." << endl
|
||
|
|
<< " Existing segment:" << endl
|
||
|
|
<< " Initial: ("
|
||
|
|
<< existingDms.GetInitialStartX()
|
||
|
|
<< " "
|
||
|
|
<< existingDms.GetInitialStartY()
|
||
|
|
<< ") - ("
|
||
|
|
<< existingDms.GetInitialEndX()
|
||
|
|
<< " "
|
||
|
|
<< existingDms.GetInitialEndY()
|
||
|
|
<< ")" << endl
|
||
|
|
<< " Final: ("
|
||
|
|
<< existingDms.GetFinalStartX()
|
||
|
|
<< " "
|
||
|
|
<< existingDms.GetFinalStartY()
|
||
|
|
<< ") - ("
|
||
|
|
<< existingDms.GetFinalEndX()
|
||
|
|
<< " "
|
||
|
|
<< existingDms.GetFinalEndY()
|
||
|
|
<< ")" << endl
|
||
|
|
<< " New segment:" << endl
|
||
|
|
<< " Initial: ("
|
||
|
|
<< dms.GetInitialStartX()
|
||
|
|
<< " "
|
||
|
|
<< dms.GetInitialStartY()
|
||
|
|
<< ") - ("
|
||
|
|
<< dms.GetInitialEndX()
|
||
|
|
<< " "
|
||
|
|
<< dms.GetInitialEndY()
|
||
|
|
<< ")" << endl
|
||
|
|
<< " Final: ("
|
||
|
|
<< dms.GetFinalStartX()
|
||
|
|
<< " "
|
||
|
|
<< dms.GetFinalStartY()
|
||
|
|
<< ") - ("
|
||
|
|
<< dms.GetFinalEndX()
|
||
|
|
<< " "
|
||
|
|
<< dms.GetFinalEndY();
|
||
|
|
throw invalid_argument(msg.str());
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
Add half segments to $cr$ and $rDir$ for region check and direction
|
||
|
|
computation.
|
||
|
|
|
||
|
|
*/
|
||
|
|
double t = intervalLen.IsZero() ? 0 : 0.5;
|
||
|
|
double xs =
|
||
|
|
dms.GetInitialStartX()
|
||
|
|
+(dms.GetFinalStartX()-dms.GetInitialStartX())*t;
|
||
|
|
double ys =
|
||
|
|
dms.GetInitialStartY()
|
||
|
|
+(dms.GetFinalStartY()-dms.GetInitialStartY())*t;
|
||
|
|
double xe =
|
||
|
|
dms.GetInitialEndX()
|
||
|
|
+(dms.GetFinalEndX()-dms.GetInitialEndX())*t;
|
||
|
|
double ye =
|
||
|
|
dms.GetInitialEndY()
|
||
|
|
+(dms.GetFinalEndY()-dms.GetInitialEndY())*t;
|
||
|
|
|
||
|
|
Point s(true, xs, ys);
|
||
|
|
Point e(true, xe, ye);
|
||
|
|
HalfSegment hs(true, s, e);
|
||
|
|
|
||
|
|
hs.attr.faceno = faceno;
|
||
|
|
hs.attr.cycleno = cycleno;
|
||
|
|
hs.attr.partnerno = partnerno;
|
||
|
|
hs.attr.edgeno = segmentno;
|
||
|
|
|
||
|
|
hs.attr.insideAbove = hs.GetLeftPoint() == s;
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::AddSegment() "
|
||
|
|
<< dms.ToString()
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::AddSegment() "
|
||
|
|
<< faceno
|
||
|
|
<< " "
|
||
|
|
<< cycleno
|
||
|
|
<< " "
|
||
|
|
<< partnerno
|
||
|
|
<< " ("
|
||
|
|
<< xs
|
||
|
|
<< ", "
|
||
|
|
<< ys
|
||
|
|
<< ")-("
|
||
|
|
<< xe
|
||
|
|
<< ", "
|
||
|
|
<< ye
|
||
|
|
<< ") ia="
|
||
|
|
<< hs.attr.insideAbove
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
if (!cr.InsertOk(hs)) {
|
||
|
|
stringstream msg;
|
||
|
|
msg << " Region checks for segment failed." << endl
|
||
|
|
<< " New segment:" << endl
|
||
|
|
<< " Initial: ("
|
||
|
|
<< dms.GetInitialStartX()
|
||
|
|
<< " "
|
||
|
|
<< dms.GetInitialStartY()
|
||
|
|
<< ") - ("
|
||
|
|
<< dms.GetInitialEndX()
|
||
|
|
<< " "
|
||
|
|
<< dms.GetInitialEndY()
|
||
|
|
<< ")" << endl
|
||
|
|
<< " Final: ("
|
||
|
|
<< dms.GetFinalStartX()
|
||
|
|
<< " "
|
||
|
|
<< dms.GetFinalStartY()
|
||
|
|
<< ") - ("
|
||
|
|
<< dms.GetFinalEndX()
|
||
|
|
<< " "
|
||
|
|
<< dms.GetFinalEndY();
|
||
|
|
throw invalid_argument(msg.str());
|
||
|
|
}
|
||
|
|
|
||
|
|
cr += hs;
|
||
|
|
if( hs.IsLeftDomPoint() )
|
||
|
|
{
|
||
|
|
rDir += hs;
|
||
|
|
hs.SetLeftDomPoint( false );
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
hs.SetLeftDomPoint( true );
|
||
|
|
rDir += hs;
|
||
|
|
}
|
||
|
|
cr += hs;
|
||
|
|
|
||
|
|
segments->resize(segmentsStartPos+segmentsNum+1);
|
||
|
|
segments->Put(segmentsStartPos+segmentsNum, dms);
|
||
|
|
segmentsNum++;
|
||
|
|
|
||
|
|
if (bbox.IsDefined()) {
|
||
|
|
double min[3] = { bbox.MinD(0), bbox.MinD(1), bbox.MinD(2) };
|
||
|
|
double max[3] = { bbox.MaxD(0), bbox.MaxD(1), bbox.MaxD(2) };
|
||
|
|
if (dms.GetInitialStartX() < min[0])
|
||
|
|
min[0] = dms.GetInitialStartX();
|
||
|
|
if (dms.GetFinalStartX() < min[0])
|
||
|
|
min[0] = dms.GetFinalStartX();
|
||
|
|
if (dms.GetInitialStartY() < min[1])
|
||
|
|
min[1] = dms.GetInitialStartY();
|
||
|
|
if (dms.GetFinalStartY() < min[1])
|
||
|
|
min[1] = dms.GetFinalStartY();
|
||
|
|
if (dms.GetInitialStartX() > max[0])
|
||
|
|
max[0] = dms.GetInitialStartX();
|
||
|
|
if (dms.GetFinalStartX() > max[0])
|
||
|
|
max[0] = dms.GetFinalStartX();
|
||
|
|
if (dms.GetInitialStartY() > max[1])
|
||
|
|
max[1] = dms.GetInitialStartY();
|
||
|
|
if (dms.GetFinalStartY() > max[1])
|
||
|
|
max[1] = dms.GetFinalStartY();
|
||
|
|
bbox.Set(true, min, max);
|
||
|
|
|
||
|
|
} else {
|
||
|
|
double min[3] =
|
||
|
|
{ dms.GetInitialStartX() < dms.GetFinalStartX()
|
||
|
|
? dms.GetInitialStartX() : dms.GetFinalStartX(),
|
||
|
|
dms.GetInitialStartY() < dms.GetFinalStartY()
|
||
|
|
? dms.GetInitialStartY() : dms.GetFinalStartY(),
|
||
|
|
timeInterval.start.ToDouble() };
|
||
|
|
double max[3] =
|
||
|
|
{ dms.GetInitialStartX() > dms.GetFinalStartX()
|
||
|
|
? dms.GetInitialStartX() : dms.GetFinalStartX(),
|
||
|
|
dms.GetInitialStartY() > dms.GetFinalStartY()
|
||
|
|
? dms.GetInitialStartY() : dms.GetFinalStartY(),
|
||
|
|
timeInterval.end.ToDouble() };
|
||
|
|
bbox.Set(true, min, max);
|
||
|
|
}
|
||
|
|
} catch (invalid_argument& e) {
|
||
|
|
cerr << "-----------------------------------------------------------"
|
||
|
|
<< endl
|
||
|
|
<< "Checking segment failed."
|
||
|
|
<< endl
|
||
|
|
<< e.what()
|
||
|
|
<< endl
|
||
|
|
<< "-----------------------------------------------------------"
|
||
|
|
<< endl;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1 Helper methods for ~RestrictedIntersection()~
|
||
|
|
|
||
|
|
1.1.1 Method ~Plumbline()~
|
||
|
|
|
||
|
|
*/
|
||
|
|
unsigned int URegionEmb::Plumbline(
|
||
|
|
const DbArray<MSegmentData>* segments,
|
||
|
|
const UPoint& up,
|
||
|
|
const Interval<Instant>& iv) const{
|
||
|
|
|
||
|
|
if (MRA_DEBUG) cerr << "URegionEmb::Plumbline() called" << endl;
|
||
|
|
/*
|
||
|
|
Since we know that ~up~ is not intersecting with any of the segments, we
|
||
|
|
can pick any time in ~iv~ to examine ~up~ and the segments. We pick the
|
||
|
|
middle of the interval:
|
||
|
|
|
||
|
|
*/
|
||
|
|
double t =
|
||
|
|
iv.start.ToDouble()
|
||
|
|
+(iv.end.ToDouble()-iv.start.ToDouble())/2;
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::Plumbline() iv.start="
|
||
|
|
<< iv.start.ToDouble()
|
||
|
|
<< " iv.end="
|
||
|
|
<< iv.end.ToDouble()
|
||
|
|
<< " t="
|
||
|
|
<< t
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
double f;
|
||
|
|
|
||
|
|
/*
|
||
|
|
Calculate the position ~x~, ~y~ of ~up~ for ~t~.
|
||
|
|
|
||
|
|
*/
|
||
|
|
if (nearlyEqual(up.timeInterval.start.ToDouble(),
|
||
|
|
up.timeInterval.end.ToDouble()))
|
||
|
|
f = 0;
|
||
|
|
else
|
||
|
|
f = (t-up.timeInterval.start.ToDouble())
|
||
|
|
/(up.timeInterval.end.ToDouble()
|
||
|
|
-up.timeInterval.start.ToDouble());
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::Plumbline() f=" << f << endl;
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::Plumbline() p0=("
|
||
|
|
<< up.p0.GetX() << " " << up.p0.GetY()
|
||
|
|
<< ") p1=("
|
||
|
|
<< up.p1.GetX() << " " << up.p1.GetY()
|
||
|
|
<< ")"
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
double x = up.p0.GetX()+(up.p1.GetX()-up.p0.GetX())*f;
|
||
|
|
double y = up.p0.GetY()+(up.p1.GetY()-up.p0.GetY())*f;
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::Plumbline() x=" << x << " y=" << y << endl;
|
||
|
|
|
||
|
|
/*
|
||
|
|
Required to calculate the position of each segment for ~t~.
|
||
|
|
|
||
|
|
*/
|
||
|
|
if (nearlyEqual(timeInterval.start.ToDouble(),
|
||
|
|
timeInterval.end.ToDouble()))
|
||
|
|
f = 0;
|
||
|
|
else
|
||
|
|
f = (t-timeInterval.start.ToDouble())
|
||
|
|
/(timeInterval.end.ToDouble()
|
||
|
|
-timeInterval.start.ToDouble());
|
||
|
|
|
||
|
|
/*
|
||
|
|
~num~ is used to count the segments above ~(x, y)~.
|
||
|
|
|
||
|
|
*/
|
||
|
|
unsigned int num = 0;
|
||
|
|
|
||
|
|
/*
|
||
|
|
Go through all segments...
|
||
|
|
|
||
|
|
*/
|
||
|
|
for (unsigned int i = 0; i < segmentsNum; i++) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::Plumbline() segment #" << i << endl;
|
||
|
|
|
||
|
|
MSegmentData dms;
|
||
|
|
segments->Get(segmentsStartPos+i, &dms);
|
||
|
|
|
||
|
|
/*
|
||
|
|
Calculate position of segment at ~t~.
|
||
|
|
|
||
|
|
*/
|
||
|
|
double p1x =
|
||
|
|
dms.GetInitialStartX()
|
||
|
|
+(dms.GetFinalStartX()-dms.GetInitialStartX())*f;
|
||
|
|
double p1y =
|
||
|
|
dms.GetInitialStartY()
|
||
|
|
+(dms.GetFinalStartY()-dms.GetInitialStartY())*f;
|
||
|
|
double p2x =
|
||
|
|
dms.GetInitialEndX()
|
||
|
|
+(dms.GetFinalEndX()-dms.GetInitialEndX())*f;
|
||
|
|
double p2y =
|
||
|
|
dms.GetInitialEndY()
|
||
|
|
+(dms.GetFinalEndY()-dms.GetInitialEndY())*f;
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::Plumbline() p1x=" << p1x
|
||
|
|
<< " p1y=" << p1y
|
||
|
|
<< " p2x=" << p2x
|
||
|
|
<< " p2y=" << p2y
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
if (nearlyEqual(p1x, p2x)) {
|
||
|
|
/*
|
||
|
|
Ignore vertical segments.
|
||
|
|
|
||
|
|
*/
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::Plumbline() "
|
||
|
|
<< "vertical, ignored"
|
||
|
|
<< endl;
|
||
|
|
} else if (nearlyEqual(p1x, x) && lowerOrNearlyEqual(y, p1y)) {
|
||
|
|
/*
|
||
|
|
~(x, y)~ is one of the endpoints. Only count it if it is the right endpoint.
|
||
|
|
|
||
|
|
*/
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::Plumbline() "
|
||
|
|
<< "plumbline through start point"
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
if (p1x > p2x) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::Plumbline() counted" << endl;
|
||
|
|
|
||
|
|
num++;
|
||
|
|
} else {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::Plumbline() ignored" << endl;
|
||
|
|
}
|
||
|
|
} else if (nearlyEqual(p2x, x) && lowerOrNearlyEqual(y, p2y)) {
|
||
|
|
/*
|
||
|
|
~(x, y)~ is one of the endpoints. Only count it if it is the right endpoint.
|
||
|
|
|
||
|
|
*/
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::Plumbline() "
|
||
|
|
<< "plumbline through end point"
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
if (p1x < p2x) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::Plumbline() counted" << endl;
|
||
|
|
|
||
|
|
num++;
|
||
|
|
} else {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::Plumbline() ignored" << endl;
|
||
|
|
}
|
||
|
|
} else if (!between(p1x, x, p2x)) {
|
||
|
|
/*
|
||
|
|
~(x, y)~ is not below the segment.
|
||
|
|
|
||
|
|
*/
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::Plumbline() "
|
||
|
|
<< "x not between p1x, p1y, ignored"
|
||
|
|
<< endl;
|
||
|
|
} else {
|
||
|
|
/*
|
||
|
|
~(x, y)~ is in the same ~x~-range as the segment. Count it if the segment
|
||
|
|
is above ~(x, y)~.
|
||
|
|
|
||
|
|
*/
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::Plumbline() "
|
||
|
|
<< "checking for intersection"
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
if (MRA_DEBUG) {
|
||
|
|
cerr << "URegionEmb::Plumbline() nearlyEqual(p1x, x)="
|
||
|
|
<< nearlyEqual(p1x, x)
|
||
|
|
<< endl;
|
||
|
|
cerr << "URegionEmb::Plumbline() nearlyEqual(p2x, x)="
|
||
|
|
<< nearlyEqual(p2x, x)
|
||
|
|
<< endl;
|
||
|
|
}
|
||
|
|
|
||
|
|
// solve p1x+(p2x-p1x)*s = x
|
||
|
|
|
||
|
|
double s = (x-p1x)/(p2x-p1x);
|
||
|
|
double ys = p1y+(p2y-p1y)*s;
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::Plumbline() ys=" << ys << endl;
|
||
|
|
|
||
|
|
if (lowerOrNearlyEqual(y, ys)) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::Plumbline() below" << endl;
|
||
|
|
|
||
|
|
num++;
|
||
|
|
} else {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::Plumbline() not below" << endl;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::Plumbline() num=" << num << endl;
|
||
|
|
}
|
||
|
|
|
||
|
|
return num;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1 Method ~RestrictedIntersectionAddUPoint()~
|
||
|
|
|
||
|
|
*/
|
||
|
|
void URegionEmb::RestrictedIntersectionAddUPoint(MPoint& res,
|
||
|
|
double starttime,
|
||
|
|
double endtime,
|
||
|
|
bool lc,
|
||
|
|
bool rc,
|
||
|
|
double x0,
|
||
|
|
double y0,
|
||
|
|
double x1,
|
||
|
|
double y1,
|
||
|
|
UPoint*& pending,
|
||
|
|
bool merge) const {
|
||
|
|
if (MRA_DEBUG) {
|
||
|
|
cerr << "URegionEmb::RIAUP() called, merge=" << merge << endl;
|
||
|
|
cerr << "URegionEmb::RIAUP() starttime="
|
||
|
|
<< setprecision(12)
|
||
|
|
<< starttime
|
||
|
|
<< " endtime=" << endtime
|
||
|
|
<< " lc=" << lc << " rc="
|
||
|
|
<< rc
|
||
|
|
<< " p0=(" << x0 << " " << y0
|
||
|
|
<< ") p1=(" << x1 << " " << y1
|
||
|
|
<< ")"
|
||
|
|
<< endl;
|
||
|
|
}
|
||
|
|
|
||
|
|
Instant start(instanttype);
|
||
|
|
start.ReadFrom(starttime);
|
||
|
|
|
||
|
|
Instant end(instanttype);
|
||
|
|
end.ReadFrom(endtime);
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::RIAUP() as instant start="
|
||
|
|
<< start.ToString()
|
||
|
|
<< " end="
|
||
|
|
<< end.ToString()
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
/*
|
||
|
|
Straightforward again. If there is a previous unit pending, try to merge
|
||
|
|
it. If we cannot merge it, put it into ~res~ and start new pending
|
||
|
|
unit.
|
||
|
|
|
||
|
|
(I am not sure, though, whether merging pending units is required. It may
|
||
|
|
reduce the number of units produced - but is this really a requirement?)
|
||
|
|
|
||
|
|
*/
|
||
|
|
if (pending) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::RIAUP() pending exists" << endl;
|
||
|
|
|
||
|
|
if (MRA_DEBUG) {
|
||
|
|
cerr << "URegionEmb::RIAUP() pending: ["
|
||
|
|
<< setprecision(8)
|
||
|
|
<< pending->timeInterval.start.ToString()
|
||
|
|
<< " "
|
||
|
|
<< pending->timeInterval.end.ToString()
|
||
|
|
<< " "
|
||
|
|
<< pending->timeInterval.lc
|
||
|
|
<< " "
|
||
|
|
<< pending->timeInterval.rc
|
||
|
|
<< "] ("
|
||
|
|
<< pending->p0.GetX() << " " << pending->p0.GetY()
|
||
|
|
<< ")-("
|
||
|
|
<< pending->p1.GetX() << " " << pending->p1.GetY()
|
||
|
|
<< ")"
|
||
|
|
<< endl;
|
||
|
|
cerr << "URegionEmb::RIAUP() current: ["
|
||
|
|
<< setprecision(8)
|
||
|
|
<< start.ToString()
|
||
|
|
<< " "
|
||
|
|
<< end.ToString()
|
||
|
|
<< " "
|
||
|
|
<< lc
|
||
|
|
<< " "
|
||
|
|
<< rc
|
||
|
|
<< "] ("
|
||
|
|
<< x0 << " " << y0
|
||
|
|
<< ")-("
|
||
|
|
<< x1 << " " << y1
|
||
|
|
<< ")"
|
||
|
|
<< endl;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (merge
|
||
|
|
&& nearlyEqual(pending->timeInterval.end.ToDouble(),
|
||
|
|
starttime)
|
||
|
|
&& (pending->timeInterval.rc || lc)
|
||
|
|
&& nearlyEqual(pending->p1.GetX(), x0)
|
||
|
|
&& nearlyEqual(pending->p1.GetY(), y0)) {
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::RIAUP() intervals match" << endl;
|
||
|
|
|
||
|
|
if (nearlyEqual(pending->timeInterval.start.ToDouble(),
|
||
|
|
pending->timeInterval.end.ToDouble())) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::RIAUP() merge #1" << endl;
|
||
|
|
|
||
|
|
Interval<Instant> iv(start,
|
||
|
|
end,
|
||
|
|
true,
|
||
|
|
rc);
|
||
|
|
|
||
|
|
delete pending;
|
||
|
|
pending = new UPoint(iv, x0, y0, x1, y1);
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::RIAUP() pending="
|
||
|
|
<< pending
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
return;
|
||
|
|
} else if (nearlyEqual(starttime, endtime)) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::RIAUP() merge #2" << endl;
|
||
|
|
|
||
|
|
Interval<Instant> iv(pending->timeInterval.start,
|
||
|
|
pending->timeInterval.end,
|
||
|
|
pending->timeInterval.lc,
|
||
|
|
true);
|
||
|
|
|
||
|
|
UPoint* dummy = new UPoint(iv,
|
||
|
|
pending->p0.GetX(),
|
||
|
|
pending->p0.GetY(),
|
||
|
|
pending->p1.GetX(),
|
||
|
|
pending->p1.GetY());
|
||
|
|
delete pending;
|
||
|
|
pending = dummy;
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::RIAUP() pending="
|
||
|
|
<< pending
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
return;
|
||
|
|
} else {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::RIAUP() checking endpoints"
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
double f =
|
||
|
|
(pending->timeInterval.start.ToDouble()
|
||
|
|
-starttime)
|
||
|
|
/(endtime-starttime);
|
||
|
|
|
||
|
|
double x = x0+(x1-x0)*f;
|
||
|
|
double y = y0+(y1-y0)*f;
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::RIAUP() f="
|
||
|
|
<< f
|
||
|
|
<< " -> x="
|
||
|
|
<< x
|
||
|
|
<< " y="
|
||
|
|
<< y
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
|
||
|
|
if (nearlyEqual(pending->p0.GetX(), x)
|
||
|
|
&& nearlyEqual(pending->p0.GetY(), y)) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::RIAUP() merge #3" << endl;
|
||
|
|
|
||
|
|
Interval<Instant> iv(pending->timeInterval.start,
|
||
|
|
end,
|
||
|
|
pending->timeInterval.lc,
|
||
|
|
rc);
|
||
|
|
|
||
|
|
UPoint* dummy = new UPoint(iv,
|
||
|
|
pending->p0.GetX(),
|
||
|
|
pending->p0.GetY(),
|
||
|
|
x1,
|
||
|
|
y1);
|
||
|
|
delete pending;
|
||
|
|
pending = dummy;
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::RIAUP() pending="
|
||
|
|
<< pending
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (MRA_DEBUG) cerr << "URegionEmb::RIAUP() no merge" << endl;
|
||
|
|
|
||
|
|
if (pending) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::RIAUP() adding "
|
||
|
|
<< pending
|
||
|
|
<< setprecision(12)
|
||
|
|
<< " iv=["
|
||
|
|
<< pending->timeInterval.start.ToDouble()
|
||
|
|
<< " "
|
||
|
|
<< pending->timeInterval.end.ToDouble()
|
||
|
|
<< " "
|
||
|
|
<< pending->timeInterval.lc
|
||
|
|
<< " "
|
||
|
|
<< pending->timeInterval.rc
|
||
|
|
<< "]"
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
if (!(nearlyEqual(pending->timeInterval.start.ToDouble(),
|
||
|
|
pending->timeInterval.end.ToDouble())
|
||
|
|
&& (!pending->timeInterval.lc
|
||
|
|
|| !pending->timeInterval.rc)))
|
||
|
|
res.Add(*pending);
|
||
|
|
|
||
|
|
delete pending;
|
||
|
|
}
|
||
|
|
|
||
|
|
Interval<Instant> iv(start, end, lc, rc);
|
||
|
|
|
||
|
|
pending = new UPoint(iv, x0, y0, x1, y1);
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::RIAUP() pending="
|
||
|
|
<< pending
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1 Method ~RestrictedIntersectionFindNormal()~
|
||
|
|
|
||
|
|
*/
|
||
|
|
void URegionEmb::RestrictedIntersectionFindNormal(
|
||
|
|
const Interval<Instant>& iv,
|
||
|
|
const UPoint& rUp,
|
||
|
|
MSegmentData& rDms,
|
||
|
|
bool& ip1present,
|
||
|
|
double& ip1x,
|
||
|
|
double& ip1y,
|
||
|
|
double& ip1t,
|
||
|
|
vector<TrapeziumSegmentIntersection>& vtsi) const {
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::RIFN() called" << endl;
|
||
|
|
|
||
|
|
/*
|
||
|
|
Calculate end points of moving segment at time of intersection ~ip1t~.
|
||
|
|
|
||
|
|
*/
|
||
|
|
double p1x, p1y, p2x, p2y;
|
||
|
|
|
||
|
|
if (nearlyEqual(iv.start.ToDouble(), iv.end.ToDouble())) {
|
||
|
|
p1x = rDms.GetInitialStartX();
|
||
|
|
p1y = rDms.GetInitialStartY();
|
||
|
|
p2x = rDms.GetInitialEndX();
|
||
|
|
p2y = rDms.GetInitialEndY();
|
||
|
|
} else {
|
||
|
|
double f =
|
||
|
|
(ip1t-iv.start.ToDouble())
|
||
|
|
/(iv.end.ToDouble()-iv.start.ToDouble());
|
||
|
|
|
||
|
|
p1x =
|
||
|
|
rDms.GetInitialStartX()
|
||
|
|
+(rDms.GetFinalStartX()-rDms.GetInitialStartX())*f;
|
||
|
|
p1y =
|
||
|
|
rDms.GetInitialStartY()
|
||
|
|
+(rDms.GetFinalStartY()-rDms.GetInitialStartY())*f;
|
||
|
|
p2x =
|
||
|
|
rDms.GetInitialEndX()
|
||
|
|
+(rDms.GetFinalEndX()-rDms.GetInitialEndX())*f;
|
||
|
|
p2y =
|
||
|
|
rDms.GetInitialEndY()
|
||
|
|
+(rDms.GetFinalEndY()-rDms.GetInitialEndY())*f;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (MRA_DEBUG) {
|
||
|
|
cerr << "URegionEmb::RIFN() rUp=("
|
||
|
|
<< rUp.p0.GetX() << " " << rUp.p0.GetY()
|
||
|
|
<< ")-("
|
||
|
|
<< rUp.p1.GetX() << " " << rUp.p1.GetY()
|
||
|
|
<< ")"
|
||
|
|
<< endl;
|
||
|
|
cerr << "URegionEmb::RIFN() p1=("
|
||
|
|
<< p1x << " " << p1y
|
||
|
|
<< ") p2=("
|
||
|
|
<< p2x << " " << p2y
|
||
|
|
<< ")"
|
||
|
|
<< " ip1=("
|
||
|
|
<< ip1x << " " << ip1y << " " << ip1t << ")"
|
||
|
|
<< endl;
|
||
|
|
}
|
||
|
|
|
||
|
|
TrapeziumSegmentIntersection tsi;
|
||
|
|
|
||
|
|
tsi.x = ip1x;
|
||
|
|
tsi.y = ip1y;
|
||
|
|
tsi.t = ip1t;
|
||
|
|
|
||
|
|
/*
|
||
|
|
Is the ~UPoint~ instance constant and is it located on the segment?
|
||
|
|
|
||
|
|
*/
|
||
|
|
if (nearlyEqual(rUp.p0.GetX(), ip1x)
|
||
|
|
&& nearlyEqual(rUp.p0.GetY(), ip1y)
|
||
|
|
&& nearlyEqual(rUp.p1.GetX(), ip1x)
|
||
|
|
&& nearlyEqual(rUp.p1.GetY(), ip1y)) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::RIFN() through p0 and p1" << endl;
|
||
|
|
|
||
|
|
/*
|
||
|
|
Yes, lets see if the moving segment did not touch the ~UPoint~ instance
|
||
|
|
during initial time. If yes, we can deduce from the ~insideAbove~ attribute
|
||
|
|
and the direction of the movement whether the ~URegion~ has been entered or
|
||
|
|
left at the intersection point. If not, we just two identical points, one
|
||
|
|
with TSI\_ENTER and one with TSI\_LEAVE, which indicates that the ~URegion~
|
||
|
|
has been entered and left in the same instance.
|
||
|
|
|
||
|
|
*/
|
||
|
|
if (!nearlyEqual(ip1t, iv.start.ToDouble())) {
|
||
|
|
if (pointAboveSegment(ip1x, ip1y,
|
||
|
|
rDms.GetInitialStartX(),
|
||
|
|
rDms.GetInitialStartY(),
|
||
|
|
rDms.GetInitialEndX(),
|
||
|
|
rDms.GetInitialEndY())) {
|
||
|
|
tsi.type = rDms.GetInsideAbove() ? TSI_LEAVE : TSI_ENTER;
|
||
|
|
} else {
|
||
|
|
tsi.type = rDms.GetInsideAbove() ? TSI_ENTER : TSI_LEAVE;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::RIFN() adding "
|
||
|
|
<< tsi.type
|
||
|
|
<< " " << tsi.x << " " << tsi.y << " " << tsi.t
|
||
|
|
<< endl;
|
||
|
|
vtsi.push_back(tsi);
|
||
|
|
} else if (!nearlyEqual(ip1t, iv.end.ToDouble())) {
|
||
|
|
if (pointAboveSegment(ip1x, ip1y,
|
||
|
|
rDms.GetFinalStartX(),
|
||
|
|
rDms.GetFinalStartY(),
|
||
|
|
rDms.GetFinalEndX(),
|
||
|
|
rDms.GetFinalEndY())) {
|
||
|
|
tsi.type = rDms.GetInsideAbove() ? TSI_ENTER : TSI_LEAVE;
|
||
|
|
} else {
|
||
|
|
tsi.type = rDms.GetInsideAbove() ? TSI_LEAVE : TSI_ENTER;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::RIFN() adding "
|
||
|
|
<< tsi.type
|
||
|
|
<< " " << tsi.x << " " << tsi.y << " " << tsi.t
|
||
|
|
<< endl;
|
||
|
|
vtsi.push_back(tsi);
|
||
|
|
} else {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::RIFN() adding "
|
||
|
|
<< tsi.type
|
||
|
|
<< " " << tsi.x << " " << tsi.y << " " << tsi.t
|
||
|
|
<< endl;
|
||
|
|
tsi.type = TSI_ENTER;
|
||
|
|
vtsi.push_back(tsi);
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::RIFN() adding "
|
||
|
|
<< tsi.type
|
||
|
|
<< " " << tsi.x << " " << tsi.y << " " << tsi.t
|
||
|
|
<< endl;
|
||
|
|
tsi.type = TSI_LEAVE;
|
||
|
|
vtsi.push_back(tsi);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
Is one of the endpoints of the ~UPoint~ instance located on the segment?
|
||
|
|
If so, check whether the other endpoint is above or below the segment.
|
||
|
|
Together with the value of the ~insideAbove~ attribute, we can deduce
|
||
|
|
whether the ~URegion~ instance has been entered or left.
|
||
|
|
|
||
|
|
The same is checked for the end of the interval. This is to determine
|
||
|
|
whether point and segment move into the same direction with the segment
|
||
|
|
being faster than the point. In this case, both only touch without the
|
||
|
|
point actually entering the ~URegion~ instance.
|
||
|
|
|
||
|
|
*/
|
||
|
|
} else if (nearlyEqual(rUp.p0.GetX(), ip1x)
|
||
|
|
&& nearlyEqual(rUp.p0.GetY(), ip1y)) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::RIFN() through p0" << endl;
|
||
|
|
|
||
|
|
if (pointAboveSegment(rUp.p1.GetX(), rUp.p1.GetY(),
|
||
|
|
p1x, p1y, p2x, p2y)) {
|
||
|
|
tsi.type = rDms.GetInsideAbove() ? TSI_ENTER : TSI_LEAVE;
|
||
|
|
} else {
|
||
|
|
tsi.type = rDms.GetInsideAbove() ? TSI_LEAVE : TSI_ENTER;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::RIFN() adding "
|
||
|
|
<< tsi.type
|
||
|
|
<< " " << tsi.x << " " << tsi.y << " " << tsi.t
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
vtsi.push_back(tsi);
|
||
|
|
|
||
|
|
if (pointAboveSegment(rUp.p1.GetX(), rUp.p1.GetY(),
|
||
|
|
rDms.GetFinalStartX(),
|
||
|
|
rDms.GetFinalStartY(),
|
||
|
|
rDms.GetFinalEndX(),
|
||
|
|
rDms.GetFinalEndY())) {
|
||
|
|
tsi.type = tsi.type == TSI_ENTER ? TSI_LEAVE : TSI_ENTER;
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::RIFN() adding "
|
||
|
|
<< tsi.type
|
||
|
|
<< " " << tsi.x << " " << tsi.y << " " << tsi.t
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
vtsi.push_back(tsi);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
Is the other endpoint of the ~UPoint~ instance located on the segment?
|
||
|
|
If so, see handling of previous case.
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
} else if (nearlyEqual(rUp.p1.GetX(), ip1x)
|
||
|
|
&& nearlyEqual(rUp.p1.GetY(), ip1y)) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::RIFN() through p1" << endl;
|
||
|
|
|
||
|
|
if (pointAboveSegment(rUp.p0.GetX(), rUp.p0.GetY(),
|
||
|
|
p1x, p1y, p2x, p2y)) {
|
||
|
|
tsi.type = rDms.GetInsideAbove() ? TSI_LEAVE : TSI_ENTER;
|
||
|
|
} else {
|
||
|
|
tsi.type = rDms.GetInsideAbove() ? TSI_ENTER : TSI_LEAVE;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::RIFN() adding "
|
||
|
|
<< tsi.type
|
||
|
|
<< " " << tsi.x << " " << tsi.y << " " << tsi.t
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
vtsi.push_back(tsi);
|
||
|
|
|
||
|
|
if (pointAboveSegment(rUp.p0.GetX(), rUp.p0.GetY(),
|
||
|
|
rDms.GetInitialStartX(),
|
||
|
|
rDms.GetInitialStartY(),
|
||
|
|
rDms.GetInitialEndX(),
|
||
|
|
rDms.GetInitialEndY())) {
|
||
|
|
tsi.type = tsi.type == TSI_ENTER ? TSI_LEAVE : TSI_ENTER;
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::RIFN() adding "
|
||
|
|
<< tsi.type
|
||
|
|
<< " " << tsi.x << " " << tsi.y << " " << tsi.t
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
vtsi.push_back(tsi);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
At this point, we do know that one endpoint of the ~UPoint~ instance is
|
||
|
|
left or above the segment. Lets find out which in the remaining two cases.
|
||
|
|
|
||
|
|
*/
|
||
|
|
} else if (pointAboveSegment(rUp.p0.GetX(), rUp.p0.GetY(),
|
||
|
|
rDms.GetInitialStartX(),
|
||
|
|
rDms.GetInitialStartY(),
|
||
|
|
rDms.GetInitialEndX(),
|
||
|
|
rDms.GetInitialEndY())) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::RIFN() p0 above segment" << endl;
|
||
|
|
|
||
|
|
tsi.type = rDms.GetInsideAbove() ? TSI_LEAVE : TSI_ENTER;
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::RIFN() adding "
|
||
|
|
<< tsi.type
|
||
|
|
<< " " << tsi.x << " " << tsi.y << " " << tsi.t
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
vtsi.push_back(tsi);
|
||
|
|
} else {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::RIFN() p0 below segment" << endl;
|
||
|
|
|
||
|
|
tsi.type = rDms.GetInsideAbove() ? TSI_ENTER : TSI_LEAVE;
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::RIFN() adding "
|
||
|
|
<< tsi.type
|
||
|
|
<< " " << tsi.x << " " << tsi.y << " " << tsi.t
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
vtsi.push_back(tsi);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1 Method ~RestrictedIntersectionFindInPlane()~
|
||
|
|
|
||
|
|
*/
|
||
|
|
void URegionEmb::RestrictedIntersectionFindInPlane(
|
||
|
|
const Interval<Instant>& iv,
|
||
|
|
const UPoint& rUp,
|
||
|
|
bool& ip1present,
|
||
|
|
double& ip1x,
|
||
|
|
double& ip1y,
|
||
|
|
double& ip1t,
|
||
|
|
bool& ip2present,
|
||
|
|
double& ip2x,
|
||
|
|
double& ip2y,
|
||
|
|
double& ip2t,
|
||
|
|
vector<TrapeziumSegmentIntersection>& vtsi) const {
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::RIFIP() called" << endl;
|
||
|
|
|
||
|
|
TrapeziumSegmentIntersection tsi;
|
||
|
|
|
||
|
|
tsi.x = ip1x;
|
||
|
|
tsi.y = ip1y;
|
||
|
|
tsi.t = ip1t;
|
||
|
|
|
||
|
|
if ((nearlyEqual(ip1x, rUp.p0.GetX())
|
||
|
|
&& nearlyEqual(ip1y, rUp.p0.GetY())
|
||
|
|
&& nearlyEqual(ip2x, rUp.p1.GetX())
|
||
|
|
&& nearlyEqual(ip2y, rUp.p1.GetY()))
|
||
|
|
|| (nearlyEqual(ip1x, rUp.p1.GetX())
|
||
|
|
&& nearlyEqual(ip1y, rUp.p1.GetY())
|
||
|
|
&& nearlyEqual(ip2x, rUp.p0.GetX())
|
||
|
|
&& nearlyEqual(ip2y, rUp.p0.GetY()))) {
|
||
|
|
/*
|
||
|
|
The ~URegion~ happily walks entirely along one of the moving segments of the
|
||
|
|
~URegion~ instance. When the segments is entered, the ~URegion~ instance
|
||
|
|
is entered, and when the segment is left, the ~URegion~ instance is left.
|
||
|
|
|
||
|
|
*/
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::RIFIP() up on segment"
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
tsi.type = ip1t < ip2t ? TSI_ENTER : TSI_LEAVE;
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::RIFIP() adding "
|
||
|
|
<< tsi.type
|
||
|
|
<< " " << tsi.x << " " << tsi.y << " " << tsi.t
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
vtsi.push_back(tsi);
|
||
|
|
|
||
|
|
tsi.type = ip1t < ip2t ? TSI_LEAVE : TSI_ENTER;
|
||
|
|
tsi.x = ip2x;
|
||
|
|
tsi.y = ip2y;
|
||
|
|
tsi.t = ip2t;
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::RIFIP() adding "
|
||
|
|
<< tsi.type
|
||
|
|
<< " " << tsi.x << " " << tsi.y << " " << tsi.t
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
vtsi.push_back(tsi);
|
||
|
|
|
||
|
|
} else if (nearlyEqual(ip1x, rUp.p0.GetX())
|
||
|
|
&& nearlyEqual(ip1y, rUp.p0.GetY())) {
|
||
|
|
/*
|
||
|
|
The ~URegion~ instance is entered via one of its edge points.
|
||
|
|
|
||
|
|
*/
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::RIFIP() ip1=p0" << endl;
|
||
|
|
|
||
|
|
tsi.type = TSI_ENTER;
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::RIFIP() adding "
|
||
|
|
<< tsi.type
|
||
|
|
<< " " << tsi.x << " " << tsi.y << " " << tsi.t
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
vtsi.push_back(tsi);
|
||
|
|
|
||
|
|
tsi.type = TSI_LEAVE;
|
||
|
|
tsi.x = ip2x;
|
||
|
|
tsi.y = ip2y;
|
||
|
|
tsi.t = ip2t;
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::RIFIP() adding "
|
||
|
|
<< tsi.type
|
||
|
|
<< " " << tsi.x << " " << tsi.y << " " << tsi.t
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
vtsi.push_back(tsi);
|
||
|
|
} else if (nearlyEqual(ip1x, rUp.p1.GetX())
|
||
|
|
&& nearlyEqual(ip1y, rUp.p1.GetY())) {
|
||
|
|
/*
|
||
|
|
The ~URegion~ instance is left via one of its edge points. See previous
|
||
|
|
case.
|
||
|
|
|
||
|
|
*/
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::RIFIP() ip1=p1" << endl;
|
||
|
|
|
||
|
|
tsi.type = TSI_LEAVE;
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::RIFIP() adding "
|
||
|
|
<< tsi.type
|
||
|
|
<< " " << tsi.x << " " << tsi.y << " " << tsi.t
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
vtsi.push_back(tsi);
|
||
|
|
|
||
|
|
tsi.type = TSI_ENTER;
|
||
|
|
tsi.x = ip2x;
|
||
|
|
tsi.y = ip2y;
|
||
|
|
tsi.t = ip2t;
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::RIFIP() adding "
|
||
|
|
<< tsi.type
|
||
|
|
<< " " << tsi.x << " " << tsi.y << " " << tsi.t
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
vtsi.push_back(tsi);
|
||
|
|
} else if (nearlyEqual(ip2x, rUp.p0.GetX())
|
||
|
|
&& nearlyEqual(ip2y, rUp.p0.GetY())) {
|
||
|
|
/*
|
||
|
|
The ~URegion~ instance is entered via one of its edge points. See previous
|
||
|
|
case.
|
||
|
|
|
||
|
|
*/
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::RIFIP() ip2=p0" << endl;
|
||
|
|
|
||
|
|
tsi.type = TSI_LEAVE;
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::RIFIP() adding "
|
||
|
|
<< tsi.type
|
||
|
|
<< " " << tsi.x << " " << tsi.y << " " << tsi.t
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
vtsi.push_back(tsi);
|
||
|
|
|
||
|
|
tsi.type = TSI_ENTER;
|
||
|
|
tsi.x = ip2x;
|
||
|
|
tsi.y = ip2y;
|
||
|
|
tsi.t = ip2t;
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::RIFIP() adding "
|
||
|
|
<< tsi.type
|
||
|
|
<< " " << tsi.x << " " << tsi.y << " " << tsi.t
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
vtsi.push_back(tsi);
|
||
|
|
} else if (nearlyEqual(ip2x, rUp.p1.GetX())
|
||
|
|
&& nearlyEqual(ip2y, rUp.p1.GetY())) {
|
||
|
|
/*
|
||
|
|
The ~URegion~ instance is left via one of its edge points. See previous
|
||
|
|
case.
|
||
|
|
|
||
|
|
*/
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::RIFIP() ip2=p1" << endl;
|
||
|
|
|
||
|
|
tsi.type = TSI_ENTER;
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::RIFIP() adding "
|
||
|
|
<< tsi.type
|
||
|
|
<< " " << tsi.x << " " << tsi.y << " " << tsi.t
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
vtsi.push_back(tsi);
|
||
|
|
|
||
|
|
tsi.type = TSI_LEAVE;
|
||
|
|
tsi.x = ip2x;
|
||
|
|
tsi.y = ip2y;
|
||
|
|
tsi.t = ip2t;
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::RIFIP() adding "
|
||
|
|
<< tsi.type
|
||
|
|
<< " " << tsi.x << " " << tsi.y << " " << tsi.t
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
vtsi.push_back(tsi);
|
||
|
|
} else {
|
||
|
|
/*
|
||
|
|
The ~URegion~ instance is entered and left elsewhere, ie. in the middle
|
||
|
|
of the segments.
|
||
|
|
|
||
|
|
*/
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::RIFIP() up covers segment" << endl;
|
||
|
|
|
||
|
|
tsi.type = ip1t < ip2t ? TSI_ENTER : TSI_LEAVE;
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::RIFIP() adding "
|
||
|
|
<< tsi.type
|
||
|
|
<< " " << tsi.x << " " << tsi.y << " " << tsi.t
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
vtsi.push_back(tsi);
|
||
|
|
|
||
|
|
tsi.type = ip1t < ip2t ? TSI_LEAVE : TSI_ENTER;
|
||
|
|
tsi.x = ip2x;
|
||
|
|
tsi.y = ip2y;
|
||
|
|
tsi.t = ip2t;
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::RIFIP() adding "
|
||
|
|
<< tsi.type
|
||
|
|
<< " " << tsi.x << " " << tsi.y << " " << tsi.t
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
vtsi.push_back(tsi);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1 Method ~RestrictedIntersectionFind()~
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
void URegionEmb::RestrictedIntersectionFind(
|
||
|
|
const DbArray<MSegmentData>* segments,
|
||
|
|
const UPoint& up,
|
||
|
|
const Interval<Instant>& iv,
|
||
|
|
vector<TrapeziumSegmentIntersection>& vtsi) const {
|
||
|
|
|
||
|
|
/*
|
||
|
|
Straightforward. Even being slightly cryptic, the debug output provides
|
||
|
|
sufficient context to understand this method.
|
||
|
|
|
||
|
|
*/
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::RIF() called" << endl;
|
||
|
|
|
||
|
|
UPoint rUp(true);
|
||
|
|
restrictUPointToInterval(up, iv, rUp);
|
||
|
|
|
||
|
|
for (unsigned int i = 0; i < segmentsNum; i++) {
|
||
|
|
MSegmentData dms;
|
||
|
|
segments->Get(segmentsStartPos+i, &dms);
|
||
|
|
|
||
|
|
if (MRA_DEBUG) {
|
||
|
|
cerr << "URegionEmb::RIF() segment #"
|
||
|
|
<< i
|
||
|
|
<< ": ["
|
||
|
|
<< timeInterval.start.ToDouble()
|
||
|
|
<< " "
|
||
|
|
<< timeInterval.end.ToDouble()
|
||
|
|
<< " "
|
||
|
|
<< timeInterval.lc << " " << timeInterval.rc
|
||
|
|
<< "] "
|
||
|
|
<< dms.ToString()
|
||
|
|
<< endl;
|
||
|
|
cerr << "URegionEmb::RIF() point is ["
|
||
|
|
<< up.timeInterval.start.ToDouble()
|
||
|
|
<< " "
|
||
|
|
<< up.timeInterval.end.ToDouble()
|
||
|
|
<< " "
|
||
|
|
<< up.timeInterval.lc << " " << up.timeInterval.rc
|
||
|
|
<< "] ("
|
||
|
|
<< up.p0.GetX() << " " << up.p0.GetY()
|
||
|
|
<< " "
|
||
|
|
<< up.p1.GetX() << " " << up.p1.GetY()
|
||
|
|
<< ")"
|
||
|
|
<< endl;
|
||
|
|
cerr << "URegionEmb::RIF() iv is ["
|
||
|
|
<< iv.start.ToDouble()
|
||
|
|
<< " "
|
||
|
|
<< iv.end.ToDouble()
|
||
|
|
<< " "
|
||
|
|
<< iv.lc
|
||
|
|
<< " "
|
||
|
|
<< iv.rc
|
||
|
|
<< "]"
|
||
|
|
<< endl;
|
||
|
|
}
|
||
|
|
|
||
|
|
MSegmentData rDms;
|
||
|
|
dms.restrictToInterval(timeInterval, iv, rDms);
|
||
|
|
|
||
|
|
if (MRA_DEBUG) {
|
||
|
|
cerr << "URegionEmb::RIF() segment restricted to iv is "
|
||
|
|
<< rDms.ToString()
|
||
|
|
<< endl;
|
||
|
|
cerr << "URegionEmb::RIF() point restricted to iv is ("
|
||
|
|
<< rUp.p0.GetX() << " " << rUp.p0.GetY()
|
||
|
|
<< " "
|
||
|
|
<< rUp.p1.GetX() << " " << rUp.p1.GetY()
|
||
|
|
<< ")"
|
||
|
|
<< endl;
|
||
|
|
}
|
||
|
|
|
||
|
|
bool ip1present;
|
||
|
|
double ip1x;
|
||
|
|
double ip1y;
|
||
|
|
double ip1t;
|
||
|
|
bool ip2present;
|
||
|
|
double ip2x;
|
||
|
|
double ip2y;
|
||
|
|
double ip2t;
|
||
|
|
|
||
|
|
specialIntersectionTrapeziumSegment(
|
||
|
|
iv.start.ToDouble(), iv.end.ToDouble(),
|
||
|
|
rDms.GetInitialStartX(), rDms.GetInitialStartY(),
|
||
|
|
rDms.GetInitialEndX(), rDms.GetInitialEndY(),
|
||
|
|
rDms.GetFinalStartX(), rDms.GetFinalStartY(),
|
||
|
|
rDms.GetFinalEndX(), rDms.GetFinalEndY(),
|
||
|
|
rUp.p0.GetX(), rUp.p0.GetY(),
|
||
|
|
rUp.p1.GetX(), rUp.p1.GetY(),
|
||
|
|
ip1present, ip1x, ip1y, ip1t,
|
||
|
|
ip2present, ip2x, ip2y, ip2t);
|
||
|
|
|
||
|
|
// debug::start
|
||
|
|
if(MRA_DEBUG){
|
||
|
|
int i = 0;
|
||
|
|
if (ip1t == 0){i++;}
|
||
|
|
if (1.0 > iv.end.ToDouble()){i++;}
|
||
|
|
if (ip2t == 0){i++;}
|
||
|
|
if ( i > 0 ) cout << __PRETTY_FUNCTION__
|
||
|
|
<< " WARNING: Probably uninitialized values!" << endl;
|
||
|
|
}
|
||
|
|
// debug::end
|
||
|
|
if(ip1present){
|
||
|
|
if(ip1t < iv.start.ToDouble() || ip1t > iv.end.ToDouble()){
|
||
|
|
ip1present = false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if(ip2present) {
|
||
|
|
if(ip2t < iv.start.ToDouble() || ip2t > iv.end.ToDouble()) {
|
||
|
|
ip2present = false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (MRA_DEBUG) {
|
||
|
|
cerr << "URegionEmb::RIF() ip1present=" << ip1present
|
||
|
|
<< endl;
|
||
|
|
cerr << "URegionEmb::RIF() ip2present=" << ip2present
|
||
|
|
<< endl;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (ip1present) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::RIF() intersection" << endl;
|
||
|
|
|
||
|
|
if (ip2present
|
||
|
|
&& !(nearlyEqual(ip1x, ip2x)
|
||
|
|
&& nearlyEqual(ip1y, ip2y)
|
||
|
|
&& nearlyEqual(ip1t, ip2t))) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::RIF() in plane, ip1t=" << ip1t
|
||
|
|
<< ", ip2t=" << ip2t
|
||
|
|
<< ", interval=" << timeInterval.start.ToDouble()
|
||
|
|
<< " " << timeInterval.end.ToDouble()
|
||
|
|
<< " " << timeInterval.lc
|
||
|
|
<< " " << timeInterval.rc
|
||
|
|
<< ", restricted=" << iv.start.ToDouble()
|
||
|
|
<< " " << iv.end.ToDouble()
|
||
|
|
<< " " << iv.lc
|
||
|
|
<< " " << iv.rc
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
RestrictedIntersectionFindInPlane(
|
||
|
|
iv, rUp,
|
||
|
|
ip1present, ip1x, ip1y, ip1t,
|
||
|
|
ip2present, ip2x, ip2y, ip2t,
|
||
|
|
vtsi);
|
||
|
|
} else {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::RIF() not in plane, ip1t=" << ip1t
|
||
|
|
<< ", interval=" << timeInterval.start.ToDouble()
|
||
|
|
<< " " << timeInterval.end.ToDouble()
|
||
|
|
<< " " << timeInterval.lc
|
||
|
|
<< " " << timeInterval.rc
|
||
|
|
<< ", restricted=" << iv.start.ToDouble()
|
||
|
|
<< " " << iv.end.ToDouble()
|
||
|
|
<< " " << iv.lc
|
||
|
|
<< " " << iv.rc
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
RestrictedIntersectionFindNormal(
|
||
|
|
iv, rUp, rDms,
|
||
|
|
ip1present, ip1x, ip1y, ip1t,
|
||
|
|
vtsi);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1 Method ~RestrictedIntersectionFix()~
|
||
|
|
|
||
|
|
*/
|
||
|
|
void URegionEmb::RestrictedIntersectionFix(
|
||
|
|
vector<TrapeziumSegmentIntersection>& vtsi) const {
|
||
|
|
|
||
|
|
/*
|
||
|
|
Examines intersections with same coordinate, counts $TSI\_LEAVE$ and
|
||
|
|
$TSI\_ENTER$ intersections and results in one or zero intersections with
|
||
|
|
the same coordinate, based on whether there are more $TSI\_LEAVE$ or
|
||
|
|
$TSI\_ENTER$ intersections or the same number of them.
|
||
|
|
|
||
|
|
*/
|
||
|
|
TsiType lastType = TSI_IGNORE;
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
for (unsigned int i = 0; i < vtsi.size(); i++)
|
||
|
|
cerr << "URegionEmb::RIFix() intersection dump #"
|
||
|
|
<< i
|
||
|
|
<< " type="
|
||
|
|
<< vtsi[i].type
|
||
|
|
<< " ip=["
|
||
|
|
<< vtsi[i].x << " " << vtsi[i].y << " " << vtsi[i].t
|
||
|
|
<< "]"
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
|
||
|
|
for (unsigned int i = 0; i < vtsi.size(); i++) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::RIFix() post-sort i=" << i << endl;
|
||
|
|
|
||
|
|
unsigned int j;
|
||
|
|
unsigned int numEnter = 0;
|
||
|
|
unsigned int numLeave = 0;
|
||
|
|
|
||
|
|
double t = vtsi[i].t;
|
||
|
|
double x = vtsi[i].x;
|
||
|
|
double y = vtsi[i].y;
|
||
|
|
|
||
|
|
for (j = i;
|
||
|
|
j < vtsi.size()
|
||
|
|
&& nearlyEqual(vtsi[j].t, t)
|
||
|
|
&& nearlyEqual(vtsi[j].x, x)
|
||
|
|
&& nearlyEqual(vtsi[j].y, y);
|
||
|
|
j++) {
|
||
|
|
if (vtsi[j].type == TSI_ENTER)
|
||
|
|
numEnter++;
|
||
|
|
else
|
||
|
|
numLeave++;
|
||
|
|
}
|
||
|
|
|
||
|
|
j--;
|
||
|
|
|
||
|
|
if (MRA_DEBUG) {
|
||
|
|
cerr << "URegionEmb::RIFix() post-sort j=" << j << endl;
|
||
|
|
cerr << "URegionEmb::RIFix() post-sort numEnter="
|
||
|
|
<< numEnter
|
||
|
|
<< endl;
|
||
|
|
cerr << "URegionEmb::RIFix() post-sort numLeave="
|
||
|
|
<< numLeave
|
||
|
|
<< endl;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (j > i) {
|
||
|
|
if (numEnter == numLeave) {
|
||
|
|
if (i > 0 && lastType == TSI_ENTER) {
|
||
|
|
vtsi[i].type = TSI_LEAVE;
|
||
|
|
vtsi[i+1].type = TSI_ENTER;
|
||
|
|
lastType = TSI_ENTER;
|
||
|
|
} else {
|
||
|
|
vtsi[i].type = TSI_ENTER;
|
||
|
|
vtsi[i+1].type = TSI_LEAVE;
|
||
|
|
lastType = TSI_LEAVE;
|
||
|
|
}
|
||
|
|
for (unsigned int k = i+2; k <= j; k++)
|
||
|
|
vtsi[k].type = TSI_IGNORE;
|
||
|
|
} else if (numEnter > numLeave) {
|
||
|
|
vtsi[i].type = TSI_ENTER;
|
||
|
|
for (unsigned int k = i+1; k <= j; k++)
|
||
|
|
vtsi[k].type = TSI_IGNORE;
|
||
|
|
lastType = TSI_ENTER;
|
||
|
|
} else {
|
||
|
|
vtsi[i].type = TSI_LEAVE;
|
||
|
|
for (unsigned int k = i+1; k <= j; k++)
|
||
|
|
vtsi[k].type = TSI_IGNORE;
|
||
|
|
lastType = TSI_LEAVE;
|
||
|
|
}
|
||
|
|
|
||
|
|
i = j;
|
||
|
|
} else {
|
||
|
|
lastType = vtsi[i].type;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1 Method ~RestrictedIntersectionProcess()~
|
||
|
|
|
||
|
|
*/
|
||
|
|
bool URegionEmb::RestrictedIntersectionProcess(
|
||
|
|
const UPoint& up,
|
||
|
|
const Interval<Instant>& iv,
|
||
|
|
vector<TrapeziumSegmentIntersection>& vtsi,
|
||
|
|
MPoint& res,
|
||
|
|
UPoint*& pending,
|
||
|
|
bool merge) const {
|
||
|
|
|
||
|
|
/*
|
||
|
|
Check all intersections with the same coordinates. Bring them in
|
||
|
|
useful order. For example, if we are inside region at a specific time
|
||
|
|
and arrive at a $TSI\_ENTER$ and $TSI\_LEAVE$ intersection, we should
|
||
|
|
consider the $TSI\_LEAVE$ intersection first.
|
||
|
|
|
||
|
|
*/
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::RIP() called, interval="
|
||
|
|
<< setprecision(12)
|
||
|
|
<< iv.start.ToDouble()
|
||
|
|
<< " "
|
||
|
|
<< iv.end.ToDouble()
|
||
|
|
<< " "
|
||
|
|
<< iv.lc
|
||
|
|
<< " "
|
||
|
|
<< iv.rc
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
if (vtsi.size() == 0) return false;
|
||
|
|
|
||
|
|
int prev_i = -1;
|
||
|
|
bool prev_c = false;
|
||
|
|
|
||
|
|
unsigned int pos = 0;
|
||
|
|
|
||
|
|
if (MRA_DEBUG && vtsi.size() > 0)
|
||
|
|
cerr << "URegionEmb::RIP() (pre) intersection dump #"
|
||
|
|
<< 0
|
||
|
|
<< " type="
|
||
|
|
<< vtsi[0].type
|
||
|
|
<< " ip=["
|
||
|
|
<< vtsi[0].x << " " << vtsi[0].y << " " << vtsi[0].t
|
||
|
|
<< "]"
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
for (unsigned int i = 1; i < vtsi.size(); i++) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::RIP() intersection dump #"
|
||
|
|
<< i
|
||
|
|
<< " type="
|
||
|
|
<< vtsi[i].type
|
||
|
|
<< " ip=["
|
||
|
|
<< vtsi[i].x << " " << vtsi[i].y << " " << vtsi[i].t
|
||
|
|
<< "] pos="
|
||
|
|
<< pos
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
// if (vtsi[i].type == vtsi[pos].type) {
|
||
|
|
if (vtsi[i].type == TSI_IGNORE) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::RIP() removing" << endl;
|
||
|
|
} else {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::RIP() keeping" << endl;
|
||
|
|
|
||
|
|
pos++;
|
||
|
|
if (pos < i) vtsi[pos] = vtsi[i];
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
for (unsigned int i = 0; i <= pos; i++)
|
||
|
|
cerr << "URegionEmb::RIP() intersection dump #"
|
||
|
|
<< setprecision(12)
|
||
|
|
<< i
|
||
|
|
<< " type="
|
||
|
|
<< vtsi[i].type
|
||
|
|
<< " ip=["
|
||
|
|
<< vtsi[i].x << " " << vtsi[i].y << " " << vtsi[i].t
|
||
|
|
<< "]"
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
for (unsigned int i = 0; i <= pos; i++) {
|
||
|
|
if (MRA_DEBUG) {
|
||
|
|
cerr << "URegionEmb::RIP() intersection dump #"
|
||
|
|
<< i
|
||
|
|
<< " type="
|
||
|
|
<< vtsi[i].type
|
||
|
|
<< " ip=["
|
||
|
|
<< vtsi[i].x << " " << vtsi[i].y << " " << vtsi[i].t
|
||
|
|
<< "]"
|
||
|
|
<< endl;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (i == 0 && vtsi[i].type == TSI_LEAVE) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::RIP() special case (start)"
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
bool rc =
|
||
|
|
nearlyEqual(vtsi[i].t, iv.end.ToDouble())
|
||
|
|
? iv.rc
|
||
|
|
: true;
|
||
|
|
|
||
|
|
UPoint rUp(true);
|
||
|
|
restrictUPointToInterval(up, iv, rUp);
|
||
|
|
|
||
|
|
RestrictedIntersectionAddUPoint(
|
||
|
|
res,
|
||
|
|
iv.start.ToDouble(), vtsi[i].t, iv.lc, rc,
|
||
|
|
rUp.p0.GetX(), rUp.p0.GetY(), vtsi[i].x, vtsi[i].y,
|
||
|
|
pending,
|
||
|
|
merge);
|
||
|
|
|
||
|
|
prev_i = i;
|
||
|
|
prev_c = rc;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (i > 0 && vtsi[i].type == TSI_LEAVE) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::RIP() normal case" << endl;
|
||
|
|
|
||
|
|
bool lc =
|
||
|
|
nearlyEqual(vtsi[i-1].t, iv.start.ToDouble())
|
||
|
|
? iv.lc
|
||
|
|
: true;
|
||
|
|
|
||
|
|
if (prev_i >= 0
|
||
|
|
&& nearlyEqual(vtsi[prev_i].t, vtsi[i-1].t)
|
||
|
|
&& prev_c)
|
||
|
|
lc = false;
|
||
|
|
|
||
|
|
bool rc =
|
||
|
|
nearlyEqual(vtsi[i].t, iv.end.ToDouble())
|
||
|
|
? iv.rc
|
||
|
|
: true;
|
||
|
|
|
||
|
|
RestrictedIntersectionAddUPoint(
|
||
|
|
res,
|
||
|
|
vtsi[i-1].t, vtsi[i].t, lc, rc,
|
||
|
|
vtsi[i-1].x, vtsi[i-1].y, vtsi[i].x, vtsi[i].y,
|
||
|
|
pending,
|
||
|
|
merge);
|
||
|
|
|
||
|
|
prev_i = i;
|
||
|
|
prev_c = rc;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (i == pos && vtsi[i].type == TSI_ENTER) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::RIP() special case (end)" << endl;
|
||
|
|
|
||
|
|
bool lc =
|
||
|
|
nearlyEqual(vtsi[i].t, iv.start.ToDouble())
|
||
|
|
? iv.lc
|
||
|
|
: true;
|
||
|
|
|
||
|
|
if (prev_i >= 0
|
||
|
|
&& nearlyEqual(vtsi[prev_i].t, vtsi[i].t)
|
||
|
|
&& prev_c)
|
||
|
|
lc = false;
|
||
|
|
|
||
|
|
UPoint rUp(true);
|
||
|
|
restrictUPointToInterval(up, iv, rUp);
|
||
|
|
|
||
|
|
RestrictedIntersectionAddUPoint(
|
||
|
|
res,
|
||
|
|
vtsi[i].t, iv.end.ToDouble(), lc, iv.rc,
|
||
|
|
vtsi[i].x, vtsi[i].y, rUp.p1.GetX(), rUp.p1.GetY(),
|
||
|
|
pending,
|
||
|
|
merge);
|
||
|
|
|
||
|
|
prev_i = 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return prev_i >= 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1 Database operator methods
|
||
|
|
|
||
|
|
These methods are used to implement the algebra's operators.
|
||
|
|
|
||
|
|
1.1.1 Method ~RestrictedIntersection()~
|
||
|
|
|
||
|
|
Checks whether the point unit ~up~ intersects this region unit, while
|
||
|
|
both units are restricted to the interval ~iv~, which must be inside
|
||
|
|
the interval of the two units (this is not checked and must be assured
|
||
|
|
before this method is called!).
|
||
|
|
|
||
|
|
*/
|
||
|
|
void URegionEmb::RestrictedIntersection(const DbArray<MSegmentData>* segments,
|
||
|
|
const UPoint& up,
|
||
|
|
const Interval<Instant>& iv,
|
||
|
|
MPoint& res,
|
||
|
|
UPoint*& pending,
|
||
|
|
bool merge) const {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::RI() called" << endl;
|
||
|
|
|
||
|
|
vector<TrapeziumSegmentIntersection> vtsi;
|
||
|
|
|
||
|
|
RestrictedIntersectionFind(segments, up, iv, vtsi);
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::RI() vtsi.size()=" << vtsi.size()
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
sort(vtsi.begin(), vtsi.end());
|
||
|
|
|
||
|
|
RestrictedIntersectionFix(vtsi);
|
||
|
|
|
||
|
|
if (!RestrictedIntersectionProcess(up, iv, vtsi, res, pending, merge)) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegionEmb::RI() no intersection in whole unit"
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
unsigned int num = Plumbline(segments, up, iv);
|
||
|
|
|
||
|
|
if (num > 0 && num % 2 == 1) {
|
||
|
|
UPoint rUp(true);
|
||
|
|
restrictUPointToInterval(up, iv, rUp);
|
||
|
|
|
||
|
|
RestrictedIntersectionAddUPoint(
|
||
|
|
res,
|
||
|
|
iv.start.ToDouble(), iv.end.ToDouble(),
|
||
|
|
iv.lc, iv.rc,
|
||
|
|
rUp.p0.GetX(), rUp.p0.GetY(),
|
||
|
|
rUp.p1.GetX(), rUp.p1.GetY(),
|
||
|
|
pending,
|
||
|
|
merge);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1 Method ~TemporalFunction()~
|
||
|
|
|
||
|
|
*/
|
||
|
|
void URegionEmb::TemporalFunction(
|
||
|
|
const DbArray<MSegmentData>* segments,
|
||
|
|
const Instant& t,
|
||
|
|
Region& res,
|
||
|
|
bool ignoreLimits ) const {
|
||
|
|
|
||
|
|
if (MRA_DEBUG){
|
||
|
|
cerr << "URegionEmb::TemporalFunction() called" << endl;
|
||
|
|
}
|
||
|
|
/*
|
||
|
|
Straightforward again. Calculate segments at specified instant,
|
||
|
|
remove degenerated segments of initial or final instant, when they
|
||
|
|
are not border of any region, and create region.
|
||
|
|
|
||
|
|
*/
|
||
|
|
assert(t.IsDefined());
|
||
|
|
assert( ignoreLimits || timeInterval.Contains(t) );
|
||
|
|
|
||
|
|
res.Clear();
|
||
|
|
if(!t.IsDefined() || !(ignoreLimits || timeInterval.Contains(t)) ) {
|
||
|
|
res.SetDefined( false );
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
res.SetDefined( true );
|
||
|
|
|
||
|
|
Instant t0 = timeInterval.start;
|
||
|
|
Instant t1 = timeInterval.end;
|
||
|
|
|
||
|
|
bool initialInstant = nearlyEqual(t0.ToDouble(), t.ToDouble());
|
||
|
|
bool finalInstant = nearlyEqual(t1.ToDouble(), t.ToDouble());
|
||
|
|
|
||
|
|
double f =
|
||
|
|
nearlyEqual(t0.ToDouble(), t1.ToDouble())
|
||
|
|
? 0
|
||
|
|
: (t-t0)/(t1-t0);
|
||
|
|
|
||
|
|
int partnerno = 0;
|
||
|
|
|
||
|
|
res.StartBulkLoad();
|
||
|
|
|
||
|
|
for (unsigned int i = 0; i < segmentsNum; i++) {
|
||
|
|
if (MRA_DEBUG){
|
||
|
|
cerr << "URegionEmb::TemporalFunction() segment #"
|
||
|
|
<< i
|
||
|
|
<< "/"
|
||
|
|
<< segmentsNum
|
||
|
|
<< " ("
|
||
|
|
<< segmentsStartPos
|
||
|
|
<< ")"
|
||
|
|
<< endl;
|
||
|
|
}
|
||
|
|
MSegmentData dms;
|
||
|
|
segments->Get(segmentsStartPos+i, &dms);
|
||
|
|
|
||
|
|
double xs =
|
||
|
|
dms.GetInitialStartX()
|
||
|
|
+(dms.GetFinalStartX()-dms.GetInitialStartX())*f;
|
||
|
|
double ys =
|
||
|
|
dms.GetInitialStartY()
|
||
|
|
+(dms.GetFinalStartY()-dms.GetInitialStartY())*f;
|
||
|
|
double xe =
|
||
|
|
dms.GetInitialEndX()
|
||
|
|
+(dms.GetFinalEndX()-dms.GetInitialEndX())*f;
|
||
|
|
double ye =
|
||
|
|
dms.GetInitialEndY()
|
||
|
|
+(dms.GetFinalEndY()-dms.GetInitialEndY())*f;
|
||
|
|
|
||
|
|
if (MRA_DEBUG){
|
||
|
|
cerr << "URegionEmb::TemporalFunction() value is "
|
||
|
|
<< xs << " " << ys << " " << xe << " " << ye
|
||
|
|
<< endl;
|
||
|
|
}
|
||
|
|
if (nearlyEqual(xs, xe) && nearlyEqual(ys, ye)) {
|
||
|
|
if (MRA_DEBUG){
|
||
|
|
cerr << "URegionEmb::TemporalFunction() "
|
||
|
|
<< "reduced to point"
|
||
|
|
<< endl;
|
||
|
|
}
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
assert(dms.GetDegeneratedInitial() != DGM_UNKNOWN);
|
||
|
|
assert(dms.GetDegeneratedFinal() != DGM_UNKNOWN);
|
||
|
|
|
||
|
|
if ((initialInstant
|
||
|
|
&& dms.GetDegeneratedInitial() == DGM_IGNORE)
|
||
|
|
|| (finalInstant
|
||
|
|
&& dms.GetDegeneratedFinal() == DGM_IGNORE)) {
|
||
|
|
if (MRA_DEBUG){
|
||
|
|
cerr << "URegionEmb::TemporalFunction() "
|
||
|
|
<< "ignored degenerated"
|
||
|
|
<< endl;
|
||
|
|
}
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
Point s(true, xs, ys);
|
||
|
|
Point e(true, xe, ye);
|
||
|
|
HalfSegment hs(true, s, e);
|
||
|
|
|
||
|
|
hs.attr.faceno = 0;
|
||
|
|
hs.attr.cycleno = 0;
|
||
|
|
hs.attr.edgeno = partnerno;
|
||
|
|
hs.attr.partnerno = partnerno++;
|
||
|
|
|
||
|
|
if (initialInstant
|
||
|
|
&& dms.GetDegeneratedInitial() == DGM_INSIDEABOVE){
|
||
|
|
hs.attr.insideAbove = true;
|
||
|
|
}else if (initialInstant
|
||
|
|
&& dms.GetDegeneratedInitial() == DGM_NOTINSIDEABOVE){
|
||
|
|
hs.attr.insideAbove = false;
|
||
|
|
}else if (finalInstant
|
||
|
|
&& dms.GetDegeneratedFinal() == DGM_INSIDEABOVE){
|
||
|
|
hs.attr.insideAbove = true;
|
||
|
|
}else if (finalInstant
|
||
|
|
&& dms.GetDegeneratedFinal() == DGM_NOTINSIDEABOVE){
|
||
|
|
hs.attr.insideAbove = false;
|
||
|
|
}else{
|
||
|
|
hs.attr.insideAbove = dms.GetInsideAbove();
|
||
|
|
}
|
||
|
|
|
||
|
|
if (MRA_DEBUG){
|
||
|
|
cerr << "URegionEmb::TemporalFunction() "
|
||
|
|
<< "Adding hs="
|
||
|
|
<< hs
|
||
|
|
<< endl;
|
||
|
|
}
|
||
|
|
res += hs;
|
||
|
|
hs.SetLeftDomPoint(!hs.IsLeftDomPoint());
|
||
|
|
if (MRA_DEBUG){
|
||
|
|
cerr << "URegionEmb::TemporalFunction() "
|
||
|
|
<< "Adding hs="
|
||
|
|
<< hs
|
||
|
|
<< endl;
|
||
|
|
}
|
||
|
|
res += hs;
|
||
|
|
}
|
||
|
|
|
||
|
|
res.EndBulkLoad();
|
||
|
|
|
||
|
|
if (MRA_DEBUG){
|
||
|
|
for (int i = 0; i < res.Size(); i++) {
|
||
|
|
HalfSegment hs;
|
||
|
|
res.Get(i, hs);
|
||
|
|
|
||
|
|
cerr << "URegionEmb::TemporalFunction() segment #"
|
||
|
|
<< i
|
||
|
|
<< " lp=("
|
||
|
|
<< hs.GetLeftPoint().GetX()
|
||
|
|
<< ", "
|
||
|
|
<< hs.GetLeftPoint().GetY()
|
||
|
|
<< ") rp=("
|
||
|
|
<< hs.GetRightPoint().GetX()
|
||
|
|
<< ", "
|
||
|
|
<< hs.GetRightPoint().GetY()
|
||
|
|
<< ") ldp="
|
||
|
|
<< hs.IsLeftDomPoint()
|
||
|
|
<< " attr="
|
||
|
|
<< hs.attr.faceno
|
||
|
|
<< " "
|
||
|
|
<< hs.attr.cycleno
|
||
|
|
<< " "
|
||
|
|
<< hs.attr.edgeno
|
||
|
|
<< " "
|
||
|
|
<< hs.attr.partnerno
|
||
|
|
<< " "
|
||
|
|
<< hs.attr.insideAbove
|
||
|
|
<< endl;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1 Method ~BoundingBox()~
|
||
|
|
|
||
|
|
*/
|
||
|
|
const Rectangle<3> URegionEmb::BoundingBox(const Geoid* geoid /*=0*/) const {
|
||
|
|
if (MRA_DEBUG) cerr << "URegionEmb::BoundingBox() called" << endl;
|
||
|
|
if(geoid){
|
||
|
|
cerr << __PRETTY_FUNCTION__ << ": Spherical geometry not implemented."
|
||
|
|
<< endl;
|
||
|
|
assert( !geoid ); // TODO: implement spherical geometry case
|
||
|
|
}
|
||
|
|
return bbox;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1 In and out functions
|
||
|
|
|
||
|
|
1.1.1 Function ~InURegionEmbedded()~
|
||
|
|
|
||
|
|
*/
|
||
|
|
static URegionEmb* InURegionEmbedded(
|
||
|
|
const ListExpr instance,
|
||
|
|
const int errorPos,
|
||
|
|
ListExpr& errorInfo,
|
||
|
|
DbArray<MSegmentData>* segments,
|
||
|
|
unsigned int segmentsStartPos) {
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "InURegionEmbedded() called, segmentsStartPos="
|
||
|
|
<< segmentsStartPos
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
/*
|
||
|
|
Please that ~Region~ creation is done as shown in ~SpatialAlgebra~.
|
||
|
|
See there for more details.
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
if (nl->ListLength(instance) == 0) {
|
||
|
|
cerr << "uregion not in format (<interval> <face>*)" << endl;
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "InURegionEmbedded() (<interval> <face>*) found" << endl;
|
||
|
|
|
||
|
|
ListExpr interval = nl->First(instance);
|
||
|
|
|
||
|
|
if (nl->ListLength(interval) != 4
|
||
|
|
|| !nl->IsAtom(nl->First(interval))
|
||
|
|
|| (nl->AtomType(nl->First(interval)) != StringType
|
||
|
|
&& nl->AtomType(nl->First(interval)) != RealType)
|
||
|
|
|| !nl->IsAtom(nl->Second(interval))
|
||
|
|
|| (nl->AtomType(nl->Second(interval)) != StringType
|
||
|
|
&& nl->AtomType(nl->Second(interval)) != RealType)
|
||
|
|
|| !nl->IsAtom(nl->Third(interval))
|
||
|
|
|| nl->AtomType(nl->Third(interval)) != BoolType
|
||
|
|
|| !nl->IsAtom(nl->Fourth(interval))
|
||
|
|
|| nl->AtomType(nl->Fourth(interval)) != BoolType) {
|
||
|
|
cerr << "uregion interval not in format "
|
||
|
|
<< "(<real> <real> <bool> <bool>)"
|
||
|
|
<< endl;
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
bool correct;
|
||
|
|
|
||
|
|
Instant *start =
|
||
|
|
(Instant *) InInstant(nl->TheEmptyList(),
|
||
|
|
nl->First(interval),
|
||
|
|
errorPos,
|
||
|
|
errorInfo,
|
||
|
|
correct).addr;
|
||
|
|
if (!correct) {
|
||
|
|
cerr << "uregion interval invalid start time" << endl;
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
Instant *end =
|
||
|
|
(Instant *) InInstant(nl->TheEmptyList(),
|
||
|
|
nl->Second(interval),
|
||
|
|
errorPos,
|
||
|
|
errorInfo,
|
||
|
|
correct ).addr;
|
||
|
|
if (!correct) {
|
||
|
|
cerr << "uregion interval invalid end time" << endl;
|
||
|
|
correct = false;
|
||
|
|
delete start;
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
bool lc = nl->BoolValue(nl->Third(interval));
|
||
|
|
bool rc = nl->BoolValue(nl->Fourth(interval));
|
||
|
|
|
||
|
|
if (end->ToDouble() < start->ToDouble()
|
||
|
|
|| (nearlyEqual(start->ToDouble(), end->ToDouble())
|
||
|
|
&& !(lc && rc))) {
|
||
|
|
cerr << "uregion invalid interval" << endl;
|
||
|
|
delete start;
|
||
|
|
delete end;
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
Interval<Instant> tinterval(*start, *end, lc, rc);
|
||
|
|
|
||
|
|
DateTime intervalLen = *end-*start;
|
||
|
|
|
||
|
|
delete start;
|
||
|
|
delete end;
|
||
|
|
|
||
|
|
/*
|
||
|
|
Create ~URegion~ instance and pass storage of segments, if we received
|
||
|
|
any.
|
||
|
|
|
||
|
|
*/
|
||
|
|
URegionEmb* uregion = new URegionEmb(tinterval, segmentsStartPos);
|
||
|
|
|
||
|
|
|
||
|
|
int pointno = -1;
|
||
|
|
unsigned int faceno = 0;
|
||
|
|
unsigned int partnerno = 0;
|
||
|
|
ListExpr faces = nl->Second(instance);
|
||
|
|
|
||
|
|
Region cr(0);
|
||
|
|
cr.StartBulkLoad();
|
||
|
|
|
||
|
|
if (nl->ListLength(faces) == 0) {
|
||
|
|
cerr << "uregion should contain at least one face" << endl;
|
||
|
|
delete uregion;
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
... all this is similar to ~Region~ creation in ~SpatialAlgebra~...
|
||
|
|
|
||
|
|
*/
|
||
|
|
while (!nl->IsEmpty(faces)) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "InURegionEmbedded() face #" << faceno << endl;
|
||
|
|
|
||
|
|
ListExpr cycles = nl->First(faces);
|
||
|
|
|
||
|
|
if (nl->ListLength(cycles) == 0) {
|
||
|
|
cerr << "uregion face should contain at least one cycle"
|
||
|
|
<< endl;
|
||
|
|
delete uregion;
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
unsigned int cycleno = 0;
|
||
|
|
|
||
|
|
while (!nl->IsEmpty(cycles)) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "InURegionEmbedded() cycle #" << cycleno << endl;
|
||
|
|
|
||
|
|
Region rDir(0);
|
||
|
|
rDir.StartBulkLoad();
|
||
|
|
|
||
|
|
ListExpr cyclepoints = nl->First(cycles);
|
||
|
|
|
||
|
|
if (nl->ListLength(cyclepoints) < 3) {
|
||
|
|
cerr << "uregion cycle should contain at "
|
||
|
|
<< "least three points"
|
||
|
|
<< endl;
|
||
|
|
delete uregion;
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
ListExpr firstPoint = nl->First(cyclepoints);
|
||
|
|
ListExpr prevPoint = 0;
|
||
|
|
|
||
|
|
unsigned int initialSegmentsNum =
|
||
|
|
uregion->GetSegmentsNum();
|
||
|
|
|
||
|
|
while (!nl->IsEmpty(cyclepoints)) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "InURegionEmbedded() point #"
|
||
|
|
<< pointno
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
ListExpr point = nl->First(cyclepoints);
|
||
|
|
|
||
|
|
if (prevPoint != 0
|
||
|
|
&& !uregion->AddSegment(segments,
|
||
|
|
cr,
|
||
|
|
rDir,
|
||
|
|
faceno,
|
||
|
|
cycleno,
|
||
|
|
pointno,
|
||
|
|
partnerno,
|
||
|
|
intervalLen,
|
||
|
|
prevPoint,
|
||
|
|
point)) {
|
||
|
|
cerr << "uregion's segment checks failed"
|
||
|
|
<< endl;
|
||
|
|
delete uregion;
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
prevPoint = point;
|
||
|
|
cyclepoints = nl->Rest(cyclepoints);
|
||
|
|
pointno++;
|
||
|
|
partnerno++;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!uregion->AddSegment(segments,
|
||
|
|
cr,
|
||
|
|
rDir,
|
||
|
|
faceno,
|
||
|
|
cycleno,
|
||
|
|
pointno,
|
||
|
|
partnerno,
|
||
|
|
intervalLen,
|
||
|
|
prevPoint,
|
||
|
|
firstPoint)) {
|
||
|
|
cerr << "uregion's segment checks failed"
|
||
|
|
<< endl;
|
||
|
|
delete uregion;
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
partnerno++;
|
||
|
|
|
||
|
|
rDir.EndBulkLoad(true, true, false, false);
|
||
|
|
|
||
|
|
bool direction = rDir.GetCycleDirection();
|
||
|
|
|
||
|
|
int h = cr.Size()-(rDir.Size()*2);
|
||
|
|
int i = initialSegmentsNum;
|
||
|
|
while (h < cr.Size()) {
|
||
|
|
HalfSegment hsInsideAbove;
|
||
|
|
bool insideAbove;
|
||
|
|
|
||
|
|
cr.Get(h, hsInsideAbove);
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "InURegionEmbedded() i="
|
||
|
|
<< i
|
||
|
|
<< " insideAbove="
|
||
|
|
<< hsInsideAbove.attr.insideAbove
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
if (direction == hsInsideAbove.attr.insideAbove)
|
||
|
|
insideAbove = false;
|
||
|
|
else
|
||
|
|
insideAbove = true;
|
||
|
|
if (cycleno > 0) insideAbove = !insideAbove;
|
||
|
|
|
||
|
|
|
||
|
|
//hsInsideAbove.attr.insideAbove = insideAbove;
|
||
|
|
//cr.UpdateAttr(h, hsInsideAbove.attr);
|
||
|
|
|
||
|
|
//cr.Get(h+1, &hsInsideAbove);
|
||
|
|
//hsInsideAbove.attr.insideAbove = insideAbove;
|
||
|
|
//cr.UpdateAttr(h+1, hsInsideAbove.attr);
|
||
|
|
|
||
|
|
uregion->SetSegmentInsideAbove(segments, i, insideAbove);
|
||
|
|
|
||
|
|
h += 2;
|
||
|
|
i++;
|
||
|
|
}
|
||
|
|
|
||
|
|
cycles = nl->Rest(cycles);
|
||
|
|
cycleno++;
|
||
|
|
}
|
||
|
|
|
||
|
|
faces = nl->Rest(faces);
|
||
|
|
faceno++;
|
||
|
|
}
|
||
|
|
|
||
|
|
cr.EndBulkLoad();
|
||
|
|
|
||
|
|
|
||
|
|
//bool nonTrivialInitial = false;
|
||
|
|
//bool nonTrivialFinal = false;
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
for (int i = 0; i < uregion->GetSegmentsNum(); i++) {
|
||
|
|
MSegmentData dms;
|
||
|
|
uregion->GetSegment(segments, i, dms);
|
||
|
|
|
||
|
|
cerr << "InURegionEmbedded() segment #"
|
||
|
|
<< i
|
||
|
|
<< ": "
|
||
|
|
<< dms.ToString()
|
||
|
|
<< endl;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
This is different from ~Region~ handling in ~SpatialAlgebra~. We have
|
||
|
|
to go through the lists of degenerated segments and count how often
|
||
|
|
a region is inside above in each list. If there are more inside above
|
||
|
|
segments than others, we need one inside above segment for the
|
||
|
|
~TemporalFunction()~ and set all others to ignore. Vice version if there
|
||
|
|
are more inside below segments. If there is the same number of inside above
|
||
|
|
and inside below segments, we can ignore the entire list.
|
||
|
|
|
||
|
|
*/
|
||
|
|
for (int i = 0; i < uregion->GetSegmentsNum(); i++) {
|
||
|
|
MSegmentData auxDms;
|
||
|
|
uregion->GetSegment(segments, i, auxDms);
|
||
|
|
MSegmentData dms( auxDms );
|
||
|
|
|
||
|
|
//if (!dms.GetPointInitial() && dms.GetDegeneratedInitialNext() < 0)
|
||
|
|
// nonTrivialInitial = true;
|
||
|
|
//if (!dms.GetPointFinal() && dms.GetDegeneratedFinalNext() < 0)
|
||
|
|
// nonTrivialFinal = true;
|
||
|
|
|
||
|
|
if (dms.GetDegeneratedInitial() == DGM_UNKNOWN) {
|
||
|
|
if (dms.GetDegeneratedInitialNext() >= 0) {
|
||
|
|
MSegmentData auxDegenDms;
|
||
|
|
MSegmentData degenDms;
|
||
|
|
unsigned int numInsideAbove = 0;
|
||
|
|
unsigned int numNotInsideAbove = 0;
|
||
|
|
for (int j = i+1;
|
||
|
|
j != 0;
|
||
|
|
j = degenDms.GetDegeneratedInitialNext()) {
|
||
|
|
uregion->GetSegment(segments, j-1, auxDegenDms);
|
||
|
|
degenDms = auxDegenDms;
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "InURegionEmbedded() degen-magic-i "
|
||
|
|
<< i
|
||
|
|
<< " "
|
||
|
|
<< j-1
|
||
|
|
<< endl;
|
||
|
|
if (degenDms.GetInsideAbove())
|
||
|
|
numInsideAbove++;
|
||
|
|
else
|
||
|
|
numNotInsideAbove++;
|
||
|
|
if (j != i+1) {
|
||
|
|
degenDms.SetDegeneratedInitial(DGM_IGNORE);
|
||
|
|
uregion->PutSegment(segments, j-1, degenDms);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "InURegionEmbedded() degen-magic-i result "
|
||
|
|
<< numInsideAbove
|
||
|
|
<< " "
|
||
|
|
<< numNotInsideAbove
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
if (numInsideAbove == numNotInsideAbove) {
|
||
|
|
dms.SetDegeneratedInitial(DGM_IGNORE);
|
||
|
|
} else if (numInsideAbove == numNotInsideAbove+1) {
|
||
|
|
dms.SetDegeneratedInitial(DGM_INSIDEABOVE);
|
||
|
|
} else if (numInsideAbove+1 == numNotInsideAbove) {
|
||
|
|
dms.SetDegeneratedInitial(DGM_NOTINSIDEABOVE);
|
||
|
|
} else {
|
||
|
|
cerr << "segment ("
|
||
|
|
<< dms.GetInitialStartX()
|
||
|
|
<< ", " << dms.GetInitialStartY()
|
||
|
|
<< ")-(" << dms.GetInitialEndX()
|
||
|
|
<< ", " << dms.GetInitialEndY()
|
||
|
|
<< ") / (" << dms.GetFinalStartX()
|
||
|
|
<< ", " << dms.GetFinalStartY()
|
||
|
|
<< ")-(" << dms.GetFinalEndX()
|
||
|
|
<< ", " << dms.GetFinalEndY()
|
||
|
|
<< ") incorrectly degenerated "
|
||
|
|
<< "in initial instant"
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
delete uregion;
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
} else
|
||
|
|
dms.SetDegeneratedInitial(DGM_NONE);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (dms.GetDegeneratedFinal() == DGM_UNKNOWN) {
|
||
|
|
if (dms.GetDegeneratedFinalNext() >= 0) {
|
||
|
|
MSegmentData auxDegenDms;
|
||
|
|
MSegmentData degenDms;
|
||
|
|
unsigned int numInsideAbove = 0;
|
||
|
|
unsigned int numNotInsideAbove = 0;
|
||
|
|
for (int j = i+1;
|
||
|
|
j != 0;
|
||
|
|
j = degenDms.GetDegeneratedFinalNext()) {
|
||
|
|
uregion->GetSegment(segments, j-1, auxDegenDms);
|
||
|
|
degenDms = auxDegenDms;
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "InURegionEmbedded() degen-magic-f "
|
||
|
|
<< i
|
||
|
|
<< " "
|
||
|
|
<< j-1
|
||
|
|
<< endl;
|
||
|
|
if (degenDms.GetInsideAbove())
|
||
|
|
numInsideAbove++;
|
||
|
|
else
|
||
|
|
numNotInsideAbove++;
|
||
|
|
if (j != i+1) {
|
||
|
|
degenDms.SetDegeneratedFinal(DGM_IGNORE);
|
||
|
|
uregion->PutSegment(segments, j-1, degenDms);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "InURegionEmbedded() degen-magic-f result "
|
||
|
|
<< numInsideAbove
|
||
|
|
<< " "
|
||
|
|
<< numNotInsideAbove
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
if (numInsideAbove == numNotInsideAbove) {
|
||
|
|
dms.SetDegeneratedFinal(DGM_IGNORE);
|
||
|
|
} else if (numInsideAbove == numNotInsideAbove+1) {
|
||
|
|
dms.SetDegeneratedFinal(DGM_INSIDEABOVE);
|
||
|
|
} else if (numInsideAbove+1 == numNotInsideAbove) {
|
||
|
|
dms.SetDegeneratedFinal(DGM_NOTINSIDEABOVE);
|
||
|
|
} else {
|
||
|
|
cerr << "segment ("
|
||
|
|
<< dms.GetInitialStartX()
|
||
|
|
<< ", " << dms.GetInitialStartY()
|
||
|
|
<< ")-(" << dms.GetInitialEndX()
|
||
|
|
<< ", " << dms.GetInitialEndY()
|
||
|
|
<< ") / (" << dms.GetFinalStartX()
|
||
|
|
<< ", " << dms.GetFinalStartY()
|
||
|
|
<< ")-(" << dms.GetFinalEndX()
|
||
|
|
<< ", " << dms.GetFinalEndY()
|
||
|
|
<< ") incorrectly degenerated "
|
||
|
|
<< "in final instant"
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
delete uregion;
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
} else
|
||
|
|
dms.SetDegeneratedFinal(DGM_NONE);
|
||
|
|
}
|
||
|
|
|
||
|
|
uregion->PutSegment(segments, i, dms);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
for (int i = 0; i < uregion->GetSegmentsNum(); i++) {
|
||
|
|
MSegmentData dms;
|
||
|
|
|
||
|
|
uregion->GetSegment(segments, i, dms);
|
||
|
|
|
||
|
|
cerr << "InURegionEmbedded() resulting segment #"
|
||
|
|
<< i
|
||
|
|
<< ": "
|
||
|
|
<< dms.ToString()
|
||
|
|
<< endl;
|
||
|
|
}
|
||
|
|
|
||
|
|
return uregion;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1 Function ~OutURegionEmbedded()~
|
||
|
|
|
||
|
|
*/
|
||
|
|
static ListExpr OutURegionEmbedded(
|
||
|
|
const URegionEmb* ur,
|
||
|
|
DbArray<MSegmentData>* segments) {
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "OutURegionEmbedded() called" << endl;
|
||
|
|
|
||
|
|
/*
|
||
|
|
Conversion to list representation is straightforward. Just loop through
|
||
|
|
faces, cylces and segments and make sure that it is realised when one of
|
||
|
|
these changes.
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
int num = ur->GetSegmentsNum();
|
||
|
|
|
||
|
|
ListExpr faces = nl->TheEmptyList();
|
||
|
|
ListExpr facesLastElem = faces;
|
||
|
|
|
||
|
|
ListExpr face = nl->TheEmptyList();
|
||
|
|
ListExpr faceLastElem = face;
|
||
|
|
ListExpr cycle = nl->TheEmptyList();
|
||
|
|
ListExpr cycleLastElem = cycle;
|
||
|
|
|
||
|
|
for (int i = 0; i < num; i++) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "OutURegionEmbedded() segment #" << i << endl;
|
||
|
|
|
||
|
|
MSegmentData dms;
|
||
|
|
ur->GetSegment(segments, i, dms);
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "OutURegionEmbedded() returned, dms=" << &dms << endl;
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "OutURegionEmbedded() point is "
|
||
|
|
<< dms.GetFaceNo()
|
||
|
|
<< " "
|
||
|
|
<< dms.GetCycleNo()
|
||
|
|
<< " ("
|
||
|
|
<< dms.GetInitialStartX()
|
||
|
|
<< ", "
|
||
|
|
<< dms.GetInitialStartY()
|
||
|
|
<< ", "
|
||
|
|
<< dms.GetFinalStartX()
|
||
|
|
<< ", "
|
||
|
|
<< dms.GetFinalStartY()
|
||
|
|
<< ")"
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
ListExpr p =
|
||
|
|
nl->FourElemList(
|
||
|
|
nl->RealAtom(dms.GetInitialStartX()),
|
||
|
|
nl->RealAtom(dms.GetInitialStartY()),
|
||
|
|
nl->RealAtom(dms.GetFinalStartX()),
|
||
|
|
nl->RealAtom(dms.GetFinalStartY()));
|
||
|
|
|
||
|
|
if (cycle == nl->TheEmptyList()) {
|
||
|
|
if (MRA_DEBUG) cerr << "OutURegionEmbedded() new cycle" << endl;
|
||
|
|
cycle = nl->OneElemList(p);
|
||
|
|
cycleLastElem = cycle;
|
||
|
|
} else {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "OutURegionEmbedded() existing cycle" << endl;
|
||
|
|
cycleLastElem = nl->Append(cycleLastElem, p);
|
||
|
|
}
|
||
|
|
|
||
|
|
MSegmentData nextDms;
|
||
|
|
if (i < num-1) ur->GetSegment(segments, i+1, nextDms);
|
||
|
|
|
||
|
|
if (i == num-1
|
||
|
|
|| dms.GetCycleNo() != nextDms.GetCycleNo()
|
||
|
|
|| dms.GetFaceNo() != nextDms.GetFaceNo()) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "OutURegionEmbedded() end of cycle" << endl;
|
||
|
|
|
||
|
|
if (face == nl->TheEmptyList()) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "OutURegionEmbedded() new face" << endl;
|
||
|
|
face = nl->OneElemList(cycle);
|
||
|
|
faceLastElem = face;
|
||
|
|
} else {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "OutURegionEmbedded() existing face" << endl;
|
||
|
|
faceLastElem = nl->Append(faceLastElem, cycle);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (i == num-1
|
||
|
|
|| dms.GetFaceNo() != nextDms.GetFaceNo()) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "OutURegionEmbedded() end of face" << endl;
|
||
|
|
if (faces == nl->TheEmptyList()) {
|
||
|
|
faces = nl->OneElemList(face);
|
||
|
|
facesLastElem = faces;
|
||
|
|
} else
|
||
|
|
facesLastElem = nl->Append(facesLastElem, face);
|
||
|
|
|
||
|
|
face = nl->TheEmptyList();
|
||
|
|
faceLastElem = face;
|
||
|
|
}
|
||
|
|
|
||
|
|
cycle = nl->TheEmptyList();
|
||
|
|
cycleLastElem = cycle;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
ListExpr res =
|
||
|
|
nl->TwoElemList(
|
||
|
|
nl->FourElemList(
|
||
|
|
OutDateTime(nl->TheEmptyList(),
|
||
|
|
SetWord((void*) &ur->timeInterval.start)),
|
||
|
|
OutDateTime(nl->TheEmptyList(),
|
||
|
|
SetWord((void*) &ur->timeInterval.end)),
|
||
|
|
nl->BoolAtom(ur->timeInterval.lc),
|
||
|
|
nl->BoolAtom(ur->timeInterval.rc)),
|
||
|
|
faces);
|
||
|
|
|
||
|
|
return res;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1 Data type ~uregion~
|
||
|
|
|
||
|
|
1.1 Class ~URegion~
|
||
|
|
|
||
|
|
1.1.1 Class definition
|
||
|
|
|
||
|
|
The class definition has been moved to ~MovingRegionAlgebra.h~.
|
||
|
|
|
||
|
|
1.1.1 Constructors
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
URegion::URegion(unsigned int n) :
|
||
|
|
SpatialTemporalUnit<Region, 3>(true),
|
||
|
|
segments(n) {
|
||
|
|
SetDefined(true);
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegion::URegion() #1 called"
|
||
|
|
<< endl;
|
||
|
|
}
|
||
|
|
|
||
|
|
bool msegcompare(const MSegmentData& s1, const MSegmentData& s2){
|
||
|
|
if(s1.GetFaceNo() < s1.GetFaceNo()) return true;
|
||
|
|
if(s1.GetFaceNo() > s1.GetFaceNo()) return false;
|
||
|
|
if(s1.GetCycleNo() < s1.GetCycleNo()) return true;
|
||
|
|
if(s1.GetCycleNo() > s1.GetCycleNo()) return false;
|
||
|
|
if(s1.GetSegmentNo() < s1.GetSegmentNo()) return true;
|
||
|
|
if(s1.GetSegmentNo() > s1.GetSegmentNo()) return false;
|
||
|
|
// should be unique
|
||
|
|
return false;
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
URegion::URegion(vector<MSegmentData> linelist, const Interval<Instant>& tiv,
|
||
|
|
bool simple) :
|
||
|
|
SpatialTemporalUnit<Region, 3>(true),
|
||
|
|
segments(0)
|
||
|
|
{
|
||
|
|
Interval<Instant> newTiv;
|
||
|
|
newTiv.CopyFrom(tiv);
|
||
|
|
uremb= URegionEmb(newTiv, 0);
|
||
|
|
timeInterval = newTiv;
|
||
|
|
if(simple){
|
||
|
|
sort(linelist.begin(),linelist.end(), msegcompare);
|
||
|
|
vector<MSegmentData>::iterator it;
|
||
|
|
for(it = linelist.begin(); it != linelist.end(); it++){
|
||
|
|
AddSegment(*it);
|
||
|
|
}
|
||
|
|
SetDefined(true);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
while(linelist.size() > 0)
|
||
|
|
{
|
||
|
|
int index = getLeftLower(linelist);
|
||
|
|
MSegmentData first = linelist[index];
|
||
|
|
#ifdef MR_DEBUG
|
||
|
|
cout<<index<<endl;
|
||
|
|
cout<<first.ToString()<<endl;
|
||
|
|
#endif
|
||
|
|
int counter = 1;
|
||
|
|
AddSegment(MSegmentData(linelist[index].GetFaceNo(),
|
||
|
|
linelist[index].GetCycleNo(), counter, true,
|
||
|
|
linelist[index].GetInitialStartX(),
|
||
|
|
linelist[index].GetInitialStartY(),
|
||
|
|
linelist[index].GetInitialEndX(),
|
||
|
|
linelist[index].GetInitialEndY(),
|
||
|
|
linelist[index].GetFinalStartX(),
|
||
|
|
linelist[index].GetFinalStartY(),
|
||
|
|
linelist[index].GetFinalEndX(),
|
||
|
|
linelist[index].GetFinalEndY()));
|
||
|
|
linelist.erase(linelist.begin() + index);
|
||
|
|
index = findNextToRight(linelist, first);
|
||
|
|
MSegmentData next = linelist[index];
|
||
|
|
//AddSegment(next);
|
||
|
|
#ifdef MR_DEBUG
|
||
|
|
cout<<"Next: "<<next.ToString()<<endl;
|
||
|
|
#endif
|
||
|
|
counter = 2;
|
||
|
|
while(1 == 1)
|
||
|
|
{
|
||
|
|
MSegmentData nextins;
|
||
|
|
if(matchesLeft(next, linelist[index]) || counter == 2)
|
||
|
|
{
|
||
|
|
nextins = MSegmentData(linelist[index].GetFaceNo(),
|
||
|
|
linelist[index].GetCycleNo(), counter, true,
|
||
|
|
linelist[index].GetInitialStartX(),
|
||
|
|
linelist[index].GetInitialStartY(),
|
||
|
|
linelist[index].GetInitialEndX(),
|
||
|
|
linelist[index].GetInitialEndY(),
|
||
|
|
linelist[index].GetFinalStartX(),
|
||
|
|
linelist[index].GetFinalStartY(),
|
||
|
|
linelist[index].GetFinalEndX(),
|
||
|
|
linelist[index].GetFinalEndY());
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
nextins = MSegmentData(linelist[index].GetFaceNo(),
|
||
|
|
linelist[index].GetCycleNo(), counter, false,
|
||
|
|
linelist[index].GetInitialEndX(),
|
||
|
|
linelist[index].GetInitialEndY(),
|
||
|
|
linelist[index].GetInitialStartX(),
|
||
|
|
linelist[index].GetInitialStartY(),
|
||
|
|
linelist[index].GetFinalEndX(),
|
||
|
|
linelist[index].GetFinalEndY(),
|
||
|
|
linelist[index].GetFinalStartX(),
|
||
|
|
linelist[index].GetFinalStartY());
|
||
|
|
}
|
||
|
|
next=linelist[index];
|
||
|
|
AddSegment(nextins);
|
||
|
|
linelist.erase(linelist.begin() + index);
|
||
|
|
index=findNext(linelist, next);
|
||
|
|
#ifdef MR_DEBUG
|
||
|
|
cout<<index<<endl;
|
||
|
|
cout<<nextins.ToString()<<endl;
|
||
|
|
#endif
|
||
|
|
if(matches(first, next) && counter > 2)
|
||
|
|
{
|
||
|
|
#ifdef MR_DEBUG
|
||
|
|
cout<<" true"<<endl;
|
||
|
|
cout<<first.ToString()<<endl;
|
||
|
|
cout<<next.ToString()<<endl;
|
||
|
|
#endif
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
#ifdef MR_DEBUG
|
||
|
|
cout<<" false"<<endl;
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
if(index == -1)
|
||
|
|
{
|
||
|
|
#ifdef MR_DEBUG
|
||
|
|
for(unsigned int i = 0; i < linelist.size(); i++)
|
||
|
|
{
|
||
|
|
cout<<i<<" :"<<linelist[i].ToString()<<endl;
|
||
|
|
}
|
||
|
|
cout<<"gesucht: "<<next.ToString()<<endl;
|
||
|
|
#endif
|
||
|
|
linelist.erase(linelist.begin()+index);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
counter++;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
SetDefined(true);
|
||
|
|
}
|
||
|
|
|
||
|
|
int URegion :: getLeftLower(const vector<MSegmentData> &linelist)
|
||
|
|
{
|
||
|
|
int res = 0;
|
||
|
|
for(unsigned int i = 1; i < linelist.size(); i++)
|
||
|
|
{
|
||
|
|
Point leftIs = Point(true, linelist[res]. GetInitialStartX(),
|
||
|
|
linelist[res].GetInitialStartY());
|
||
|
|
Point leftIe = Point(true, linelist[res].GetInitialEndX(),
|
||
|
|
linelist[res].GetInitialEndY());
|
||
|
|
Point leftFs = Point(true, linelist[res].GetFinalStartX(),
|
||
|
|
linelist[res].GetFinalStartY());
|
||
|
|
Point leftFe = Point(true, linelist[res].GetFinalEndX(),
|
||
|
|
linelist[res].GetFinalEndY());
|
||
|
|
Point llIs = Point(true, linelist[i].GetInitialStartX(),
|
||
|
|
linelist[i].GetInitialStartY());
|
||
|
|
Point llIe = Point(true, linelist[i].GetInitialEndX(),
|
||
|
|
linelist[i].GetInitialEndY());
|
||
|
|
Point llFs = Point(true, linelist[i].GetFinalStartX(),
|
||
|
|
linelist[i].GetFinalStartY());
|
||
|
|
Point llFe = Point(true, linelist[i].GetFinalEndX(),
|
||
|
|
linelist[i].GetFinalEndY());
|
||
|
|
if(leftIs.GetX()>llIs.GetX() || (AlmostEqual(leftIs.GetX(),llIs.GetX()&&
|
||
|
|
leftIs.GetY() > llIs.GetY())))
|
||
|
|
{
|
||
|
|
res = i;
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
if(AlmostEqual(leftIs, llIs))
|
||
|
|
{
|
||
|
|
if((leftIe.GetY() > llIe.GetY()) ||
|
||
|
|
((AlmostEqual(leftIe.GetY(), llIe.GetY())) &&
|
||
|
|
(leftIe.GetX() > llIe.GetX())))
|
||
|
|
{
|
||
|
|
res = i;
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
if(AlmostEqual(leftIe, llIe))
|
||
|
|
{
|
||
|
|
if(leftFs > llFs)
|
||
|
|
{
|
||
|
|
res = i;
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
if(AlmostEqual(leftFs, llFs))
|
||
|
|
{
|
||
|
|
if((leftFe.GetY() > llFe.GetY()) ||
|
||
|
|
((AlmostEqual(leftFe.GetY(), llFe.GetY())) &&
|
||
|
|
(leftFe.GetX() > llFe.GetX())))
|
||
|
|
{
|
||
|
|
res = i;
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return(res);
|
||
|
|
}
|
||
|
|
|
||
|
|
int URegion :: findNext(const vector<MSegmentData> &linelist,
|
||
|
|
const MSegmentData dms)
|
||
|
|
{
|
||
|
|
for(unsigned int i = 0; i < linelist.size(); i++)
|
||
|
|
{
|
||
|
|
if(matches(linelist[i], dms))
|
||
|
|
return(i);
|
||
|
|
}
|
||
|
|
return(-1);
|
||
|
|
}
|
||
|
|
|
||
|
|
int URegion :: findNextToRight(const vector<MSegmentData> &linelist,
|
||
|
|
const MSegmentData dms)
|
||
|
|
{
|
||
|
|
for(unsigned int i = 0; i < linelist.size(); i++)
|
||
|
|
{
|
||
|
|
if(matchesToRight(dms, linelist[i]))
|
||
|
|
return(i);
|
||
|
|
}
|
||
|
|
return(-1);
|
||
|
|
}
|
||
|
|
|
||
|
|
bool URegion :: matches(const MSegmentData &dms1, const MSegmentData &dms2)
|
||
|
|
{
|
||
|
|
if(matchesLeft(dms1, dms2) || matchesRight(dms1, dms2))
|
||
|
|
return(true);
|
||
|
|
return(false);
|
||
|
|
}
|
||
|
|
|
||
|
|
bool URegion :: matchesLeft(const MSegmentData &dms1, const MSegmentData &dms2)
|
||
|
|
{
|
||
|
|
if(dms1.GetFaceNo() != dms2.GetFaceNo())
|
||
|
|
return(false);
|
||
|
|
if(dms1.GetCycleNo() != dms2.GetCycleNo())
|
||
|
|
return(false);
|
||
|
|
double isx1 = dms1.GetInitialStartX();
|
||
|
|
double isx2 = dms2.GetInitialStartX();
|
||
|
|
double isy1 = dms1.GetInitialStartY();
|
||
|
|
double isy2 = dms2.GetInitialStartY();
|
||
|
|
double iex1 = dms1.GetInitialEndX();
|
||
|
|
double iey1 = dms1.GetInitialEndY();
|
||
|
|
double iey2 = dms2.GetInitialEndY();
|
||
|
|
double fsx1 = dms1.GetFinalStartX();
|
||
|
|
double fsx2 = dms2.GetFinalStartX();
|
||
|
|
double fsy1 = dms1.GetFinalStartY();
|
||
|
|
double fsy2 = dms2.GetFinalStartY();
|
||
|
|
double fex1 = dms1.GetFinalEndX();
|
||
|
|
double fey1 = dms1.GetFinalEndY();
|
||
|
|
double fey2 = dms2.GetFinalEndY();
|
||
|
|
if(AlmostEqual(isx1, isx2) && AlmostEqual(isy1, isy2) &&
|
||
|
|
AlmostEqual(fsx1, fsx2) && AlmostEqual(fsy1, fsy2) &&
|
||
|
|
!(AlmostEqual(iex1, iex1) && AlmostEqual(iey1, iey2) &&
|
||
|
|
AlmostEqual(fex1, fex1) && AlmostEqual(fey1, fey2)))
|
||
|
|
{
|
||
|
|
return(true);
|
||
|
|
}
|
||
|
|
if(AlmostEqual(iex1, isx2) && AlmostEqual(iey1, isy2) &&
|
||
|
|
AlmostEqual(fex1, fsx2) && AlmostEqual(fey1, fsy2) &&
|
||
|
|
!(AlmostEqual(isx1, iex1) && AlmostEqual(isy1, iey2) &&
|
||
|
|
AlmostEqual(fsx1, fex1) && AlmostEqual(fsy1, fey2)))
|
||
|
|
{
|
||
|
|
return(true);
|
||
|
|
}
|
||
|
|
return(false);
|
||
|
|
}
|
||
|
|
|
||
|
|
bool URegion :: matchesRight(const MSegmentData &dms1, const MSegmentData &dms2)
|
||
|
|
{
|
||
|
|
if(dms1.GetFaceNo() != dms2.GetFaceNo())
|
||
|
|
return(false);
|
||
|
|
if(dms1.GetCycleNo() != dms2.GetCycleNo())
|
||
|
|
return(false);
|
||
|
|
double isx1 = dms1.GetInitialStartX();
|
||
|
|
double isy1= dms1.GetInitialStartY();
|
||
|
|
double isy2 = dms2.GetInitialStartY();
|
||
|
|
double iex1 = dms1.GetInitialEndX();
|
||
|
|
double iex2 = dms2.GetInitialEndX();
|
||
|
|
double iey1 = dms1.GetInitialEndY();
|
||
|
|
double iey2 = dms2.GetInitialEndY();
|
||
|
|
double fsx1= dms1.GetFinalStartX();
|
||
|
|
double fsy1 = dms1.GetFinalStartY();
|
||
|
|
double fsy2 = dms2.GetFinalStartY();
|
||
|
|
double fex1 = dms1.GetFinalEndX();
|
||
|
|
double fex2 = dms2.GetFinalEndX();
|
||
|
|
double fey1 = dms1.GetFinalEndY();
|
||
|
|
double fey2 = dms2.GetFinalEndY();
|
||
|
|
if(AlmostEqual(isx1, iex2) && AlmostEqual(isy1, iey2) &&
|
||
|
|
AlmostEqual(fsx1, fex2) && AlmostEqual(fsy1, fey2) &&
|
||
|
|
!(AlmostEqual(iex1, isx1) && AlmostEqual(iey1, isy2) &&
|
||
|
|
AlmostEqual(fex1, fsx1) && AlmostEqual(fey1, fsy2)))
|
||
|
|
{
|
||
|
|
return(true);
|
||
|
|
}
|
||
|
|
if(AlmostEqual(iex1, iex2) && AlmostEqual(iey1, iey2) &&
|
||
|
|
AlmostEqual(fex1, fex2) && AlmostEqual(fey1, fey2) &&
|
||
|
|
!(AlmostEqual(isx1, isx1) && AlmostEqual(isy1, isy2) &&
|
||
|
|
AlmostEqual(fsx1, fsx1) && AlmostEqual(fsy1, fsy2)))
|
||
|
|
{
|
||
|
|
return(true);
|
||
|
|
}
|
||
|
|
return(false);
|
||
|
|
}
|
||
|
|
|
||
|
|
bool URegion::matchesToRight(const MSegmentData &dms1,const MSegmentData &dms2)
|
||
|
|
{
|
||
|
|
if(dms1.GetFaceNo() != dms2.GetFaceNo())
|
||
|
|
return(false);
|
||
|
|
if(dms1.GetCycleNo() != dms2.GetCycleNo())
|
||
|
|
return(false);
|
||
|
|
double isx1 = dms1.GetInitialStartX();
|
||
|
|
double isx2 = dms2.GetInitialStartX();
|
||
|
|
double isy1 = dms1.GetInitialStartY();
|
||
|
|
double isy2 = dms2.GetInitialStartY();
|
||
|
|
double iex1 = dms1.GetInitialEndX();
|
||
|
|
double iex2 = dms2.GetInitialEndX();
|
||
|
|
double iey1 = dms1.GetInitialEndY();
|
||
|
|
double iey2 = dms2.GetInitialEndY();
|
||
|
|
double fsx1 = dms1.GetFinalStartX();
|
||
|
|
double fsx2 = dms2.GetFinalStartX();
|
||
|
|
double fsy1 = dms1.GetFinalStartY();
|
||
|
|
double fsy2 = dms2.GetFinalStartY();
|
||
|
|
double fex1 = dms1.GetFinalEndX();
|
||
|
|
double fex2 = dms2.GetFinalEndX();
|
||
|
|
double fey1 = dms1.GetFinalEndY();
|
||
|
|
double fey2 = dms2.GetFinalEndY();
|
||
|
|
if(AlmostEqual(iex1, isx2) && AlmostEqual(iey1, isy2) &&
|
||
|
|
AlmostEqual(fex1, fsx2) && AlmostEqual(fey1, fsy2) &&
|
||
|
|
!(AlmostEqual(isx1, iex1) && AlmostEqual(isy1, iey2) &&
|
||
|
|
AlmostEqual(fsx1, fex1) && AlmostEqual(fsy1, fey2)))
|
||
|
|
{
|
||
|
|
return(true);
|
||
|
|
}
|
||
|
|
if(AlmostEqual(iex1, iex2) && AlmostEqual(iey1, iey2) &&
|
||
|
|
AlmostEqual(fex1, fex2) && AlmostEqual(fey1, fey2) &&
|
||
|
|
!(AlmostEqual(isx1, isx1) && AlmostEqual(isy1, isy2) &&
|
||
|
|
AlmostEqual(fsx1, fsx1) && AlmostEqual(fsy1, fsy2)))
|
||
|
|
{
|
||
|
|
return(true);
|
||
|
|
}
|
||
|
|
return(false);
|
||
|
|
}
|
||
|
|
|
||
|
|
void URegion :: AddURegion(URegion *newRegion)
|
||
|
|
{
|
||
|
|
if(timeInterval != newRegion->timeInterval)
|
||
|
|
{
|
||
|
|
throw invalid_argument("Intervals are not equal");
|
||
|
|
}
|
||
|
|
const DbArray<MSegmentData> *lines = newRegion->GetMSegmentData();
|
||
|
|
for(int i = 0; i < lines->Size(); i++)
|
||
|
|
{
|
||
|
|
MSegmentData line;
|
||
|
|
lines->Get(i, line);
|
||
|
|
AddSegment(line);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void URegion::AddSegment(MSegmentData newSeg)
|
||
|
|
{
|
||
|
|
uremb.PutSegment(&segments, segments.Size(), newSeg, true);
|
||
|
|
if (uremb.BoundingBox().IsDefined())
|
||
|
|
{
|
||
|
|
double min[3] =
|
||
|
|
{ uremb.BoundingBox().MinD(0),
|
||
|
|
uremb.BoundingBox().MinD(1),
|
||
|
|
uremb.BoundingBox().MinD(2) };
|
||
|
|
double max[3] =
|
||
|
|
{ uremb.BoundingBox().MaxD(0),
|
||
|
|
uremb.BoundingBox().MaxD(1),
|
||
|
|
uremb.BoundingBox().MaxD(2) };
|
||
|
|
if (newSeg.GetInitialStartX() < min[0])
|
||
|
|
min[0] = newSeg.GetInitialStartX();
|
||
|
|
if (newSeg.GetFinalStartX() < min[0])
|
||
|
|
min[0] = newSeg.GetFinalStartX();
|
||
|
|
if (newSeg.GetInitialStartY() < min[1])
|
||
|
|
min[1] = newSeg.GetInitialStartY();
|
||
|
|
if (newSeg.GetFinalStartY() < min[1])
|
||
|
|
min[1] = newSeg.GetFinalStartY();
|
||
|
|
if (newSeg.GetInitialStartX() > max[0])
|
||
|
|
max[0] = newSeg.GetInitialStartX();
|
||
|
|
if (newSeg.GetFinalStartX() > max[0])
|
||
|
|
max[0] = newSeg.GetFinalStartX();
|
||
|
|
if (newSeg.GetInitialStartY() > max[1])
|
||
|
|
max[1] = newSeg.GetInitialStartY();
|
||
|
|
if (newSeg.GetFinalStartY() > max[1])
|
||
|
|
max[1] = newSeg.GetFinalStartY();
|
||
|
|
uremb.SetBBox(Rectangle<3>(true, min, max));
|
||
|
|
|
||
|
|
} else {
|
||
|
|
double min[3] =
|
||
|
|
{ newSeg.GetInitialStartX() < newSeg.GetFinalStartX()
|
||
|
|
? newSeg.GetInitialStartX() : newSeg.GetFinalStartX(),
|
||
|
|
newSeg.GetInitialStartY() < newSeg.GetFinalStartY()
|
||
|
|
? newSeg.GetInitialStartY() : newSeg.GetFinalStartY(),
|
||
|
|
uremb.timeInterval.start.ToDouble() };
|
||
|
|
double max[3] =
|
||
|
|
{ newSeg.GetInitialStartX() > newSeg.GetFinalStartX()
|
||
|
|
? newSeg.GetInitialStartX() : newSeg.GetFinalStartX(),
|
||
|
|
newSeg.GetInitialStartY() > newSeg.GetFinalStartY()
|
||
|
|
? newSeg.GetInitialStartY() : newSeg.GetFinalStartY(),
|
||
|
|
uremb.timeInterval.end.ToDouble() };
|
||
|
|
uremb.SetBBox(Rectangle<3>(true, min, max));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
URegion::URegion(int i, MRegion& mr):
|
||
|
|
SpatialTemporalUnit<Region, 3>(true),
|
||
|
|
segments(0)
|
||
|
|
{
|
||
|
|
|
||
|
|
assert( mr.IsDefined() );
|
||
|
|
assert( i>=0 );
|
||
|
|
assert( i<mr.GetNoComponents() );
|
||
|
|
|
||
|
|
// get the appropriate URegionEmb from MRegion::units
|
||
|
|
URegionEmb OrigURemb;
|
||
|
|
mr.Get( i, OrigURemb );
|
||
|
|
uremb = OrigURemb;
|
||
|
|
uremb.SetSegmentsNum(0);
|
||
|
|
uremb.SetStartPos(0);
|
||
|
|
|
||
|
|
// copy timeInterval from URegionEmb to URegion
|
||
|
|
timeInterval = uremb.timeInterval;
|
||
|
|
|
||
|
|
// copy MSegmentData
|
||
|
|
const int startSeg = OrigURemb.GetStartPos();
|
||
|
|
const int numSegs = OrigURemb.GetSegmentsNum();
|
||
|
|
|
||
|
|
for(int s=0 ; s<numSegs ; s++)
|
||
|
|
{
|
||
|
|
MSegmentData segment;
|
||
|
|
mr.GetMSegmentData()->Get( s+startSeg, segment );
|
||
|
|
uremb.PutSegment(&segments, s, segment, true);
|
||
|
|
}
|
||
|
|
SetDefined( true );
|
||
|
|
}
|
||
|
|
|
||
|
|
URegionEmb& URegionEmb::operator=(const URegionEmb& U) {
|
||
|
|
segmentsStartPos = U.segmentsStartPos;
|
||
|
|
segmentsNum = U.segmentsNum;
|
||
|
|
bbox = U.bbox;
|
||
|
|
timeInterval = U.timeInterval;
|
||
|
|
return *this;
|
||
|
|
}
|
||
|
|
|
||
|
|
size_t URegionEmb::HashValue() const{
|
||
|
|
return ( timeInterval.start.HashValue() ^ timeInterval.end.HashValue() );
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1 Methods for database operators
|
||
|
|
|
||
|
|
1.1.1.1 Method ~BoundingBox()~
|
||
|
|
|
||
|
|
*/
|
||
|
|
const Rectangle<3> URegion::BoundingBox(const Geoid* geoid /*=0*/) const {
|
||
|
|
if (MRA_DEBUG) cerr << "URegion::BoundingBox() called" << endl;
|
||
|
|
if(geoid){
|
||
|
|
cerr << __PRETTY_FUNCTION__ << ": Spherical geometry not implemented."
|
||
|
|
<< endl;
|
||
|
|
assert( !geoid ); // TODO: implement spherical geometry case
|
||
|
|
}
|
||
|
|
return uremb.BoundingBox();
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1.1 Method ~At()~
|
||
|
|
|
||
|
|
This method is not part of the bachelor thesis but a stub is required to make
|
||
|
|
~URegion~ non-abstract. To assure that accidential calls of this method are
|
||
|
|
recognized, its body contains a failed assertion.
|
||
|
|
|
||
|
|
*/
|
||
|
|
bool URegion::At(const Region& val, TemporalUnit<Region>& result) const {
|
||
|
|
if (MRA_DEBUG) cerr << "URegion::At() called" << endl;
|
||
|
|
assert( IsDefined() );
|
||
|
|
assert( val.IsDefined() );
|
||
|
|
|
||
|
|
cerr << __PRETTY_FUNCTION__ << " not implemented!" << endl;
|
||
|
|
assert(false);
|
||
|
|
|
||
|
|
URegion* res = static_cast<URegion*>(&result);
|
||
|
|
res->SetDefined( false );
|
||
|
|
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1.1 Method ~Passes()~
|
||
|
|
|
||
|
|
This method is not part of the bachelor thesis but a stub is required to make
|
||
|
|
~URegion~ non-abstract. To assure that accidential calls of this method are
|
||
|
|
recognized, its body contains a failed assertion.
|
||
|
|
|
||
|
|
*/
|
||
|
|
bool URegion::Passes(const Region& val) const {
|
||
|
|
if (MRA_DEBUG) cerr << "URegion::At() called" << endl;
|
||
|
|
assert( IsDefined() );
|
||
|
|
assert( val.IsDefined() );
|
||
|
|
|
||
|
|
cerr << __PRETTY_FUNCTION__ << " not implemented!" << endl;
|
||
|
|
assert(false);
|
||
|
|
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1.1 Method ~TemporalFunction()~
|
||
|
|
|
||
|
|
*/
|
||
|
|
void URegion::TemporalFunction(const Instant& t,
|
||
|
|
Region& res,
|
||
|
|
bool ignoreLimits ) const {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "URegion::TemporalFunction() called" << endl;
|
||
|
|
res.Clear();
|
||
|
|
if( !IsDefined() || !t.IsDefined()
|
||
|
|
|| !(ignoreLimits || timeInterval.Contains(t) ) ) {
|
||
|
|
res.SetDefined( false );
|
||
|
|
} else {
|
||
|
|
res.SetDefined( true );
|
||
|
|
uremb.TemporalFunction(&segments, t, res, ignoreLimits);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1 Methods for algebra integration
|
||
|
|
|
||
|
|
1.1.1.1 Method ~Clone()~
|
||
|
|
|
||
|
|
*/
|
||
|
|
URegion* URegion::Clone(void) const {
|
||
|
|
if (MRA_DEBUG) cerr << "URegion::Clone() called" << endl;
|
||
|
|
|
||
|
|
URegion* res = new URegion( (unsigned int)0 );
|
||
|
|
res->CopyFrom(this);
|
||
|
|
res->SetDefined( this->del.isDefined );
|
||
|
|
return res;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1.1 Method ~CopyFrom()~
|
||
|
|
|
||
|
|
*/
|
||
|
|
void URegion::CopyFrom(const Attribute* right) {
|
||
|
|
if (MRA_DEBUG) cerr << "URegion::CopyFrom() called" << endl;
|
||
|
|
|
||
|
|
const URegion* ur = (const URegion*) right;
|
||
|
|
|
||
|
|
*this = *ur;
|
||
|
|
this->SetDefined( ur->IsDefined() );
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
Assignment operator
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
URegion& URegion::operator= ( const URegion& U) {
|
||
|
|
|
||
|
|
if(!U.IsDefined())
|
||
|
|
{
|
||
|
|
uremb = U.uremb;
|
||
|
|
segments = U.segments;
|
||
|
|
SetDefined(false);
|
||
|
|
return *this;
|
||
|
|
}
|
||
|
|
timeInterval = U.timeInterval; // copy units copy of deftime!
|
||
|
|
uremb = U.uremb; // copy bbox, timeInterval, segmentsNum
|
||
|
|
uremb.SetStartPos(0); // set uremb.segmentsStartPos = 0
|
||
|
|
del.isDefined = U.del.isDefined;
|
||
|
|
|
||
|
|
int start = U.uremb.GetStartPos();
|
||
|
|
int numsegs = U.uremb.GetSegmentsNum();
|
||
|
|
segments.clean();
|
||
|
|
segments.resize( U.uremb.GetSegmentsNum() );
|
||
|
|
for( int i=0 ; i<numsegs ; i++ )
|
||
|
|
{// copy single movingsegment
|
||
|
|
MSegmentData seg;
|
||
|
|
U.segments.Get(i+start, &seg);
|
||
|
|
segments.Put(i, seg);
|
||
|
|
}
|
||
|
|
return *this;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1.1 ~DBArray~ access
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
int URegion::NumOfFLOBs() const {
|
||
|
|
if (MRA_DEBUG) cerr << "URegion::NumOfFLOBs() called" << endl;
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
Flob* URegion::GetFLOB(const int i) {
|
||
|
|
if (MRA_DEBUG) cerr << "URegion::GetFLOB() called" << endl;
|
||
|
|
assert(i == 0);
|
||
|
|
return &segments;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1 Algebra integration
|
||
|
|
|
||
|
|
1.1.1 Function ~OutURegion()~
|
||
|
|
|
||
|
|
*/
|
||
|
|
static ListExpr OutURegion(ListExpr typeInfo, Word value) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "OutURegion() called" << endl;
|
||
|
|
|
||
|
|
URegion* ur = (URegion*) value.addr;
|
||
|
|
|
||
|
|
// check for undefined value
|
||
|
|
if( !ur->IsDefined() )
|
||
|
|
return (nl->SymbolAtom(Symbol::UNDEFINED()));
|
||
|
|
|
||
|
|
return
|
||
|
|
OutURegionEmbedded(
|
||
|
|
ur->GetEmbedded(),
|
||
|
|
(DbArray<MSegmentData>*) ur->GetFLOB(0));
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1 Function ~InURegion()~
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
static Word InURegion(const ListExpr typeInfo,
|
||
|
|
const ListExpr instance,
|
||
|
|
const int errorPos,
|
||
|
|
ListExpr& errorInfo,
|
||
|
|
bool& correct) {
|
||
|
|
if (MRA_DEBUG) cerr << "InURegion() called" << endl;
|
||
|
|
|
||
|
|
|
||
|
|
URegion* ur = new URegion((unsigned int)0);
|
||
|
|
|
||
|
|
// Check for undefined value
|
||
|
|
if ( listutils::isSymbolUndefined( instance ) )
|
||
|
|
{
|
||
|
|
ur->SetDefined(false);
|
||
|
|
correct = true;
|
||
|
|
return SetWord ( ur );
|
||
|
|
}
|
||
|
|
|
||
|
|
URegionEmb* uremb =
|
||
|
|
InURegionEmbedded(
|
||
|
|
instance,
|
||
|
|
errorPos,
|
||
|
|
errorInfo,
|
||
|
|
(DbArray<MSegmentData>*) ur->GetFLOB(0),
|
||
|
|
0);
|
||
|
|
|
||
|
|
if (!uremb) {
|
||
|
|
cerr << "Could not grok list representation of region unit."
|
||
|
|
<< endl;
|
||
|
|
delete ur;
|
||
|
|
correct = false;
|
||
|
|
return SetWord(Address(0));
|
||
|
|
}
|
||
|
|
|
||
|
|
ur->timeInterval = uremb->timeInterval;
|
||
|
|
ur->SetEmbedded(uremb);
|
||
|
|
ur->SetDefined(true);
|
||
|
|
|
||
|
|
delete uremb;
|
||
|
|
|
||
|
|
correct = true;
|
||
|
|
return SetWord(Address(ur));
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1 Function ~URegionProperty()~
|
||
|
|
|
||
|
|
*/
|
||
|
|
static ListExpr URegionProperty() {
|
||
|
|
if (MRA_DEBUG) cerr << "URegionProperty() called" << endl;
|
||
|
|
|
||
|
|
ListExpr listrep = nl->TextAtom();
|
||
|
|
nl->AppendText(listrep,
|
||
|
|
"(<interval> <face>*), where <interval> is "
|
||
|
|
"(<real> <real> <bool> <bool>) and where "
|
||
|
|
"<face> is (<outercycle> <holecycle>*), "
|
||
|
|
"where <outercycle> and <holecycle> are "
|
||
|
|
"(<real> <real> <real> <real>), representing "
|
||
|
|
"start X, start Y, end X and end Y values.");
|
||
|
|
ListExpr example = nl->TextAtom();
|
||
|
|
nl->AppendText(example,
|
||
|
|
"((0.0 10.0 TRUE TRUE)"
|
||
|
|
"((((1.0 3.5 1.5 1.5)"
|
||
|
|
"(2.0 5.5 3.0 4.5)"
|
||
|
|
"(3.0 6.5 3.5 5.0)"
|
||
|
|
"(4.0 6.5 5.5 5.0)"
|
||
|
|
"(4.0 5.5 5.5 4.5)"
|
||
|
|
"(5.0 4.5 7.5 2.5)"
|
||
|
|
"(5.0 2.5 7.5 1.0)"
|
||
|
|
"(4.0 1.5 7.0 0.5)"
|
||
|
|
"(3.0 1.5 2.5 0.5))"
|
||
|
|
"((2.0 3.0 3.0 2.0)"
|
||
|
|
"(2.0 4.0 3.0 3.0)"
|
||
|
|
"(3.0 4.0 4.0 3.0)"
|
||
|
|
"(3.0 3.0 4.0 2.0)))))");
|
||
|
|
ListExpr remarks = nl->TextAtom();
|
||
|
|
nl->AppendText(remarks,
|
||
|
|
"All <holecycle> must be completely within "
|
||
|
|
"corresponding <outercylce>.");
|
||
|
|
|
||
|
|
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("-> UNIT"),
|
||
|
|
nl->StringAtom("(uregion)"),
|
||
|
|
listrep,
|
||
|
|
example,
|
||
|
|
remarks));
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1 Function ~CheckURegion()~
|
||
|
|
|
||
|
|
*/
|
||
|
|
static bool CheckURegion(ListExpr type, ListExpr& errorInfo) {
|
||
|
|
if (MRA_DEBUG) cerr << "CheckURegion() called" << endl;
|
||
|
|
|
||
|
|
return nl->IsEqual(type, URegion::BasicType());
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1 Function ~CreateURegion()~
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
static Word CreateURegion(const ListExpr typeInfo) {
|
||
|
|
if (MRA_DEBUG) cerr << "CreateURegion() called" << endl;
|
||
|
|
|
||
|
|
return (SetWord(new URegion((unsigned int)0)));
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1 Function ~DeleteURegion()~
|
||
|
|
|
||
|
|
*/
|
||
|
|
static void DeleteURegion(const ListExpr typeInfo, Word& w) {
|
||
|
|
if (MRA_DEBUG) cerr << "DeleteURegion() called" << endl;
|
||
|
|
|
||
|
|
URegion *ur = (URegion*)w.addr;
|
||
|
|
delete ur;
|
||
|
|
w.addr = 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1 Function ~CloseURegion()~
|
||
|
|
|
||
|
|
*/
|
||
|
|
static void CloseURegion(const ListExpr typeInfo, Word& w) {
|
||
|
|
if (MRA_DEBUG) cerr << "CloseURegion() called" << endl;
|
||
|
|
|
||
|
|
delete (URegion*) w.addr;
|
||
|
|
w.addr = 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1 Function ~CloneURegion()~
|
||
|
|
|
||
|
|
*/
|
||
|
|
static Word CloneURegion(const ListExpr typeInfo, const Word& w) {
|
||
|
|
if (MRA_DEBUG) cerr << "CloneURegion() called" << endl;
|
||
|
|
|
||
|
|
return SetWord(((URegion*)w.addr)->Clone());
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1 Function ~CastURegion()~
|
||
|
|
|
||
|
|
*/
|
||
|
|
static void* CastURegion(void* addr) {
|
||
|
|
if (MRA_DEBUG) cerr << "CastURegion() called" << endl;
|
||
|
|
|
||
|
|
return new (addr) URegion;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1 Function ~SizeOfURegion()~
|
||
|
|
|
||
|
|
*/
|
||
|
|
static int SizeOfURegion() {
|
||
|
|
if (MRA_DEBUG) cerr << "SizeOfURegion() called" << endl;
|
||
|
|
|
||
|
|
return sizeof(URegion);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1 Function ~OpenURegion()~
|
||
|
|
|
||
|
|
*/
|
||
|
|
bool OpenURegion(SmiRecord& rec,
|
||
|
|
size_t& offset,
|
||
|
|
const ListExpr typeInfo,
|
||
|
|
Word& w) {
|
||
|
|
if (MRA_DEBUG) cerr << "OpenURegion() called" << endl;
|
||
|
|
|
||
|
|
w = SetWord(Attribute::Open(rec, offset, typeInfo));
|
||
|
|
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1 Function ~SaveURegion()~
|
||
|
|
|
||
|
|
Makes sense on ~URegion~ instances with own segment storage only and will
|
||
|
|
run into failed assertion for other instances.
|
||
|
|
|
||
|
|
*/
|
||
|
|
static bool SaveURegion(SmiRecord& rec,
|
||
|
|
size_t& offset,
|
||
|
|
const ListExpr typeInfo,
|
||
|
|
Word& w) {
|
||
|
|
if (MRA_DEBUG) cerr << "SaveURegion() called" << endl;
|
||
|
|
|
||
|
|
URegion* ur = static_cast<URegion*> (w.addr);
|
||
|
|
Attribute::Save(rec, offset, typeInfo, ur);
|
||
|
|
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1 Type constructor ~uregion~
|
||
|
|
|
||
|
|
*/
|
||
|
|
static TypeConstructor uregion(
|
||
|
|
URegion::BasicType(),
|
||
|
|
URegionProperty,
|
||
|
|
OutURegion,
|
||
|
|
InURegion,
|
||
|
|
0, 0, // SaveToList, RestoreFromList
|
||
|
|
CreateURegion,
|
||
|
|
DeleteURegion,
|
||
|
|
OpenURegion,
|
||
|
|
SaveURegion,
|
||
|
|
CloseURegion,
|
||
|
|
CloneURegion,
|
||
|
|
CastURegion,
|
||
|
|
SizeOfURegion,
|
||
|
|
CheckURegion);
|
||
|
|
|
||
|
|
/*
|
||
|
|
1 Data type ~mregion~
|
||
|
|
|
||
|
|
1.1 Class ~MRegion~
|
||
|
|
|
||
|
|
1.1.1 Class definition
|
||
|
|
|
||
|
|
The class definition has been moved to ~MovingRegionAlgebra.h~.
|
||
|
|
|
||
|
|
1.1.1 Private methods
|
||
|
|
|
||
|
|
1.1.1.1 Method ~IntersectionRP()~
|
||
|
|
|
||
|
|
*/
|
||
|
|
void MRegion::IntersectionRP(
|
||
|
|
const MPoint& mp,
|
||
|
|
MPoint& res,
|
||
|
|
RefinementPartition<
|
||
|
|
MRegion,
|
||
|
|
MPoint,
|
||
|
|
URegionEmb,
|
||
|
|
UPoint>& rp,
|
||
|
|
bool merge) {
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "MRegion::IntersectionRP() #1 called" << endl;
|
||
|
|
|
||
|
|
res = MPoint(0);
|
||
|
|
|
||
|
|
UPoint* pending = 0;
|
||
|
|
|
||
|
|
/*
|
||
|
|
|
||
|
|
For each interval in the refinement partition, we have to check whether
|
||
|
|
it maps to a region and point unit. If not, there is obviously no intersection
|
||
|
|
during this interval and we can skip it. Otherwise, we check if the region
|
||
|
|
and point unit, both restricted to this interval, intersect.
|
||
|
|
|
||
|
|
*/
|
||
|
|
for (unsigned int i = 0; i < rp.Size(); i++) {
|
||
|
|
Interval<Instant> iv;
|
||
|
|
int urPos;
|
||
|
|
int upPos;
|
||
|
|
|
||
|
|
rp.Get(i, iv, urPos, upPos);
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "MRegion::IntersectionRP() interval#"
|
||
|
|
<< i
|
||
|
|
<< ": "
|
||
|
|
<< iv.start.ToDouble()
|
||
|
|
<< " "
|
||
|
|
<< iv.end.ToDouble()
|
||
|
|
<< " "
|
||
|
|
<< iv.lc
|
||
|
|
<< " "
|
||
|
|
<< iv.rc
|
||
|
|
<< " "
|
||
|
|
<< urPos
|
||
|
|
<< " "
|
||
|
|
<< upPos
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
if (urPos == -1 || upPos == -1) continue;
|
||
|
|
|
||
|
|
URegionEmb ur;
|
||
|
|
UPoint up;
|
||
|
|
|
||
|
|
Get(urPos, ur);
|
||
|
|
mp.Get(upPos, up);
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "MRegion::IntersectionRP() both elements present"
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
ur.RestrictedIntersection(
|
||
|
|
&msegmentdata, up, iv, res, pending, merge);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (pending) {
|
||
|
|
if (!(nearlyEqual(pending->timeInterval.start.ToDouble(),
|
||
|
|
pending->timeInterval.end.ToDouble())
|
||
|
|
&& (!pending->timeInterval.lc
|
||
|
|
|| !pending->timeInterval.rc))) {
|
||
|
|
res.Add(*pending);
|
||
|
|
}
|
||
|
|
|
||
|
|
delete pending;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "MRegion::IntersectionRP() res.IsEmpty()="
|
||
|
|
<< res.IsEmpty()
|
||
|
|
<< endl;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1.1 Method ~InsideAddUBool()~
|
||
|
|
|
||
|
|
*/
|
||
|
|
void MRegion::InsideAddUBool(MBool& res,
|
||
|
|
Instant starttime,
|
||
|
|
Instant endtime,
|
||
|
|
bool lc,
|
||
|
|
bool rc,
|
||
|
|
bool value,
|
||
|
|
Instant& prev,
|
||
|
|
bool& prev_c,
|
||
|
|
UBool*& pending) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "MRegion::InsideAddUBool() called, value="
|
||
|
|
<< value
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
Instant start(starttime);
|
||
|
|
|
||
|
|
Instant end(endtime);
|
||
|
|
|
||
|
|
CcBool bv(true, value);
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "MRegion::InsideAddUBool() adding "
|
||
|
|
<< setprecision(20)
|
||
|
|
<< start.ToString()
|
||
|
|
<< " ("
|
||
|
|
<< starttime.ToString()
|
||
|
|
<< ") "
|
||
|
|
<< end.ToString()
|
||
|
|
<< " ("
|
||
|
|
<< endtime
|
||
|
|
<< ") "
|
||
|
|
<< lc
|
||
|
|
<< " "
|
||
|
|
<< rc
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
if (pending) {
|
||
|
|
if (MRA_DEBUG) {
|
||
|
|
cerr << "MRegion::InsideAddUBool() pending end="
|
||
|
|
<< pending->timeInterval.end.ToString()
|
||
|
|
<< " rc="
|
||
|
|
<< pending->timeInterval.rc
|
||
|
|
<< endl;
|
||
|
|
cerr << "MRegion::InsideAddUBool() current start="
|
||
|
|
<< start.ToString()
|
||
|
|
<< " lc="
|
||
|
|
<< lc
|
||
|
|
<< endl;
|
||
|
|
}
|
||
|
|
|
||
|
|
if ((starttime == pending->timeInterval.end)
|
||
|
|
&& (pending->timeInterval.rc || lc)
|
||
|
|
&& pending->constValue.GetBoolval() == value) {
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "MRegion::InsideAddUBool() connecting"
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
if (pending->timeInterval.start == pending->timeInterval.end) {
|
||
|
|
Interval<Instant> iv(start,
|
||
|
|
end,
|
||
|
|
true,
|
||
|
|
rc);
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "MRegion::InsideAddUBool() connecting #1 to "
|
||
|
|
<< iv.start.ToString()
|
||
|
|
<< " "
|
||
|
|
<< iv.end.ToString()
|
||
|
|
<< " "
|
||
|
|
<< iv.lc
|
||
|
|
<< " "
|
||
|
|
<< iv.rc
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
delete pending;
|
||
|
|
pending = new UBool(iv, bv);
|
||
|
|
} else if (starttime == endtime) {
|
||
|
|
Interval<Instant> iv(start,
|
||
|
|
end,
|
||
|
|
pending->timeInterval.lc,
|
||
|
|
true);
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "MRegion::InsideAddUBool() connecting #2 to "
|
||
|
|
<< iv.start.ToString()
|
||
|
|
<< " "
|
||
|
|
<< iv.end.ToString()
|
||
|
|
<< " "
|
||
|
|
<< iv.lc
|
||
|
|
<< " "
|
||
|
|
<< iv.rc
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
delete pending;
|
||
|
|
pending = new UBool(iv, bv);
|
||
|
|
} else {
|
||
|
|
Interval<Instant> iv(pending->timeInterval.start,
|
||
|
|
end,
|
||
|
|
pending->timeInterval.lc,
|
||
|
|
rc);
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "MRegion::InsideAddUBool() connecting #3 to "
|
||
|
|
<< iv.start.ToString()
|
||
|
|
<< " "
|
||
|
|
<< iv.end.ToString()
|
||
|
|
<< " "
|
||
|
|
<< iv.lc
|
||
|
|
<< " "
|
||
|
|
<< iv.rc
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
delete pending;
|
||
|
|
pending = new UBool(iv, bv);
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "MRegion::InsideAddUBool() not connecting, pending is "
|
||
|
|
<< pending->timeInterval.start.ToString()
|
||
|
|
<< " "
|
||
|
|
<< pending->timeInterval.end.ToString()
|
||
|
|
<< " "
|
||
|
|
<< pending->timeInterval.lc
|
||
|
|
<< " "
|
||
|
|
<< pending->timeInterval.rc
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
if(pending->IsValid())
|
||
|
|
res.Add(*pending);
|
||
|
|
delete pending;
|
||
|
|
|
||
|
|
Interval<Instant> iv(start, end, lc, rc);
|
||
|
|
|
||
|
|
pending = new UBool(iv, bv);
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "MRegion::InsideAddUBool() "
|
||
|
|
<< "pending does not exist"
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
Interval<Instant> iv(start, end, lc, rc);
|
||
|
|
|
||
|
|
pending = new UBool(iv, bv);
|
||
|
|
}
|
||
|
|
|
||
|
|
prev = endtime;
|
||
|
|
prev_c = rc;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
Rectangle<3> MRegion::BoundingBox() const{
|
||
|
|
double min[] = {0.0,0.0,0.0};
|
||
|
|
double max[] = {1.0,1.0,1.0};
|
||
|
|
Rectangle<3> res(false, min,max );
|
||
|
|
|
||
|
|
// undefined or empty mregion
|
||
|
|
if (!IsDefined() || GetNoComponents() < 1) {
|
||
|
|
return res;
|
||
|
|
}
|
||
|
|
|
||
|
|
res.SetDefined(true);
|
||
|
|
URegionEmb ur;
|
||
|
|
Get(0, ur);
|
||
|
|
res = ur.BoundingBox();
|
||
|
|
for(int i=1; i<GetNoComponents(); i++) {
|
||
|
|
Get(i, ur);
|
||
|
|
res = res.Union( ur.BoundingBox() );
|
||
|
|
}
|
||
|
|
return res;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1 Constructors
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
MRegion::MRegion(const int n) :
|
||
|
|
Mapping<URegionEmb, Region>(n),
|
||
|
|
msegmentdata(n) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "MRegion::MRegion(int) called" << endl;
|
||
|
|
}
|
||
|
|
|
||
|
|
//MRegion::MRegion(MPoint& mp, Region& r) :
|
||
|
|
// original signature replaced with
|
||
|
|
// 'call by copy' for 2nd arg due to problems when reading r
|
||
|
|
// directly from disk ( raised assert( type == InMemory ) ):
|
||
|
|
MRegion::MRegion(const MPoint& mp, const Region& _r) :
|
||
|
|
Mapping<URegionEmb, Region>(0),
|
||
|
|
msegmentdata(0) {
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "MRegion::MRegion(MPoint, Region) called"
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
if( !_r.IsDefined() || !mp.IsDefined() ){
|
||
|
|
del.isDefined=false;
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
Region* r = new Region(_r);
|
||
|
|
r->LogicSort();
|
||
|
|
|
||
|
|
for (int i = 0; i < mp.GetNoComponents(); i++) {
|
||
|
|
UPoint up;
|
||
|
|
|
||
|
|
mp.Get(i, up);
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "MRegion::MRegion(MPoint, Region) i="
|
||
|
|
<< i
|
||
|
|
<< " interval=["
|
||
|
|
<< up.timeInterval.start.ToString()
|
||
|
|
<< " ("
|
||
|
|
<< up.timeInterval.start.ToDouble()
|
||
|
|
<< ") "
|
||
|
|
<< up.timeInterval.end.ToString()
|
||
|
|
<< "("
|
||
|
|
<< up.timeInterval.end.ToDouble()
|
||
|
|
<< ") "
|
||
|
|
<< up.timeInterval.lc
|
||
|
|
<< " "
|
||
|
|
<< up.timeInterval.rc
|
||
|
|
<< "]"
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
URegionEmb
|
||
|
|
ur(&msegmentdata,
|
||
|
|
up.timeInterval,
|
||
|
|
*r,
|
||
|
|
msegmentdata.Size());
|
||
|
|
if(ur.IsValid())
|
||
|
|
Add(ur);
|
||
|
|
}
|
||
|
|
del.isDefined=true;
|
||
|
|
r->DeleteIfAllowed();
|
||
|
|
}
|
||
|
|
|
||
|
|
MRegion::MRegion(const MPoint& mp, const Region& _r, const int dummy) :
|
||
|
|
Mapping<URegionEmb, Region>(0),
|
||
|
|
msegmentdata(0) {
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "MRegion::MRegion(MPoint, Region,int) called"
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
if( !_r.IsDefined() || !mp.IsDefined() ){
|
||
|
|
del.isDefined=false;
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
Region* r = new Region(_r);
|
||
|
|
|
||
|
|
r->LogicSort();
|
||
|
|
bool isFirst = true;
|
||
|
|
Coord lastX = 0.0, lastY = 0.0;
|
||
|
|
Coord firstX = 0.0, firstY = 0.0;
|
||
|
|
for (int i = 0; i < mp.GetNoComponents(); i++) {
|
||
|
|
UPoint up;
|
||
|
|
mp.Get(i, up);
|
||
|
|
firstX = up.p0.GetX();
|
||
|
|
firstY = up.p0.GetY();
|
||
|
|
|
||
|
|
if( ! isFirst && (firstX !=lastX || firstY != lastY)){
|
||
|
|
r->Translate(firstX-lastX, firstY-lastY);
|
||
|
|
}else{
|
||
|
|
isFirst=false;
|
||
|
|
}
|
||
|
|
|
||
|
|
lastX = up.p1.GetX();
|
||
|
|
lastY = up.p1.GetY();
|
||
|
|
|
||
|
|
URegionEmb
|
||
|
|
ur(&msegmentdata,
|
||
|
|
up.timeInterval,
|
||
|
|
*r,
|
||
|
|
msegmentdata.Size());
|
||
|
|
// now ur represents a static region
|
||
|
|
// if this is not the case, we change the final line
|
||
|
|
Coord tx = lastX-firstX;
|
||
|
|
Coord ty = lastY-firstY;
|
||
|
|
if(tx!=0 || ty!=0){
|
||
|
|
size_t usize = ur.GetSegmentsNum();
|
||
|
|
MSegmentData mseg;
|
||
|
|
for(size_t i=0;i<usize;i++){
|
||
|
|
ur.GetSegment(&msegmentdata, i, mseg);
|
||
|
|
MSegmentData dms(mseg);
|
||
|
|
dms.SetFinalStartX(dms.GetFinalStartX()+tx);
|
||
|
|
dms.SetFinalStartY(dms.GetFinalStartY()+ty);
|
||
|
|
dms.SetFinalEndX(dms.GetFinalEndX()+tx);
|
||
|
|
dms.SetFinalEndY(dms.GetFinalEndY()+ty);
|
||
|
|
ur.PutSegment(&msegmentdata, i, dms);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
// change the bounding box of ur
|
||
|
|
Rectangle<3> rbb(ur.BoundingBox());
|
||
|
|
double t[3];
|
||
|
|
t[0] = tx;
|
||
|
|
t[1] = ty;
|
||
|
|
t[2] = 0.0;
|
||
|
|
rbb = rbb.Translate(t);
|
||
|
|
ur.SetBBox(ur.BoundingBox().Union(rbb));
|
||
|
|
|
||
|
|
r->Translate(tx,ty);
|
||
|
|
Add(ur);
|
||
|
|
}
|
||
|
|
del.isDefined=true;
|
||
|
|
r->DeleteIfAllowed();
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1 Attribute access methods
|
||
|
|
|
||
|
|
1.1.1.1 Method ~Get()~
|
||
|
|
|
||
|
|
*/
|
||
|
|
void MRegion::Get(const int i, URegionEmb& ur) const {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "MRegion::Get() #2 called i="
|
||
|
|
<< i
|
||
|
|
<< " (msegmentdata="
|
||
|
|
<< &msegmentdata
|
||
|
|
<< ")"
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
Mapping<URegionEmb, Region>::Get(i, ur);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1.1 Method ~GetMSegmentData()~
|
||
|
|
|
||
|
|
*/
|
||
|
|
const DbArray<MSegmentData>* MRegion::GetMSegmentData(void) {
|
||
|
|
return &msegmentdata;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
Add an idependent ~URegion~ object to the moving region. The URegions moving
|
||
|
|
segment is copied to the DBArrays for ~msegmentdata~ and ~units~.
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
void MRegion::AddURegion( URegion& U ) {
|
||
|
|
|
||
|
|
|
||
|
|
#ifdef MR_DEBUG
|
||
|
|
cout << "MRegion::AddURegion" << endl;
|
||
|
|
U.Print(cout);
|
||
|
|
#endif
|
||
|
|
assert( IsDefined() );
|
||
|
|
if ( !U.IsDefined() || !IsDefined() )
|
||
|
|
return;
|
||
|
|
|
||
|
|
URegionEmb tmp(true);
|
||
|
|
int start=0, end=0;
|
||
|
|
|
||
|
|
StartBulkLoad();
|
||
|
|
|
||
|
|
// copy adjusted U.uremb data to units
|
||
|
|
start = msegmentdata.Size();
|
||
|
|
end = U.uremb.GetSegmentsNum();
|
||
|
|
tmp = *(U.GetEmbedded());
|
||
|
|
tmp.SetStartPos(start);
|
||
|
|
Add(tmp);
|
||
|
|
|
||
|
|
// append U.segments to msegmentdata
|
||
|
|
for(int i=0 ; i<end ; i++)
|
||
|
|
{
|
||
|
|
MSegmentData dms;
|
||
|
|
U.segments.Get(i, &dms);
|
||
|
|
msegmentdata.Put(i+start, dms);
|
||
|
|
}
|
||
|
|
EndBulkLoad(true);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1 Methods for database operators
|
||
|
|
|
||
|
|
1.1.1.1 Method ~Intersection()~
|
||
|
|
|
||
|
|
*/
|
||
|
|
void MRegion::Intersection(MPoint& mp, MPoint& res) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "MRegion::Intersection() #2 called" << endl;
|
||
|
|
|
||
|
|
res.Clear();
|
||
|
|
if( !IsDefined() || !mp.IsDefined() ){
|
||
|
|
res.SetDefined( false );
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
res.SetDefined( true );
|
||
|
|
|
||
|
|
RefinementPartition<
|
||
|
|
MRegion,
|
||
|
|
MPoint,
|
||
|
|
URegionEmb,
|
||
|
|
UPoint> rp(*this, mp);
|
||
|
|
|
||
|
|
IntersectionRP(mp, res, rp, true);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1.1 Method ~Inside()~
|
||
|
|
|
||
|
|
*/
|
||
|
|
void MRegion::Inside(const MPoint& mp, MBool& res) {
|
||
|
|
if (MRA_DEBUG) cerr << "MRegion::Inside() called" << endl;
|
||
|
|
|
||
|
|
res.Clear();
|
||
|
|
if( !IsDefined() || !mp.IsDefined() ){
|
||
|
|
res.SetDefined( false );
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
res.SetDefined( true );
|
||
|
|
|
||
|
|
/*
|
||
|
|
Use intersection algorithm and then see how the units in the result
|
||
|
|
match to the original units in ~mp~.
|
||
|
|
|
||
|
|
First, we have to create the refinement partition for ~mp~ and this
|
||
|
|
~MRegion~ instance.
|
||
|
|
|
||
|
|
*/
|
||
|
|
RefinementPartition<
|
||
|
|
MRegion,
|
||
|
|
MPoint,
|
||
|
|
URegionEmb,
|
||
|
|
UPoint> rp(*this, mp);
|
||
|
|
|
||
|
|
/*
|
||
|
|
We are calling ~IntersectionRP()~ with value ~false~ for parameter ~merge~.
|
||
|
|
This means that the resulting ~URegionEmb~ instances in ~resMp~ are not
|
||
|
|
merged, ie. one ~URegionEmb~ instance's interval is entirely within one
|
||
|
|
interval in ~rp~.
|
||
|
|
|
||
|
|
*/
|
||
|
|
MPoint resMp(0);
|
||
|
|
IntersectionRP(mp, resMp, rp, false);
|
||
|
|
|
||
|
|
int mpPos = 0;
|
||
|
|
|
||
|
|
/*
|
||
|
|
Required for ~InsideAddUBool()~.
|
||
|
|
|
||
|
|
*/
|
||
|
|
UBool* pending = 0;
|
||
|
|
|
||
|
|
/*
|
||
|
|
Pass through all the intervals in ~rp~.
|
||
|
|
|
||
|
|
*/
|
||
|
|
for (unsigned int rpPos = 0; rpPos < rp.Size(); rpPos++) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "MRegion::Inside() rpPos=" << rpPos
|
||
|
|
<< " mpPos=" << mpPos
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
/*
|
||
|
|
Get the units for each interval in ~rp~.
|
||
|
|
|
||
|
|
*/
|
||
|
|
Interval<Instant> iv;
|
||
|
|
int urPos;
|
||
|
|
int upPos;
|
||
|
|
|
||
|
|
rp.Get(rpPos, iv, urPos, upPos);
|
||
|
|
|
||
|
|
/*
|
||
|
|
We are only interested in the intervals, which are contained in ~mp~.
|
||
|
|
If an interval in ~rp~ is not in ~mp~, ~upPos~ is lower than $0$ and
|
||
|
|
we skip this interval.
|
||
|
|
|
||
|
|
*/
|
||
|
|
if (upPos < 0) continue;
|
||
|
|
|
||
|
|
Instant prev = iv.start;
|
||
|
|
bool prev_c = !iv.lc;
|
||
|
|
|
||
|
|
/*
|
||
|
|
Check every ~upoint~ instance in the intersection,
|
||
|
|
which has an interval within the current interval.
|
||
|
|
If we reach an instance outside the current interval,
|
||
|
|
the ~for~ loop is left via a ~break~ statement.
|
||
|
|
|
||
|
|
*/
|
||
|
|
for (; mpPos < resMp.GetNoComponents(); mpPos++) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "MRegion::Inside() mpPos=" << mpPos
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
/*
|
||
|
|
Get the current ~upoint~ instance.
|
||
|
|
|
||
|
|
*/
|
||
|
|
UPoint up;
|
||
|
|
resMp.Get(mpPos, up);
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "MRegion::Inside() rp iv=["
|
||
|
|
<< iv.start.ToString()
|
||
|
|
<< " "
|
||
|
|
<< iv.end.ToString()
|
||
|
|
<< " "
|
||
|
|
<< iv.lc
|
||
|
|
<< " "
|
||
|
|
<< iv.rc
|
||
|
|
<< "] up iv=["
|
||
|
|
<< up.timeInterval.start.ToString()
|
||
|
|
<< " "
|
||
|
|
<< up.timeInterval.end.ToString()
|
||
|
|
<< " "
|
||
|
|
<< up.timeInterval.lc
|
||
|
|
<< " "
|
||
|
|
<< up.timeInterval.rc
|
||
|
|
<< "]"
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
/*
|
||
|
|
Is this ~upoint~ instance really within the current interval?
|
||
|
|
|
||
|
|
*/
|
||
|
|
if (up.timeInterval.start.Compare(&iv.end) > 0
|
||
|
|
|| (up.timeInterval.start.Compare(&iv.end) == 0
|
||
|
|
&& up.timeInterval.lc
|
||
|
|
&& !iv.rc)) {
|
||
|
|
/*
|
||
|
|
No, we reached the end of the current interval. We add a ~ubool~ instance
|
||
|
|
with value ~false~ to the result, which closes the gap between the previously
|
||
|
|
added ~ubool~ instance and the end of the current interval (only if
|
||
|
|
applicable).
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "MRegion::Inside() end of unit"
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
if (prev.Compare(&iv.end) < 0) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "MRegion::Inside() closing gap #2a"
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
InsideAddUBool(res,
|
||
|
|
prev,
|
||
|
|
iv.end,
|
||
|
|
!prev_c,
|
||
|
|
iv.rc,
|
||
|
|
false,
|
||
|
|
prev,
|
||
|
|
prev_c,
|
||
|
|
pending);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
Break out of the loop iterating through the ~upoint~ instances in the
|
||
|
|
intersection.
|
||
|
|
|
||
|
|
*/
|
||
|
|
break;
|
||
|
|
} else {
|
||
|
|
/*
|
||
|
|
Yes, the current ~upoint~ instance is still within the current interval.
|
||
|
|
|
||
|
|
*/
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "MRegion::Inside() inside unit"
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
/*
|
||
|
|
Is there a gap between the previously added ~ubool~ instance and the
|
||
|
|
start of the interval of the current ~upoint~ instance? If so, close
|
||
|
|
the gap by adding an ~ubool~ instance with an appropriate interval
|
||
|
|
and value ~false~.
|
||
|
|
|
||
|
|
*/
|
||
|
|
if (up.timeInterval.start.Compare(&prev) > 0) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "MRegion::Inside() closing gap #1a, prev="
|
||
|
|
<< setprecision(20)
|
||
|
|
<< prev
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
InsideAddUBool(res,
|
||
|
|
prev,
|
||
|
|
up.timeInterval.start,
|
||
|
|
!prev_c,
|
||
|
|
!up.timeInterval.lc,
|
||
|
|
false,
|
||
|
|
prev,
|
||
|
|
prev_c,
|
||
|
|
pending);
|
||
|
|
} else if (up.timeInterval.start.Compare(&prev) == 0
|
||
|
|
&& !up.timeInterval.lc
|
||
|
|
&& prev_c) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "MRegion::Inside() closing gap #1b, prev="
|
||
|
|
<< setprecision(15)
|
||
|
|
<< prev
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
InsideAddUBool(res,
|
||
|
|
up.timeInterval.start,
|
||
|
|
up.timeInterval.start,
|
||
|
|
true,
|
||
|
|
true,
|
||
|
|
false,
|
||
|
|
prev,
|
||
|
|
prev_c,
|
||
|
|
pending);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
Add a ~ubool~ instance with the interval of the current ~upoint~ instance
|
||
|
|
and value ~true~.
|
||
|
|
|
||
|
|
*/
|
||
|
|
InsideAddUBool(res,
|
||
|
|
up.timeInterval.start,
|
||
|
|
up.timeInterval.end,
|
||
|
|
up.timeInterval.lc,
|
||
|
|
up.timeInterval.rc,
|
||
|
|
true,
|
||
|
|
prev,
|
||
|
|
prev_c,
|
||
|
|
pending);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (mpPos == resMp.GetNoComponents()) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "MRegion::Inside() end of units reached before"
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
if (prev.Compare(&iv.end) < 0) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "MRegion::Inside() closing gap #3a"
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
InsideAddUBool(res,
|
||
|
|
prev,
|
||
|
|
iv.end,
|
||
|
|
!prev_c,
|
||
|
|
iv.rc,
|
||
|
|
false,
|
||
|
|
prev,
|
||
|
|
prev_c,
|
||
|
|
pending);
|
||
|
|
} else if (prev.Compare(&iv.end) == 0
|
||
|
|
&& !prev_c
|
||
|
|
&& iv.rc) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "MRegion::Inside() closing gap #3b"
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
InsideAddUBool(res,
|
||
|
|
iv.end,
|
||
|
|
iv.end,
|
||
|
|
true,
|
||
|
|
true,
|
||
|
|
false,
|
||
|
|
prev,
|
||
|
|
prev_c,
|
||
|
|
pending);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
Since ~InsideAddUBool()~ is trying to merge adjacent ~ubool~ instances
|
||
|
|
with identical value, there may be an ~ubool~ instance left in ~pending~,
|
||
|
|
which needs to be added to the result.
|
||
|
|
|
||
|
|
*/
|
||
|
|
if (pending) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "MRegion::Inside() adding pending" << endl;
|
||
|
|
if(pending->IsValid())
|
||
|
|
res.Add(*pending);
|
||
|
|
delete pending;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1.1 Method ~AtInstant()~
|
||
|
|
|
||
|
|
Method ~Mapping<Unit, Alpha>::AtInstant()~ is not sufficient since it
|
||
|
|
does not deal with setting the unit's segment data DBArray.
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
void MRegion::AtInstant(const Instant& t, Intime<Region>& result) {
|
||
|
|
if (MRA_DEBUG) cerr << "MRegion::AtInstant() called" << endl;
|
||
|
|
|
||
|
|
assert(IsOrdered() && t.IsDefined());
|
||
|
|
|
||
|
|
int pos = Position(t );
|
||
|
|
|
||
|
|
if( pos == -1 )
|
||
|
|
result.SetDefined(false);
|
||
|
|
else {
|
||
|
|
URegionEmb posUnit;
|
||
|
|
Get(pos, posUnit);
|
||
|
|
result.SetDefined(true);
|
||
|
|
posUnit.TemporalFunction(&msegmentdata, t, result.value);
|
||
|
|
result.instant.CopyFrom(&t);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1.1 Method ~Initial()~
|
||
|
|
|
||
|
|
Method ~Mapping<Unit, Alpha>::Initial()~ is not sufficient since it
|
||
|
|
does not deal with setting the unit's segment data DBArray.
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
void MRegion::Initial(Intime<Region>& result) {
|
||
|
|
if (MRA_DEBUG) cerr << "MRegion::Initial() called" << endl;
|
||
|
|
|
||
|
|
if ( !IsDefined() || IsEmpty() ) {
|
||
|
|
result.SetDefined(false);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
result.SetDefined(true);
|
||
|
|
|
||
|
|
assert(IsOrdered());
|
||
|
|
URegionEmb unit;
|
||
|
|
Get(0, unit);
|
||
|
|
|
||
|
|
if (!unit.timeInterval.lc) {
|
||
|
|
result.SetDefined(false);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
result.value.Clear();
|
||
|
|
result.value.SetDefined(true);
|
||
|
|
result.SetDefined(true);
|
||
|
|
unit.TemporalFunction(
|
||
|
|
&msegmentdata,
|
||
|
|
unit.timeInterval.start,
|
||
|
|
result.value);
|
||
|
|
result.instant.CopyFrom(&unit.timeInterval.start);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1.1 Method ~Final()~
|
||
|
|
|
||
|
|
Method ~Mapping<Unit, Alpha>::Final()~ is not sufficient since it
|
||
|
|
does not deal with setting the unit's segment data DBArray.
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
void MRegion::Final(Intime<Region>& result) {
|
||
|
|
if (MRA_DEBUG) cerr << "MRegion::Final() called" << endl;
|
||
|
|
|
||
|
|
if ( !IsDefined() || IsEmpty() ) {
|
||
|
|
result.SetDefined(false);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
result.SetDefined(true);
|
||
|
|
assert(IsOrdered());
|
||
|
|
|
||
|
|
URegionEmb unit;
|
||
|
|
Get(GetNoComponents()-1, unit);
|
||
|
|
|
||
|
|
if (!unit.timeInterval.rc) {
|
||
|
|
result.SetDefined(false);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
result.value.Clear();
|
||
|
|
result.value.SetDefined(true);
|
||
|
|
result.SetDefined(true);
|
||
|
|
unit.TemporalFunction(
|
||
|
|
&msegmentdata,
|
||
|
|
unit.timeInterval.end,
|
||
|
|
result.value);
|
||
|
|
result.instant.CopyFrom(&unit.timeInterval.end);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1.1 Method ~Traversed()~
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
#ifdef MRA_TRAVERSED
|
||
|
|
void MRegion::Traversed(Region& res) {
|
||
|
|
if (MRA_DEBUG) cerr << "MRegion::Traversed() called" << endl;
|
||
|
|
|
||
|
|
/*
|
||
|
|
Methods relating to operator ~traversed~ are currently being developed.
|
||
|
|
In the meantime, we provide a stub with a failed assertion to recognize
|
||
|
|
accidential calls of this method.
|
||
|
|
|
||
|
|
*/
|
||
|
|
cerr << "WARNING: Unimplemented function " << __PRETTY_FUNCTION__
|
||
|
|
<< " called!" << endl;
|
||
|
|
assert(false);
|
||
|
|
res.Clear();
|
||
|
|
res.SetDefined( false );
|
||
|
|
}
|
||
|
|
#endif // MRA_TRAVERSED
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1 Methods for algebra integration
|
||
|
|
|
||
|
|
1.1.1.1 Method ~Clone()~
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
MRegion* MRegion::Clone(void) const {
|
||
|
|
if (MRA_DEBUG) cerr << "MRegion::Clone() called" << endl;
|
||
|
|
|
||
|
|
MRegion* res = new MRegion(0);
|
||
|
|
res->CopyFrom(this);
|
||
|
|
return res;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1.1 Method ~CopyFrom()~
|
||
|
|
|
||
|
|
*/
|
||
|
|
void MRegion::CopyFrom(const Attribute* right) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "MRegion::CopyFrom() called, this="
|
||
|
|
<< this
|
||
|
|
<< ", &msegmentdata="
|
||
|
|
<< &msegmentdata
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
MRegion* mr = (MRegion*) right;
|
||
|
|
|
||
|
|
Clear();
|
||
|
|
if( !mr->IsDefined() ){
|
||
|
|
SetDefined( false );
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
SetDefined( true );
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "MRegion::CopyFrom() called, &mr->msegmentdata="
|
||
|
|
<< &mr->msegmentdata
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
/*
|
||
|
|
~InMRegion()~ sorts the region units, therefore the following assumption
|
||
|
|
should hold.
|
||
|
|
|
||
|
|
*/
|
||
|
|
assert(mr->IsOrdered());
|
||
|
|
|
||
|
|
/*
|
||
|
|
Copy the units and assure that their pointer to the ~DBAarry~ containing
|
||
|
|
their moving segments points to this instance's ~DBArray~.
|
||
|
|
|
||
|
|
*/
|
||
|
|
StartBulkLoad();
|
||
|
|
for(int i = 0; i < mr->GetNoComponents(); i++) {
|
||
|
|
URegionEmb ur;
|
||
|
|
mr->Get(i, ur);
|
||
|
|
Add(ur);
|
||
|
|
}
|
||
|
|
EndBulkLoad(false);
|
||
|
|
|
||
|
|
/*
|
||
|
|
Copy the moving segments.
|
||
|
|
|
||
|
|
*/
|
||
|
|
msegmentdata.clean();
|
||
|
|
if (mr->msegmentdata.Size() > 0)
|
||
|
|
msegmentdata.resize(mr->msegmentdata.Size());
|
||
|
|
for (int i = 0; i < mr->msegmentdata.Size(); i++) {
|
||
|
|
MSegmentData dms;
|
||
|
|
mr->msegmentdata.Get(i, dms);
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "MRegion::CopyFrom() segment "
|
||
|
|
<< i
|
||
|
|
<< ": initial=["
|
||
|
|
<< dms.GetInitialStartX()
|
||
|
|
<< " " << dms.GetInitialStartY()
|
||
|
|
<< " " << dms.GetInitialEndX()
|
||
|
|
<< " " << dms.GetInitialEndY()
|
||
|
|
<< "] final=["
|
||
|
|
<< dms.GetFinalStartX()
|
||
|
|
<< " " << dms.GetFinalStartY()
|
||
|
|
<< " " << dms.GetFinalEndX()
|
||
|
|
<< " " << dms.GetFinalEndY()
|
||
|
|
<< "]"
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
msegmentdata.Put(i, dms);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1.1 ~DBArray~ access
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
int MRegion::NumOfFLOBs() const {
|
||
|
|
if (MRA_DEBUG) cerr << "MRegion::NumOfFLOBs() called" << endl;
|
||
|
|
return 2;
|
||
|
|
}
|
||
|
|
|
||
|
|
Flob* MRegion::GetFLOB(const int i) {
|
||
|
|
if (MRA_DEBUG) cerr << "MRegion::GetFLOB() called" << endl;
|
||
|
|
assert(i == 0 || i == 1);
|
||
|
|
return
|
||
|
|
i == 0
|
||
|
|
? Mapping<URegionEmb, Region>::GetFLOB(0)
|
||
|
|
: &msegmentdata;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1 Unit testing
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
#ifdef MRA_UNITTEST
|
||
|
|
bool MRegion::Unittest2(int pos) {
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "MRegion::Unittest2() called pos="
|
||
|
|
<< pos
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
if ( !IsDefined() || pos < 0 || pos >= msegmentdata.Size()) return -1;
|
||
|
|
|
||
|
|
MSegmentData dms;
|
||
|
|
msegmentdata.Get(pos, &dms);
|
||
|
|
|
||
|
|
return dms.GetInsideAbove();
|
||
|
|
}
|
||
|
|
#endif // MRA_UNITTEST
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1 Algebra integration
|
||
|
|
|
||
|
|
1.1.1 Function ~MRegionProperty()~
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
static ListExpr MRegionProperty() {
|
||
|
|
if (MRA_DEBUG) cerr << "MRegionProperty() called" << endl;
|
||
|
|
|
||
|
|
ListExpr listrep = nl->TextAtom();
|
||
|
|
nl->AppendText(listrep,
|
||
|
|
"(u1 ... un) with ui uregion list representations "
|
||
|
|
"and n >= 1. Each ui is of format "
|
||
|
|
"(<interval> <face>*), where <interval> is "
|
||
|
|
"(<real> <real> <bool> <bool>) and where "
|
||
|
|
"<face> is (<outercycle> <holecycle>*), "
|
||
|
|
"where <outercycle> and <holecycle> are "
|
||
|
|
"(<real> <real> <real> <real>), representing "
|
||
|
|
"start X, start Y, end X and end Y values.");
|
||
|
|
ListExpr example = nl->TextAtom();
|
||
|
|
nl->AppendText(example,
|
||
|
|
"(((0.0 10.0 TRUE TRUE)"
|
||
|
|
"((((1.0 3.5 1.5 1.5)"
|
||
|
|
"(2.0 5.5 3.0 4.5)"
|
||
|
|
"(3.0 6.5 3.5 5.0)"
|
||
|
|
"(4.0 6.5 5.5 5.0)"
|
||
|
|
"(4.0 5.5 5.5 4.5)"
|
||
|
|
"(5.0 4.5 7.5 2.5)"
|
||
|
|
"(5.0 2.5 7.5 1.0)"
|
||
|
|
"(4.0 1.5 7.0 0.5)"
|
||
|
|
"(3.0 1.5 2.5 0.5))"
|
||
|
|
"((2.0 3.0 3.0 2.0)"
|
||
|
|
"(2.0 4.0 3.0 3.0)"
|
||
|
|
"(3.0 4.0 4.0 3.0)"
|
||
|
|
"(3.0 3.0 4.0 2.0))))))");
|
||
|
|
|
||
|
|
return
|
||
|
|
nl->TwoElemList(
|
||
|
|
nl->FourElemList(
|
||
|
|
nl->StringAtom("Signature"),
|
||
|
|
nl->StringAtom("Example Type List"),
|
||
|
|
nl->StringAtom("List Rep"),
|
||
|
|
nl->StringAtom("Example List")),
|
||
|
|
nl->FourElemList(
|
||
|
|
nl->StringAtom("-> MAPPING"),
|
||
|
|
nl->StringAtom("(mregion)"),
|
||
|
|
listrep,
|
||
|
|
example));
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1 Function ~CheckMRegion()~
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
static bool CheckMRegion(ListExpr type, ListExpr& errorInfo) {
|
||
|
|
if (MRA_DEBUG) cerr << "CheckMRegion() called" << endl;
|
||
|
|
|
||
|
|
return nl->IsEqual(type, MRegion::BasicType())
|
||
|
|
|| nl->IsEqual(type, "movingregion");
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1 Function ~OutMRegion()~
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
ListExpr OutMRegion(ListExpr typeInfo, Word value) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "OutMRegion() called" << endl;
|
||
|
|
|
||
|
|
MRegion* mr = (MRegion*) value.addr;
|
||
|
|
|
||
|
|
// check for undefined value
|
||
|
|
if( !mr->IsDefined() ) return (nl->SymbolAtom(Symbol::UNDEFINED()));
|
||
|
|
|
||
|
|
if (mr->IsEmpty()) return (nl->TheEmptyList());
|
||
|
|
|
||
|
|
assert(mr->IsOrdered());
|
||
|
|
|
||
|
|
ListExpr l = nl->TheEmptyList();
|
||
|
|
ListExpr lastElem = l; /* CD: lastElem was uninitialized */
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "OutMRegion() #units=" << mr->GetNoComponents() << endl;
|
||
|
|
|
||
|
|
for (int i = 0; i < mr->GetNoComponents(); i++) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "OutMRegion() i=" << i << endl;
|
||
|
|
|
||
|
|
URegionEmb ur;
|
||
|
|
mr->Get(i, ur);
|
||
|
|
|
||
|
|
ListExpr unitList =
|
||
|
|
OutURegionEmbedded(
|
||
|
|
&ur,
|
||
|
|
(DbArray<MSegmentData>*) mr->GetFLOB(1));
|
||
|
|
|
||
|
|
if (l == nl->TheEmptyList()) {
|
||
|
|
l = nl->Cons(unitList, nl->TheEmptyList());
|
||
|
|
lastElem = l;
|
||
|
|
} else
|
||
|
|
lastElem = nl->Append(lastElem, unitList);
|
||
|
|
}
|
||
|
|
return l;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1 Function ~InMRegion()~
|
||
|
|
|
||
|
|
*/
|
||
|
|
Word InMRegion(const ListExpr typeInfo,
|
||
|
|
const ListExpr instance,
|
||
|
|
const int errorPos,
|
||
|
|
ListExpr& errorInfo,
|
||
|
|
bool& correct) {
|
||
|
|
if (MRA_DEBUG) cerr << "InMRegion() called" << endl;
|
||
|
|
|
||
|
|
MRegion* mr = new MRegion(0);
|
||
|
|
|
||
|
|
if ( listutils::isSymbolUndefined( instance ) )
|
||
|
|
{
|
||
|
|
mr->SetDefined(false);
|
||
|
|
correct = true;
|
||
|
|
return SetWord ( mr );
|
||
|
|
}
|
||
|
|
|
||
|
|
mr->StartBulkLoad();
|
||
|
|
|
||
|
|
ListExpr rest = instance;
|
||
|
|
while(!nl->IsEmpty(rest)) {
|
||
|
|
ListExpr first = nl->First(rest);
|
||
|
|
rest = nl->Rest(rest);
|
||
|
|
|
||
|
|
URegionEmb* ur =
|
||
|
|
(URegionEmb*) InURegionEmbedded(
|
||
|
|
first,
|
||
|
|
errorPos,
|
||
|
|
errorInfo,
|
||
|
|
&mr->msegmentdata,
|
||
|
|
mr->msegmentdata.Size());
|
||
|
|
if (!ur) {
|
||
|
|
correct = false;
|
||
|
|
mr->Destroy();
|
||
|
|
delete mr;
|
||
|
|
return SetWord(Address(0));
|
||
|
|
}
|
||
|
|
mr->Add(*ur);
|
||
|
|
delete ur;
|
||
|
|
}
|
||
|
|
|
||
|
|
mr->EndBulkLoad(true);
|
||
|
|
|
||
|
|
if (mr->IsValid()) {
|
||
|
|
correct = true;
|
||
|
|
return SetWord(mr);
|
||
|
|
} else {
|
||
|
|
correct = false;
|
||
|
|
mr->Destroy();
|
||
|
|
delete mr;
|
||
|
|
return SetWord(Address(0));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1 Function ~OpenMRegion()~
|
||
|
|
|
||
|
|
*/
|
||
|
|
bool OpenMRegion(SmiRecord& rec,
|
||
|
|
size_t& offset,
|
||
|
|
const ListExpr typeInfo,
|
||
|
|
Word& w) {
|
||
|
|
if (MRA_DEBUG) cerr << "OpenMRegion() called" << endl;
|
||
|
|
|
||
|
|
w = SetWord(Attribute::Open(rec, offset, typeInfo));
|
||
|
|
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1 Function ~SaveMRegion()~
|
||
|
|
|
||
|
|
*/
|
||
|
|
static bool SaveMRegion(SmiRecord& rec,
|
||
|
|
size_t& offset,
|
||
|
|
const ListExpr typeInfo,
|
||
|
|
Word& w) {
|
||
|
|
if (MRA_DEBUG) cerr << "SaveMRegion() called" << endl;
|
||
|
|
|
||
|
|
MRegion* mr = static_cast<MRegion*> (w.addr);
|
||
|
|
Attribute::Save(rec, offset, typeInfo, mr);
|
||
|
|
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1 Type constructor ~mregion~
|
||
|
|
|
||
|
|
*/
|
||
|
|
static Word CreateMRegion(const ListExpr typeInfo) {
|
||
|
|
if (MRA_DEBUG) cerr << "CreateMRegion() called" << endl;
|
||
|
|
return SetWord(new MRegion(0));
|
||
|
|
}
|
||
|
|
static void DeleteMRegion(const ListExpr typeInfo, Word& w) {
|
||
|
|
if (MRA_DEBUG) cerr << "DeleteMRegion() called" << endl;
|
||
|
|
((MRegion*) w.addr)->Destroy();
|
||
|
|
delete (MRegion*) w.addr;
|
||
|
|
w.addr = 0;
|
||
|
|
}
|
||
|
|
static void CloseMRegion(const ListExpr typeInfo, Word& w) {
|
||
|
|
if (MRA_DEBUG) cerr << "CloseMRegion() called" << endl;
|
||
|
|
delete (MRegion*) w.addr;
|
||
|
|
w.addr = 0;
|
||
|
|
}
|
||
|
|
static Word CloneMRegion(const ListExpr typeInfo, const Word& w) {
|
||
|
|
if (MRA_DEBUG) cerr << "CloneMRegion() called" << endl;
|
||
|
|
return SetWord(((MRegion*) w.addr)->Clone());
|
||
|
|
}
|
||
|
|
static void* CastMRegion(void* addr) {
|
||
|
|
if (MRA_DEBUG) cerr << "CastMRegion() called" << endl;
|
||
|
|
return new (addr) MRegion;
|
||
|
|
}
|
||
|
|
static int SizeOfMRegion() {
|
||
|
|
if (MRA_DEBUG) cerr << "SizeOfMRegion() called" << endl;
|
||
|
|
int s = sizeof(MRegion);
|
||
|
|
return s;
|
||
|
|
}
|
||
|
|
|
||
|
|
static TypeConstructor movingregion(
|
||
|
|
MRegion::BasicType(),
|
||
|
|
MRegionProperty,
|
||
|
|
OutMRegion,
|
||
|
|
InMRegion,
|
||
|
|
0, 0, // SaveToList, RestoreFromList
|
||
|
|
CreateMRegion, DeleteMRegion,
|
||
|
|
OpenMRegion, SaveMRegion,
|
||
|
|
CloseMRegion, CloneMRegion,
|
||
|
|
CastMRegion,
|
||
|
|
SizeOfMRegion,
|
||
|
|
CheckMRegion);
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1 Helper function(s)
|
||
|
|
|
||
|
|
Create ~MPoint~ instance from intervals in units in ~MRegion~ instance
|
||
|
|
~mr~ and the constant point ~p~.
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
static MPoint CreateMPointFromPoint(MRegion* mr, Point* p) {
|
||
|
|
if (MRA_DEBUG) cerr << "CreateMPointFromPoint() called" << endl;
|
||
|
|
|
||
|
|
MPoint mp(0);
|
||
|
|
if( !mr->IsDefined() || !p->IsDefined() ){
|
||
|
|
mp.SetDefined( false );
|
||
|
|
} else {
|
||
|
|
mp.SetDefined( true );
|
||
|
|
for (int i = 0; i < mr->GetNoComponents(); i++) {
|
||
|
|
URegionEmb ur;
|
||
|
|
|
||
|
|
mr->Get(i, ur);
|
||
|
|
|
||
|
|
UPoint up(ur.timeInterval,
|
||
|
|
p->GetX(), p->GetY(),
|
||
|
|
p->GetX(), p->GetY());
|
||
|
|
|
||
|
|
mp.Add(up);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return mp;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1 Operator definition
|
||
|
|
|
||
|
|
1.1 Type mapping functions
|
||
|
|
|
||
|
|
1.1.1 Generic
|
||
|
|
|
||
|
|
Used by ~intersection~:
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
static ListExpr MPointMRegionToMPointTypeMap(ListExpr args)
|
||
|
|
{
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
{
|
||
|
|
cerr << "MPointMRegionToMPointTypeMap() called" << endl;
|
||
|
|
cerr << nl->SymbolValue(nl->First(args)) << endl;
|
||
|
|
cerr << nl->SymbolValue(nl->Second(args)) << endl;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (nl->ListLength(args) == 2
|
||
|
|
&& nl->IsEqual(nl->First(args), MPoint::BasicType())
|
||
|
|
&& nl->IsEqual(nl->Second(args), MRegion::BasicType()))
|
||
|
|
return nl->SymbolAtom(MPoint::BasicType());
|
||
|
|
else
|
||
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
Used by ~inside~:
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
static ListExpr MPointMRegionToMBoolTypeMap(ListExpr args) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "MPointMRegionToMBoolTypeMap() called" << endl;
|
||
|
|
|
||
|
|
if (nl->ListLength(args) == 2
|
||
|
|
&& nl->IsEqual(nl->First(args), MPoint::BasicType())
|
||
|
|
&& nl->IsEqual(nl->Second(args), MRegion::BasicType()))
|
||
|
|
return nl->SymbolAtom(MBool::BasicType());
|
||
|
|
else
|
||
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
Used by ~initial~ and ~final~:
|
||
|
|
|
||
|
|
*/
|
||
|
|
static ListExpr MRegionToIRegionTypeMap(ListExpr args) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "MRegionToIRegionTypeMap() called" << endl;
|
||
|
|
|
||
|
|
if (nl->ListLength(args) == 1
|
||
|
|
&& nl->IsEqual(nl->First(args), MRegion::BasicType()))
|
||
|
|
return nl->SymbolAtom(IRegion::BasicType());
|
||
|
|
else
|
||
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
Used by ~deftime~:
|
||
|
|
|
||
|
|
*/
|
||
|
|
static ListExpr MRegionToPeriodsTypeMap(ListExpr args) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "MRegionToPeriodsTypeMap() called" << endl;
|
||
|
|
|
||
|
|
if (nl->ListLength(args) == 1
|
||
|
|
&& nl->IsEqual(nl->First(args), MRegion::BasicType()))
|
||
|
|
return nl->SymbolAtom(Range<Instant>::BasicType());
|
||
|
|
else
|
||
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
Used by ~inst~:
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
static ListExpr IRegionToInstantTypeMap(ListExpr args) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "IRegionToInstantTypeMap() called" << endl;
|
||
|
|
|
||
|
|
if (nl->ListLength(args) == 1
|
||
|
|
&& nl->IsEqual(nl->First(args), IRegion::BasicType()))
|
||
|
|
return nl->SymbolAtom(Instant::BasicType());
|
||
|
|
else
|
||
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
Used by ~val~:
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
static ListExpr IRegionToRegionTypeMap(ListExpr args) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "IRegionToRegionTypeMap() called" << endl;
|
||
|
|
|
||
|
|
if (nl->ListLength(args) == 1
|
||
|
|
&& nl->IsEqual(nl->First(args), IRegion::BasicType()))
|
||
|
|
return nl->SymbolAtom(Region::BasicType());
|
||
|
|
else
|
||
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
Used by ~traversed~:
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
#ifdef MRA_TRAVERSED
|
||
|
|
static ListExpr MRegionToRegionTypeMap(ListExpr args) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "MRegionToRegionTypeMap() called" << endl;
|
||
|
|
|
||
|
|
if (nl->ListLength(args) == 1
|
||
|
|
&& nl->IsEqual(nl->First(args), MRegion::BasicType()))
|
||
|
|
return nl->SymbolAtom(Region::BasicType());
|
||
|
|
else
|
||
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
||
|
|
}
|
||
|
|
#endif // MRA_TRAVERSED
|
||
|
|
|
||
|
|
/*
|
||
|
|
|
||
|
|
1.1.1 Operator specific
|
||
|
|
|
||
|
|
Used by ~present~:
|
||
|
|
|
||
|
|
*/
|
||
|
|
static ListExpr PresentTypeMap(ListExpr args) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "PresentTypeMap() called" << endl;
|
||
|
|
|
||
|
|
if (nl->ListLength(args) == 2
|
||
|
|
&& nl->IsEqual(nl->First(args), MRegion::BasicType())
|
||
|
|
&& (nl->IsEqual(nl->Second(args), Instant::BasicType())
|
||
|
|
|| nl->IsEqual(nl->Second(args), Range<Instant>::BasicType())))
|
||
|
|
return nl->SymbolAtom(CcBool::BasicType());
|
||
|
|
else
|
||
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
|
||
|
|
Used by ~at~:
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
static ListExpr AtTypeMap(ListExpr args) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "AtTypeMap() called" << endl;
|
||
|
|
|
||
|
|
if (nl->ListLength(args) == 2
|
||
|
|
&& nl->IsEqual(nl->First(args), MPoint::BasicType())
|
||
|
|
&& nl->IsEqual(nl->Second(args), Region::BasicType()))
|
||
|
|
return nl->SymbolAtom(MPoint::BasicType());
|
||
|
|
else if (nl->ListLength(args) == 2
|
||
|
|
&& nl->IsEqual(nl->First(args), MRegion::BasicType())
|
||
|
|
&& nl->IsEqual(nl->Second(args), Point::BasicType()))
|
||
|
|
return nl->SymbolAtom(MPoint::BasicType());
|
||
|
|
else
|
||
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
|
||
|
|
used by addURegion
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
ListExpr AddTypeMap( ListExpr args )
|
||
|
|
{
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "AddTypeMap() called" << endl;
|
||
|
|
|
||
|
|
if (nl->ListLength(args) == 2
|
||
|
|
&& nl->IsEqual(nl->First(args), MRegion::BasicType())
|
||
|
|
&& nl->IsEqual(nl->Second(args), URegion::BasicType()))
|
||
|
|
return nl->SymbolAtom(MRegion::BasicType());
|
||
|
|
else
|
||
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
Used by ~union~:
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
static ListExpr UnionTypeMap(ListExpr args) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "UnionTypeMap() called" << endl;
|
||
|
|
|
||
|
|
if (nl->ListLength(args) == 2
|
||
|
|
&& nl->IsEqual(nl->First(args), URegion::BasicType())
|
||
|
|
&& nl->IsEqual(nl->Second(args), URegion::BasicType()))
|
||
|
|
return nl->SymbolAtom(URegion::BasicType());
|
||
|
|
else
|
||
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
Used by ~atinstant~:
|
||
|
|
|
||
|
|
*/
|
||
|
|
static ListExpr AtInstantTypeMap(ListExpr args) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "AtInstantTypeMap() called" << endl;
|
||
|
|
|
||
|
|
if (nl->ListLength(args) == 2
|
||
|
|
&& nl->IsEqual(nl->First(args), MRegion::BasicType())
|
||
|
|
&& nl->IsEqual(nl->Second(args), Instant::BasicType()))
|
||
|
|
return nl->SymbolAtom(IRegion::BasicType());
|
||
|
|
else if (nl->ListLength(args) == 2
|
||
|
|
&& nl->IsEqual(nl->First(args), URegion::BasicType())
|
||
|
|
&& nl->IsEqual(nl->Second(args), Instant::BasicType()))
|
||
|
|
return nl->SymbolAtom(IRegion::BasicType());
|
||
|
|
else
|
||
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
Used by ~mraprec~:
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
#ifdef MRA_PREC
|
||
|
|
static ListExpr MraprecTypeMap(ListExpr args) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "MraprecTypeMap() called" << endl;
|
||
|
|
|
||
|
|
if (nl->ListLength(args) == 2
|
||
|
|
&& nl->IsEqual(nl->First(args), CcReal::BasicType())
|
||
|
|
&& nl->IsEqual(nl->Second(args), CcReal::BasicType()))
|
||
|
|
return nl->SymbolAtom(CcBool::BasicType());
|
||
|
|
else
|
||
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
||
|
|
}
|
||
|
|
#endif // MRA_PREC
|
||
|
|
|
||
|
|
/*
|
||
|
|
Type mapping of the ~move~ operator:
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
static ListExpr MoveTypeMap(ListExpr args){
|
||
|
|
if (MRA_DEBUG) cout << "MOveTypeMap called " << endl;
|
||
|
|
if(nl->ListLength(args)!=2){
|
||
|
|
ErrorReporter::ReportError("invalid number of arguments");
|
||
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
||
|
|
}
|
||
|
|
if(!nl->IsEqual(nl->First(args),MPoint::BasicType())){
|
||
|
|
ErrorReporter::ReportError("mpoint as first argument required");
|
||
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
||
|
|
}
|
||
|
|
if(!nl->IsEqual(nl->Second(args),Region::BasicType())){
|
||
|
|
ErrorReporter::ReportError("region as second argument required");
|
||
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
||
|
|
}
|
||
|
|
if (MRA_DEBUG) cout << "Typemap returns mregion" << endl;
|
||
|
|
return nl->SymbolAtom(MRegion::BasicType());
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
Used by ~bbox~:
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
static ListExpr BboxTypeMap(ListExpr args) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "BboxTypeMap() called" << endl;
|
||
|
|
|
||
|
|
if (nl->ListLength(args) == 1
|
||
|
|
&& nl->IsEqual(nl->First(args), URegion::BasicType()))
|
||
|
|
return nl->SymbolAtom(Rectangle<3>::BasicType());
|
||
|
|
|
||
|
|
if (nl->ListLength(args) == 1
|
||
|
|
&& nl->IsEqual(nl->First(args), IRegion::BasicType()))
|
||
|
|
return nl->SymbolAtom(Rectangle<3>::BasicType());
|
||
|
|
|
||
|
|
if (nl->ListLength(args) == 1
|
||
|
|
&& nl->IsEqual(nl->First(args), MRegion::BasicType()))
|
||
|
|
return nl->SymbolAtom(Rectangle<3>::BasicType());
|
||
|
|
|
||
|
|
else
|
||
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
Used by ~bbox2d~:
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
static ListExpr Bbox2dTypeMap(ListExpr args) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "Bbox2dTypeMap() called" << endl;
|
||
|
|
|
||
|
|
if (nl->ListLength(args) == 1
|
||
|
|
&& nl->IsEqual(nl->First(args), URegion::BasicType()))
|
||
|
|
return nl->SymbolAtom(Rectangle<2>::BasicType());
|
||
|
|
|
||
|
|
if (nl->ListLength(args) == 1
|
||
|
|
&& nl->IsEqual(nl->First(args), IRegion::BasicType()))
|
||
|
|
return nl->SymbolAtom(Rectangle<2>::BasicType());
|
||
|
|
|
||
|
|
if (nl->ListLength(args) == 1
|
||
|
|
&& nl->IsEqual(nl->First(args), MRegion::BasicType()))
|
||
|
|
return nl->SymbolAtom(Rectangle<2>::BasicType());
|
||
|
|
|
||
|
|
else
|
||
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
Type mapping of the ~vertextrajectory~ operator:
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
static ListExpr VertTrajectoryTypeMap(ListExpr args){
|
||
|
|
if(nl->ListLength(args)!=1){
|
||
|
|
ErrorReporter::ReportError("wrong number of arguments");
|
||
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
||
|
|
}
|
||
|
|
ListExpr arg = nl->First(args);
|
||
|
|
if(nl->IsEqual(arg,URegion::BasicType())
|
||
|
|
|| nl->IsEqual(arg,MRegion::BasicType())){
|
||
|
|
return nl->SymbolAtom(Line::BasicType());
|
||
|
|
}
|
||
|
|
ErrorReporter::ReportError("uregion or mregion"
|
||
|
|
" expected but got ");
|
||
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/*
|
||
|
|
Type mapping for the ~units~ operator:
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
ListExpr MRAUnitsTypeMap( ListExpr args )
|
||
|
|
{
|
||
|
|
if ( nl->ListLength(args) == 1 )
|
||
|
|
{
|
||
|
|
ListExpr arg1 = nl->First(args);
|
||
|
|
|
||
|
|
if( nl->IsEqual( arg1, MRegion::BasicType() ) )
|
||
|
|
return nl->TwoElemList(nl->SymbolAtom(Symbol::STREAM()),
|
||
|
|
nl->SymbolAtom(URegion::BasicType()));
|
||
|
|
|
||
|
|
}
|
||
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
Type mapping for the ~timsshift~ operator:
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
ListExpr MRegTimeShiftTM( ListExpr args )
|
||
|
|
{
|
||
|
|
if ( nl->ListLength( args ) == 2 )
|
||
|
|
{
|
||
|
|
ListExpr arg1 = nl->First( args ),
|
||
|
|
arg2 = nl->Second( args );
|
||
|
|
|
||
|
|
if( nl->IsEqual( arg2, Duration::BasicType() ) )
|
||
|
|
{
|
||
|
|
if( nl->IsEqual( arg1, MRegion::BasicType() ) )
|
||
|
|
return nl->SymbolAtom( MRegion::BasicType() );
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return nl->SymbolAtom( Symbol::TYPEERROR() );
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1 For unit testing operators
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
#ifdef MRA_UNITTEST
|
||
|
|
static ListExpr Unittest1TypeMap(ListExpr args) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "Unittest1TypeMap() called" << endl;
|
||
|
|
|
||
|
|
if (nl->ListLength(args) != 17)
|
||
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
||
|
|
|
||
|
|
for (; !nl->IsEmpty(args); args = nl->Rest(args))
|
||
|
|
if (nl->SymbolValue(nl->First(args)) != CcReal::BasicType())
|
||
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
||
|
|
|
||
|
|
return nl->SymbolAtom(CcInt::BasicType());
|
||
|
|
}
|
||
|
|
|
||
|
|
static ListExpr Unittest2TypeMap(ListExpr args) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "Unittest2TypeMap() called" << endl;
|
||
|
|
|
||
|
|
if (nl->ListLength(args) == 2
|
||
|
|
&& nl->IsEqual(nl->First(args), MRegion::BasicType())
|
||
|
|
&& nl->IsEqual(nl->Second(args), CcInt::BasicType()))
|
||
|
|
return nl->SymbolAtom(CcBool::BasicType());
|
||
|
|
else
|
||
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
||
|
|
}
|
||
|
|
|
||
|
|
static ListExpr Unittest3TypeMap(ListExpr args) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "Unittest3TypeMap() called" << endl;
|
||
|
|
|
||
|
|
if (nl->ListLength(args) == 2
|
||
|
|
&& nl->IsEqual(nl->First(args), MPoint::BasicType())
|
||
|
|
&& nl->IsEqual(nl->Second(args), MPoint::BasicType()))
|
||
|
|
return nl->SymbolAtom(Range<CcReal>::BasicType());
|
||
|
|
else
|
||
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
||
|
|
}
|
||
|
|
#endif // MRA_UNITTEST
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1 Selection functions
|
||
|
|
|
||
|
|
1.1.1 Generic
|
||
|
|
|
||
|
|
Used by ~intersection~ and ~inside~:
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
static int MPointMRegionSelect(ListExpr args) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "MPointMRegionSelect() called" << endl;
|
||
|
|
|
||
|
|
if (nl->ListLength(args) == 2
|
||
|
|
&& nl->SymbolValue(nl->First(args)) == MPoint::BasicType()
|
||
|
|
&& nl->SymbolValue(nl->Second(args)) == MRegion::BasicType())
|
||
|
|
return 0;
|
||
|
|
else
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
Used by ~initial~, ~final~, ~deftime~ and ~traversed~:
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
static int MRegionSelect(ListExpr args) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "MRegionSelect() called" << endl;
|
||
|
|
|
||
|
|
if (nl->ListLength(args) == 1
|
||
|
|
&& nl->SymbolValue(nl->First(args)) == MRegion::BasicType())
|
||
|
|
return 0;
|
||
|
|
else
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
Used by ~inst~ and ~val~:
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
static int IRegionSelect(ListExpr args) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "IRegionSelect() called" << endl;
|
||
|
|
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "IRegionSelect() len="
|
||
|
|
<< nl->ListLength(args)
|
||
|
|
<< endl;
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "IRegionSelect() symbolvalue(first)="
|
||
|
|
<< nl->SymbolValue(nl->First(args))
|
||
|
|
<< endl;
|
||
|
|
|
||
|
|
if (nl->ListLength(args) == 1
|
||
|
|
&& nl->SymbolValue(nl->First(args)) == IRegion::BasicType())
|
||
|
|
return 0;
|
||
|
|
else
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1 Operator specific
|
||
|
|
|
||
|
|
For ~present~:
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
static int PresentSelect(ListExpr args) {
|
||
|
|
if (MRA_DEBUG) cerr << "PresentSelect() called" << endl;
|
||
|
|
|
||
|
|
if (nl->ListLength(args) == 2
|
||
|
|
&& nl->SymbolValue(nl->First(args)) == MRegion::BasicType()
|
||
|
|
&& nl->SymbolValue(nl->Second(args)) == Instant::BasicType())
|
||
|
|
return 0;
|
||
|
|
else if (nl->ListLength(args) == 2
|
||
|
|
&& nl->SymbolValue(nl->First(args)) == MRegion::BasicType()
|
||
|
|
&& nl->SymbolValue(nl->Second(args)) == Range<Instant>::BasicType())
|
||
|
|
return 1;
|
||
|
|
else
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
For ~at~:
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
static int AtSelect(ListExpr args) {
|
||
|
|
if (MRA_DEBUG) cerr << "AtSelect() called" << endl;
|
||
|
|
|
||
|
|
if (nl->ListLength(args) == 2
|
||
|
|
&& nl->SymbolValue(nl->First(args)) == MPoint::BasicType()
|
||
|
|
&& nl->SymbolValue(nl->Second(args)) == Region::BasicType())
|
||
|
|
return 0;
|
||
|
|
else if (nl->ListLength(args) == 2
|
||
|
|
&& nl->SymbolValue(nl->First(args)) == MRegion::BasicType()
|
||
|
|
&& nl->SymbolValue(nl->Second(args)) == Point::BasicType())
|
||
|
|
return 1;
|
||
|
|
else
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
Used by ~atinstant~:
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
static int AtInstantSelect(ListExpr args) {
|
||
|
|
if (MRA_DEBUG)
|
||
|
|
cerr << "AtInstantSelect() called" << endl;
|
||
|
|
|
||
|
|
if (nl->ListLength(args) == 2
|
||
|
|
&& nl->SymbolValue(nl->First(args)) == MRegion::BasicType()
|
||
|
|
&& nl->SymbolValue(nl->Second(args)) == Instant::BasicType())
|
||
|
|
return 0;
|
||
|
|
else if (nl->ListLength(args) == 2
|
||
|
|
&& nl->SymbolValue(nl->First(args)) == URegion::BasicType()
|
||
|
|
&& nl->SymbolValue(nl->Second(args)) == Instant::BasicType())
|
||
|
|
return 1;
|
||
|
|
else
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
Used by ~vertrajectory~:
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
static int VertTrajectorySelect(ListExpr args){
|
||
|
|
ListExpr arg = nl->First(args);
|
||
|
|
if(nl->IsEqual(arg,URegion::BasicType()))
|
||
|
|
return 0;
|
||
|
|
else
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
Used by ~bbox~ and ~bbox2d~:
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
static int BBoxSelect(ListExpr args){
|
||
|
|
ListExpr arg = nl->First(args);
|
||
|
|
if(nl->IsEqual(arg,URegion::BasicType()))
|
||
|
|
return 0;
|
||
|
|
if(nl->IsEqual(arg,IRegion::BasicType()))
|
||
|
|
return 1;
|
||
|
|
if(nl->IsEqual(arg,MRegion::BasicType()))
|
||
|
|
return 2;
|
||
|
|
else
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1 Value mapping functions
|
||
|
|
|
||
|
|
1.1.1 Normal value mapping functions
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
static int IntersectionValueMap(Word* args,
|
||
|
|
Word& result,
|
||
|
|
int message,
|
||
|
|
Word& local,
|
||
|
|
Supplier s) {
|
||
|
|
if (MRA_DEBUG) cerr << "IntersectionValueMap() called" << endl;
|
||
|
|
|
||
|
|
result = qp->ResultStorage(s);
|
||
|
|
MPoint* res = (MPoint*) result.addr;
|
||
|
|
|
||
|
|
try {
|
||
|
|
MPoint* mp = (MPoint*) args[0].addr;
|
||
|
|
MRegion* mr = (MRegion*) args[1].addr;
|
||
|
|
|
||
|
|
if (!mp->IsDefined() || !mr->IsDefined()){
|
||
|
|
res->Clear();
|
||
|
|
res->SetDefined(false);
|
||
|
|
} else
|
||
|
|
mr->Intersection(*mp, *res);
|
||
|
|
} catch (invalid_argument& e) {
|
||
|
|
cerr << "-----------------------------------------------------------"
|
||
|
|
<< endl
|
||
|
|
<< "An error occured during the intersection operation:"
|
||
|
|
<< endl
|
||
|
|
<< e.what()
|
||
|
|
<< endl
|
||
|
|
<< "-----------------------------------------------------------"
|
||
|
|
<< endl;
|
||
|
|
res->SetDefined(false);
|
||
|
|
}
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
static int InsideValueMap(Word* args,
|
||
|
|
Word& result,
|
||
|
|
int message,
|
||
|
|
Word& local,
|
||
|
|
Supplier s) {
|
||
|
|
if (MRA_DEBUG) cerr << "InsideValueMap() called" << endl;
|
||
|
|
|
||
|
|
result = qp->ResultStorage(s);
|
||
|
|
MBool* res = (MBool*) result.addr;
|
||
|
|
|
||
|
|
try {
|
||
|
|
MPoint* mp = (MPoint*) args[0].addr;
|
||
|
|
MRegion* mr = (MRegion*) args[1].addr;
|
||
|
|
|
||
|
|
if (!mp->IsDefined() || !mr->IsDefined()){
|
||
|
|
res->Clear();
|
||
|
|
res->SetDefined(false);
|
||
|
|
} else
|
||
|
|
mr->Inside(*mp, *res);
|
||
|
|
} catch (invalid_argument& e) {
|
||
|
|
cerr << "-----------------------------------------------------------"
|
||
|
|
<< endl
|
||
|
|
<< "An error occured during the inside operation:"
|
||
|
|
<< endl
|
||
|
|
<< e.what()
|
||
|
|
<< endl
|
||
|
|
<< "-----------------------------------------------------------"
|
||
|
|
<< endl;
|
||
|
|
((MBool*) result.addr)->SetDefined(false);
|
||
|
|
}
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
// old implementation creates a MRegion:
|
||
|
|
/*
|
||
|
|
static int AtValueMap_MPointOld(Word* args,
|
||
|
|
Word& result,
|
||
|
|
int message,
|
||
|
|
Word& local,
|
||
|
|
Supplier s) {
|
||
|
|
if (MRA_DEBUG) cerr << "AtValueMap_MPoint() called" << endl;
|
||
|
|
|
||
|
|
result = qp->ResultStorage(s);
|
||
|
|
MPoint* res = (MPoint*) result.addr;
|
||
|
|
res->Clear();
|
||
|
|
res->SetDefined(true);
|
||
|
|
|
||
|
|
try {
|
||
|
|
MPoint* mp = (MPoint*) args[0].addr;
|
||
|
|
Region* r = (Region*) args[1].addr;
|
||
|
|
|
||
|
|
if (!mp->IsDefined() || !r->IsDefined()){
|
||
|
|
res->Clear();
|
||
|
|
res->SetDefined(false);
|
||
|
|
} else {
|
||
|
|
MRegion* mr = new MRegion(*mp, *r);
|
||
|
|
|
||
|
|
mr->Intersection(*mp, *res);
|
||
|
|
mr->DeleteIfAllowed();
|
||
|
|
}
|
||
|
|
} catch (invalid_argument& e) {
|
||
|
|
cerr << "-----------------------------------------------------------"
|
||
|
|
<< endl
|
||
|
|
<< "An error occured during the at operation:"
|
||
|
|
<< endl
|
||
|
|
<< e.what()
|
||
|
|
<< endl
|
||
|
|
<< "-----------------------------------------------------------"
|
||
|
|
<< endl;
|
||
|
|
((MPoint*) result.addr)->SetDefined(false);
|
||
|
|
}
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
*/
|
||
|
|
|
||
|
|
// new implementation calls specialized member of class MPoint:
|
||
|
|
static int AtValueMap_MPoint(Word* args,
|
||
|
|
Word& result,
|
||
|
|
int message,
|
||
|
|
Word& local,
|
||
|
|
Supplier s) {
|
||
|
|
if (MRA_DEBUG) cerr << __PRETTY_FUNCTION__ << "(...) called" << endl;
|
||
|
|
|
||
|
|
result = qp->ResultStorage(s);
|
||
|
|
MPoint* res = static_cast<MPoint*>(result.addr);
|
||
|
|
res->Clear();
|
||
|
|
try {
|
||
|
|
MPoint* mp = static_cast<MPoint*>(args[0].addr);
|
||
|
|
Region* r = static_cast<Region*>(args[1].addr);
|
||
|
|
mp->AtRegion(r, *res);
|
||
|
|
} catch (invalid_argument& e) {
|
||
|
|
cerr << "-----------------------------------------------------------"
|
||
|
|
<< endl
|
||
|
|
<< "An error occured during the at operation:"
|
||
|
|
<< endl
|
||
|
|
<< e.what()
|
||
|
|
<< endl
|
||
|
|
<< "-----------------------------------------------------------"
|
||
|
|
<< endl;
|
||
|
|
res->SetDefined(false);
|
||
|
|
}
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
static int AtValueMap_MRegion(Word* args,
|
||
|
|
Word& result,
|
||
|
|
int message,
|
||
|
|
Word& local,
|
||
|
|
Supplier s) {
|
||
|
|
if (MRA_DEBUG) cerr << "AtValueMap_MRegion() called" << endl;
|
||
|
|
|
||
|
|
result = qp->ResultStorage(s);
|
||
|
|
MPoint* res = (MPoint*) result.addr;
|
||
|
|
res->Clear();
|
||
|
|
res->SetDefined(true);
|
||
|
|
|
||
|
|
try {
|
||
|
|
MRegion* mr = (MRegion*) args[0].addr;
|
||
|
|
Point* p = (Point*) args[1].addr;
|
||
|
|
|
||
|
|
if (!mr->IsDefined() || !p->IsDefined()){
|
||
|
|
res->Clear();
|
||
|
|
res->SetDefined(false);
|
||
|
|
} else {
|
||
|
|
MPoint mp = CreateMPointFromPoint(mr, p);
|
||
|
|
|
||
|
|
mr->Intersection(mp, *res);
|
||
|
|
}
|
||
|
|
} catch (invalid_argument& e) {
|
||
|
|
cerr << "-----------------------------------------------------------"
|
||
|
|
<< endl
|
||
|
|
<< "An error occured during the at operation:"
|
||
|
|
<< endl
|
||
|
|
<< e.what()
|
||
|
|
<< endl
|
||
|
|
<< "-----------------------------------------------------------"
|
||
|
|
<< endl;
|
||
|
|
((MPoint*) result.addr)->SetDefined(false);
|
||
|
|
}
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
static int AtInstantValueMap_URegion(Word* args,
|
||
|
|
Word& result,
|
||
|
|
int message,
|
||
|
|
Word& local,
|
||
|
|
Supplier s) {
|
||
|
|
if (MRA_DEBUG) cerr << "AtInstantValueMap_URegion() called" << endl;
|
||
|
|
|
||
|
|
result = qp->ResultStorage(s);
|
||
|
|
Intime<Region>* res = (Intime<Region>*) result.addr;
|
||
|
|
URegion* ur = (URegion*) args[0].addr;
|
||
|
|
Instant* inst = (Instant*) args[1].addr;
|
||
|
|
|
||
|
|
if (ur->IsDefined() && ur->timeInterval.Contains(*inst)) {
|
||
|
|
ur->TemporalFunction(*inst, res->value);
|
||
|
|
res->instant.CopyFrom(inst);
|
||
|
|
res->SetDefined(true);
|
||
|
|
} else {
|
||
|
|
res->SetDefined(false);
|
||
|
|
}
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
#ifdef MRA_TRAVERSED
|
||
|
|
static int TraversedValueMap(Word* args,
|
||
|
|
Word& result,
|
||
|
|
int message,
|
||
|
|
Word& local,
|
||
|
|
Supplier s) {
|
||
|
|
if (MRA_DEBUG) cerr << "TraversedValueMap() called" << endl;
|
||
|
|
|
||
|
|
result = qp->ResultStorage(s);
|
||
|
|
Region* res = (Region*) result.addr;
|
||
|
|
|
||
|
|
MRegion* mr = (MRegion*) args[0].addr;
|
||
|
|
|
||
|
|
if (!mr->IsDefined())
|
||
|
|
res->SetDefined(false);
|
||
|
|
else
|
||
|
|
mr->Traversed(*res);
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
#endif // MRA_TRAVERSED
|
||
|
|
|
||
|
|
#ifdef MRA_PREC
|
||
|
|
static int MraprecValueMap(Word* args,
|
||
|
|
Word& result,
|
||
|
|
int message,
|
||
|
|
Word& local,
|
||
|
|
Supplier s) {
|
||
|
|
if (MRA_DEBUG) cerr << "MraprecValueMap() called" << endl;
|
||
|
|
|
||
|
|
result = qp->ResultStorage(s);
|
||
|
|
CcBool* res = (CcBool*) result.addr;
|
||
|
|
|
||
|
|
CcReal* r1 = (CcReal*) args[0].addr;
|
||
|
|
CcReal* r2 = (CcReal*) args[1].addr;
|
||
|
|
|
||
|
|
if (!r1->IsDefined() || !r2->IsDefined())
|
||
|
|
res->SetDefined(false);
|
||
|
|
else {
|
||
|
|
eps = r1->GetRealval();
|
||
|
|
epsRelaxFactor = r2->GetRealval();
|
||
|
|
res->Set(true, true);
|
||
|
|
}
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
#endif // MRA_PREC
|
||
|
|
|
||
|
|
static int BboxValueMapURegion(Word* args,
|
||
|
|
Word& result,
|
||
|
|
int message,
|
||
|
|
Word& local,
|
||
|
|
Supplier s) {
|
||
|
|
if (MRA_DEBUG) cerr << "BBox() called" << endl;
|
||
|
|
|
||
|
|
result = qp->ResultStorage(s);
|
||
|
|
Rectangle<3>* res = (Rectangle<3>*) result.addr;
|
||
|
|
|
||
|
|
URegion* ur = (URegion*) args[0].addr;
|
||
|
|
|
||
|
|
if (!ur->IsDefined())
|
||
|
|
res->SetDefined(false);
|
||
|
|
else
|
||
|
|
*res = ur->BoundingBox();
|
||
|
|
|
||
|
|
return (0);
|
||
|
|
}
|
||
|
|
|
||
|
|
static int BboxValueMapIRegion(Word* args,
|
||
|
|
Word& result,
|
||
|
|
int message,
|
||
|
|
Word& local,
|
||
|
|
Supplier s) {
|
||
|
|
if (MRA_DEBUG) cerr << "BBox() called" << endl;
|
||
|
|
|
||
|
|
result = qp->ResultStorage(s);
|
||
|
|
Rectangle<3>* res = (Rectangle<3>*) result.addr;
|
||
|
|
|
||
|
|
Intime<Region>* ur = (Intime<Region>*) args[0].addr;
|
||
|
|
|
||
|
|
if (!ur->IsDefined())
|
||
|
|
res->SetDefined(false);
|
||
|
|
else
|
||
|
|
{
|
||
|
|
Rectangle<2> r = ur->value.BoundingBox();
|
||
|
|
double min[3], max[3];
|
||
|
|
min[0] = r.MinD(0);
|
||
|
|
min[1] = r.MinD(1);
|
||
|
|
min[2] = ur->instant.ToDouble();
|
||
|
|
max[0] = r.MaxD(0);
|
||
|
|
max[1] = r.MaxD(1);
|
||
|
|
max[2] = min[2];
|
||
|
|
res->Set(true, min, max);
|
||
|
|
}
|
||
|
|
return (0);
|
||
|
|
}
|
||
|
|
|
||
|
|
static int BboxValueMapMRegion(Word* args,
|
||
|
|
Word& result,
|
||
|
|
int message,
|
||
|
|
Word& local,
|
||
|
|
Supplier s) {
|
||
|
|
if (MRA_DEBUG) cerr << "BBox() called" << endl;
|
||
|
|
result = qp->ResultStorage(s);
|
||
|
|
Rectangle<3>* res = (Rectangle<3>*) result.addr;
|
||
|
|
MRegion* mr = (MRegion*) args[0].addr;
|
||
|
|
*res = mr->BoundingBox();
|
||
|
|
return (0);
|
||
|
|
}
|
||
|
|
|
||
|
|
static int Bbox2dValueMapURegion(Word* args,
|
||
|
|
Word& result,
|
||
|
|
int message,
|
||
|
|
Word& local,
|
||
|
|
Supplier s) {
|
||
|
|
if (MRA_DEBUG) cerr << "BBox2d() called" << endl;
|
||
|
|
|
||
|
|
result = qp->ResultStorage(s);
|
||
|
|
Rectangle<2>* res = (Rectangle<2>*) result.addr;
|
||
|
|
|
||
|
|
URegion* ur = (URegion*) args[0].addr;
|
||
|
|
|
||
|
|
if (!ur->IsDefined())
|
||
|
|
res->SetDefined(false);
|
||
|
|
else
|
||
|
|
{
|
||
|
|
Rectangle<3> bb3 = ur->BoundingBox();
|
||
|
|
double min[2] = {bb3.MinD(0), bb3.MinD(1)};
|
||
|
|
double max[2] = {bb3.MaxD(0), bb3.MaxD(1)};
|
||
|
|
res->Set( true, min, max );
|
||
|
|
}
|
||
|
|
return (0);
|
||
|
|
}
|
||
|
|
|
||
|
|
static int Bbox2dValueMapIRegion(Word* args,
|
||
|
|
Word& result,
|
||
|
|
int message,
|
||
|
|
Word& local,
|
||
|
|
Supplier s) {
|
||
|
|
if (MRA_DEBUG) cerr << "BBox2d() called" << endl;
|
||
|
|
|
||
|
|
result = qp->ResultStorage(s);
|
||
|
|
Rectangle<2>* res = (Rectangle<2>*) result.addr;
|
||
|
|
|
||
|
|
Intime<Region>* ur = (Intime<Region>*) args[0].addr;
|
||
|
|
|
||
|
|
if (!ur->IsDefined())
|
||
|
|
res->SetDefined(false);
|
||
|
|
else
|
||
|
|
{
|
||
|
|
res->SetDefined(true);
|
||
|
|
*res = ur->value.BoundingBox();
|
||
|
|
}
|
||
|
|
return (0);
|
||
|
|
}
|
||
|
|
|
||
|
|
static int Bbox2dValueMapMRegion(Word* args,
|
||
|
|
Word& result,
|
||
|
|
int message,
|
||
|
|
Word& local,
|
||
|
|
Supplier s) {
|
||
|
|
if (MRA_DEBUG) cerr << "BBox2d() called" << endl;
|
||
|
|
|
||
|
|
result = qp->ResultStorage(s);
|
||
|
|
Rectangle<2>* res = (Rectangle<2>*) result.addr;
|
||
|
|
|
||
|
|
MRegion* mr = (MRegion*) args[0].addr;
|
||
|
|
|
||
|
|
if (!mr->IsDefined() || (mr->GetNoComponents() < 1) )
|
||
|
|
res->SetDefined(false);
|
||
|
|
else
|
||
|
|
{
|
||
|
|
res->SetDefined(true);
|
||
|
|
URegionEmb ur;
|
||
|
|
mr->Get(0, ur);
|
||
|
|
Rectangle<3> bb3 = ur.BoundingBox();
|
||
|
|
for(int i=1; i<mr->GetNoComponents(); i++)
|
||
|
|
{
|
||
|
|
mr->Get(i, ur);
|
||
|
|
bb3 = bb3.Union( ur.BoundingBox() );
|
||
|
|
}
|
||
|
|
double min[2] = {bb3.MinD(0), bb3.MinD(1)};
|
||
|
|
double max[2] = {bb3.MaxD(0), bb3.MaxD(1)};
|
||
|
|
res->Set( true, min, max );
|
||
|
|
}
|
||
|
|
return (0);
|
||
|
|
}
|
||
|
|
|
||
|
|
static int MoveValueMap(Word* args,
|
||
|
|
Word& result,
|
||
|
|
int message,
|
||
|
|
Word& local,
|
||
|
|
Supplier s) {
|
||
|
|
result = qp->ResultStorage(s);
|
||
|
|
MPoint* mp = (MPoint* ) args[0].addr;
|
||
|
|
Region* reg = (Region*) args[1].addr;
|
||
|
|
MRegion res(*mp,*reg,0);
|
||
|
|
((MRegion*)result.addr)->CopyFrom(&res);
|
||
|
|
res.Destroy();
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
Value mapping functions of operator ~units~
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
struct MRAUnitsLocalInfo
|
||
|
|
{
|
||
|
|
Word mWord; // the address of the moving point/int/real value
|
||
|
|
int unitIndex; // current item index
|
||
|
|
};
|
||
|
|
|
||
|
|
int mraunitsvalmap(Word* args, Word& result,
|
||
|
|
int message, Word& local, Supplier s)
|
||
|
|
{
|
||
|
|
MRegion* m;
|
||
|
|
URegion* unit;
|
||
|
|
MRAUnitsLocalInfo *localinfo;
|
||
|
|
|
||
|
|
switch( message )
|
||
|
|
{
|
||
|
|
case OPEN:
|
||
|
|
m = static_cast<MRegion*>(args[0].addr);
|
||
|
|
if(m->IsDefined()){
|
||
|
|
localinfo = new MRAUnitsLocalInfo;
|
||
|
|
localinfo->mWord = args[0];
|
||
|
|
localinfo->unitIndex = 0;
|
||
|
|
local = SetWord(localinfo);
|
||
|
|
} else {
|
||
|
|
local.setAddr( 0 );
|
||
|
|
}
|
||
|
|
return 0;
|
||
|
|
|
||
|
|
case REQUEST:
|
||
|
|
|
||
|
|
if( local.addr == 0 )
|
||
|
|
return CANCEL;
|
||
|
|
localinfo = (MRAUnitsLocalInfo *) local.addr;
|
||
|
|
m = (MRegion*)localinfo->mWord.addr;
|
||
|
|
if( (0 <= localinfo->unitIndex)
|
||
|
|
&& (localinfo->unitIndex < m->GetNoComponents()) )
|
||
|
|
{
|
||
|
|
unit = new URegion(localinfo->unitIndex++, *m);
|
||
|
|
result = SetWord( unit );
|
||
|
|
return YIELD;
|
||
|
|
}
|
||
|
|
return CANCEL;
|
||
|
|
|
||
|
|
case CLOSE:
|
||
|
|
|
||
|
|
if( local.addr != 0 )
|
||
|
|
{
|
||
|
|
delete (MRAUnitsLocalInfo *)local.addr;
|
||
|
|
local = SetWord(Address(0));
|
||
|
|
}
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
// should not happen
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
Value mapping functions of operator ~timeshift~
|
||
|
|
|
||
|
|
*/
|
||
|
|
int MRegTimeShiftMap( Word* args, Word& result,
|
||
|
|
int message, Word& local, Supplier s )
|
||
|
|
{
|
||
|
|
Word t;
|
||
|
|
DateTime* dd;
|
||
|
|
URegionEmb uregEmb;
|
||
|
|
MRegion * mapping, *mpResult;
|
||
|
|
|
||
|
|
result = qp->ResultStorage( s );
|
||
|
|
|
||
|
|
mapping= (MRegion*)args[0].addr,
|
||
|
|
mpResult = (MRegion*)result.addr;
|
||
|
|
mpResult->Clear();
|
||
|
|
|
||
|
|
dd = (DateTime *)args[1].addr;
|
||
|
|
|
||
|
|
if( mapping->IsDefined() &&
|
||
|
|
dd->IsDefined() )
|
||
|
|
{
|
||
|
|
mpResult->SetDefined( true );
|
||
|
|
if(mapping->GetNoComponents() == 0)
|
||
|
|
return 0;
|
||
|
|
mapping->Get(0, uregEmb);
|
||
|
|
if( (uregEmb.timeInterval.start.ToDouble() + dd->ToDouble()) < 0 )
|
||
|
|
{
|
||
|
|
mpResult->SetDefined( false );
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
for( int i = 0; i < mapping->GetNoComponents(); i++ )
|
||
|
|
{
|
||
|
|
URegion aux( i, *mapping );
|
||
|
|
aux.GetEmbedded()->timeInterval.start.Add(dd);
|
||
|
|
aux.GetEmbedded()->timeInterval.end.Add(dd);
|
||
|
|
mpResult->AddURegion(aux);
|
||
|
|
}
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
mpResult->SetDefined( false );
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1.1 For unit testing operators
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
#ifdef MRA_UNITTEST
|
||
|
|
static int Unittest1ValueMap(Word* args,
|
||
|
|
Word& result,
|
||
|
|
int message,
|
||
|
|
Word& local,
|
||
|
|
Supplier s) {
|
||
|
|
if (MRA_DEBUG) cerr << "Unittest1ValueMap() called" << endl;
|
||
|
|
|
||
|
|
unsigned int detailedResult;
|
||
|
|
|
||
|
|
for(int i=0; i<17; i++){
|
||
|
|
if( !(static_cast<CcReal*>(args[i].addr))->IsDefined() ){
|
||
|
|
((CcInt *)result.addr)->Set(false, -666);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
specialTrapeziumIntersects(
|
||
|
|
((CcReal*) args[0].addr)->GetRealval(), // dt
|
||
|
|
((CcReal*) args[1].addr)->GetRealval(), // t1p1x
|
||
|
|
((CcReal*) args[2].addr)->GetRealval(), // t1p1y
|
||
|
|
((CcReal*) args[3].addr)->GetRealval(), // t1p2x
|
||
|
|
((CcReal*) args[4].addr)->GetRealval(), // t1p2y
|
||
|
|
((CcReal*) args[5].addr)->GetRealval(), // t1p3x
|
||
|
|
((CcReal*) args[6].addr)->GetRealval(), // t1p3y
|
||
|
|
((CcReal*) args[7].addr)->GetRealval(), // t1p4x
|
||
|
|
((CcReal*) args[8].addr)->GetRealval(), // t1p4y
|
||
|
|
((CcReal*) args[9].addr)->GetRealval(), // t2p1x
|
||
|
|
((CcReal*) args[10].addr)->GetRealval(), // t2p1y
|
||
|
|
((CcReal*) args[11].addr)->GetRealval(), // t2p2x
|
||
|
|
((CcReal*) args[12].addr)->GetRealval(), // t2p2y
|
||
|
|
((CcReal*) args[13].addr)->GetRealval(), // t2p3x
|
||
|
|
((CcReal*) args[14].addr)->GetRealval(), // t2p3y
|
||
|
|
((CcReal*) args[15].addr)->GetRealval(), // t2p4x
|
||
|
|
((CcReal*) args[16].addr)->GetRealval(), // t2p4y
|
||
|
|
detailedResult);
|
||
|
|
|
||
|
|
if (MRA_DEBUG) cerr << "Unittest1ValueMap() #1" << endl;
|
||
|
|
|
||
|
|
result = qp->ResultStorage(s);
|
||
|
|
((CcInt *)result.addr)->Set(true, detailedResult);
|
||
|
|
|
||
|
|
if (MRA_DEBUG) cerr << "Unittest1ValueMap() #2" << endl;
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
static int Unittest2ValueMap(Word* args,
|
||
|
|
Word& result,
|
||
|
|
int message,
|
||
|
|
Word& local,
|
||
|
|
Supplier s) {
|
||
|
|
if (MRA_DEBUG) cerr << "Unittest2ValueMap() called" << endl;
|
||
|
|
|
||
|
|
result = qp->ResultStorage(s);
|
||
|
|
MRegion* mr = static_cast<MRegion*>(args[0].addr);
|
||
|
|
CcInt* ci = static_cast<CcInt*>(args[1].addr);
|
||
|
|
if( mr->IsDefined() && ci->IsDefined() ){
|
||
|
|
((CcBool *)result.addr)->Set( true, mr->Unittest2( ci->GetIntval()) );
|
||
|
|
} else {
|
||
|
|
((CcBool *)result.addr)->Set( false, false );
|
||
|
|
}
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
static int Unittest3ValueMap(Word* args,
|
||
|
|
Word& result,
|
||
|
|
int message,
|
||
|
|
Word& local,
|
||
|
|
Supplier s) {
|
||
|
|
if (MRA_DEBUG) cerr << "Unittest3ValueMap() called" << endl;
|
||
|
|
|
||
|
|
result = qp->ResultStorage(s);
|
||
|
|
RReal* res = (RReal *) result.addr;
|
||
|
|
|
||
|
|
MPoint* mp1 = (MPoint*) args[0].addr;
|
||
|
|
MPoint* mp2 = (MPoint*) args[1].addr;
|
||
|
|
|
||
|
|
res->Clear();
|
||
|
|
if( !mp1->IsDefined() || !mp2->IsDefined() ){
|
||
|
|
res->SetDefined( false );
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
res->SetDefined( true );
|
||
|
|
|
||
|
|
RefinementPartition<MPoint,MPoint,UPoint,UPoint> rp(*mp1, *mp2);
|
||
|
|
|
||
|
|
res->StartBulkLoad();
|
||
|
|
|
||
|
|
for (unsigned int i = 0; i < rp.Size(); i++) {
|
||
|
|
Interval<Instant> iv;
|
||
|
|
int urPos;
|
||
|
|
int upPos;
|
||
|
|
|
||
|
|
rp.Get(i, iv, urPos, upPos);
|
||
|
|
|
||
|
|
CcReal left(true, iv.start.ToDouble());
|
||
|
|
CcReal right(true, iv.end.ToDouble());
|
||
|
|
Interval<CcReal> resIv(left, right, iv.lc, iv.rc);
|
||
|
|
|
||
|
|
res->Add(resIv);
|
||
|
|
}
|
||
|
|
|
||
|
|
res->EndBulkLoad(true);
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
#endif // MRA_UNITTEST
|
||
|
|
|
||
|
|
template <class T>
|
||
|
|
static int VertTrajectory_ValueMap(Word* args,
|
||
|
|
Word& result,
|
||
|
|
int message,
|
||
|
|
Word& local,
|
||
|
|
Supplier s) {
|
||
|
|
result = qp->ResultStorage(s);
|
||
|
|
T* ur = (T*) args[0].addr;
|
||
|
|
const DbArray<MSegmentData>* segments = ur->GetMSegmentData();
|
||
|
|
int size = segments->Size();
|
||
|
|
Line* L = (Line*) result.addr;
|
||
|
|
L->Clear();
|
||
|
|
if( !ur->IsDefined() ){
|
||
|
|
L->SetDefined( false );
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
L->SetDefined( true );
|
||
|
|
L->StartBulkLoad();
|
||
|
|
MSegmentData mseg;
|
||
|
|
cout << " insert " << size << " segments" << endl;
|
||
|
|
HalfSegment hs;
|
||
|
|
int edgeno = 0;
|
||
|
|
for(int i=0;i<size;i++){
|
||
|
|
segments->Get(i,&mseg);
|
||
|
|
Point P1(true,mseg.GetInitialStartX(),mseg.GetInitialStartY());
|
||
|
|
Point P2(true,mseg.GetFinalStartX(),mseg.GetFinalStartY());
|
||
|
|
hs.Set(true,P1,P2);
|
||
|
|
hs.attr.edgeno = edgeno++;
|
||
|
|
//cout << "insert " << hs << "to the line" << endl;
|
||
|
|
(*L)+=hs;
|
||
|
|
hs.SetLeftDomPoint(!hs.IsLeftDomPoint());
|
||
|
|
(*L)+=hs;
|
||
|
|
}
|
||
|
|
L->EndBulkLoad();
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
static int addvaluemap(Word* args,
|
||
|
|
Word& result,
|
||
|
|
int message,
|
||
|
|
Word& local,
|
||
|
|
Supplier s)
|
||
|
|
{
|
||
|
|
result = qp->ResultStorage(s);
|
||
|
|
MRegion* mreg1 = (MRegion* ) args[0].addr;
|
||
|
|
URegion* ureg1 = (URegion*) args[1].addr;
|
||
|
|
MRegion* res = static_cast<MRegion*>(result.addr);
|
||
|
|
res->Clear();
|
||
|
|
if( !mreg1->IsDefined() || !ureg1->IsDefined() ){
|
||
|
|
res->SetDefined( false );
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
res->SetDefined( true );
|
||
|
|
|
||
|
|
bool disj=true;
|
||
|
|
for(int i=0;i<mreg1->GetNoComponents();i++)
|
||
|
|
{
|
||
|
|
URegionEmb ur;
|
||
|
|
mreg1->Get(i,ur);
|
||
|
|
if(!ureg1->timeInterval.Disjoint(ur.timeInterval))
|
||
|
|
{
|
||
|
|
disj=false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if(disj)
|
||
|
|
{
|
||
|
|
res->CopyFrom(mreg1);
|
||
|
|
res->AddURegion(*ureg1);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
res->SetDefined(false);
|
||
|
|
cerr<<"Error, Intervals are not disjoint"<<endl;
|
||
|
|
}
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
static int unionvaluemap(Word* args,
|
||
|
|
Word& result,
|
||
|
|
int message,
|
||
|
|
Word& local,
|
||
|
|
Supplier s)
|
||
|
|
{
|
||
|
|
result = qp->ResultStorage(s);
|
||
|
|
URegion* reg1 = static_cast<URegion*>(args[0].addr);
|
||
|
|
URegion* reg2 = static_cast<URegion*>(args[1].addr);
|
||
|
|
URegion* res = static_cast<URegion*>(result.addr);
|
||
|
|
|
||
|
|
if( !reg1->IsDefined() || !reg2->IsDefined() ){
|
||
|
|
res->SetDefined( false );
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
try
|
||
|
|
{
|
||
|
|
res->CopyFrom(reg1);
|
||
|
|
res->AddURegion(reg2);
|
||
|
|
}
|
||
|
|
catch (invalid_argument& e)
|
||
|
|
{
|
||
|
|
res->SetDefined( false );
|
||
|
|
cerr<<e.what()<<endl;
|
||
|
|
}
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1 Value mapping arrays
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
static ValueMapping atinstantvaluemap[] =
|
||
|
|
{ MappingAtInstant<MRegion, Region>,
|
||
|
|
AtInstantValueMap_URegion };
|
||
|
|
|
||
|
|
static ValueMapping initialvaluemap[] =
|
||
|
|
{ MappingInitial<MRegion, URegionEmb, Region> };
|
||
|
|
|
||
|
|
static ValueMapping finalvaluemap[] =
|
||
|
|
{ MappingFinal<MRegion, URegionEmb, Region> };
|
||
|
|
|
||
|
|
static ValueMapping instvaluemap[] =
|
||
|
|
{ IntimeInst<Region> };
|
||
|
|
|
||
|
|
static ValueMapping valvaluemap[] =
|
||
|
|
{ IntimeVal<Region> };
|
||
|
|
|
||
|
|
static ValueMapping deftimevaluemap[] =
|
||
|
|
{ MappingDefTime<MRegion> };
|
||
|
|
|
||
|
|
static ValueMapping presentvaluemap[] =
|
||
|
|
{ MappingPresent_i<MRegion>,
|
||
|
|
MappingPresent_p<MRegion> };
|
||
|
|
|
||
|
|
static ValueMapping intersectionvaluemap[] =
|
||
|
|
{ IntersectionValueMap };
|
||
|
|
|
||
|
|
static ValueMapping insidevaluemap[] =
|
||
|
|
{ InsideValueMap };
|
||
|
|
|
||
|
|
static ValueMapping atvaluemap[] =
|
||
|
|
{ AtValueMap_MPoint,
|
||
|
|
AtValueMap_MRegion };
|
||
|
|
|
||
|
|
static ValueMapping verttrajectoryvaluemap[] =
|
||
|
|
{ VertTrajectory_ValueMap<URegion>,
|
||
|
|
VertTrajectory_ValueMap<MRegion>};
|
||
|
|
|
||
|
|
#ifdef MRA_TRAVERSED
|
||
|
|
static ValueMapping traversedvaluemap[] =
|
||
|
|
{ TraversedValueMap };
|
||
|
|
#endif // MRA_TRAVERSED
|
||
|
|
|
||
|
|
static ValueMapping BboxValueMap[] =
|
||
|
|
{ BboxValueMapURegion,
|
||
|
|
BboxValueMapIRegion,
|
||
|
|
BboxValueMapMRegion };
|
||
|
|
|
||
|
|
static ValueMapping Bbox2dValueMap[] =
|
||
|
|
{ Bbox2dValueMapURegion,
|
||
|
|
Bbox2dValueMapIRegion,
|
||
|
|
Bbox2dValueMapMRegion };
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1 Operator specifications
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
static const string atinstantspec =
|
||
|
|
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
|
||
|
|
" ( <text>(mregion instant) -> iregion, "
|
||
|
|
" (uregion instant) -> iregion,</text--->"
|
||
|
|
" <text>_ atinstant _ </text--->"
|
||
|
|
" <text>Get the iregion value corresponding "
|
||
|
|
"to the instant.</text--->"
|
||
|
|
" <text>mregion1 atinstant instant1</text---> ) )";
|
||
|
|
|
||
|
|
static const string initialspec =
|
||
|
|
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
|
||
|
|
" ( <text>mregion -> iregion</text--->"
|
||
|
|
" <text>initial( _ )</text--->"
|
||
|
|
" <text>Get the iregion value corresponding to "
|
||
|
|
"the initial instant."
|
||
|
|
" </text--->"
|
||
|
|
" <text>initial( mregion1 )</text---> ) )";
|
||
|
|
|
||
|
|
static const string finalspec =
|
||
|
|
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
|
||
|
|
" ( <text>mregion -> iregion</text--->"
|
||
|
|
" <text>final( _ )</text--->"
|
||
|
|
" <text>Get the iregion value corresponding to "
|
||
|
|
"the final instant."
|
||
|
|
" </text--->"
|
||
|
|
" <text>final( mregion1 )</text---> ) )";
|
||
|
|
|
||
|
|
static const string instspec =
|
||
|
|
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
|
||
|
|
" ( <text>iregion -> instant</text--->"
|
||
|
|
" <text>inst ( _ )</text--->"
|
||
|
|
" <text>iregion time instant.</text--->"
|
||
|
|
" <text>inst ( iregion1 )</text---> ) )";
|
||
|
|
|
||
|
|
static const string valspec =
|
||
|
|
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
|
||
|
|
" ( <text>iregion -> region</text--->"
|
||
|
|
" <text>val ( _ )</text--->"
|
||
|
|
" <text>Intime value.</text--->"
|
||
|
|
" <text>val ( iregion1 )</text---> ) )";
|
||
|
|
|
||
|
|
static const string deftimespec =
|
||
|
|
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
|
||
|
|
" ( <text>mregion -> periods</text--->"
|
||
|
|
" <text>deftime( _ )</text--->"
|
||
|
|
" <text>Get the defined time of the mregion object.</text--->"
|
||
|
|
" <text>deftime( mregion1 )</text---> ) )";
|
||
|
|
|
||
|
|
static const string presentspec =
|
||
|
|
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
|
||
|
|
" ( <text>(mregion instant) -> bool, "
|
||
|
|
"(mregion periods) -> bool</text--->"
|
||
|
|
" <text>_ present _ </text--->"
|
||
|
|
" <text>Whether the object is present at the given instant or"
|
||
|
|
" period.</text--->"
|
||
|
|
" <text>mregion1 present instant1</text---> ) )";
|
||
|
|
|
||
|
|
static const string intersectionspec =
|
||
|
|
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
|
||
|
|
" ( <text>(mpoint mregion) -> mpoint</text--->"
|
||
|
|
" <text>intersection( _ , _ )</text--->"
|
||
|
|
" <text>Intersection between mpoint and mregion.</text--->"
|
||
|
|
" <text>intersection(mpoint1, mregion1)</text---> ) )";
|
||
|
|
|
||
|
|
static const string insidespec =
|
||
|
|
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
|
||
|
|
" ( <text>(mpoint mregion) -> mbool</text--->"
|
||
|
|
" <text>_ inside _</text--->"
|
||
|
|
" <text>Calculates if and when mpoint is inside "
|
||
|
|
"mregion.</text--->"
|
||
|
|
" <text>mpoint1 inside mregion1</text---> ) )";
|
||
|
|
|
||
|
|
static const string atspec =
|
||
|
|
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
|
||
|
|
" ( <text>(mpoint region) -> mpoint, "
|
||
|
|
"(mregion point) -> mpoint</text--->"
|
||
|
|
" <text>_ at _</text--->"
|
||
|
|
" <text>Restrict moving point to region or restrict moving region "
|
||
|
|
"to point.</text--->"
|
||
|
|
" <text>mpoint1 at region1</text---> ) )";
|
||
|
|
|
||
|
|
|
||
|
|
static const string addspec =
|
||
|
|
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
|
||
|
|
" ( <text>(mregion uregion) -> mregion</text--->"
|
||
|
|
" <text>adduregion(_, _)</text--->"
|
||
|
|
" <text>Add a uregion to a mregion,"
|
||
|
|
"if all the periods are disjoint.</text--->"
|
||
|
|
" <text>query adduregion( msnow ,interpolate(thecenter, "
|
||
|
|
"thecenter translate[100.0, -1000.0], theRange(theInstant(2003, 11, 20, 9),"
|
||
|
|
"theInstant(2003, 11, 20, 11), TRUE, FALSE)))</text---> ) )";
|
||
|
|
|
||
|
|
|
||
|
|
static const string unionspec =
|
||
|
|
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
|
||
|
|
" ( <text>(uregion uregion) -> uregion </text--->"
|
||
|
|
" <text>_ union _</text--->"
|
||
|
|
" <text>Calculate a URegion by adding one URegion to another."
|
||
|
|
"Works only, if the periods are equal</text--->"
|
||
|
|
" <text>uregion1 unit uregion2</text---> ) )";
|
||
|
|
|
||
|
|
|
||
|
|
static const string movespec =
|
||
|
|
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
|
||
|
|
" ( <text>mpoint x region -> mregion</text--->"
|
||
|
|
" <text>move( _ , _)</text--->"
|
||
|
|
" <text>Creates a moving region from the given region"
|
||
|
|
" using the mpoint speed and direction </text--->"
|
||
|
|
" <text>query move(mp,reg)</text---> ) )";
|
||
|
|
|
||
|
|
#ifdef MRA_TRAVERSED
|
||
|
|
static const string traversedspec =
|
||
|
|
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
|
||
|
|
" ( <text>mregion -> region</text--->"
|
||
|
|
" <text>traversed( _ )</text--->"
|
||
|
|
" <text>Projection of a moving region into "
|
||
|
|
"the plane.</text--->"
|
||
|
|
" <text>traversed(mregion1)</text---> ) )";
|
||
|
|
#endif // MRA_TRAVERSED
|
||
|
|
|
||
|
|
#ifdef MRA_PREC
|
||
|
|
static const string mraprecspec =
|
||
|
|
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
|
||
|
|
" ( <text>(real) -> bool</text--->"
|
||
|
|
" <text>mraprec( _ , _ )</text--->"
|
||
|
|
" <text>Sets precision of comparisons. Two floating point values "
|
||
|
|
"are considered equal by the algebra, if their difference is lower "
|
||
|
|
"or equal than the first parameter. The second parameter specifies "
|
||
|
|
"a relaxed comparison precision for the check whether a moving "
|
||
|
|
"segment is collinear with itself in its the initial and final "
|
||
|
|
"instant. In this case, two floating point values are considered "
|
||
|
|
"equal if their difference is lower or equal than the first "
|
||
|
|
"parameter times the second parameter. The operator "
|
||
|
|
"always returns true.</text--->"
|
||
|
|
" <text>mraprec(0.0001, 10)</text---> ) )";
|
||
|
|
#endif // MRA_PREC
|
||
|
|
|
||
|
|
static const string bboxspec =
|
||
|
|
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
|
||
|
|
" ( <text>uregion -> rect3,\n"
|
||
|
|
"iregion -> rect3, \n"
|
||
|
|
"mregion -> rect3</text--->"
|
||
|
|
" <text>bbox( _ )</text--->"
|
||
|
|
" <text>Returns the 3d bounding box of the spatio-temporal "
|
||
|
|
"value.</text--->"
|
||
|
|
" <text>bbox(mregion1)</text---> ) )";
|
||
|
|
|
||
|
|
static const string bbox2dspec =
|
||
|
|
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
|
||
|
|
" ( <text>uregion -> rect,\n"
|
||
|
|
"iregion -> rect, \n"
|
||
|
|
"mregion -> rect</text--->"
|
||
|
|
" <text>bbox2d( _ )</text--->"
|
||
|
|
" <text>Returns the 2d bounding box of the "
|
||
|
|
"spatio-temporal value.</text--->"
|
||
|
|
" <text>bbox2d(mregion1)</text---> ) )";
|
||
|
|
|
||
|
|
static const string verttrajectoryspec =
|
||
|
|
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
|
||
|
|
" ( <text>(uregion || mregion) -> line</text--->"
|
||
|
|
" <text>vertextrajectory( _ )</text--->"
|
||
|
|
" <text>Computes the trajectory of the vertices </text--->"
|
||
|
|
" <text>vertextrajectory(mregion1)</text---> ) )";
|
||
|
|
|
||
|
|
const string mraunitsspec =
|
||
|
|
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
|
||
|
|
" ( <text>mregion -> (stream uregion)</text--->"
|
||
|
|
"<text>units( _ )</text--->"
|
||
|
|
"<text>Create the stream of all uregions contained by "
|
||
|
|
"the moving region.</text--->"
|
||
|
|
"<text>units( mregion1 )</text--->) )";
|
||
|
|
|
||
|
|
const string MRegTimeShiftSpec =
|
||
|
|
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
|
||
|
|
"( <text>mregion x duration -> mregion</text--->"
|
||
|
|
"<text>_ timeshift[ _ ]</text--->"
|
||
|
|
"<text>Shifts the definition time of the moving region object.</text--->"
|
||
|
|
"<text>msnow timeshift[ create_duration(1, 0) ]</text--->"
|
||
|
|
") )";
|
||
|
|
/*
|
||
|
|
Used for unit testing only.
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
#ifdef MRA_UNITTEST
|
||
|
|
static const string unittestspec =
|
||
|
|
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
|
||
|
|
" ( <text>unit testing only</text--->"
|
||
|
|
" <text>unit testing only</text--->"
|
||
|
|
" <text>unit testing only</text--->"
|
||
|
|
" <text>unit testing only</text---> ) )";
|
||
|
|
#endif // MRA_UNITTEST
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1 Operator creation
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
namespace movingregionops{
|
||
|
|
|
||
|
|
|
||
|
|
static Operator atinstant("atinstant",
|
||
|
|
atinstantspec,
|
||
|
|
2,
|
||
|
|
atinstantvaluemap,
|
||
|
|
AtInstantSelect,
|
||
|
|
AtInstantTypeMap);
|
||
|
|
|
||
|
|
static Operator initial("initial",
|
||
|
|
initialspec,
|
||
|
|
1,
|
||
|
|
initialvaluemap,
|
||
|
|
MRegionSelect,
|
||
|
|
MRegionToIRegionTypeMap);
|
||
|
|
|
||
|
|
static Operator final("final",
|
||
|
|
finalspec,
|
||
|
|
1,
|
||
|
|
finalvaluemap,
|
||
|
|
MRegionSelect,
|
||
|
|
MRegionToIRegionTypeMap);
|
||
|
|
|
||
|
|
static Operator inst("inst",
|
||
|
|
instspec,
|
||
|
|
1,
|
||
|
|
instvaluemap,
|
||
|
|
IRegionSelect,
|
||
|
|
IRegionToInstantTypeMap);
|
||
|
|
|
||
|
|
static Operator val("val",
|
||
|
|
valspec,
|
||
|
|
1,
|
||
|
|
valvaluemap,
|
||
|
|
IRegionSelect,
|
||
|
|
IRegionToRegionTypeMap);
|
||
|
|
|
||
|
|
static Operator deftime("deftime",
|
||
|
|
deftimespec,
|
||
|
|
1,
|
||
|
|
deftimevaluemap,
|
||
|
|
MRegionSelect,
|
||
|
|
MRegionToPeriodsTypeMap);
|
||
|
|
|
||
|
|
static Operator present("present",
|
||
|
|
presentspec,
|
||
|
|
2,
|
||
|
|
presentvaluemap,
|
||
|
|
PresentSelect,
|
||
|
|
PresentTypeMap);
|
||
|
|
|
||
|
|
static Operator intersection("intersection",
|
||
|
|
intersectionspec,
|
||
|
|
1,
|
||
|
|
intersectionvaluemap,
|
||
|
|
MPointMRegionSelect,
|
||
|
|
MPointMRegionToMPointTypeMap);
|
||
|
|
|
||
|
|
static Operator inside("inside",
|
||
|
|
insidespec,
|
||
|
|
1,
|
||
|
|
insidevaluemap,
|
||
|
|
MPointMRegionSelect,
|
||
|
|
MPointMRegionToMBoolTypeMap);
|
||
|
|
|
||
|
|
static Operator at("at",
|
||
|
|
atspec,
|
||
|
|
2,
|
||
|
|
atvaluemap,
|
||
|
|
AtSelect,
|
||
|
|
AtTypeMap);
|
||
|
|
|
||
|
|
static Operator addURegion("adduregion",
|
||
|
|
addspec,
|
||
|
|
addvaluemap,
|
||
|
|
Operator::SimpleSelect,
|
||
|
|
AddTypeMap);
|
||
|
|
|
||
|
|
static Operator Union("union",
|
||
|
|
unionspec,
|
||
|
|
unionvaluemap,
|
||
|
|
Operator::SimpleSelect,
|
||
|
|
UnionTypeMap);
|
||
|
|
|
||
|
|
#ifdef MRA_TRAVERSED
|
||
|
|
static Operator traversed("traversed",
|
||
|
|
traversedspec,
|
||
|
|
1,
|
||
|
|
traversedvaluemap,
|
||
|
|
MRegionSelect,
|
||
|
|
MRegionToRegionTypeMap);
|
||
|
|
#endif // MRA_TRAVERSED
|
||
|
|
|
||
|
|
#ifdef MRA_PREC
|
||
|
|
static Operator mraprec("mraprec",
|
||
|
|
mraprecspec,
|
||
|
|
MraprecValueMap,
|
||
|
|
simpleSelect,
|
||
|
|
MraprecTypeMap);
|
||
|
|
#endif // MRA_PREC
|
||
|
|
|
||
|
|
static Operator bbox("bbox",
|
||
|
|
bboxspec,
|
||
|
|
3,
|
||
|
|
BboxValueMap,
|
||
|
|
BBoxSelect,
|
||
|
|
BboxTypeMap);
|
||
|
|
|
||
|
|
static Operator bbox2d("bbox2d",
|
||
|
|
bbox2dspec,
|
||
|
|
3,
|
||
|
|
Bbox2dValueMap,
|
||
|
|
BBoxSelect,
|
||
|
|
Bbox2dTypeMap);
|
||
|
|
|
||
|
|
static Operator move("move",
|
||
|
|
movespec,
|
||
|
|
MoveValueMap,
|
||
|
|
simpleSelect,
|
||
|
|
MoveTypeMap);
|
||
|
|
|
||
|
|
static Operator vertextrajectory("vertextrajectory",
|
||
|
|
verttrajectoryspec,
|
||
|
|
2,
|
||
|
|
verttrajectoryvaluemap,
|
||
|
|
VertTrajectorySelect,
|
||
|
|
VertTrajectoryTypeMap);
|
||
|
|
|
||
|
|
static Operator mraunits("units",
|
||
|
|
mraunitsspec,
|
||
|
|
mraunitsvalmap,
|
||
|
|
Operator::SimpleSelect,
|
||
|
|
MRAUnitsTypeMap);
|
||
|
|
|
||
|
|
|
||
|
|
Operator mregtimeshift( "timeshift",
|
||
|
|
MRegTimeShiftSpec,
|
||
|
|
MRegTimeShiftMap,
|
||
|
|
Operator::SimpleSelect,
|
||
|
|
MRegTimeShiftTM );
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
/*
|
||
|
|
Used for unit testing only.
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
#ifdef MRA_UNITTEST
|
||
|
|
static Operator unittest1("unittest1",
|
||
|
|
unittestspec,
|
||
|
|
Unittest1ValueMap,
|
||
|
|
simpleSelect,
|
||
|
|
Unittest1TypeMap);
|
||
|
|
static Operator unittest2("unittest2",
|
||
|
|
unittestspec,
|
||
|
|
Unittest2ValueMap,
|
||
|
|
simpleSelect,
|
||
|
|
Unittest2TypeMap);
|
||
|
|
static Operator unittest3("unittest3",
|
||
|
|
unittestspec,
|
||
|
|
Unittest3ValueMap,
|
||
|
|
simpleSelect,
|
||
|
|
Unittest3TypeMap);
|
||
|
|
#endif // MRA_UNITTEST
|
||
|
|
|
||
|
|
|
||
|
|
} // end of namespace movingregionops
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
/*
|
||
|
|
1 Algebra creation
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
class MovingRegionAlgebra : public Algebra {
|
||
|
|
public:
|
||
|
|
MovingRegionAlgebra() : Algebra() {
|
||
|
|
AddTypeConstructor(&intimeregion);
|
||
|
|
AddTypeConstructor(&uregion);
|
||
|
|
AddTypeConstructor(&movingregion);
|
||
|
|
|
||
|
|
intimeregion.AssociateKind(Kind::TEMPORAL());
|
||
|
|
intimeregion.AssociateKind(Kind::DATA());
|
||
|
|
|
||
|
|
uregion.AssociateKind(Kind::TEMPORAL());
|
||
|
|
uregion.AssociateKind(Kind::SPATIAL3D());
|
||
|
|
uregion.AssociateKind(Kind::DATA());
|
||
|
|
|
||
|
|
movingregion.AssociateKind(Kind::TEMPORAL());
|
||
|
|
movingregion.AssociateKind(Kind::DATA());
|
||
|
|
|
||
|
|
AddOperator(&movingregionops::atinstant);
|
||
|
|
AddOperator(&movingregionops::initial);
|
||
|
|
AddOperator(&movingregionops::final);
|
||
|
|
AddOperator(&movingregionops::inst);
|
||
|
|
AddOperator(&movingregionops::val);
|
||
|
|
AddOperator(&movingregionops::deftime);
|
||
|
|
AddOperator(&movingregionops::present);
|
||
|
|
AddOperator(&movingregionops::intersection);
|
||
|
|
AddOperator(&movingregionops::inside);
|
||
|
|
AddOperator(&movingregionops::at);
|
||
|
|
AddOperator(&movingregionops::addURegion);
|
||
|
|
AddOperator(&movingregionops::Union);
|
||
|
|
AddOperator(&movingregionops::bbox);
|
||
|
|
AddOperator(&movingregionops::bbox2d);
|
||
|
|
AddOperator(&movingregionops::move);
|
||
|
|
AddOperator(&movingregionops::vertextrajectory);
|
||
|
|
AddOperator(&movingregionops::mraunits);
|
||
|
|
AddOperator(&movingregionops::mregtimeshift);
|
||
|
|
|
||
|
|
#ifdef MRA_TRAVERSED
|
||
|
|
AddOperator(&movingregionops::traversed);
|
||
|
|
#endif // MRA_TRAVERSED
|
||
|
|
|
||
|
|
#ifdef MRA_PREC
|
||
|
|
AddOperator(&movingregionops::mraprec);
|
||
|
|
#endif // MRA_PREC
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
/*
|
||
|
|
Used for unit testing only.
|
||
|
|
|
||
|
|
*/
|
||
|
|
#ifdef MRA_UNITTEST
|
||
|
|
AddOperator(&movingregionops::unittest1);
|
||
|
|
AddOperator(&movingregionops::unittest2);
|
||
|
|
AddOperator(&movingregionops::unittest3);
|
||
|
|
#endif // MRA_UNITTEST
|
||
|
|
}
|
||
|
|
~MovingRegionAlgebra() {}
|
||
|
|
};
|
||
|
|
|
||
|
|
} // end of namespace temporalalgebra
|
||
|
|
|
||
|
|
|
||
|
|
extern "C"
|
||
|
|
Algebra* InitializeMovingRegionAlgebra(NestedList* nlRef,
|
||
|
|
QueryProcessor *qpRef) {
|
||
|
|
nl = nlRef;
|
||
|
|
qp = qpRef;
|
||
|
|
return new temporalalgebra::MovingRegionAlgebra();
|
||
|
|
}
|