Files
secondo/Algebras/MRegionOps/SetOps.h
2026-01-23 17:03:45 +08:00

3221 lines
53 KiB
C++

/*
----
This file is part of SECONDO.
Copyright (C) 2008, University in Hagen, Department of Computer Science,
Database Systems for New Applications.
SECONDO is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
SECONDO is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with SECONDO; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
----
//paragraph [1] Title: [{\Large \bf \begin {center}] [\end {center}}]
//[TOC] [\tableofcontents]
//[ue] [\"u]
//[ae] [\"a]
//[oe] [\"o]
//[x] [$\times $]
//[->] [$\rightarrow $]
[1] Headerfile of the Set Operator Classes
April - November 2008, M. H[oe]ger for bachelor thesis.
[TOC]
1 Introduction
This file essentially contains the definitions of several classes which
provides the core functionality of the three set operators
~intersection~, ~union~ and ~minus~ with the signature \\
mregion [x] mregion [->] mregion \\
used in the ~MovingRegionAlgebra~.
A general overview about the relationship of this classes is shown below:
Figure 1: Class diagram [classdiagram.eps]
2 Defines and Includes
*/
#ifndef SETOPS_H_
#define SETOPS_H_
#include "Algebras/MovingRegion/MovingRegionAlgebra.h"
#include "Algebras/Temporal/TemporalAlgebra.h"
#include "NList.h"
#include "NumericUtil.h"
#include "PointVector.h"
#include "Segment.h"
#include "Statistic.h"
#include "DateTime.h"
#include "StopWatch.h"
#include <vector>
#include <set>
#include <list>
namespace temporalalgebra{
namespace mregionops {
/*
1.1 $PRINT\_DEBUG\_MESSAGES$
Enables the output of messages useful for debugging.
Note: The output might be very verbose.
*/
//#define PRINT_DEBUG_MESSAGES
/*
1.1 $PRINT\_STATISTIC$
Enables the output of statistic data for each set-operation.
*/
#define PRINT_STATISTIC
#ifdef PRINT_DEBUG_MESSAGES
#define PRINT_STATISTIC
#endif
/*
1.1 $WRITE\_VRML\_FILE$
Enables the creation of one vrml-file for each source unit pair,
showing it's elements as wireframes in the xyt-space.
Use the flags below to specify the desired output.
Note: The file will be created in the current directory and follows
the naming convention $unitpair\_<starttime>.wrl$
*/
//#define WRITE_VRML_FILE
const bool showSourceUnitA = true;
const bool showSourceUnitB = true;
const bool showResultUnits = true;
/*
1.1 $OPTIMIZE\_BY\_BOUNDING\_RECT$
Enables an optimization, using the
projection bounding rectangles of both source units.
See the class ~SourceUnit~ for details.
*/
#define OPTIMIZE_BY_BOUNDING_RECT
/*
1.1 $CACHE\_TESTREGIONS$
Enables the caching of ~Testregions~, used in the class ~SourceUnit~.
See it's documentation for details.
*/
#define CACHE_TESTREGIONS
/*
1.1 $NORMALIZE\_TIME\_INTERVAL\_OF\_SOURCE\_UNITS$
Enables the normalization of the interval of a ~SourceUnit~ to 1.0.
This might be useful to improve the numerical stability of very thin units.
*/
const bool NORMALIZE_TIME_INTERVAL_OF_SOURCE_UNITS = true;
/*
1.1 $DECIDE\_BY\_ENTIRELY\_IN\_OUT$
Enables an optimization during the construction of a result unit.
See the class ~ResultUnitFactory~ for details.
*/
const bool DECIDE_BY_ENTIRELY_IN_OUT = true;
/*
1.1 $DECIDE\_BY\_PLUMBLINE\_ONLY$
Disables an optimization during the construction of a result unit.
See the class ~ResultUnitFactory~ for details.
*/
const bool DECIDE_BY_PLUMBLINE_ONLY = false;
/*
1.1 $MERGE\_RESULT\_MSEGMENTS$
Merge adjacent and coplanar moving segments of a result unit.
Note: This feature is not implemented yet!
*/
const bool MERGE_RESULT_MSEGMENTS = false;
/*
1 Forward declarations
*/
class SetOperator;
class SourceUnit;
class SourceUnitPair;
class Point3DExt;
struct PointExtCompare;
class PointExtSet;
class IntersectionSegment;
class MSegment;
class MSegmentCritical;
class ResultUnit;
struct DoubleCompare;
class ResultUnitFactory;
struct TestRegion;
struct IntSegCompare;
class IntSegContainer;
class PFace;
/*
1 Enumeration SetOp
Indicates the kind of set operation.
*/
enum SetOp {
INTERSECTION,
UNION,
MINUS
};
/*
1 Class SetOperator
This class provides the three set operations
~intersection~, ~union~ and ~minus~ with the signature
mregion [x] mregion [->] mregion.
*/
class SetOperator {
public:
/*
1.1 Constructor
The constructor takes three pointers to ~MRegion~ instances,
according to the signature a [x] b [->] res.
*/
SetOperator(MRegion* const _a,
MRegion* const _b,
MRegion* const _res) :
a(_a), b(_b), res(_res) {
}
/*
1.1 Operators
1.1.1 Intersection
Performs the operation $a \cap b$ and writes the result to res.
*/
void Intersection();
/*
1.1.1 Union
Performs the operation $a \cup b$ and writes the result to res.
*/
void Union();
/*
1.1.1 Minus
Performs the operation $a \setminus b$ and writes the result to res.
*/
void Minus();
private:
/*
1.1 Private methods
*/
void Operate(const SetOp op);
/*
1.1 Attributes
*/
MRegion* const a;
MRegion* const b;
MRegion* const res;
};
/*
1 Struct TestRegion
This datastructure is used in the class ~SourceUnit~.
See it's documentation for more details.
*/
struct TestRegion {
inline TestRegion() :
region(0),
instant(datetime::instanttype),
defined(false) {
}
Region region;
Instant instant;
bool defined;
};
/*
1 Class SourceUnit
This class represents a single unit of a ~MRegion~ A or B,
which are the arguments of the set operation.
*/
class SourceUnit {
friend class SourceUnitPair;
public:
/*
1.1 Constructor
Note that the interval of the parameter ~uRegion~ might be changed!
*/
SourceUnit(const bool isUnitA,
URegionEmb* const uRegion,
const DbArray<MSegmentData>* const array,
const bool isEmpty,
SourceUnitPair* const parent);
/*
1.1 Destructor
*/
~SourceUnit();
/*
1.1 Getter and setter methods
1.1.1 SetPartner
Sets a pointer the other ~SourceUnit~ instance, which
is the other argument of the set operation.
*/
inline void SetPartner(SourceUnit* _partner) {
partner = _partner;
}
/*
1.1.1 GetPartner
Returns a pointer the other ~SourceUnit~ instance, which
is the other argument of the set operation.
*/
inline SourceUnit* GetPartner() const {
return partner;
}
/*
1.1.1 GetParent
Returns a pointer the parent object.
*/
inline SourceUnitPair* GetParent() const {
return parent;
}
/*
1.1.1 GetParent
Returns a pointer the corresponding ~URegionEmb~ instance.
*/
inline const URegionEmb* GetURegionEmb() const {
return uRegion;
}
/*
1.1.1 IsUnitA/B
Returns ~true~, if this ~SourceUnit~ represents the first/second argument
of the set operation.
*/
inline bool IsUnitA() const {
return isUnitA;
}
inline bool IsUnitB() const {
return !isUnitA;
}
/*
1.1.1 GetOperation
Returns an enum to indicate the current set operation:
INTERSECTION, UNION or MINUS.
*/
const SetOp GetOperation() const;
/*
1.1.1 IsEmpty
Returns ~true~, if this ~SourceUnit~ represents an empty unit.
*/
inline bool IsEmpty() const {
return isEmpty;
}
/*
1.1.1 HasNormalizedTimeInterval
Returns ~true~, if the interval of this ~SourceUnit~ was normalized to 1.0.
This might be useful to improve the numerical stability of very thin units.
*/
inline bool HasNormalizedTimeInterval() const {
return hasNormalizedTimeInterval;
}
/*
1.1.1 GetTimeInterval
Returns the current interval of this ~SourceUnit~.
*/
inline const Interval<Instant>& GetTimeInterval() const {
return uRegion->timeInterval;
}
/*
1.1.1 GetOriginalTimeInterval
Returns the original interval of this ~SourceUnit~ before normalization.
*/
inline const Interval<Instant>& GetOriginalTimeInterval() const {
return originalTimeInterval;
}
/*
1.1.1 GetStart/EndTime
Returns the start/end of the interval as double value.
*/
inline double GetStartTime() const {
return startTime;
}
inline double GetEndTime() const {
return endTime;
}
/*
1.1.1 GetBoundingRect
Returns the projection bounding rectangle of this ~SourceUnit~ to the xy-plane.
*/
inline Rectangle<2> GetBoundingRect() const {
return boundingRect;
}
/*
1.1.1 GetNoOfPFaces
Returns the number of ~PFaces~ of this ~SourceUnit~,
which is equal to the number of ~MSegmentData~ in the ~URegionEmb~.
*/
inline unsigned int GetNoOfPFaces() const {
return pFaces.size();
}
/*
1.1 Operators and Predicates
1.1.1 AddGlobalTimeValue
Adds a relevant timevalue, which marks the border of a result unit.
This value is passed to the ~ResultUnitFactory~.
*/
void AddGlobalTimeValue(double t);
/*
1.1.1 AddToMRegion
Adds this unit to target.
*/
void AddToMRegion(MRegion* const target) const;
/*
1.1.1 CreatePFaces
Creates a new ~PFace~ for each ~MSegmentData~ of this unit.
*/
void CreatePFaces();
/*
1.1.1 CollectRelevantPFaces
Performs a linear scan over the list of all ~PFaces~,
collecting those which are relevant for the result and
pass them to the ~ResultUnitFactory~.
*/
void CollectRelevantPFaces(ResultUnitFactory* receiver);
/*
1.1.1 IsEntirelyOutside
Returns ~true~, if pFace is entirely outside of this ~SourceUnit~.
Precondition: pFace is already known as entirely inside or entirely outside!
*/
bool IsEntirelyOutside(const PFace* pFace);
/*
1.1.1 IsOutside
Returns ~true~, if ~p~ is outside of this ~SourceUnit~.
Note: We create a ~TestRegion~ ~tr~ by evaluating this ~SourceUnit~
at time ~p.t~ and check, if the point ~(p.x; p.y)~ is outside of ~tr~.
For the sake of efficency, we cache ~tr~ for later use.
*/
bool IsOutside(const Point3D& p);
/*
1.1.1 IsOnBorder
Returns ~true~, if ~p~ is on the border of this ~SourceUnit~.
Note: We create a ~TestRegion~ ~tr~ by evaluating this ~SourceUnit~
at time ~p.t~ and check, if the point ~(p.x; p.y)~ is on the border of ~tr~.
For the sake of efficency, we cache ~tr~ for later use.
*/
bool IsOnBorder(const Point3D& p);
/*
1.1 Methods for debugging
*/
void Print() const;
void PrintPFaces();
void PrintVRMLDesc(std::ofstream& target, const std::string& color);
private:
/*
1.1 Private methods
*/
void NormalizeTimeInterval();
void ComputeBoundingRect();
const Region GetTestRegion(const double t);
/*
1.1 Attributes
1.1.1 isUnitA
A flag, indicating which argument of the set operation
this ~SourceUnit~ represents: A or B.
*/
const bool isUnitA;
/*
1.1.1 isEmpty
A flag, indicating that this ~SourceUnit~ is empty.
*/
const bool isEmpty;
/*
1.1.1 uRegion
A pointer to the corresponding ~URegionEmb~.
Note that the interval of uRegion might be changed!
*/
URegionEmb* const uRegion;
/*
1.1.1 array
A pointer to the corresponding ~DBArray<MSegmentData>~.
*/
const DbArray<MSegmentData>* const array;
/*
1.1.1 partner
A pointer to the other ~SourceUnit~ instance, which
is the other argument of the set operation.
*/
SourceUnit* partner;
/*
1.1.1 parent
A pointer the parent object.
*/
SourceUnitPair* const parent;
/*
1.1.1 startTime, endTime
The start/end of the interval as double value.
*/
double startTime;
double endTime;
/*
1.1.1 hasNormalizedTimeInterval
A flag, indicating if the interval of this ~SourceUnit~ was normalized to 1.0.
This might be useful to improve the numerical stability of very thin units.
*/
bool hasNormalizedTimeInterval;
/*
1.1.1 originalTimeInterval
The original interval of this ~SourceUnit~ before normalization.
*/
Interval<Instant> originalTimeInterval;
/*
1.1.1 pFaces
A ~std::vector~ to store all ~PFaces~.
*/
std::vector<PFace*> pFaces;
/*
1.1.1 pFacesReduced
A ~std::vector~ to store a reduced set of ~PFaces~, relevant for the
intersection process. This optimization can be done in advance by using
the projection bounding rectangles of both ~SourceUnits~.
*/
std::vector<PFace*> pFacesReduced;
/*
1.1.1 boundingRect
The projection bounding rectangle of this ~SourceUnit~ to the xy-plane.
*/
Rectangle<2> boundingRect;
/*
1.1.1 testRegion
The cached ~TestRegion~ used by the methods ~IsOutside~ and ~IsOnBorder~.
*/
TestRegion testRegion;
};
/*
1 Enumeration Decision
Used in the class ~ResultUnitFactory~ to indicate,
if a brick of a ~PFace~ belongs to the result unit.
*/
enum Decision {
UNDEFINED,
ACCEPT,
SKIP
};
/*
1 Class ResultUnitFactory
This class essentially collects all relevant ~PFaces~ from both ~SourceUnits~
and performs afterwards a plane-sweep in t-direction from bottom to top
over all ~PFaces~. For each relevant timevalue a new ~ResultUnit~ is
constructed and added to the result ~MRegion~.
*/
class ResultUnitFactory {
public:
/*
1.1 Constructor
*/
ResultUnitFactory(MRegion* const _resMRegion,
const SourceUnitPair* const _parent) :
resMRegion(_resMRegion),
parent(_parent),
noUnits(0),
noEmptyUnits(0),
evalutedIntSegs(0),
noMSegsValid(0),
noMSegsSkipped(0),
noMSegCritical(0),
decisionsByPlumbline(0),
decisionsByEntirelyInOut(0),
decisionsByAdjacency(0),
decisionsByDegeneration(0) {
}
/*
1.1 Operators and Predicates
1.1.1 Start
This method starts the construction of all ~ResultUnits~.
*/
void Start();
/*
1.1.1 AddPFace
Adds a relevant ~PFace~.
*/
inline void AddPFace(PFace* pf) {
pFaces.push_back(pf);
}
/*
1.1.1 AddTimeValue
Adds a relevant timevalue.
*/
inline void AddTimeValue(double t) {
time.insert(t);
}
/*
1.1 Methods for debugging
*/
void Print() const;
std::string GetVRMLDesc() const;
void AddToOverallStatistic() const;
private:
/*
1.1 Private methods
*/
void ComputeCurrentTimeLevel();
void ProcessNormalPFace(PFace* pFace);
void ProcessCriticalPFace(PFace* pFace);
void ConstructResultUnitAsURegionEmb();
Decision BelongsToResultUnit(const Point3D& p, const PFace* pFace);
void AddCriticalMSegments();
/*
1.1 Attributes
1.1.1 time, timeIter
A ~std::set~ to store the relevant timevalues and a suitable iterator.
*/
std::set<double, DoubleCompare> time;
std::set<double, DoubleCompare>::const_iterator timeIter;
/*
1.1.1 t1, t12, t2
The start-, middle- and endtime of the current ~ResultUnit~.
*/
double t1;
double t12;
double t2;
/*
1.1.1 pFaces
A ~std::vector~ to store the relevant ~PFaces~.
*/
std::vector<PFace*> pFaces;
/*
1.1.1 criticalMSegs
A ~std::vector~ to store the critical MSegments.
*/
std::vector<MSegmentCritical> criticalMSegs;
/*
1.1.1 resMRegion
A pointer to the result ~MRegion~.
*/
MRegion* resMRegion;
/*
1.1.1 parent
A pointer to the parent object.
*/
const SourceUnitPair* const parent;
/*
1.1.1 resultUnit
A pointer to the current ~ResultUnit~.
*/
ResultUnit* resultUnit;
/*
1.1.1 Attributes used for debugging
*/
unsigned int noUnits;
unsigned int noEmptyUnits;
unsigned int evalutedIntSegs;
unsigned int noMSegsValid;
unsigned int noMSegsSkipped;
unsigned int noMSegCritical;
unsigned int decisionsByPlumbline;
unsigned int decisionsByEntirelyInOut;
unsigned int decisionsByAdjacency;
unsigned int decisionsByDegeneration;
std::vector<std::string> vrml;
};
/*
1 Class SourceUnitPair
This class is essentially a container for both ~SourceUnits~ A and B,
creates and initialise the ~ResultUnitFactory~ and runs the main-loop
of the set operation by calling the method ~Operate~.
*/
class SourceUnitPair {
public:
/*
1.1 Constructor
The constructor takes essentially two pointers to ~URegionEmb~ instances,
one pointer to the global result ~MRegion~ and an enum to indicate the
kind of set operation.
*/
SourceUnitPair(URegionEmb* const unitA,
const DbArray<MSegmentData>* const aArray,
const bool aIsEmpty,
URegionEmb* const unitB,
const DbArray<MSegmentData>* const bArray,
const bool bIsEmpty,
const SetOp operation,
MRegion* const resultMRegion);
/*
1.1 Getter and setter methods
1.1.1 GetOperation
Returns an enum to indicate the current set operation:
INTERSECTION, UNION or MINUS.
*/
inline const SetOp GetOperation() const {
return op;
}
/*
1.1.1 GetOverlapRect
Returns the intersection of the projection bounding rectangles of
both ~SourceUnits~, A and B.
*/
inline Rectangle<2> GetOverlapRect() const {
return overlapRect;
}
/*
1.1.1 HasOverlappingBoundingRect
Returns ~true~, if the intersection of the projection bounding rectangles of
both ~SourceUnits~ is not empty.
*/
inline bool HasOverlappingBoundingRect() const {
return overlapRect.IsDefined();
}
/*
1.1.1 GetTimeInterval
Returns the common current interval of both ~SourceUnits~.
*/
inline const Interval<Instant>& GetTimeInterval() const {
return unitA.GetTimeInterval();
}
/*
1.1.1 GetOriginalTimeInterval
Returns the common original interval of both ~SourceUnits~
before normalization.
*/
inline const Interval<Instant>& GetOriginalTimeInterval() const {
return unitA.GetOriginalTimeInterval();
}
/*
1.1.1 GetStart/EndTime
Returns the start/end of the interval as double value.
*/
inline double GetStartTime() const {
return unitA.GetStartTime();
}
inline double GetEndTime() const {
return unitA.GetEndTime();
}
/*
1.1.1 HasNormalizedTimeInterval
Returns ~true~, if the interval was normalized to 1.0.
This might be useful to improve the numerical stability of very thin units.
*/
inline bool HasNormalizedTimeInterval() const {
return unitA.HasNormalizedTimeInterval();
}
/*
1.1 Operators
1.1.1 Operate
This method runs the main-loop of the set operation by calling
the following methods:
1 CreatePFaces
2 ComputeIntSegs
3 CollectRelevantPFaces
4 ConstructResultUnits
*/
void Operate();
/*
1.1.1 AddGlobalTimeValue
Adds a relevant timevalue, which marks the border of a result unit.
This value is passed to the ~ResultUnitFactory~.
*/
inline void AddGlobalTimeValue(double t) {
resultUnitFactory.AddTimeValue(t);
}
/*
1.1 Methods for debugging
*/
void PrintPFaces();
void ToVrmlFile(bool a, bool b, bool res);
private:
/*
1.1 Private methods
1.1.1 CreatePFaces
Calls ~SourceUnit::CreatePFaces~ on both instances.
*/
void CreatePFaces();
/*
1.1.1 ComputeIntSegs
Intersects each ~PFace~ from ~SourceUnit A~ with each ~PFace~ from
~SourceUnit B~. The result might be an ~IntersectionSegment~ pair.
*/
void ComputeIntSegs();
/*
1.1.1 CollectRelevantPFaces
Performs a linear scan over all ~PFaces~ of both ~SourceUnits~,
collecting those which are relevant for the result and
pass them to the ~ResultUnitFactory~.
*/
void CollectRelevantPFaces();
/*
1.1.1 ConstructResultUnits
Runs the construction of all result units by calling
~ResultUnitFactory::Start~.
*/
void ConstructResultUnits();
/*
1.1.1 ComputeOverlapRect
Computes the intersection of the projection bounding rectangles of
both ~SourceUnits~.
*/
void ComputeOverlapRect();
/*
1.1 Attributes
*/
SourceUnit unitA;
SourceUnit unitB;
const SetOp op;
Rectangle<2> overlapRect;
MRegion* const resultMRegion;
ResultUnitFactory resultUnitFactory;
};
/*
1 Class IntersectionSegment
This class represents essentially an oriented segment in the xyt-space.
Each intersection of two non-disjunct ~PFaces~ create a pair of two
~IntersectionSegment~ instances.
Each instance keeps a pointer to the ~PFace~, it belongs to.
*/
class IntersectionSegment {
public:
/*
1.1 Constructor
The constructor assures the condition: $startpoint.t <= endpoint.t$
*/
IntersectionSegment(const Segment3D& s);
/*
1.1 Getter and setter methods
1.1.1 GetPFace
Returns a pointer to the ~PFace~, this instance belongs to.
*/
inline const PFace* GetPFace() const {
assert(pFace != 0);
return pFace;
}
/*
1.1.1 SetPFace
Initialise the field ~pFace~.
*/
inline void SetPFace(const PFace* _pFace) {
assert(pFace == 0);
pFace = _pFace;
}
/*
1.1.1 SetWCoords
Intitialise the fields ~startWT~ and ~endWT~ by the transformations:
* startXYT [->] startWT
* endXYT [->] endWT
*/
void SetWCoords();
/*
1.1.1 Get$<$Coordinate$>$ methods
This methods returns points of this ~IntersectionSegment~
either in xyt-coords or in wt-coords.
*/
inline const Point3D* GetStartXYT() const {
return &startXYT;
}
inline const Point2D GetStartXY() const {
return Point2D(startXYT);
}
inline double GetStartT() const {
return startXYT.GetT();
}
inline const Point3D* GetEndXYT() const {
return &endXYT;
}
inline const Point2D GetEndXY() const {
return Point2D(endXYT);
}
inline double GetEndT() const {
return endXYT.GetT();
}
inline const Point2D* GetStartWT() const {
return &startWT;
}
inline const Point2D* GetEndWT() const {
return &endWT;
}
inline double GetStartW() const {
return startWT.GetW();
}
inline double GetEndW() const {
return endWT.GetW();
}
/*
1.1 Operators and Predicates
1.1.1 IsOrthogonalToTAxis
Returns ~true~, if this is parallel to the xy-plane.
*/
inline bool IsOrthogonalToTAxis() const {
return NumericUtil::NearlyEqual(GetStartT(), GetEndT());
}
/*
1.1.1 IsLeftOf
Returns ~true~, if this is left of intSeg.
Preconditions:
* $intSeg.startpoint.t <= this.startpoint.t <= intSeg.endpoint.t$
* this and intSeg don't intersect in their interior.
*/
bool IsLeftOf(const IntersectionSegment* intSeg) const;
/*
1.1.1 Evaluate
Returns the point (in xyt-coords) on this segment with t-coord t.
Precondition: $startpoint.t <= t <= endpoint.t$
*/
Point3D Evaluate(const double t) const;
/*
1.1 Methods for debugging
*/
inline unsigned int GetID() const {
return id;
}
std::string GetVRMLDesc();
void Print() const;
private:
/*
1.1 Private methods
*/
inline void SetStartWT(const Point2D& _startWT) {
startWT = _startWT;
}
inline void SetEndWT(const Point2D& _endWT) {
endWT = _endWT;
}
/*
1.1 Attributes
1.1.1 id
A unique id for each instance.
Used for debugging only.
*/
unsigned int id;
static unsigned int instanceCount;
/*
1.1.1 startXYT and endXYT
Start- and endpoint of this segment in xyt-coordinates.
Note that they are independed of the ~PFace~.
*/
Point3D startXYT;
Point3D endXYT;
/*
1.1.1 startWT and endWT
Start- and endpoint of this segment in wt-coordinates.
Note that the w-coord depends on the ~PFace~.
We store them here for the sake of efficency.
*/
Point2D startWT;
Point2D endWT;
/*
1.1.1 pFace
A pointer to the ~PFace~, this instance belongs to.
*/
const PFace* pFace;
};
/*
1 Class MSegment
This class represents a moving segment, which is constructed by
the ~ResultUnitFactory~.
*/
class MSegment {
public:
/*
1.1 Constructor
*/
MSegment(const Segment3D& initial,
const Segment3D& median,
const Segment3D& final,
const PFace* const pFace);
/*
1.1 Getter and setter methods
1.1.1 GetPFace
Returns a pointer to the ~PFace~, this ~MSegment~ comes from.
*/
inline const PFace* GetPFace() const {
return pFace;
}
/*
1.1.1 GetInitial/GetFinal
Returns the initial/final state of this ~MSegment~.
This segment might be degenerated to a point.
*/
inline const Segment2D& GetInitial() const {
return initial;
}
inline const Segment2D& GetFinal() const {
return final;
}
/*
1.1.1 GetMedian
Returns the median state of this ~MSegment~.
This segment can never degenerate.
*/
inline const Segment2D& GetMedian() const {
return median;
}
/*
1.1.1 GetMedianHS
Returns the median state of this ~MSegment~ as ~HalfSegment~.
This segment can never degenerate.
*/
inline const HalfSegment& GetMedianHS() const {
return medianHS;
}
/*
1.1.1 GetFaceNo/GetCycleNo/GetSegmentNo
Returns the faceno/cycleno/edgeno of this ~MSegment~.
*/
inline int GetFaceNo() const {
return medianHS.attr.faceno;
}
inline int GetCycleNo() const {
return medianHS.attr.cycleno;
}
inline int GetSegmentNo() const {
return medianHS.attr.edgeno;
}
/*
1.1.1 GetInsideAbove
Returns the flag insideAbove of this ~MSegment~.
*/
inline int GetInsideAbove() const {
return insideAbove;
}
/*
1.1.1 GetStartAsListExpr/GetEndAsListExpr
Coverts this ~MSegment~ to ~ListExpr~.
*/
inline const ListExpr GetStartAsListExpr() const {
return NList(NList(initial.GetStart().GetX()),
NList(initial.GetStart().GetY()),
NList(final.GetStart().GetX()),
NList(final.GetStart().GetY())).listExpr();
}
inline const ListExpr GetEndAsListExpr() const {
return NList(NList(initial.GetEnd().GetX()),
NList(initial.GetEnd().GetY()),
NList(final.GetEnd().GetX()),
NList(final.GetEnd().GetY())).listExpr();
}
/*
1.1.1 IsLeftDomPoint
Returns ~true~, if this ~MSegment~ is a left one.
Note: This is indicated by the median ~HalfSegment~.
*/
inline bool IsLeftDomPoint() const {
return medianHS.IsLeftDomPoint();
}
/*
1.1.1 SetLeftDomPoint
Marks this ~MSegment~ as left.
*/
inline void SetLeftDomPoint(bool ldp) {
medianHS.SetLeftDomPoint(ldp);
}
/*
1.1.1 SetSegmentNo
Sets the segmentno to sn.
*/
inline void SetSegmentNo(int sn) {
medianHS.attr.edgeno = sn;
}
/*
1.1 Operators and Predicates
1.1.1 CopyIndicesFrom
Copies the faceno/cycleno/edgeno from hs to this.
*/
inline void CopyIndicesFrom(const HalfSegment* hs) {
medianHS.attr.faceno = hs->attr.faceno;
medianHS.attr.cycleno = hs->attr.cycleno;
medianHS.attr.edgeno = hs->attr.edgeno;
//medianHS.attr.insideAbove = hs->attr.insideAbove;
}
/*
1.1.1 IsParallel
Returns ~true~, if this ~MSegment~ is parallel to ms.
*/
bool IsParallel(const MSegment& ms) const;
/*
1.1.1 LessByMedianHS
Returns ~true~, if the median ~HalfSegment~ of this is
lower than the median ~HalfSegment~ of ms,
according to the ~HalfSegment~ order, specified in the ~SpatialAlgebra~.
*/
inline bool LessByMedianHS(const MSegment& ms) const {
return GetMedianHS() < ms.GetMedianHS();
}
/*
1.1.1 LogicLess
Returns ~true~, if the median ~HalfSegment~ of this is
lower than the median ~HalfSegment~ of ms,
similar to ~HalfSegment::LogicCompare~, specified in the ~SpatialAlgebra~.
*/
inline bool LogicLess(const MSegment& ms) const {
if (IsLeftDomPoint() != ms.IsLeftDomPoint())
return IsLeftDomPoint() > ms.IsLeftDomPoint();
return GetMedianHS().LogicCompare(ms.GetMedianHS()) == -1;
}
/*
1.1 Methods for debugging
*/
void Print() const;
private:
/*
1.1 Attributes
1.1.1 initial/median/final
The initial/median/final state as ~Segment2D~.
*/
Segment2D initial;
Segment2D median;
Segment2D final;
/*
1.1.1 medianHS
The median state as ~HalfSegment~.
*/
HalfSegment medianHS;
/*
1.1.1 insideAbove
The flag insideAbove.
*/
bool insideAbove;
/*
1.1.1 pFace
A pointer to the ~PFace~, this ~MSegment~ comes from.
*/
const PFace* pFace;
};
/*
1 Class MSegmentCritical
This class extends the class ~MSegment~ with the attribute ~midPoint~,
which is needed to handle critical ~MSegments~.
A pair of critical ~MSegments~ is constructed as a result of the
intersection of two overlapping coplanar PFaces.
*/
class MSegmentCritical : public MSegment {
public:
/*
1.1 Constructor
*/
MSegmentCritical(const Segment3D& _initial,
const Segment3D& _median,
const Segment3D& _final,
const Point3D& _midPoint,
const PFace* const _pFace) :
MSegment(_initial, _median, _final, _pFace),
midPoint(_midPoint) {
}
/*
1.1 Getter and setter methods
1.1.1 GetMidPoint
Returns the midpoint of this ~MSegmentCritical~, which is equal to
the midpoint of the median ~HalfSegment~.
*/
inline const Point2D& GetMidpoint() const {
return midPoint;
}
/*
1.1 Operators and Predicates
1.1.1 IsPartOfUnitA
Returns ~true~, if the ~Face~ of this belongs to ~SourceUnit~ A.
*/
bool IsPartOfUnitA() const;
/*
1.1.1 HasEqualNormalVector
Returns ~true~, if the normal vectors of this' and pf' ~Face~ are equal.
*/
bool HasEqualNormalVector(const MSegmentCritical& msc) const;
/*
1.1.1 Operator $<$
Returns ~true~, if the midPoint of this is lower as the midpoint of msc.
*/
bool operator <(const MSegmentCritical& msc) const {
return midPoint < msc.midPoint;
}
private:
/*
1.1 Attributes
1.1.1 midPoint
The midpoint of this ~MSegmentCritical~, which is equal to
the midpoint of the median ~HalfSegment~.
*/
Point2D midPoint;
};
/*
1 Class ResultUnit
This class essentially collects at first all ~MSegments~ of a result unit,
produced by the ~ResultUnitFactory~. Afterwards, the ~MSegments~ will be
suitably linked together, to form a proper ~URegionEmb~. This is done by
calling the method EndBulkLoad.
*/
class ResultUnit {
public:
/*
1.1 Constructor
*/
ResultUnit(const Interval<Instant> _interval) :
interval(_interval),
index(0) {
}
/*
1.1 Getter and setter methods
1.1.1 GetInterval
Returns the interval as set by the constructor.
*/
inline const Interval<Instant>& GetInterval() const {
return interval;
}
/*
1.1 Operators and Predicates
1.1.1 StartBulkLoad
This method must be called before adding the first ~MSegment~.
*/
inline void StartBulkLoad() {
index = 0;
}
/*
1.1.1 AddSegment
Adds a ~MSegment~ to this ~ResultUnit~.
*/
inline void AddSegment(MSegment ms) {
ms.SetSegmentNo(index++);
ms.SetLeftDomPoint(true);
msegments.push_back(ms);
ms.SetLeftDomPoint(false);
msegments.push_back(ms);
}
/*
1.1.1 EndBulkLoad
This method must be called after adding the last ~MSegment~ and
performs the following tasks:
* Sort the list ~ms~ of the ~MSegments~ by their median ~HalfSegments~,
using ~MSegment::LessByMedianHS~ for comparison.
* Construct a ~Region~ ~r~ from all median ~HalfSegments~ of ~ms~.
* Copy the faceNo, cycleNo and edgeNo of each ~HalfSegment~ of ~r~ to
the corresponding ~MSegment~ of ~ms~. Since ~r~ and ~ms~ has the same order
this can be done by a linear scan.
* Sort ~ms~ by faceno, cycleno and segmentno,
using ~MSegment::LogicLess~ for comparison.
The parameter ~merge~ is not used yet.
*/
void EndBulkLoad(bool merge);
/*
1.1.1 ConvertToListExpr
Converts this ~ResultUnit~ to a ~ListExpr~.
*/
const ListExpr ConvertToListExpr() const;
/*
1.1.1 ConvertToURegionEmb
Converts this ~ResultUnit~ to a ~URegionEmb~.
*/
URegionEmb* ConvertToURegionEmb(DbArray<MSegmentData>* segments) const;
/*
1.1.1 IsEmpty
Returns ~true~, if this ~ResultUnit~ contains no ~MSegments~.
*/
inline bool IsEmpty() const {
return msegments.size() == 0;
}
/*
1.1 Methods for debugging
*/
void Print(const bool segments = true) const;
std::string GetVRMLDesc() const;
bool Check() const;
private:
/*
1.1 Private methods
*/
void AddMSegmentData(URegionEmb* uregion,
DbArray<MSegmentData>* segments,
MSegmentData& dms) const;
static bool Less(const MSegment& ms1, const MSegment& ms2) {
return ms1.LessByMedianHS(ms2);
}
static bool LogicLess(const MSegment& ms1, const MSegment& ms2) {
return ms1.LogicLess(ms2);
}
/*
1.1 Attributes
1.1.1 interval
The interval of this ~ResultUnit~
*/
const Interval<Instant> interval;
/*
1.1.1 msegments
The list of the ~MSegments~.
*/
std::vector<MSegment> msegments;
/*
1.1.1 index
A counter, used in ~AddSegment~.
*/
unsigned int index;
};
/*
1 Enumeration SourceFlag
Indicates the source unit of a ~Point3DExt~.
*/
enum SourceFlag {
PFACE_A,
PFACE_B
};
/*
1 Class Point3DExt
This datastructure is used in the class ~PointExtSet~.
It simply extends ~Point3D~ with the attribute ~sourceFlag~.
*/
class Point3DExt : public Point3D {
public:
/*
1.1 Constructors
*/
inline Point3DExt() :
Point3D() {
}
inline Point3DExt(double a, double b, double c, SourceFlag _sourceFlag) :
Point3D(a, b, c),
sourceFlag(_sourceFlag) {
}
/*
1.1 Operators and Predicates
1.1.1 operator $<$
*/
bool operator <(const Point3DExt& p) const;
/*
1.1 Attributes
1.1.1 sourceFlag
An enum, indicating the ~PFace~, this ~Point3D~ belongs to.
Possible values are:
* $PFACE\_A$
* $PFACE\_B$
*/
SourceFlag sourceFlag;
};
/*
1 Class PointExtSet
This set is used in the class ~PFace~ to compute the intersection segment of
two ~PFaces~.
*/
class PointExtSet {
public:
/*
1.1 Constructors
*/
inline PointExtSet() {
}
/*
1.1 Operators and Predicates
1.1.1 Insert
Inserts p, if p isn't already inserted.
*/
inline void Insert(const Point3DExt& p) {
s.insert(p);
}
/*
1.1.1 Size
Returns the number of points in the set.
*/
inline unsigned int Size() const {
return s.size();
}
/*
1.1.1 GetIntersectionSegment
Returns ~true~, if there is an intersection segment and writes it to result.
*/
bool GetIntersectionSegment(Segment3D& result) const;
/*
1.1 Methods for debugging
*/
void Print() const;
private:
/*
1.1 Attributes
1.1.1 s
A ~std::set~, using the overloaded operator $<$ for comparison.
*/
std::set<Point3DExt> s;
};
/*
1 Struct IntSegCompare
This struct implements the ~IntersectionSegment~ order,
used in ~IntSegContainer~.
*/
struct IntSegCompare {
bool operator()(const IntersectionSegment* const& s1,
const IntersectionSegment* const& s2) const;
};
/*
1 Class IntSegContainer
This class is used by the class ~PFace~ and provides essentially
* an ordered set of ~IntersectionSegments~
* an ordered multiset of critical timelevels
* the ability to perform a plane-sweep in t-direction from bottom to top.
*/
class IntSegContainer {
public:
/*
1.1 Constructor
*/
inline IntSegContainer() :
firstTimeLevel(true),
lastDecision(UNDEFINED) {
}
/*
1.1 Destructor
*/
~IntSegContainer();
/*
1.1 Operators
1.1.1 AddIntSeg
Adds seg to the set of ~IntersectionSegments~.
*/
inline void AddIntSeg(IntersectionSegment* seg) {
intSegs.insert(seg);
}
/*
1.1.1 AddCriticalTime
Adds t to the multiset of critical timelevels.
*/
inline void AddCriticalTime(const double& t) {
criticalTimes.insert(t);
}
/*
1.1.1 GetActiveIntSegs
Returns a pointer to a list of the currently active ~IntersectionSegments~,
according to the previous call of ~UpdateTimeLevel~. An ~IntersectionSegment~ s
is active at time t, if the condition $s.startpoint.t <= t < s.endpoint.t$
holds.
*/
inline const std::list<IntersectionSegment*>* GetActiveIntSegs() const {
return &active;
}
/*
1.1.1 UpdateTimeLevel
Updates the list of the currently active ~IntersectionSegments~: Insert
segments with $startpoint.t = t$ and remove segments with $endpoint.t = t$.
*/
void UpdateTimeLevel(double t);
/*
1.1.1 SetLastDecision
Remembers the decision for the first brick of the current timelevel.
*/
inline void SetLastDecision(const Decision d) {
lastDecision = d;
}
/*
1.1.1 GetLastDecision
Returns the correct decision for the first brick of a new timelevel.
Precondition: ~UpdateTimeLevel~ was already called.
*/
inline const Decision GetLastDecision() const {
if (lastDecision == UNDEFINED) {
return UNDEFINED;
}
if (criticalTimes.count(t) % 2 == 0) {
return lastDecision;
}
if (lastDecision == ACCEPT)
return SKIP;
else
return ACCEPT;
}
/*
1.1 Methods for debugging
*/
void Print() const;
void PrintActive() const;
private:
/*
1.1 Private methods
*/
inline bool IsOutOfRange(IntersectionSegment* seg) const {
return NumericUtil::NearlyEqual(seg->GetEndT(), t);
}
inline bool HasMoreSegsToInsert() const {
return intSegIter != intSegs.end() &&
NumericUtil::NearlyEqual((*intSegIter)->GetStartT(), t);
}
/*
1.1 Attributes
1.1.1 intSegs, intSegIter
A ~std::set~ to store the ~IntersectionSegments~ using the order
provided by ~IntSegCompare~ and a suitable iterator.
*/
std::set<IntersectionSegment*, IntSegCompare> intSegs;
std::set<IntersectionSegment*, IntSegCompare>::iterator intSegIter;
/*
1.1.1 active, activeIter
A ~std::list~ to store the active ~IntersectionSegments~ during the plane-sweep
and a suitable iterator.
*/
std::list<IntersectionSegment*> active;
std::list<IntersectionSegment*>::iterator activeIter;
/*
1.1.1 criticalTimes
A ~std::multiset~ to store the the critical timelevels.
*/
std::multiset<double, DoubleCompare> criticalTimes;
/*
1.1.1 t
The current timelevel.
*/
double t;
/*
1.1.1 firstTimeLevel
A flag, indicating that the current timelevel is the lowest one.
*/
bool firstTimeLevel;
/*
1.1.1 lastDecision
An enum, that stores the decision for the first brick of the current timelevel:
* UNDEFINED
* ACCEPT
* SKIP
*/
Decision lastDecision;
};
/*
1 Enumeration Boundary
Used in the class ~PFace~ to indicate the border.
*/
enum Boundary {
LEFT_BOUNDARY,
RIGHT_BOUNDARY
};
/*
1 Enumeration RelationToBoundary
Used in the class ~PFace~ to indicate the relation of an
~IntersectionSegment~ to the ~PFace~ boundary.
*/
enum RelationToBoundary {
NO_TOUCH,
TOUCH_IN_STARTPOINT,
TOUCH_IN_ENDPOINT,
COLINEAR
};
/*
1 Enumeration State
Used in the class ~PFace~ to indicate it's current state.
*/
enum State {
UNKNOWN,
ENTIRELY_INSIDE,
ENTIRELY_OUTSIDE,
RELEVANT_NOT_CRITICAL,
RELEVANT_CRITICAL,
NOT_RELEVANT
};
/*
1 Class PFace
This class represents essentially a movingsegment,
viewed as a polygonal face in a 3-dimensional xyt-space(time).
Due to the restrictions of movingsegments,
a ~PFace~ can be either a planar trapezium or a triangle.
To simplify computations, we define another 2-dimensional coordinate system for
each ~PFace~: The wt-system, which is basically constructed as follows:
* We keep the t-axis from the xyt-system.
* The w-unitvector is given by the crossproduct of the t-unitvector and
the normalvector of the ~PFace~.
*/
class PFace {
public:
/*
1.1 Constructor
*/
PFace(SourceUnit* _unit, const MSegmentData* _mSeg);
/*
1.1 Getter and setter methods
1.1.1 GetMSeg
Returns a pointer to the corresponding ~MSegmentData~ instance.
*/
inline const MSegmentData* GetMSeg() const {
return mSeg;
}
/*
1.1.1 GetBoundingRect
Returns the projection bounding rectangle in xy-coords.
*/
inline Rectangle<2> GetBoundingRect() const {
return boundingRect;
}
/*
1.1.1 GetStartTime/GetEndTime
Returns the min./max. value of t.
*/
inline double GetStartTime() const {
return unit->GetStartTime();
}
inline double GetEndTime() const {
return unit->GetEndTime();
}
/*
1.1.1 GetA XYT
Returns the lower left point in xyt-coords of the ~PFace~,
if viewed from outside.
*/
inline Point3D GetA_XYT() const {
if (InitialStartPointIsA())
return Point3D(mSeg->GetInitialStartX(), mSeg->GetInitialStartY(),
unit->GetStartTime());
else
return Point3D(mSeg->GetInitialEndX(), mSeg->GetInitialEndY(),
unit->GetStartTime());
}
/*
1.1.1 GetB XYT
Returns the lower right point in xyt-coords of the ~PFace~,
if viewed from outside.
*/
inline Point3D GetB_XYT() const {
if (InitialStartPointIsA())
return Point3D(mSeg->GetInitialEndX(), mSeg->GetInitialEndY(),
unit->GetStartTime());
else
return Point3D(mSeg->GetInitialStartX(), mSeg->GetInitialStartY(),
unit->GetStartTime());
}
/*
1.1.1 GetC XYT
Returns the upper left point in xyt-coords of the ~PFace~,
if viewed from outside.
*/
inline Point3D GetC_XYT() const {
if (InitialStartPointIsA())
return Point3D(mSeg->GetFinalStartX(), mSeg->GetFinalStartY(),
unit->GetEndTime());
else
return Point3D(mSeg->GetFinalEndX(), mSeg->GetFinalEndY(),
unit->GetEndTime());
}
/*
1.1.1 GetD XYT
Returns the upper right point in xyt-coords of the ~PFace~,
if viewed from outside.
*/
inline Point3D GetD_XYT() const {
if (InitialStartPointIsA())
return Point3D(mSeg->GetFinalEndX(), mSeg->GetFinalEndY(),
unit->GetEndTime());
else
return Point3D(mSeg->GetFinalStartX(), mSeg->GetFinalStartY(),
unit->GetEndTime());
}
/*
1.1.1 GetA WT
Returns the lower left point in wt-coords of the ~PFace~,
if viewed from outside.
*/
inline Point2D GetA_WT() const {
return Point2D(aW, unit->GetStartTime());
}
/*
1.1.1 GetB WT
Returns the lower right point in wt-coords of the ~PFace~,
if viewed from outside.
*/
inline Point2D GetB_WT() const {
return Point2D(bW, unit->GetStartTime());
}
/*
1.1.1 GetC WT
Returns the upper left point in wt-coords of the ~PFace~,
if viewed from outside.
*/
inline Point2D GetC_WT() const {
return Point2D(cW, unit->GetEndTime());
}
/*
1.1.1 GetD WT
Returns the upper right point in wt-coords of the ~PFace~,
if viewed from outside.
*/
inline Point2D GetD_WT() const {
return Point2D(dW, unit->GetEndTime());
}
/*
1.1.1 GetNormalVector
Returns the normal unitvector of this ~PFace~,
which is pointing to the outside.
*/
inline Vector3D GetNormalVector() const {
return normalVector;
}
/*
1.1.1 GetOperation
Returns an enum to indicate the current set operation:
INTERSECTION, UNION or MINUS.
*/
inline const SetOp GetOperation() const {
return unit->GetOperation();
}
/*
1.1.1 GetWVector
Returns the w-unitvector of this ~PFace~,
which defines the w-axis of the wt-system.
The vector w is either the normalized cross product
of the normal vector and the t-unit-vector, or it's negative.
This depends on the kind of set-operation, we want to perform.
*/
inline Vector3D GetWVector() const {
return wVector;
}
/*
1.1.1 GetBoundary
Returns a ~Segment2D~ which represents the left or right boundary
of this ~PFace~, as specified by the parameter b.
Note that the result depends on the kind of set operation.
*/
inline Segment2D GetBoundary(const Boundary b) const {
if (GetOperation() == MINUS && IsPartOfUnitB()) {
if (b == LEFT_BOUNDARY)
return Segment2D(GetA_WT(), GetC_WT());
else
return Segment2D(GetB_WT(), GetD_WT());
} else {
if (b == RIGHT_BOUNDARY)
return Segment2D(GetA_WT(), GetC_WT());
else
return Segment2D(GetB_WT(), GetD_WT());
}
}
/*
1.1 Operators and Predicates
1.1.1 AEqualsB
Returns ~true~, if this ~PFace~ is a triangle and
the edge AB is degenerated to a point.
*/
inline bool AEqualsB() const {
return mSeg->GetPointInitial();
}
/*
1.1.1 CEqualsD
Returns ~true~, if this ~PFace~ is a triangle and
the edge CD is degenerated to a point.
*/
inline bool CEqualsD() const {
return mSeg->GetPointFinal();
}
/*
1.1.1 Intersection
Computes the intersection of this ~PFace~ with pf and adds
one ~IntersectionSegment~ instance to both ~PFaces~.
*/
void Intersection(PFace& pf);
/*
1.1.1 IsParallelTo
Returns ~true~, if this ~PFace~ is parallel to the ~PFace~ pf.
*/
bool IsParallelTo(const PFace& pf) const;
/*
1.1.1 IsCoplanarTo
Returns ~true~, if this ~PFace~ is coplanar to the argument.
*/
bool IsCoplanarTo(const PFace& pf) const;
bool IsCoplanarTo(const Point3D& p) const;
bool IsCoplanarTo(const Segment3D& s) const;
bool IsCoplanarTo(const IntersectionSegment& s) const;
/*
1.1.1 HasEqualNormalVector
Returns ~true~, if the normalvectors of this and pf are equal.
*/
bool HasEqualNormalVector(const PFace& pf) const;
/*
1.1.1 TransformToWT
Transforms the argument from the xyt-system to the wt-system.
*/
inline double TransformToW(const Point3D& xyt) const {
return xyt.GetX() * GetWVector().GetX() +
xyt.GetY() * GetWVector().GetY();
}
inline double TransformToW(const Vector3D& xyt) const {
return xyt.GetX() * GetWVector().GetX() +
xyt.GetY() * GetWVector().GetY();
}
inline Vector2D TransformToWT(const Vector3D& xyt) const {
return Vector2D(TransformToW(xyt), xyt.GetT() );
}
inline Point2D TransformToWT(const Point3D& xyt) const {
return Point2D(TransformToW(xyt), xyt.GetT());
}
inline Segment2D TransformToWT(const Segment3D& xyt) const {
return Segment2D(TransformToWT(xyt.GetStart()),
TransformToWT(xyt.GetEnd()));
}
/*
1.1.1 MarkAsEntirelyOutside
Marks this ~PFace~ as entirely outside the other mregion.
*/
inline void MarkAsEntirelyOutside() {
state = ENTIRELY_OUTSIDE;
}
/*
1.1.1 IsEntirelyOutside
Returns ~true~, if this ~PFace~ is entirely outside the other mregion.
*/
inline bool IsEntirelyOutside() const {
return state == ENTIRELY_OUTSIDE;
}
/*
1.1.1 MarkAsEntirelyInside
Marks this ~PFace~ as entirely inside the other mregion.
*/
inline void MarkAsEntirelyInside() {
state = ENTIRELY_INSIDE;
}
/*
1.1.1 IsEntirelyInside
Returns ~true~, if this ~PFace~ is entirely inside the other mregion.
*/
inline bool IsEntirelyInside() const {
return state == ENTIRELY_INSIDE;
}
/*
1.1.1 MarkAsNormalRelevant
Marks this ~PFace~ as normal relevant for the result mregion.
This means, that no critical case occured during the intersection process.
*/
inline void MarkAsNormalRelevant() {
if (!IsCriticalRelevant())
state = RELEVANT_NOT_CRITICAL;
}
/*
1.1.1 MarkAsCriticalRelevant
Marks this ~PFace~ as critical relevant for the result mregion.
This means, that at least one critical case occured during the
intersection process.
*/
inline void MarkAsCriticalRelevant() {
state = RELEVANT_CRITICAL;
}
/*
1.1.1 MarkAsIrrelevant
Marks this ~PFace~ as irrelevant for the result mregion.
*/
inline void MarkAsIrrelevant() {
state = NOT_RELEVANT;
}
/*
1.1.1 IsNormalRelevant
Returns ~true~, if this ~PFace~ is normal relevant for the result mregion.
*/
inline bool IsNormalRelevant() const {
return state == RELEVANT_NOT_CRITICAL;
}
/*
1.1.1 IsCriticalRelevant
Returns ~true~, if this ~PFace~ is critical relevant
for the result mregion.
*/
inline bool IsCriticalRelevant() const {
return state == RELEVANT_CRITICAL;
}
/*
1.1.1 IsIrrelevant
Returns ~true~, if this ~PFace~ is irrelevant for the result mregion.
*/
inline bool IsIrrelevant() const {
return state == NOT_RELEVANT;
}
/*
1.1.1 GetUnit
Returns a pointer to the ~SourceUnit~ this ~PFace~ belongs to.
*/
inline SourceUnit* GetUnit() const {
return unit;
}
/*
1.1.1 IsPartOfUnitA/B
Returns ~true~, if this ~PFace~ belongs to ~SourceUnit~ A/B.
*/
inline bool IsPartOfUnitA() const {
return unit->IsUnitA();
}
inline bool IsPartOfUnitB() const {
return !unit->IsUnitA();
}
/*
1.1.1 GetState
Returns an enum to indicate the state of this ~PFace~.
*/
inline State GetState() const {
return state;
}
/*
1.1.1 HasInnerIntSegs
Returns ~true~, if this ~PFace~ contains ~IntersectionSegments~ which are not
colinear to the boundary.
*/
inline bool HasInnerIntSegs() const {
return hasInnerIntSegs;
}
/*
1.1.1 IsColinearToBoundary
Returns ~true~, if s is colinear to the left or right boundary of this ~PFace~.
*/
bool IsColinearToBoundary(const Segment3D& s) const;
/*
1.1.1 GetMidPoint
Returns the midpoint of this ~PFace~.
Note that this point is never part of the boundary.
*/
const Point3D GetMidPoint() const;
/*
1.1.1 GetRelationToBoundary
Returns an enum to indicate the spatial relationship of s and b.
*/
const RelationToBoundary
GetRelationToBoundary(const Segment3D& s, const Boundary b) const;
/*
1.1 Methods used by ~ResultUnitFactory~.
The ~ResultUnitFactory~ performs a plane-sweep in t-direction
from bottom to top, over all relevant ~PFaces~, to construct the result units.
1.1.1 Finalize
This method is called before the plane-sweep starts and
adds two ~IntersectionSegments~ to each relevant ~PFace~:
The left and right border.
*/
inline void Finalize() {
DecideRelevanceAndAddBoundary();
}
/*
1.1.1 GetActiveIntSegs
Returns a pointer to a list of the currently active ~IntersectionSegments~,
according to the previous call of ~UpdateTimeLevel~. An ~IntersectionSegment~ s
is active at time t, if the condition $s.startpoint.t <= t < s.endpoint.t$
holds.
*/
inline const std::list<IntersectionSegment*>* GetActiveIntSegs() const {
return intSegs.GetActiveIntSegs();
}
/*
1.1.1 UpdateTimeLevel
Updates the list of the currently active ~IntersectionSegments~: Insert
segments with $startpoint.t = t$ and remove segments with $endpoint.t = t$.
*/
inline void UpdateTimeLevel(double t) {
intSegs.UpdateTimeLevel(t);
}
/*
1.1.1 SetLastDecision
Remembers the decision for the first brick of the current timelevel.
*/
inline void SetLastDecision(const Decision d) {
intSegs.SetLastDecision(d);
}
/*
1.1.1 GetLastDecision
Returns the correct decision for the first brick of a new timelevel,
or UNDEFINED, if this ~PFace~ is critical.
Precondition: ~UpdateTimeLevel~ is already called.
*/
inline const Decision GetLastDecision() const {
if (IsCriticalRelevant())
return UNDEFINED;
return intSegs.GetLastDecision();
}
/*
1.1 Methods for debugging
*/
inline unsigned int GetID() const {
return id;
}
std::string GetVRMLDesc();
std::string GetStateAsString() const;
void Print() const;
private:
/*
1.1 Private methods
*/
inline bool InitialStartPointIsA() const {
return initialStartPointIsA;
}
void SetInitialStartPointIsA();
void ComputeBoundingRect();
void ComputeNormalVector();
void ComputeWTCoords();
bool IntersectionPlaneSegment(const Segment3D& seg, Point3D& result);
void DecideRelevanceAndAddBoundary();
void AddEntireBoundary();
void AddIntSeg(const Segment3D& seg, PFace& other);
void AddBoundaryIntSeg(const Segment3D& seg);
/*
1.1 Attributes
1.1.1 unit
A pointer to the ~SourceUnit~, this ~PFace~ belongs to.
*/
SourceUnit* const unit;
/*
1.1.1 mSeg
A pointer to the ~MSegmentData~, this ~PFace~ represents.
*/
const MSegmentData* const mSeg;
/*
1.1.1 boundingRect
The projection bounding rectangle in xy-coords.
*/
Rectangle<2> boundingRect;
/*
1.1.1 normalVector
The normal vector of this ~PFace~, pointing to the outside.
*/
Vector3D normalVector;
/*
1.1.1 wVector
The w-unitvector of this ~PFace~,
which defines the w-axis of the wt-system.
The vector w is either the normalized cross product
of the normal vector and the t-unit-vector, or it's negative.
This depends on the kind of set-operation, we want to perform.
*/
Vector3D wVector;
/*
1.1.1 intSegs
A container to store all ~IntersectionSegments~ of this ~PFace~.
*/
IntSegContainer intSegs;
/*
1.1.1 aW, bW, cW, dW
The w-coords of the four vertices of this ~PFace~.
*/
double aW;
double bW;
double cW;
double dW;
/*
1.1.1 initialStartPointIsA
A flag, indicating if the vertex A equals the ~initialStartPoint~ of the
corresponding ~MSegmentData~ instance.
*/
bool initialStartPointIsA;
/*
1.1.1 hasInnerIntSegs
A flag, indicating if this ~PFace~ contains ~IntersectionSegments~ which are not
colinear to the boundary.
*/
bool hasInnerIntSegs;
/*
1.1.1 state
An enum, indicating the state of this ~PFace~. Possible values are:
* $UNKNOWN$
* $ENTIRELY\_INSIDE$
* $ENTIRELY\_OUTSIDE$
* $RELEVANT\_NOT\_CRITICAL$
* $RELEVANT\_CRITICAL$
* $NOT\_RELEVANT$
*/
State state;
/*
1.1.1 id
A unique id for each instance.
Used for debugging only.
*/
unsigned int id;
static unsigned int instanceCount;
};
} // end of namespace mregionops
} // end of namespace temporalalgebra
#endif /*SETOPS_H_*/