302 lines
8.2 KiB
C
302 lines
8.2 KiB
C
|
|
/*
|
||
|
|
----
|
||
|
|
This file is part of SECONDO.
|
||
|
|
|
||
|
|
Copyright (C) 2004, 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]
|
||
|
|
//[_] [\_]
|
||
|
|
|
||
|
|
[1] Header File for the class ~LineIntersection~
|
||
|
|
|
||
|
|
[TOC]
|
||
|
|
|
||
|
|
1 Overview
|
||
|
|
|
||
|
|
This header file contains the class ~LineIntersection~.
|
||
|
|
|
||
|
|
This class detects intersections between two line segments.
|
||
|
|
|
||
|
|
1 Defines and includes
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
#pragma once
|
||
|
|
|
||
|
|
#include <stdlib.h>
|
||
|
|
|
||
|
|
#include "InternalGeometries.h"
|
||
|
|
#include "Rational.h"
|
||
|
|
|
||
|
|
namespace RobustPlaneSweep
|
||
|
|
{
|
||
|
|
/*
|
||
|
|
|
||
|
|
1 Class ~LineIntersection~
|
||
|
|
|
||
|
|
*/
|
||
|
|
class LineIntersection
|
||
|
|
{
|
||
|
|
private:
|
||
|
|
/*
|
||
|
|
|
||
|
|
1.1 ~IsPointOnLineHelper~
|
||
|
|
|
||
|
|
*/
|
||
|
|
static bool IsPointOnLineHelper(long long p,
|
||
|
|
long long s0,
|
||
|
|
long long s1,
|
||
|
|
bool includePseudoIntersections)
|
||
|
|
{
|
||
|
|
if (includePseudoIntersections) {
|
||
|
|
if ((p >= s0 && p <= s1) || (p >= s1 && p <= s0)) {
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
if ((p > s0 && p < s1) || (p > s1 && p < s0)) {
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
public:
|
||
|
|
/*
|
||
|
|
|
||
|
|
1.1 ~GetIntersections~
|
||
|
|
|
||
|
|
Determines if the segments with the end points a0-a1 and b0-b1 have any
|
||
|
|
intersections. Returns 0 if there is none,
|
||
|
|
1 if there is one (not necessarily proper) intersection and
|
||
|
|
2 if there is the segments overlap.
|
||
|
|
if ~includePseudoIntersections~ is false, then only intersection points are
|
||
|
|
returned that split at least one segment into two pieces.
|
||
|
|
if ~includeCompleteOverlaps~ is false, then overlapping segments where
|
||
|
|
both segments have equal end points are returned as zero intersection points.
|
||
|
|
|
||
|
|
*/
|
||
|
|
static int GetIntersections(const InternalPoint& a0,
|
||
|
|
const InternalPoint& a1,
|
||
|
|
const InternalPoint& b0,
|
||
|
|
const InternalPoint& b1,
|
||
|
|
const bool includePseudoIntersections,
|
||
|
|
const bool includeCompleteOverlaps,
|
||
|
|
InternalIntersectionPoint &i0,
|
||
|
|
InternalIntersectionPoint &i1)
|
||
|
|
{
|
||
|
|
long long ax = (a1.GetX() - a0.GetX());
|
||
|
|
long long ay = (a1.GetY() - a0.GetY());
|
||
|
|
long long bx = (b1.GetX() - b0.GetX());
|
||
|
|
long long by = (b1.GetY() - b0.GetY());
|
||
|
|
long long abx = (a0.GetX() - b0.GetX());
|
||
|
|
long long aby = (a0.GetY() - b0.GetY());
|
||
|
|
|
||
|
|
long long denominator = bx * ay - by * ax;
|
||
|
|
if (denominator == 0) {
|
||
|
|
if ((bx * aby - by * abx) != 0 || (ax * aby - ay * abx) != 0) {
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
bool aIsPoint = (ax == 0 && ay == 0);
|
||
|
|
bool bIsPoint = (bx == 0 && by == 0);
|
||
|
|
|
||
|
|
if (aIsPoint && bIsPoint) {
|
||
|
|
if (abx == 0 && aby == 0) {
|
||
|
|
i0 = InternalIntersectionPoint(a0);
|
||
|
|
return 1;
|
||
|
|
} else {
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
} else if (aIsPoint) {
|
||
|
|
if (llabs(bx) > llabs(by)) {
|
||
|
|
if (!IsPointOnLineHelper(a0.GetX(),
|
||
|
|
b0.GetX(),
|
||
|
|
b1.GetX(),
|
||
|
|
includePseudoIntersections)) {
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
if (!IsPointOnLineHelper(a0.GetY(),
|
||
|
|
b0.GetY(),
|
||
|
|
b1.GetY(),
|
||
|
|
includePseudoIntersections)) {
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
i0 = InternalIntersectionPoint(a0);
|
||
|
|
return 1;
|
||
|
|
} else if (bIsPoint) {
|
||
|
|
if (llabs(ax) > llabs(ay)) {
|
||
|
|
if (!IsPointOnLineHelper(b0.GetX(),
|
||
|
|
a0.GetX(),
|
||
|
|
a1.GetX(),
|
||
|
|
includePseudoIntersections)) {
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
if (!IsPointOnLineHelper(b0.GetY(),
|
||
|
|
a0.GetY(),
|
||
|
|
a1.GetY(),
|
||
|
|
includePseudoIntersections)) {
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
i0 = InternalIntersectionPoint(b0);
|
||
|
|
return 1;
|
||
|
|
} else {
|
||
|
|
SimpleRational t0(0, 1), t1(0, 1);
|
||
|
|
if (llabs(bx) > llabs(by)) {
|
||
|
|
t0 = SimpleRational(abx, bx);
|
||
|
|
t1 = SimpleRational(a1.GetX() - b0.GetX(), bx);
|
||
|
|
} else {
|
||
|
|
t0 = SimpleRational(aby, by);
|
||
|
|
t1 = SimpleRational(a1.GetY() - b0.GetY(), by);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (t0 > t1) {
|
||
|
|
SimpleRational temp = t0;
|
||
|
|
t0 = t1;
|
||
|
|
t1 = temp;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (t1 < 0 || t0 > 1) {
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (t0 < 0) {
|
||
|
|
t0 = SimpleRational(0, 1);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (t1 > 1) {
|
||
|
|
t1 = SimpleRational(1, 1);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (t1 == 0) {
|
||
|
|
// touches only at start point
|
||
|
|
if (!includePseudoIntersections) {
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
i0 = InternalIntersectionPoint(b0);
|
||
|
|
return 1;
|
||
|
|
} else if (t0 == 1) {
|
||
|
|
// touches only at end point
|
||
|
|
if (!includePseudoIntersections) {
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
i0 = InternalIntersectionPoint(b1);
|
||
|
|
return 1;
|
||
|
|
} else if (t0 == 0 && t1 == 1) {
|
||
|
|
if (!includeCompleteOverlaps) {
|
||
|
|
if (a0.GetX() == b0.GetX() && a0.GetY() == b0.GetY()
|
||
|
|
&& a1.GetX() == b1.GetX()
|
||
|
|
&& a1.GetY() == b1.GetY()) {
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
if (a0.GetX() == b1.GetX() && a0.GetY() == b1.GetY()
|
||
|
|
&& a1.GetX() == b0.GetX()
|
||
|
|
&& a1.GetY() == b0.GetY()) {
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
i0 = InternalIntersectionPoint(b0);
|
||
|
|
i1 = InternalIntersectionPoint(b1);
|
||
|
|
return 2;
|
||
|
|
} else if (t0 == t1) {
|
||
|
|
Rational ratt0 = (Rational)t0;
|
||
|
|
i0 = InternalIntersectionPoint((ratt0 * (int)bx + b0.GetX()),
|
||
|
|
(ratt0 * (int)by + b0.GetY()));
|
||
|
|
return 1;
|
||
|
|
} else {
|
||
|
|
Rational ratt0 = (Rational)t0;
|
||
|
|
Rational ratt1 = (Rational)t1;
|
||
|
|
|
||
|
|
i0 = InternalIntersectionPoint((ratt0 * (int)bx + b0.GetX()),
|
||
|
|
(ratt0 * (int)by + b0.GetY()));
|
||
|
|
|
||
|
|
i1 = InternalIntersectionPoint((ratt1 * (int)bx + b0.GetX()),
|
||
|
|
(ratt1 * (int)by + b0.GetY()));
|
||
|
|
|
||
|
|
return 2;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
SimpleRational si((by * abx - bx * aby), denominator);
|
||
|
|
|
||
|
|
if (si < 0 || si > 1) {
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
SimpleRational ti((ax * aby - ay * abx), -denominator);
|
||
|
|
if (ti < 0 || ti > 1) {
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (si == 0) {
|
||
|
|
if (!includePseudoIntersections && (ti == 0 || ti == 1)) {
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
i0 = InternalIntersectionPoint(a0);
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (si == 1) {
|
||
|
|
if (!includePseudoIntersections && (ti == 0 || ti == 1)) {
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
i0 = InternalIntersectionPoint(a1);
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (ti == 0) {
|
||
|
|
if (!includePseudoIntersections && (si == 0 || si == 1)) {
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
i0 = InternalIntersectionPoint(b0);
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (ti == 1) {
|
||
|
|
if (!includePseudoIntersections && (si == 0 || si == 1)) {
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
i0 = InternalIntersectionPoint(b1);
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
Rational ratSi = (Rational)si;
|
||
|
|
Rational ix = (ratSi * (int)ax + a0.GetX());
|
||
|
|
Rational iy = (ratSi * (int)ay + a0.GetY());
|
||
|
|
|
||
|
|
i0 = InternalIntersectionPoint(ix, iy);
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
};
|
||
|
|
}
|