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

712 lines
20 KiB
C++

/*
This file is part of SECONDO.
Copyright (C) 2013, 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
*/
/*
TileAlgebra includes
*/
#include "HalfSegment.h"
/*
declaration of namespace TileAlgebra
*/
namespace TileAlgebra
{
/*
Method CheckPoints checks the consistency of given left point and right point.
author: Dirk Zacher
parameters: rLeftPoint - reference to left point
rRightPoint - reference to right point
return value: true, if left point and right point were exchanged,
otherwise false
exceptions: -
*/
bool CheckPoints(Point& rLeftPoint,
Point& rRightPoint)
{
bool bPointsExchanged = false;
if(rLeftPoint.IsDefined() &&
rRightPoint.IsDefined())
{
if((rLeftPoint.GetX() > rRightPoint.GetX()) ||
(rLeftPoint.GetX() == rRightPoint.GetX() &&
rLeftPoint.GetY() > rRightPoint.GetY()))
{
Point point = rLeftPoint;
rLeftPoint = rRightPoint;
rRightPoint = point;
bPointsExchanged = true;
}
}
return bPointsExchanged;
}
/*
Method IsPointInRectangle checks if given Point is in given Rectangle<2>.
author: Dirk Zacher
parameters: rPoint - reference to a point
rRectangle - reference to a rectangle
return value: true, if rPoint is in rRectangle,
otherwise false
exceptions: -
*/
bool IsPointInRectangle(const Point& rPoint,
const Rectangle<2>& rRectangle)
{
bool bIsPointInRectangle = false;
if(rPoint.IsDefined() &&
rRectangle.IsDefined())
{
if(rPoint.GetX() >= rRectangle.MinD(0) &&
rPoint.GetX() < rRectangle.MaxD(0) &&
rPoint.GetY() >= rRectangle.MinD(1) &&
rPoint.GetY() < rRectangle.MaxD(1))
{
bIsPointInRectangle = true;
}
}
return bIsPointInRectangle;
}
/*
Method CheckHalfSegment checks the consistency of the given HalfSegment.
author: Dirk Zacher
parameters: rHalfSegment - reference to a HalfSegment
return value: -
exceptions: -
*/
void CheckHalfSegment(HalfSegment& rHalfSegment)
{
Point leftPoint = rHalfSegment.GetLeftPoint();
Point rightPoint = rHalfSegment.GetRightPoint();
if(leftPoint.IsDefined() &&
rightPoint.IsDefined())
{
bool bIsLeftDomPoint = rHalfSegment.IsLeftDomPoint();
if(CheckPoints(leftPoint, rightPoint) == true)
{
rHalfSegment.Set(!bIsLeftDomPoint, leftPoint, rightPoint);
}
}
}
/*
Method IsHorizontalHalfSegment checks if given HalfSegment is a horizontal line.
author: Dirk Zacher
parameters: rHalfSegment - reference to a HalfSegment
return value: true, if rHalfSegment is a horizontal line, otherwise false
exceptions: -
*/
bool IsHorizontalHalfSegment(const HalfSegment& rHalfSegment)
{
bool bIsHorizontalHalfSegment = false;
Point leftPoint = rHalfSegment.GetLeftPoint();
Point rightPoint = rHalfSegment.GetRightPoint();
if(leftPoint.IsDefined() &&
rightPoint.IsDefined())
{
if(AlmostEqual(leftPoint.GetY(), rightPoint.GetY()))
{
bIsHorizontalHalfSegment = true;
}
}
return bIsHorizontalHalfSegment;
}
/*
Method IsVerticalHalfSegment checks if given HalfSegment is a vertical line.
author: Dirk Zacher
parameters: rHalfSegment - reference to a HalfSegment
return value: true, if rHalfSegment is a vertical line, otherwise false
exceptions: -
*/
bool IsVerticalHalfSegment(const HalfSegment& rHalfSegment)
{
bool bIsVerticalHalfSegment = false;
Point leftPoint = rHalfSegment.GetLeftPoint();
Point rightPoint = rHalfSegment.GetRightPoint();
if(leftPoint.IsDefined() &&
rightPoint.IsDefined())
{
if(AlmostEqual(leftPoint.GetX(), rightPoint.GetX()))
{
bIsVerticalHalfSegment = true;
}
}
return bIsVerticalHalfSegment;
}
/*
Method HalfSegmentPointsInRectangle returns the number of HalfSegment points
inside the given Rectangle<2>.
author: Dirk Zacher
parameters: rHalfSegment - reference to a HalfSegment
rRectangle - reference to a Rectangle<2>
return value: number of HalfSegment points inside rRectangle
exceptions: -
*/
unsigned char HalfSegmentPointsInRectangle(const HalfSegment& rHalfSegment,
const Rectangle<2>& rRectangle)
{
unsigned char halfSegmentPointsInRectangle = 0;
if(rRectangle.IsDefined())
{
Point leftPoint = rHalfSegment.GetLeftPoint();
Point rightPoint = rHalfSegment.GetRightPoint();
if(leftPoint.IsDefined() &&
rightPoint.IsDefined())
{
CheckPoints(leftPoint, rightPoint);
if(IsPointInRectangle(leftPoint, rRectangle))
{
halfSegmentPointsInRectangle++;
}
if(IsPointInRectangle(rightPoint, rRectangle))
{
halfSegmentPointsInRectangle++;
}
}
}
return halfSegmentPointsInRectangle;
}
/*
Method HalfSegmentIntersectsLeftRectangleBorder checks if given HalfSegment
intersects the left border of given Rectangle<2> and returns
the intersection point between HalfSegment and left rectangle border.
author: Dirk Zacher
parameters: rHalfSegment - reference to a HalfSegment
rRectangle - reference to a Rectangle<2>
rPoint - reference to a Point containing intersection coordinates
return value: true, if rHalfSegment intersects left border of rRectangle,
otherwise false
exceptions: -
*/
bool HalfSegmentIntersectsLeftRectangleBorder(const HalfSegment& rHalfSegment,
const Rectangle<2>& rRectangle,
Point& rPoint)
{
bool bHalfSegmentIntersectsLeftRectangleBorder = false;
if(rRectangle.IsDefined())
{
Point halfSegmentLeftPoint = rHalfSegment.GetLeftPoint();
Point halfSegmentRightPoint = rHalfSegment.GetRightPoint();
if(halfSegmentLeftPoint.IsDefined() &&
halfSegmentRightPoint.IsDefined())
{
CheckPoints(halfSegmentLeftPoint, halfSegmentRightPoint);
if(halfSegmentLeftPoint.GetX() <= rRectangle.MinD(0) &&
rRectangle.MinD(0) <= halfSegmentRightPoint.GetX())
{
double deltaX = halfSegmentRightPoint.GetX() -
halfSegmentLeftPoint.GetX();
double deltaY = halfSegmentRightPoint.GetY() -
halfSegmentLeftPoint.GetY();
double m = deltaY / deltaX;
double n = halfSegmentLeftPoint.GetY() -
m * halfSegmentLeftPoint.GetX();
double y = m * rRectangle.MinD(0) + n;
if(y >= rRectangle.MinD(1) &&
y < rRectangle.MaxD(1))
{
bHalfSegmentIntersectsLeftRectangleBorder = true;
rPoint.Set(rRectangle.MinD(0), y);
}
}
}
}
return bHalfSegmentIntersectsLeftRectangleBorder;
}
/*
Method HalfSegmentIntersectsRightRectangleBorder checks if given HalfSegment
intersects the right border of given Rectangle<2> and returns
the intersection point between HalfSegment and right rectangle border.
author: Dirk Zacher
parameters: rHalfSegment - reference to a HalfSegment
rRectangle - reference to a Rectangle<2>
rPoint - reference to a Point containing intersection coordinates
return value: true, if rHalfSegment intersects right border of rRectangle,
otherwise false
exceptions: -
*/
bool HalfSegmentIntersectsRightRectangleBorder(const HalfSegment& rHalfSegment,
const Rectangle<2>& rRectangle,
Point& rPoint)
{
bool bHalfSegmentIntersectsRightRectangleBorder = false;
if(rRectangle.IsDefined())
{
Point halfSegmentLeftPoint = rHalfSegment.GetLeftPoint();
Point halfSegmentRightPoint = rHalfSegment.GetRightPoint();
if(halfSegmentLeftPoint.IsDefined() &&
halfSegmentRightPoint.IsDefined())
{
CheckPoints(halfSegmentLeftPoint, halfSegmentRightPoint);
if(halfSegmentLeftPoint.GetX() <= rRectangle.MaxD(0) &&
rRectangle.MaxD(0) <= halfSegmentRightPoint.GetX())
{
double deltaX = halfSegmentRightPoint.GetX() -
halfSegmentLeftPoint.GetX();
double deltaY = halfSegmentRightPoint.GetY() -
halfSegmentLeftPoint.GetY();
double m = deltaY / deltaX;
double n = halfSegmentLeftPoint.GetY() -
m * halfSegmentLeftPoint.GetX();
double y = m * rRectangle.MaxD(0) + n;
if(y >= rRectangle.MinD(1) &&
y < rRectangle.MaxD(1))
{
bHalfSegmentIntersectsRightRectangleBorder = true;
rPoint.Set(rRectangle.MaxD(0), y);
}
}
}
}
return bHalfSegmentIntersectsRightRectangleBorder;
}
/*
Method HalfSegmentIntersectsLowerRectangleBorder checks if given HalfSegment
intersects the lower border of given Rectangle<2> and returns
the intersection point between HalfSegment and lower rectangle border.
author: Dirk Zacher
parameters: rHalfSegment - reference to a HalfSegment
rRectangle - reference to a Rectangle<2>
rPoint - reference to a Point containing intersection coordinates
return value: true, if rHalfSegment intersects lower border of rRectangle,
otherwise false
exceptions: -
*/
bool HalfSegmentIntersectsLowerRectangleBorder(const HalfSegment& rHalfSegment,
const Rectangle<2>& rRectangle,
Point& rPoint)
{
bool bHalfSegmentIntersectsLowerRectangleBorder = false;
if(rRectangle.IsDefined())
{
Point halfSegmentLeftPoint = rHalfSegment.GetLeftPoint();
Point halfSegmentRightPoint = rHalfSegment.GetRightPoint();
if(halfSegmentLeftPoint.IsDefined() &&
halfSegmentRightPoint.IsDefined())
{
CheckPoints(halfSegmentLeftPoint, halfSegmentRightPoint);
double deltaX = halfSegmentRightPoint.GetX() -
halfSegmentLeftPoint.GetX();
double deltaY = halfSegmentRightPoint.GetY() -
halfSegmentLeftPoint.GetY();
double m = deltaY / deltaX;
double n = halfSegmentLeftPoint.GetY() -
m * halfSegmentLeftPoint.GetX();
double x = (rRectangle.MinD(1) - n) / m;
if(halfSegmentLeftPoint.GetX() <= x &&
x <= halfSegmentRightPoint.GetX() &&
x >= rRectangle.MinD(0) &&
x < rRectangle.MaxD(0))
{
bHalfSegmentIntersectsLowerRectangleBorder = true;
rPoint.Set(x, rRectangle.MinD(1));
}
}
}
return bHalfSegmentIntersectsLowerRectangleBorder;
}
/*
Method HalfSegmentIntersectsUpperRectangleBorder checks if given HalfSegment
intersects the upper border of given Rectangle<2> and returns
the intersection point between HalfSegment and upper rectangle border.
author: Dirk Zacher
parameters: rHalfSegment - reference to a HalfSegment
rRectangle - reference to a Rectangle<2>
rPoint - reference to a Point containing intersection coordinates
return value: true, if rHalfSegment intersects upper border of rRectangle,
otherwise false
exceptions: -
*/
bool HalfSegmentIntersectsUpperRectangleBorder(const HalfSegment& rHalfSegment,
const Rectangle<2>& rRectangle,
Point& rPoint)
{
bool bHalfSegmentIntersectsUpperRectangleBorder = false;
if(rRectangle.IsDefined())
{
Point halfSegmentLeftPoint = rHalfSegment.GetLeftPoint();
Point halfSegmentRightPoint = rHalfSegment.GetRightPoint();
if(halfSegmentLeftPoint.IsDefined() &&
halfSegmentRightPoint.IsDefined())
{
CheckPoints(halfSegmentLeftPoint, halfSegmentRightPoint);
double deltaX = halfSegmentRightPoint.GetX() -
halfSegmentLeftPoint.GetX();
double deltaY = halfSegmentRightPoint.GetY() -
halfSegmentLeftPoint.GetY();
double m = deltaY / deltaX;
double n = halfSegmentLeftPoint.GetY() -
m * halfSegmentLeftPoint.GetX();
double x = (rRectangle.MaxD(1) - n) / m;
if(halfSegmentLeftPoint.GetX() <= x &&
x <= halfSegmentRightPoint.GetX() &&
x >= rRectangle.MinD(0) &&
x < rRectangle.MaxD(0))
{
bHalfSegmentIntersectsUpperRectangleBorder = true;
rPoint.Set(x, rRectangle.MaxD(1));
}
}
}
return bHalfSegmentIntersectsUpperRectangleBorder;
}
/*
Method HalfSegmentIntersectsRectangle checks if given HalfSegment
intersects given Rectangle<2>.
author: Dirk Zacher
parameters: rHalfSegment - reference to a HalfSegment
rRectangle - reference to a Rectangle<2>
return value: true, if rHalfSegment intersects rRectangle, otherwise false
exceptions: -
*/
bool HalfSegmentIntersectsRectangle(const HalfSegment& rHalfSegment,
const Rectangle<2>& rRectangle)
{
bool bHalfSegmentIntersectsRectangle = false;
if(rRectangle.IsDefined())
{
Point leftPoint = rHalfSegment.GetLeftPoint();
Point rightPoint = rHalfSegment.GetRightPoint();
if(leftPoint.IsDefined() &&
rightPoint.IsDefined())
{
CheckPoints(leftPoint, rightPoint);
unsigned char halfSegmentPointsInRectangle =
HalfSegmentPointsInRectangle(rHalfSegment, rRectangle);
if(halfSegmentPointsInRectangle > 0)
{
bHalfSegmentIntersectsRectangle = true;
}
else
{
if(IsHorizontalHalfSegment(rHalfSegment) &&
leftPoint.GetX() < rRectangle.MinD(0) &&
rightPoint.GetX() >= rRectangle.MaxD(0) &&
leftPoint.GetY() >= rRectangle.MinD(1) &&
leftPoint.GetY() < rRectangle.MaxD(1))
{
/*
case: horizontal line
*/
bHalfSegmentIntersectsRectangle = true;
}
if(IsVerticalHalfSegment(rHalfSegment) &&
leftPoint.GetX() >= rRectangle.MinD(0) &&
leftPoint.GetX() < rRectangle.MaxD(0) &&
leftPoint.GetY() < rRectangle.MinD(1) &&
rightPoint.GetY() >= rRectangle.MaxD(1))
{
/*
case: vertical line
*/
bHalfSegmentIntersectsRectangle = true;
}
if(bHalfSegmentIntersectsRectangle == false)
{
Point point(true, 0.0, 0.0);
if(HalfSegmentIntersectsLeftRectangleBorder(rHalfSegment,
rRectangle,
point) ||
HalfSegmentIntersectsRightRectangleBorder(rHalfSegment,
rRectangle,
point) ||
HalfSegmentIntersectsLowerRectangleBorder(rHalfSegment,
rRectangle,
point) ||
HalfSegmentIntersectsUpperRectangleBorder(rHalfSegment,
rRectangle,
point))
{
bHalfSegmentIntersectsRectangle = true;
}
}
}
}
}
return bHalfSegmentIntersectsRectangle;
}
/*
Method GetPointsInRectangle returns a left point and a right point
of given HalfSegment inside the given Rectangle<2>.
author: Dirk Zacher
parameters: rHalfSegment - reference to a HalfSegment
rRectangle - reference to a Rectangle<2>
rLeftPoint - reference to the left point inside rRectangle
rRightPoint - reference to the right point inside rRectangle
return value: true, if left point and right point were successfully calculated,
otherwise false
exceptions: -
*/
bool GetPointsInRectangle(const HalfSegment& rHalfSegment,
const Rectangle<2>& rRectangle,
Point& rLeftPoint,
Point& rRightPoint)
{
bool bRetVal = false;
if(rRectangle.IsDefined())
{
if(HalfSegmentIntersectsRectangle(rHalfSegment, rRectangle))
{
Point halfSegmentLeftPoint = rHalfSegment.GetLeftPoint();
Point halfSegmentRightPoint = rHalfSegment.GetRightPoint();
if(halfSegmentLeftPoint.IsDefined() &&
halfSegmentRightPoint.IsDefined())
{
CheckPoints(halfSegmentLeftPoint, halfSegmentRightPoint);
rLeftPoint.Set(halfSegmentLeftPoint);
rRightPoint.Set(halfSegmentRightPoint);
unsigned char halfSegmentPointsInRectangle =
HalfSegmentPointsInRectangle(rHalfSegment, rRectangle);
if(halfSegmentPointsInRectangle < 2)
{
if(IsHorizontalHalfSegment(rHalfSegment))
{
if(rLeftPoint.GetX() < rRectangle.MinD(0))
{
rLeftPoint.Set(rRectangle.MinD(0), rLeftPoint.GetY());
}
if(rRightPoint.GetX() > rRectangle.MaxD(0))
{
rRightPoint.Set(rRectangle.MaxD(0), rRightPoint.GetY());
}
}
else if(IsVerticalHalfSegment(rHalfSegment))
{
if(rLeftPoint.GetY() < rRectangle.MinD(1))
{
rLeftPoint.Set(rLeftPoint.GetX(), rRectangle.MinD(1));
}
if(rRightPoint.GetY() > rRectangle.MaxD(1))
{
rRightPoint.Set(rRightPoint.GetX(), rRectangle.MaxD(1));
}
}
else
{
rLeftPoint.SetDefined(false);
rRightPoint.SetDefined(false);
if(halfSegmentPointsInRectangle == 1)
{
if(IsPointInRectangle(halfSegmentLeftPoint, rRectangle))
{
rLeftPoint.Set(halfSegmentLeftPoint);
}
if(IsPointInRectangle(halfSegmentRightPoint, rRectangle))
{
rLeftPoint.Set(halfSegmentRightPoint);
}
}
Point point(true, 0.0, 0.0);
if(rRightPoint.IsDefined() == false &&
HalfSegmentIntersectsLeftRectangleBorder(rHalfSegment,
rRectangle,
point))
{
if(rLeftPoint.IsDefined() == false)
{
rLeftPoint.Set(point);
}
else
{
rRightPoint.Set(point);
}
}
if(rRightPoint.IsDefined() == false &&
HalfSegmentIntersectsRightRectangleBorder(rHalfSegment,
rRectangle,
point))
{
if(rLeftPoint.IsDefined() == false)
{
rLeftPoint.Set(point);
}
else
{
rRightPoint.Set(point);
}
}
if(rRightPoint.IsDefined() == false &&
HalfSegmentIntersectsLowerRectangleBorder(rHalfSegment,
rRectangle,
point))
{
if(rLeftPoint.IsDefined() == false)
{
rLeftPoint.Set(point);
}
else
{
rRightPoint.Set(point);
}
}
if(rRightPoint.IsDefined() == false &&
HalfSegmentIntersectsUpperRectangleBorder(rHalfSegment,
rRectangle,
point))
{
if(rLeftPoint.IsDefined() == false)
{
assert(false);
}
else
{
rRightPoint.Set(point);
}
}
CheckPoints(rLeftPoint, rRightPoint);
}
}
bRetVal = true;
}
}
}
return bRetVal;
}
}