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

273 lines
7.0 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] Implementation of the MRegionOpsAlgebra
April - November 2008, M. H[oe]ger for bachelor thesis.
[2] Implementation with exakt dataype,
Oktober 2014 - Maerz 2015, S. Schroeer for master thesis.
[TOC]
1 Introduction
2 Defines and Includes
*/
#include "IntersectionSegment.h"
#include "PFace.h"
#include <iostream>
#include "NumericUtil.h"
namespace temporalalgebra {
namespace mregionops2 {
bool IntSegWCompare::operator()(const IntersectionSegment* const& s1,
const IntersectionSegment* const& s2) const {
// &&& to be implemented
if (s1->GetIntervalStartW() < s2->GetIntervalStartW()) return true;
if (s2->GetIntervalStartW() < s1->GetIntervalStartW()) return false;
if (s1->GetIntervalEndW() < s2->GetIntervalEndW()) return true;
return false;
}
IntersectionSegment::IntersectionSegment(const Segment3D& s, PFace* _pface,
Angle leftAng, Angle rightAng, Direction dir)
{
cout << "ctor IntersectionSegment() started\n";
// The startpoint's t-coord is always lower or equal to the
// endpoint's t-coord.
// Note: We don't care for x and y!
if (s.GetStart().GetT() <= s.GetEnd().GetT()) {
startXYT = s.GetStart();
endXYT = s.GetEnd();
} else
{
startXYT = s.GetEnd();
endXYT = s.GetStart();
}
pFace = _pface;
SetWCoords();
rightNeighbour = rightAng;
rightNeighbourDir = dir;
leftNeighbour = leftAng;
leftNeighbourDir = dir;
if (rightNeighbour.IsZero()) rightNeighbour = Angle();
if (leftNeighbour.IsZero()) leftNeighbour = Angle();
Print();
cout << "ctor IntersectionSegment() finished\n";
}
void IntersectionSegment::UpdateWith(IntersectionSegment* seg)
{
if (seg->rightNeighbour < rightNeighbour)
{
rightNeighbour = seg->rightNeighbour;
rightNeighbourDir = seg->rightNeighbourDir;
}
if (seg->leftNeighbour < leftNeighbour)
{
leftNeighbour = seg->leftNeighbour;
leftNeighbourDir = seg->leftNeighbourDir;
}
}
void IntersectionSegment::SetWCoords() {
SetStartWT(GetPFace()->TransformToWT(*GetStartXYT()));
SetEndWT(GetPFace()->TransformToWT(*GetEndXYT()));
}
AreaDirection IntersectionSegment::GetAreaDirection()
{
return areaDirection;
}
void IntersectionSegment::Finalize()
{
SetOp op = pFace->GetOperation();
if ((op == UNION) || (op == INTERSECTION))
{
if (rightNeighbourDir == NEGATIVE)
{
areaDirection = RIGHT;
if (leftNeighbourDir == POSITIVE) areaDirection = BOTH;
}
else
{
areaDirection = NONE;
if (leftNeighbourDir == POSITIVE) areaDirection = LEFT;
}
}
else
{
if (rightNeighbourDir == POSITIVE)
{
areaDirection = RIGHT;
if (leftNeighbourDir == NEGATIVE) areaDirection = BOTH;
}
else
{
areaDirection = NONE;
if (leftNeighbourDir == NEGATIVE) areaDirection = LEFT;
}
}
}
void IntersectionSegment::ComputeIntervalW(mpq_class startTime,
mpq_class endTime)
{
// compute IntervalW
// Interval: startTime - endTime
// Segment: GetStartT - GetEndT
intervalStartW = Point2D(startWT, endWT,
(startTime-GetStartT())/(GetEndT()-GetStartT())).GetW();
intervalEndW = Point2D(startWT, endWT,
(endTime-GetStartT())/(GetEndT()-GetStartT())).GetW();
}
void IntersectionSegment::Print() {
Point3D p1 = *GetStartXYT();
Point3D p2 = *GetEndXYT();
cout << p1 << " -> " << p2 << endl;
Point2D p21 = *GetStartWT();
Point2D p22 = *GetEndWT();
cout << p21 << " -> " << p22 << endl;
Angle a = rightNeighbour;
cout << "right neighbour angle: " << a << endl;
cout << "right neighbour direction: " << rightNeighbourDir << endl;
a = leftNeighbour;
cout << "left neighbour angle: " << a << endl;
cout << "left neighbour direction: " << leftNeighbourDir << endl;
AreaDirection ad = GetAreaDirection();
cout << "area direction: " << ad << endl;
}
void IntersectionSegment::InvertAreaDirection()
{
switch (areaDirection)
{
case LEFT:
areaDirection = RIGHT;
break;
case RIGHT:
areaDirection = LEFT;
break;
default:
break;
}
}
Point3D IntersectionSegment::Evaluate(const mpq_class mpqt) const {
//double t = mpqt.get_d();
// We compute the intersection point
// of the horizontal plane, defined by t, and this segment.
// Precondition:
// t is between t_start and t_end.
//assert(NumericUtil::Between(GetStartT(), t, GetEndT()));
// Point3D pointInPlane(0.0, 0.0, t);
// Vector3D normalVectorOfPlane(0.0, 0.0, 1.0);
// Vector3D u = *this->GetEndXYT() - *this->GetStartXYT();
// Vector3D w = this->GetStartXYT() - pointInPlane;
// double d = normalVectorOfPlane * u;
// double n = -normalVectorOfPlane * w;
// This can be simplified to:
//
// const Vector3D u = endXYT - startXYT;//GetEndXYT() - GetStartXYT();
// const double d = GetEndT() - GetStartT();
// const double n = t - GetStartT();
//
// This segment must not be parallel to plane:
//assert(!NumericUtil::NearlyEqual(d, 0.0));
//const double s = n / d;
// This segment intersects the plane:
//assert(NumericUtil::Between(0.0, s, 1.0));
// Compute segment intersection point:
//return *GetStartXYT() + s * u;
Point3D p;
return p;
}
bool IntersectionSegment::IsLeftOf(const IntersectionSegment* intSeg) const {
// Precondition:
// this->GetStartT() is inside the interval
// [intSeg->GetStartT(), intSeg->GetEndT()]
// and this and intSeg don't intersect in their interior.
const mpq_class sideOfStart = GetStartWT()->WhichSide(*intSeg->GetStartWT(),
*intSeg->GetEndWT());
// Null anstatt eps vs -eps
if (sideOfStart > 0)
return true;
if (sideOfStart < 0)
return false;
const mpq_class sideOfEnd = GetEndWT()->WhichSide(*intSeg->GetStartWT(),
*intSeg->GetEndWT());
return sideOfEnd > 0;
}
} // end namespace
} // end namespace