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

2193 lines
52 KiB
C++

/*
----
This file is part of SECONDO.
Copyright (C) 2009, University in Hagen, Faculty of Mathematics and
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}}]
//paragraph [10] Footnote: [{\footnote{] [}}]
//[TOC] [\tableofcontents]
[TOC]
0 Overview
1 Includes and defines
*/
#ifndef _Line2_CPP
#define _Line2_CPP
#include "Line2.h"
#include "AVL_Tree.h"
using namespace std;
namespace p2d {
/*
2 Class SegmentData
*/
/*
2.1 Constructors
*/
SegmentData::SegmentData(int xl, int yl, int xr, int yr, bool l,
int edgeNo/*=-999999*/) :
xLeft(xl), yLeft(yl), xRight(xr), yRight(yr),
xLeftPos(0), yLeftPos(0), xRightPos(0), yRightPos(0),
xLeftNumOfChars(0), yLeftNumOfChars(0),
xRightNumOfChars(0), yRightNumOfChars(0), ldp(l), cycleno(-999999),
edgeno(edgeNo), coverageno(-999999), insideAbove(false),
partnerno(-999999) {
}
SegmentData::SegmentData(Point2* lp, Point2* rp, bool ldp, int edgeno,
Flob& preciseCoordinates) :
xLeft(lp->getGridX()), yLeft(lp->getGridY()),
xRight(rp->getGridX()), yRight(rp->getGridY()),
xLeftPos(0), yLeftPos(0), xRightPos(0), yRightPos(0),
xLeftNumOfChars(0), yLeftNumOfChars(0), xRightNumOfChars(0),
yRightNumOfChars(0), ldp(ldp), cycleno(-999999), edgeno(edgeno),
coverageno(-999999), insideAbove(false), partnerno(-999999) {
SetPreciseLeftCoordinates(lp, preciseCoordinates);
SetPreciseRightCoordinates(rp, preciseCoordinates);
}
SegmentData::SegmentData(SegmentData& d) :
xLeft(d.xLeft), yLeft(d.yLeft), xRight(d.xRight), yRight(d.yRight),
xLeftPos(d.xLeftPos), yLeftPos(d.yLeftPos),
xRightPos(d.xRightPos), yRightPos(d.yRightPos),
xLeftNumOfChars(d.xLeftNumOfChars), yLeftNumOfChars(d.yLeftNumOfChars),
xRightNumOfChars(d.xRightNumOfChars), yRightNumOfChars(d.yRightNumOfChars),
ldp(d.ldp), cycleno(d.cycleno), edgeno(d.edgeno),
coverageno(d.coverageno), insideAbove(d.insideAbove),
partnerno(d.partnerno) {
}
/*
2.2 Read access methods
*/
/*
2.2.1 ~getPreciseLeftX~
*/
mpq_class SegmentData::getPreciseLeftX(const Flob& preciseCoordinates) const {
if (xLeftNumOfChars == 0) {
mpq_class theValue(0);
return theValue;
}
SmiSize sz = preciseCoordinates.getSize();
char* s;
if (sz == 0) {
s = new char[1];
s[0] = 0;
} else {
s = new char[xLeftNumOfChars + 1];
assert((xLeftPos + xLeftNumOfChars) <= sz);
bool ok = preciseCoordinates.read(s, xLeftNumOfChars, xLeftPos);
assert(ok);
s[xLeftNumOfChars] = 0;
}
mpq_class theValue(s);
theValue.canonicalize();
delete s;
return theValue;
}
/*
2.2.1 ~getPreciseLeftY~
*/
mpq_class SegmentData::getPreciseLeftY(const Flob& preciseCoordinates) const {
if (yLeftNumOfChars == 0) {
mpq_class theValue(0);
return theValue;
}
SmiSize sz = preciseCoordinates.getSize();
char* s;
if (sz == 0 || sz == yLeftPos) {
s = new char[1];
s[0] = 0;
} else {
s = new char[yLeftNumOfChars + 1];
bool ok = preciseCoordinates.read(s, yLeftNumOfChars, yLeftPos);
assert(ok);
s[yLeftNumOfChars] = 0;
}
mpq_class theValue(s);
theValue.canonicalize();
delete s;
return theValue;
}
/*
2.2.1 ~getPreciseRightX~
*/
mpq_class SegmentData::getPreciseRightX(const Flob& preciseCoordinates) const {
if (xRightNumOfChars == 0) {
mpq_class theValue(0);
return theValue;
}
SmiSize sz = preciseCoordinates.getSize();
char* s;
if (sz == 0 || sz == xRightPos) {
s = new char[1];
s[0] = 0;
} else {
s = new char[xRightNumOfChars + 1];
bool ok = preciseCoordinates.read(s, xRightNumOfChars, xRightPos);
assert(ok);
s[xRightNumOfChars] = 0;
}
mpq_class theValue(s);
theValue.canonicalize();
delete s;
return theValue;
}
/*
2.2.1 ~getPreciseRightY~
*/
mpq_class SegmentData::getPreciseRightY(const Flob& preciseCoordinates) const {
if (yRightNumOfChars == 0) {
mpq_class theValue(0);
return theValue;
}
SmiSize sz = preciseCoordinates.getSize();
char* s;
if (sz == 0 || sz == yRightPos) {
s = new char[1];
s[0] = 0;
} else {
s = new char[yRightNumOfChars + 1];
bool ok = preciseCoordinates.read(s, yRightNumOfChars, yRightPos);
assert(ok);
s[yRightNumOfChars] = 0;
}
mpq_class theValue(s);
theValue.canonicalize();
delete s;
return theValue;
}
/*
2.2.1 ~GetDomGridXCoord~
Returns the named value of the dominating point of the
half segment.
*/
const int SegmentData::GetDomGridXCoord() const {
if (ldp) {
return xLeft;
} else {
return xRight;
}
}
/*
2.2.1 ~GetDomGridYCoord~
*/
const int SegmentData::GetDomGridYCoord() const {
if (ldp) {
return yLeft;
} else {
return yRight;
}
}
/*
2.2.1 ~GetDomPreciseXCoord~
*/
const mpq_class SegmentData::GetDomPreciseXCoord(
const Flob& preciseCoordinates) const {
if (ldp) {
return getPreciseLeftX(preciseCoordinates);
} else {
return getPreciseRightX(preciseCoordinates);
}
}
/*
2.2.1 ~GetDomPreciseYCoord~
*/
const mpq_class SegmentData::GetDomPreciseYCoord(
const Flob& preciseCoordinates) const {
if (ldp) {
return getPreciseLeftY(preciseCoordinates);
} else {
return getPreciseRightY(preciseCoordinates);
}
}
/*
2.2.1 ~GetSecGridXCoord~
*/
const int SegmentData::GetSecGridXCoord() const {
if (!ldp) {
return xLeft;
} else {
return xRight;
}
}
/*
2.2.1 ~GetSecGridYCoord~
*/
const int SegmentData::GetSecGridYCoord() const {
if (!ldp) {
return yLeft;
} else {
return yRight;
}
}
/*
2.2.1 ~GetSecPreciseXCoord~
*/
const mpq_class SegmentData::GetSecPreciseXCoord(
const Flob& preciseCoordinates) const {
if (!ldp) {
return getPreciseLeftX(preciseCoordinates);
} else {
return getPreciseRightX(preciseCoordinates);
}
}
/*
2.2.1 ~GetSecPreciseYCoord~
*/
const mpq_class SegmentData::GetSecPreciseYCoord(
const Flob& preciseCoordinates) const {
if (!ldp) {
return getPreciseLeftY(preciseCoordinates);
} else {
return getPreciseRightY(preciseCoordinates);
}
}
/*
2.2.1 ~IsLeftDomPoint~
*/
bool SegmentData::IsLeftDomPoint() const {
return ldp;
}
/*
2.2 Write access methods
*/
/*
2.2.1 ~SetPreciseLeftX~
*/
void SegmentData::SetPreciseLeftX(Flob& preciseCoordinates, mpq_class lx) {
if (cmp(lx, 0) == 0) {
xLeftPos = 0;
xLeftNumOfChars = 0;
return;
}
SmiSize sz = preciseCoordinates.getSize();
string str = lx.get_str();
char* s = new char[str.length() + 1];
std::strcpy(s, str.c_str());
xLeftNumOfChars = strlen(s);
if (sz == 0) {
xLeftPos = 0;
// We have to allocate one byte for the ending-0 in the FLOB.
preciseCoordinates.resize(xLeftNumOfChars + 1);
} else {
xLeftPos = sz - 1;
// The FLOB already ends with 0.
preciseCoordinates.resize(sz + xLeftNumOfChars);
}
assert(preciseCoordinates.write(s, xLeftNumOfChars + 1, xLeftPos));
delete[] s;
}
/*
2.2.1 ~SetPreciseLeftY~
*/
void SegmentData::SetPreciseLeftY(Flob& preciseCoordinates, mpq_class ly) {
if (cmp(ly, 0) == 0) {
yLeftPos = 0;
yLeftNumOfChars = 0;
return;
}
SmiSize sz = preciseCoordinates.getSize();
string str = ly.get_str();
char* s = new char[str.length() + 1];
std::strcpy(s, str.c_str());
yLeftNumOfChars = strlen(s);
if (sz == 0) {
// We have to allocate one byte for the ending-0 in the FLOB.
yLeftPos = 0;
preciseCoordinates.resize(yLeftNumOfChars + 1);
} else {
yLeftPos = sz - 1;
// The FLOB already ends with 0.
preciseCoordinates.resize(sz + yLeftNumOfChars);
}
assert(preciseCoordinates.write(s, yLeftNumOfChars + 1, yLeftPos));
delete[] s;
}
/*
2.2.1 ~SetPreciseRightX~
*/
void SegmentData::SetPreciseRightX(Flob& preciseCoordinates, mpq_class rx) {
if (cmp(rx, 0) == 0) {
xRightPos = 0;
xRightNumOfChars = 0;
return;
}
SmiSize sz = preciseCoordinates.getSize();
string str = rx.get_str();
char* s = new char[str.length() + 1];
std::strcpy(s, str.c_str());
xRightNumOfChars = strlen(s);
if (sz == 0) {
xRightPos = 0;
// We have to allocate one byte for the ending-0 in the FLOB.
preciseCoordinates.resize(xRightNumOfChars + 1);
} else {
xRightPos = sz - 1;
// The FLOB already ends with 0.
preciseCoordinates.resize(sz + xRightNumOfChars);
}
assert(preciseCoordinates.write(s, xRightNumOfChars + 1, xRightPos));
delete[] s;
}
/*
2.2.1 ~SetPreciseRightY~
*/
void SegmentData::SetPreciseRightY(Flob& preciseCoordinates, mpq_class ry) {
if (cmp(ry, 0) == 0) {
yRightPos = 0;
yRightNumOfChars = 0;
return;
}
SmiSize sz = preciseCoordinates.getSize();
string str = ry.get_str();
char* s = new char[str.length() + 1];
std::strcpy(s, str.c_str());
yRightNumOfChars = strlen(s);
if (sz == 0) {
yRightPos = 0;
// We have to allocate one byte for the ending-0 in the FLOB.
preciseCoordinates.resize(yRightNumOfChars + 1);
} else {
yRightPos = sz - 1;
// The FLOB already ends with 0.
preciseCoordinates.resize(sz + yRightNumOfChars);
}
assert(preciseCoordinates.write(s, yRightNumOfChars + 1, yRightPos));
delete[] s;
}
/*
2.2.1 ~SetPreciseLeftCoordinates~
*/
void SegmentData::SetPreciseLeftCoordinates(Point2* lp,
Flob& preciseCoordinates) {
SmiSize sz = preciseCoordinates.getSize();
string slx(lp->getPreciseXAsString());
if (slx == "0") {
slx = "";
xLeftPos = 0;
xLeftNumOfChars = 0;
} else {
xLeftPos = sz;
xLeftNumOfChars = slx.length();
}
string sly(lp->getPreciseYAsString());
if (sly == "0") {
sly = "";
yLeftPos = 0;
yLeftNumOfChars = 0;
} else {
yLeftPos = sz + xLeftNumOfChars;
yLeftNumOfChars = sly.length();
}
size_t length = xLeftNumOfChars + yLeftNumOfChars;
if (length > 0) {
SmiSize newSize;
if (sz == 0) {
newSize = length + 1;
} else {
newSize = sz + length;
}
preciseCoordinates.resize(newSize);
length++;
string value = slx + sly;
char* s = new char[length];
std::strcpy(s, value.c_str());
if (xLeftNumOfChars > 0) {
assert(preciseCoordinates.write(s, length, xLeftPos));
} else {
assert(preciseCoordinates.write(s, length, yLeftPos));
}
delete[] s;
}
}
/*
2.2.1 ~SetPreciseRightCoordinates~
*/
void SegmentData::SetPreciseRightCoordinates(Point2* rp,
Flob& preciseCoordinates) {
SmiSize sz = preciseCoordinates.getSize();
string srx(rp->getPreciseXAsString());
if (srx == "0") {
srx = "";
xRightPos = 0;
xRightNumOfChars = 0;
} else {
xRightPos = sz;
xRightNumOfChars = srx.length();
}
string sry(rp->getPreciseYAsString());
if (sry == "0") {
sry = "";
yRightPos = 0;
yRightNumOfChars = 0;
} else {
yRightPos = sz + xRightNumOfChars;
yRightNumOfChars = sry.length();
}
size_t length = xRightNumOfChars + yRightNumOfChars;
if (length > 0) {
SmiSize newSize;
if (sz == 0) {
newSize = length + 1;
} else {
newSize = sz + length;
}
preciseCoordinates.resize(newSize);
string value = srx + sry;
char* s = new char[value.length() + 1];
std::strcpy(s, value.c_str());
if (xRightNumOfChars > 0) {
assert(
preciseCoordinates.write(s, xRightNumOfChars + yRightNumOfChars + 1,
xRightPos));
} else {
assert(
preciseCoordinates.write(s, xRightNumOfChars + yRightNumOfChars + 1,
yRightPos));
}
delete[] s;
}
}
/*
2.2.1 ~SetPartnerNo~
*/
void SegmentData::SetPartnerno(int no) {
partnerno = no;
}
/*
2.2.1 ~SetInsideAbove~
*/
void SegmentData::SetInsideAbove(bool b) {
insideAbove = b;
}
/*
2.2.1 ~SetCoverageno~
*/
void SegmentData::SetCoverageno(int no) {
coverageno = no;
}
/*
2.2.1 ~SetCycleno~
*/
void SegmentData::SetCycleno(int no) {
cycleno = no;
}
/*
2.2.1 ~setFaceno~
*/
void SegmentData::SetFaceno(int no) {
faceno = no;
}
/*
2.2.1 ~SetEdgeNo~
*/
void SegmentData::SetEdgeNo(int no) {
edgeno = no;
}
/*
2.2.1 ~addPreciseValues~
*/
void SegmentData::addPreciseValues(Flob& preciseCoordinates, mpq_class pLeftX,
mpq_class pLeftY, mpq_class pRightX, mpq_class pRightY) {
SetPreciseLeftX(preciseCoordinates, pLeftX);
SetPreciseLeftY(preciseCoordinates, pLeftY);
SetPreciseRightX(preciseCoordinates, pRightX);
SetPreciseRightY(preciseCoordinates, pRightY);
}
/*
2.3 Member functions
*/
/*
2.2.1 ~=~
*/
SegmentData& SegmentData::operator=(const SegmentData& s) {
xLeft = s.xLeft;
yLeft = s.yLeft;
xRight = s.xRight;
yRight = s.yRight;
xLeftPos = s.xLeftPos;
yLeftPos = s.yLeftPos;
xRightPos = s.xRightPos;
yRightPos = s.yRightPos;
xLeftNumOfChars = s.xLeftNumOfChars;
yLeftNumOfChars = s.yLeftNumOfChars;
xRightNumOfChars = s.xRightNumOfChars;
yRightNumOfChars = s.yRightNumOfChars;
ldp = s.ldp;
cycleno = s.cycleno;
edgeno = s.edgeno;
coverageno = s.coverageno;
insideAbove = s.insideAbove;
partnerno = s.partnerno;
return *this;
}
/*
2.2.1 ~BoundingBox~
*/
const Rectangle<2> SegmentData::BoundingBox(const Flob& preciseCoordinates,
const Geoid* geoid /*= 0*/) const {
assert(!geoid);
/*
double minx = getLeftX() < getRightX() ? getLeftX() : getRightX();
double maxx = getLeftX() < getRightX() ? getRightX() + 1 : getLeftX() + 1;
double miny = getLeftY() < getRightY() ? getLeftY() : getRightY();
double maxy = getLeftY() < getRightY() ? getRightY() + 1 : getLeftY() + 1;
return Rectangle<2>(true, minx, maxx, miny, maxy);*/
double xd = GetDomPreciseXCoord(preciseCoordinates).get_d()
+ GetDomGridXCoord();
double yd = GetDomPreciseYCoord(preciseCoordinates).get_d()
+ GetDomGridYCoord();
double xs = GetSecPreciseXCoord(preciseCoordinates).get_d()
+ GetSecGridXCoord();
double ys = GetSecPreciseYCoord(preciseCoordinates).get_d()
+ GetSecGridYCoord();
double minX = xd < xs ? xd : xs;
double maxX = xd < xs ? xs : xd;
double minY = yd < ys ? yd : ys;
double maxY = yd < ys ? ys : yd;
double minMax[] = {minX , maxX ,minY ,maxY };
return Rectangle<2>( true, minMax );
}
/*
2.2.1 ~isVertical~
*/
bool SegmentData::IsVertical(const Flob& preciseCoordinates) const {
if (xLeft != xRight) {
return false;
} else {
if (cmp(getPreciseLeftX(preciseCoordinates),
getPreciseRightX(preciseCoordinates)) == 0) {
return true;
} else {
return false;
}
}
}
/*
3 Class Line2
*/
/*
3.1 Constructors
*/
Line2::Line2() {};
Line2::Line2(const bool def, bool ldp, int xl, int yl, int xr, int yr,
mpq_class pxl, mpq_class pyl, mpq_class pxr, mpq_class pyr) :
StandardSpatialAttribute<2>(def), preciseCoordinates(0), segmentData(0) {
SegmentData sd(xl, yl, xr, yr, ldp);
sd.SetPreciseLeftX(preciseCoordinates, pxl);
sd.SetPreciseLeftY(preciseCoordinates, pyl);
sd.SetPreciseRightX(preciseCoordinates, pxr);
sd.SetPreciseRightY(preciseCoordinates, pyr);
segmentData.Append(sd);
bbox = sd.BoundingBox(preciseCoordinates);
assert(IsDefined() && BoundingBox().IsDefined());
}
Line2::Line2(const Line2& l) :
StandardSpatialAttribute<2>(l.IsDefined()), preciseCoordinates(
l.preciseCoordinates.getSize()), segmentData(l.segmentData.Size()), bbox(
l.bbox) {
preciseCoordinates.copyFrom(l.preciseCoordinates);
segmentData.copyFrom(l.segmentData);
assert(IsDefined() == BoundingBox().IsDefined());
}
Line2::Line2(bool def) :
StandardSpatialAttribute<2>(def), preciseCoordinates(0), segmentData(0),
bbox(false) {
}
/*
3.2 Read access methods
*/
/*
3.2.1 Read grid values
*/
int Line2::getLeftGridX(int i) const {
assert(0 <= i && i < segmentData.Size());
SegmentData sd;
segmentData.Get(i, &sd);
return sd.getLeftX();
}
int Line2::getLeftGridY(int i) const {
assert(0 <= i && i < segmentData.Size());
SegmentData sd;
segmentData.Get(i, &sd);
return sd.getLeftY();
}
int Line2::getRightGridX(int i) const {
assert(0 <= i && i < segmentData.Size());
SegmentData sd;
segmentData.Get(i, &sd);
return sd.getRightX();
}
int Line2::getRightGridY(int i) const {
assert(0 <= i && i < segmentData.Size());
SegmentData sd;
segmentData.Get(i, &sd);
return sd.getRightY();
}
/*
3.2.1 Read precise values
*/
mpq_class Line2::getPreciseLeftX(int i) const {
assert(0 <= i && i < segmentData.Size());
SegmentData sd;
segmentData.Get(i, &sd);
return sd.getPreciseLeftX(preciseCoordinates);
}
mpq_class Line2::getPreciseLeftY(int i) const {
assert(0 <= i && i < segmentData.Size());
SegmentData sd;
segmentData.Get(i, &sd);
return sd.getPreciseLeftY(preciseCoordinates);
}
mpq_class Line2::getPreciseRightX(int i) const {
assert(0 <= i && i < segmentData.Size());
SegmentData sd;
segmentData.Get(i, &sd);
return sd.getPreciseRightX(preciseCoordinates);
}
mpq_class Line2::getPreciseRightY(int i) const {
assert(0 <= i && i < segmentData.Size());
SegmentData sd;
assert(segmentData.Get(i, &sd));
return sd.getPreciseRightY(preciseCoordinates);
}
/*
3.2.1 ~get~
*/
void Line2::get(int i, SegmentData& sd) const {
assert(0 <= i && i <= segmentData.Size());
segmentData.Get(i, sd);
}
/*
3.2.1 ~IsLeftDomPoint~
*/
bool Line2::IsLeftDomPoint(int i) const {
assert(0 <= i && i < segmentData.Size());
SegmentData sd;
assert(segmentData.Get(i, &sd));
return sd.IsLeftDomPoint();
}
/*
3.3 Write access methods
*/
/*
3.3.1 ~addSegment~
*/
void Line2::addSegment(bool ldp, int leftX, int leftY, int rightX, int rightY,
mpq_class pLeftX, mpq_class pLeftY, mpq_class pRightX, mpq_class pRightY,
int edgeNo) {
SegmentData sd(leftX, leftY, rightX, rightY, ldp, edgeNo);
sd.addPreciseValues(preciseCoordinates, pLeftX, pLeftY, pRightX, pRightY);
segmentData.Append(sd);
}
void Line2::addSegment(bool ldp, Point2* lp, Point2* rp, int edgeno) {
SegmentData sd(lp, rp, ldp, edgeno, preciseCoordinates);
segmentData.Append(sd);
}
/*
3.4 Member functions
*/
/*
3.4.1 ~=~
*/
Line2& Line2::operator=(const Line2& l) {
assert(l.ordered);
SetDefined(l.IsDefined());
preciseCoordinates.copyFrom(l.preciseCoordinates);
segmentData.copyFrom(l.segmentData);
noComponents = l.noComponents;
ordered = true;
bbox = l.bbox;
return *this;
}
/*
3.4.1 ~Size~
*/
int Line2::Size() const {
return segmentData.Size();
}
/*
3.4.1 ~Destroy=~
*/
inline void Line2::Destroy() {
preciseCoordinates.destroy();
segmentData.destroy();
}
/*
3.4.1 ~collectFace~
*/
void Line2::collectFace(int faceno, int startPos, DbArray<bool>& used) {
set<int> extensionPos;
used.Put(startPos, true);
SegmentData sd1;
SegmentData sd2;
int pos = startPos;
segmentData.Get(startPos, sd1);
SegmentData Sd1 = sd1;
int edgeno = 0;
Sd1.SetInsideAbove(false);
Sd1.SetCoverageno(0);
Sd1.SetCycleno(0);
Sd1.SetFaceno(faceno);
Sd1.SetEdgeNo(edgeno);
segmentData.Put(pos, Sd1);
used.Put(pos, true);
// get and Set the Partner
int partner = Sd1.GetPartnerno();
segmentData.Get(partner, sd2);
SegmentData Sd2 = sd2;
Sd2.SetInsideAbove(false);
Sd2.SetCoverageno(0);
Sd2.SetCycleno(0);
Sd2.SetFaceno(faceno);
Sd2.SetEdgeNo(edgeno);
used.Put(partner, true);
segmentData.Put(partner, Sd2);
if (!bbox.IsDefined()) {
bbox = sd1.BoundingBox(preciseCoordinates);
} else {
bbox = bbox.Union(sd1.BoundingBox(preciseCoordinates));
}
if (getUnusedExtension(pos, used) >= 0) {
extensionPos.insert(pos);
}
if (getUnusedExtension(partner, used) >= 0) {
extensionPos.insert(partner);
}
edgeno++;
while (!extensionPos.empty()) {
int spos = *(extensionPos.begin());
pos = getUnusedExtension(spos, used);
if (pos < 0) {
extensionPos.erase(spos);
} else { // extension found at position pos
segmentData.Get(pos, sd1);
Sd1 = (sd1);
Sd1.SetInsideAbove(false);
Sd1.SetCoverageno(0);
Sd1.SetCycleno(0);
Sd1.SetFaceno(faceno);
Sd1.SetEdgeNo(edgeno);
used.Put(pos, true);
segmentData.Put(pos, Sd1);
partner = Sd1.GetPartnerno();
segmentData.Get(partner, sd2);
Sd2 = (sd2);
Sd2.SetInsideAbove(false);
Sd2.SetCoverageno(0);
Sd2.SetCycleno(0);
Sd2.SetFaceno(faceno);
Sd2.SetEdgeNo(edgeno);
used.Put(partner, true);
segmentData.Put(partner, Sd2);
if (getUnusedExtension(partner, used) >= 0) {
extensionPos.insert(partner);
}
bbox = bbox.Union(sd1.BoundingBox(preciseCoordinates));
edgeno++;
}
}
}
/*
3.4.1 ~getUnusedExtension~
*/
int Line2::getUnusedExtension(int startPos, const DbArray<bool>& used) const {
SegmentData hs, hs2;
segmentData.Get(startPos, hs);
int pos = startPos - 1;
bool done = false;
bool u;
// search on the left side
while (pos >= 0 && !done) {
segmentData.Get(pos, hs2);
if (hs.GetDomGridXCoord() != hs2.GetDomGridXCoord()
|| hs.GetDomGridYCoord() != hs2.GetDomGridYCoord()
|| cmp(hs.GetDomPreciseXCoord(preciseCoordinates),
hs2.GetDomPreciseXCoord(preciseCoordinates)) != 0
|| cmp(hs.GetDomPreciseYCoord(preciseCoordinates),
hs2.GetDomPreciseYCoord(preciseCoordinates)) != 0) {
done = true;
} else {
used.Get(pos, u);
if (!u) {
return pos;
} else {
pos--;
}
}
}
// search on the right side
done = false;
pos = startPos + 1;
int size = segmentData.Size();
while (!done && pos < size) {
segmentData.Get(pos, hs);
if (hs.GetDomGridXCoord() != hs2.GetDomGridXCoord()
|| hs.GetDomGridYCoord() != hs2.GetDomGridYCoord()
|| cmp(hs.GetDomPreciseXCoord(preciseCoordinates),
hs2.GetDomPreciseXCoord(preciseCoordinates)) != 0
|| cmp(hs.GetDomPreciseYCoord(preciseCoordinates),
hs2.GetDomPreciseYCoord(preciseCoordinates)) != 0) {
done = true;
} else {
used.Get(pos, u);
if (!u) {
return pos;
} else {
pos++;
}
}
}
return -1;
}
/*
3.4.1 ~computeComponents~
Computes the length of this lines as well as its bounding box and the number
of components of this line. Each halfsegment is assigned to a face number
(the component) and an edge number within this face.
*/
void Line2::computeComponents() {
noComponents = 0;
bbox.SetDefined(false);
if (!IsDefined() || Size() == 0) {
return;
}
DbArray<bool> used(segmentData.Size());
for (int i = 0; i < segmentData.Size(); i++) {
used.Append(false);
}
int faceno = 0;
bool u;
for (int i = 0; i < segmentData.Size(); i++) {
used.Get(i, u);
if (!(u)) { // an unused halfsegment
collectFace(faceno, i, used);
faceno++;
}
}
noComponents = faceno;
used.Destroy();
}
void Line2::StartBulkLoad() {
ordered = false;
}
/*
3.4.1 ~EndBulkLoad~
Finishes the bulkload for a line. If this function is called,
both halfSegments assigned to a segment of the line must be part
of this line.
The parameter ~sort~ can be set to __false__ if the halfsegments are
already ordered using the falfSegment order.
The parameter ~realminize~ can be set to __false__ if the line is
already realminized, meaning each pair of different Segments has
at most a common endpoint. Furthermore, the two halfsegments belonging
to a segment must have the same edge number. The edge numbers must be
in Range [0..Size()-1]. HalfSegments belonging to different segments
must have different edge numbers.
Only change one of the parameters if you exactly know what you do.
Changing such parameters without fulfilling the conditions stated
above may construct invalid line representations which again may
produce a system crash within some operators.
*/
void Line2::EndBulkLoad(const bool sort /* = true*/,
const bool realminize /* = true*/, const bool robust /* = false*/) {
if (!IsDefined()) {
Clear();
SetDefined(false);
}
if (sort) {
Sort();
}
if (Size() > 0) {
if (realminize) {
Line2* resultLine = new Line2(true);
Realminize(*this, *resultLine, false);
resultLine->Sort();
this->CopyFrom(resultLine);
resultLine->Destroy();
delete resultLine;
}
SetPartnerNo();
}
computeComponents();
segmentData.TrimToSize();
}
/*
3.4.1 ~Clear~
*/
void Line2::Clear() {
segmentData.clean();
preciseCoordinates.clean();
ordered = true;
bbox.SetDefined(false);
SetDefined(true);
}
/*
3.4.1 ~SegmentIsVertical~
*/
bool Line2::SegmentIsVertical(int lx, mpq_class plx, int rx, mpq_class prx) {
if (lx != rx) {
return false;
}
if (cmp(plx, prx) != 0) {
return false;
}
return true;
}
/*
3.4.1 ~CompareSegment~
Compares the given halfsegments. Returns
1 if ~seg1~ $>$ ~seg2~,
0 if ~seg1~ $=$ ~seg2~ and
-1 if ~seg1~ $<$ ~seg2~
First the dominating points of both halfsegments will be
compared. If both halfsegments have the same left
dominating point, we compare the slopes of the
halfsegments. If they are equal too, the second point of
both halfsegments will be compared.
*/
int Line2::CompareSegment(const SegmentData& seg1,
const SegmentData& seg2) const {
int seg1DomGridX = seg1.GetDomGridXCoord();
int seg1DomGridY = seg1.GetDomGridYCoord();
int seg1SecGridX = seg1.GetSecGridXCoord();
int seg1SecGridY = seg1.GetSecGridYCoord();
mpq_class seg1DomPreciseX = seg1.GetDomPreciseXCoord(preciseCoordinates);
mpq_class seg1DomPreciseY = seg1.GetDomPreciseYCoord(preciseCoordinates);
int seg2DomGridX = seg2.GetDomGridXCoord();
int seg2DomGridY = seg2.GetDomGridYCoord();
int seg2SecGridX = seg2.GetSecGridXCoord();
int seg2SecGridY = seg2.GetSecGridYCoord();
mpq_class seg2DomPreciseX = seg2.GetDomPreciseXCoord(preciseCoordinates);
mpq_class seg2DomPreciseY = seg2.GetDomPreciseYCoord(preciseCoordinates);
int cmpDomPreciseX = cmp(seg1DomPreciseX, seg2DomPreciseX);
//comparing the dominating points
if ((seg1DomGridX < seg2DomGridX)
|| ((seg1DomGridX == seg2DomGridX) && (cmpDomPreciseX < 0))
|| ((seg1DomGridX == seg2DomGridX) && (cmpDomPreciseX == 0)
&& (seg1DomGridY < seg2DomGridY))
|| ((seg1DomGridX == seg2DomGridX) && (cmpDomPreciseX == 0)
&& (seg1DomGridY == seg2DomGridY)
&& (cmp(seg1DomPreciseY, seg2DomPreciseY) < 0))) {
//The dominating point of ~this~ is less than
//the dominating point of ~s~.
return -1;
} else {
if ((seg1DomGridX > seg2DomGridX)
|| ((seg1DomGridX == seg2DomGridX) && (cmpDomPreciseX > 0))
|| ((seg1DomGridX == seg2DomGridX) && (cmpDomPreciseX == 0)
&& (seg1DomGridY > seg2DomGridY))
|| ((seg1DomGridX == seg2DomGridX) && (cmpDomPreciseX == 0)
&& (seg1DomGridY == seg2DomGridY)
&& (cmp(seg1DomPreciseY, seg2DomPreciseY) > 0))) {
//The dominating point of ~this~ is greater
//than the dominating point of ~s~.
return 1;
}
}
//both halfsegments have the same dominating point
//they might be the both halfsegments of one segment.
//If so, this function returns 1 if the left point of
//~seg1~ is the dominating point (in this case the
//second point of ~seg2~ is a dominating point too.)
if (seg1.IsLeftDomPoint() != seg2.IsLeftDomPoint()) {
if (!seg1.IsLeftDomPoint()) {
return -1;
}
return 1;
} else {
//both halfsegments have the same dominating point,
//which are in both halfsegments the left points.
//Now we compare the slopes of both halfsegments
mpq_class seg1SecPreciseX = seg1.GetSecPreciseXCoord(preciseCoordinates);
mpq_class seg1SecPreciseY = seg1.GetSecPreciseYCoord(preciseCoordinates);
mpq_class seg2SecPreciseX = seg2.GetSecPreciseXCoord(preciseCoordinates);
mpq_class seg2SecPreciseY = seg2.GetSecPreciseYCoord(preciseCoordinates);
bool v1 = ((seg1DomGridX == seg1SecGridX)
&& (seg1DomPreciseX == seg1SecPreciseX));
bool v2 = ((seg2DomGridX == seg2SecGridX)
&& (seg2DomPreciseX == seg2SecPreciseX));
if (v1 && v2) {
//both halfsegments are vertical
int cmpThisY = cmp(seg1SecPreciseY, seg1DomPreciseY);
int cmpSY = cmp(seg2SecPreciseY, seg2DomPreciseY);
if ((((seg1SecGridY > seg1DomGridY)
|| ((seg1SecGridY == seg1DomGridY) && cmpThisY > 0))
&& ((seg2SecGridY > seg2DomGridY)
|| ((seg2SecGridY == seg2DomGridY) && cmpSY > 0)))
|| (((seg1SecGridY < seg1DomGridY)
|| ((seg1SecGridY == seg1DomGridY) && cmpThisY < 0))
&& ((seg2SecGridY < seg2DomGridY)
|| ((seg2SecGridY == seg2DomGridY) && cmpSY < 0)))) {
//The y-value of the second points of both
//halfsegments are greater than their
//dominating points or the y-value of the
//second points of the halfsegments are less
//than their dominating points.
int cmpSecPreciseX = cmp(seg1SecPreciseX, seg2SecPreciseX);
if ((seg1SecGridX < seg2SecGridX)
|| ((seg1SecGridX == seg2SecGridX) && (cmpSecPreciseX < 0))
|| ((seg1SecGridX == seg2SecGridX) && (cmpSecPreciseX == 0)
&& (seg1SecGridY < seg2SecGridY))
|| ((seg1SecGridX == seg2SecGridX) && (cmpSecPreciseX == 0)
&& (seg1SecGridY == seg2SecGridY)
&& (cmp(seg1SecPreciseX, seg2SecPreciseX) < 0))) {
//The second point of ~this~ is less
//than the
//second point of ~s~.
return -1;
}
if ((seg1SecGridX > seg2SecGridX)
|| ((seg1SecGridX == seg2SecGridX) && (cmpSecPreciseX > 0))
|| ((seg1SecGridX == seg2SecGridX) && (cmpSecPreciseX == 0)
&& (seg1SecGridY > seg2SecGridY))
|| ((seg1SecGridX == seg2SecGridX) && (cmpSecPreciseX == 0)
&& (seg1SecGridY == seg2SecGridY)
&& (cmp(seg1SecPreciseX, seg2SecPreciseX) > 0))) {
//The second point of ~this~ is greater
//than the second point of ~s~.
return 1;
}
return 0;
} else {
if ((seg1SecGridY > seg1DomGridY)
|| ((seg1SecGridY == seg1DomGridY)
&& (cmp(seg1SecPreciseY, seg1DomPreciseY) > 0))) {
//The y-value of the second point of
//~this~ is greater than the y-value of
//the dominating point of ~this~.
if (seg1.IsLeftDomPoint()) {
return 1;
} else {
return -1;
}
} else {
if (seg1.IsLeftDomPoint()) {
return -1;
} else {
return 1;
}
}
}
} else {
if (v1) {
//~this~ is vertical
if ((seg1SecGridY > seg1DomGridY)
|| ((seg1SecGridY == seg1DomGridY)
&& cmp(seg1SecPreciseY, seg1DomPreciseY) > 0)) {
//the y-value of the second point of
//~this~ is greater than
//the dominating point of ~this~
if (seg1.IsLeftDomPoint())
return 1;
return -1;
} else {
if ((seg1SecGridY < seg1DomGridY)
|| ((seg1SecGridY == seg1DomGridY)
&& cmp(seg1SecPreciseY, seg1DomPreciseY) < 0))
{
if (seg1.IsLeftDomPoint())
return -1;
return 1;
}
}
} else {
if (v2) {
//~s~ is vertical
if ((seg2SecGridY > seg2DomGridY)
|| ((seg2SecGridY == seg2DomGridY)
&& cmp(seg2SecPreciseY, seg2DomPreciseY) > 0))
//the y-value of the second
//point of ~s~ is greater
//than the dominating point
//of ~s~
{
if (seg1.IsLeftDomPoint())
return -1;
return 1;
} else if ((seg2SecGridY < seg2DomGridY)
|| ((seg2SecGridY == seg2DomGridY)
&& cmp(seg2SecPreciseY, seg2DomPreciseY) < 0)) {
//the y-value of the second
//point of ~s~ is greater
//than the dominating point
//of ~s~
if (seg1.IsLeftDomPoint())
return 1;
return -1;
}
} else {
mpq_class xd = seg1DomPreciseX + seg1DomGridX;
mpq_class yd = seg1DomPreciseY + seg1DomGridY;
mpq_class xs = seg1SecPreciseX + seg1SecGridX;
mpq_class ys = seg1SecPreciseY + seg1SecGridY;
mpq_class Xd = seg2DomPreciseX + seg2DomGridX;
mpq_class Yd = seg2DomPreciseY + seg2DomGridY;
mpq_class Xs = seg2SecPreciseX + seg2SecGridX;
mpq_class Ys = seg2SecPreciseY + seg2SecGridY;
mpq_class seg1Slope = (yd - ys) / (xd - xs);
mpq_class seg2Slope = (Yd - Ys) / (Xd - Xs);
int cmpSlope = cmp(seg1Slope, seg2Slope);
if (cmpSlope < 0) {
return -1;
}
if (cmpSlope > 0) {
return 1;
}
int cmpSecPreciseX = cmp(seg1SecPreciseX, seg2SecPreciseX);
if ((seg1SecGridX < seg2SecGridX)
|| ((seg1SecGridX == seg2SecGridX) && (cmpSecPreciseX < 0))
|| ((seg1SecGridX == seg2SecGridX) && (cmpSecPreciseX == 0)
&& (seg1SecGridY < seg2SecGridY))
|| ((seg1SecGridX == seg2SecGridX) && (cmpSecPreciseX == 0)
&& (seg1SecGridY == seg2SecGridY)
&& (cmp(seg1SecPreciseX, seg2SecPreciseX) < 0))) {
//The second point of ~this~ is less
//than the second point of ~s~
return -1;
}
if ((seg1SecGridX > seg2SecGridX)
|| ((seg1SecGridX == seg2SecGridX) && (cmpSecPreciseX > 0))
|| ((seg1SecGridX == seg2SecGridX) && (cmpSecPreciseX == 0)
&& (seg1SecGridY > seg2SecGridY))
|| ((seg1SecGridX == seg2SecGridX) && (cmpSecPreciseX == 0)
&& (seg1SecGridY == seg2SecGridY)
&& (cmp(seg1SecPreciseX, seg2SecPreciseX) > 0))) {
//The second point of ~this~ is
//greater than
//the second point of ~s~
return 1;
}
return 0;
}
}
}
}
assert(false); // This code should never be reached
return 0;
}
/*
3.4.1 ~CompareSegment2~
Compares the given halfsegments. Returns
1 if ~seg1~ $>$ ~seg2~,
0 if ~seg1~ $=$ ~seg2~ and
-1 if ~seg1~ $<$ ~seg2~
First the dominating points of both halfsegments will be
compared. If both halfsegments have the same left
dominating point, we compare the slopes of the
halfsegments. If they are equal too, the second
point of both halfsegments will be compared.
*/
int Line2::CompareSegment2(const SegmentData& seg1, const SegmentData& seg2,
const Flob& preciseCoordOfSeg2) const {
int seg1DomGridX = seg1.GetDomGridXCoord();
int seg1DomGridY = seg1.GetDomGridYCoord();
int seg1SecGridX = seg1.GetSecGridXCoord();
int seg1SecGridY = seg1.GetSecGridYCoord();
mpq_class seg1DomPreciseX = seg1.GetDomPreciseXCoord(preciseCoordinates);
mpq_class seg1DomPreciseY = seg1.GetDomPreciseYCoord(preciseCoordinates);
int seg2DomGridX = seg2.GetDomGridXCoord();
int seg2DomGridY = seg2.GetDomGridYCoord();
int seg2SecGridX = seg2.GetSecGridXCoord();
int seg2SecGridY = seg2.GetSecGridYCoord();
mpq_class seg2DomPreciseX = seg2.GetDomPreciseXCoord(preciseCoordOfSeg2);
mpq_class seg2DomPreciseY = seg2.GetDomPreciseYCoord(preciseCoordOfSeg2);
int cmpDomPreciseX = cmp(seg1DomPreciseX, seg2DomPreciseX);
//comparing the dominating points
if ((seg1DomGridX < seg2DomGridX)
|| ((seg1DomGridX == seg2DomGridX) && (cmpDomPreciseX < 0))
|| ((seg1DomGridX == seg2DomGridX) && (cmpDomPreciseX == 0)
&& (seg1DomGridY < seg2DomGridY))
|| ((seg1DomGridX == seg2DomGridX) && (cmpDomPreciseX == 0)
&& (seg1DomGridY == seg2DomGridY)
&& (cmp(seg1DomPreciseY, seg2DomPreciseY) < 0))) {
//The dominating point of ~this~ is less than the
//dominating point of ~s~.
return -1;
} else {
if ((seg1DomGridX > seg2DomGridX)
|| ((seg1DomGridX == seg2DomGridX) && (cmpDomPreciseX > 0))
|| ((seg1DomGridX == seg2DomGridX) && (cmpDomPreciseX == 0)
&& (seg1DomGridY > seg2DomGridY))
|| ((seg1DomGridX == seg2DomGridX) && (cmpDomPreciseX == 0)
&& (seg1DomGridY == seg2DomGridY)
&& (cmp(seg1DomPreciseX, seg2DomPreciseX) > 0))) {
//The dominating point of ~this~ is greater than the
//dominating point of ~s~.
return 1;
}
}
//both halfsegments have the same dominating point
//they might be the both halfsegments of one segment.
//If so, this function returns 1 if the left point of
//~seg1~ is the dominating point (in this case the
//second point of ~seg2~ is a dominating point too.)
if (seg1.IsLeftDomPoint() != seg2.IsLeftDomPoint()) {
if (!seg1.IsLeftDomPoint()) {
return -1;
}
return 1;
} else {
//both halfsegments have the same dominating point,
//which are in both
//halfsegments the left points.
//Now we compare the slopes of both halfsegments
mpq_class seg1SecPreciseX = seg1.GetSecPreciseXCoord(preciseCoordinates);
mpq_class seg1SecPreciseY = seg1.GetSecPreciseYCoord(preciseCoordinates);
mpq_class seg2SecPreciseX = seg2.GetSecPreciseXCoord(preciseCoordOfSeg2);
mpq_class seg2SecPreciseY = seg2.GetSecPreciseYCoord(preciseCoordOfSeg2);
bool v1 = ((seg1DomGridX == seg1SecGridX)
&& (seg1DomPreciseX == seg1SecPreciseX));
bool v2 = ((seg2DomGridX == seg2SecGridX)
&& (seg2DomPreciseX == seg2SecPreciseX));
if (v1 && v2) {
//both halfsegments are vertical
int cmpThisY = cmp(seg1SecPreciseY, seg1DomPreciseY);
int cmpSY = cmp(seg2SecPreciseY, seg2DomPreciseY);
if ((((seg1SecGridY > seg1DomGridY)
|| ((seg1SecGridY == seg1DomGridY) && cmpThisY > 0))
&& ((seg2SecGridY > seg2DomGridY)
|| ((seg2SecGridY == seg2DomGridY) && cmpSY > 0)))
|| (((seg1SecGridY < seg1DomGridY)
|| ((seg1SecGridY == seg1DomGridY) && cmpThisY < 0))
&& ((seg2SecGridY < seg2DomGridY)
|| ((seg2SecGridY == seg2DomGridY) && cmpSY < 0)))) {
//The y-value of the second points of both
//halfsegments are greater than their
//dominating points or the y-value of the
//second points of the halfsegments are
//less than their dominating points.
int cmpSecPreciseX = cmp(seg1SecPreciseX, seg2SecPreciseX);
if ((seg1SecGridX < seg2SecGridX)
|| ((seg1SecGridX == seg2SecGridX) && (cmpSecPreciseX < 0))
|| ((seg1SecGridX == seg2SecGridX) && (cmpSecPreciseX == 0)
&& (seg1SecGridY < seg2SecGridY))
|| ((seg1SecGridX == seg2SecGridX) && (cmpSecPreciseX == 0)
&& (seg1SecGridY == seg2SecGridY)
&& (cmp(seg1SecPreciseX, seg2SecPreciseX) < 0))) {
//The second point of ~this~ is less
//than the second point of ~s~.
return -1;
}
if ((seg1SecGridX > seg2SecGridX)
|| ((seg1SecGridX == seg2SecGridX) && (cmpSecPreciseX > 0))
|| ((seg1SecGridX == seg2SecGridX) && (cmpSecPreciseX == 0)
&& (seg1SecGridY > seg2SecGridY))
|| ((seg1SecGridX == seg2SecGridX) && (cmpSecPreciseX == 0)
&& (seg1SecGridY == seg2SecGridY)
&& (cmp(seg1SecPreciseX, seg2SecPreciseX) > 0))) {
//The second point of ~this~ is greater
//than the second point of ~s~.
return 1;
}
return 0;
} else {
if ((seg1SecGridY > seg1DomGridY)
|| ((seg1SecGridY == seg1DomGridY)
&& (cmp(seg1SecPreciseY, seg1DomPreciseY) > 0))) {
//The y-value of the second point of
//~this~ is greater than the y-value
//of the dominating point of ~this~.
if (seg1.IsLeftDomPoint()) {
return 1;
} else {
return -1;
}
} else {
if (seg1.IsLeftDomPoint()) {
return -1;
} else {
return 1;
}
}
}
} else {
if (v1) {
//~this~ is vertical
if ((seg1SecGridY > seg1DomGridY)
|| ((seg1SecGridY == seg1DomGridY)
&& cmp(seg1SecPreciseY, seg1DomPreciseY) > 0)) {
//the y-value of the second point
//of ~this~ is greater than
//the dominating point of ~this~
if (seg1.IsLeftDomPoint())
return 1;
return -1;
} else {
if ((seg1SecGridY < seg1DomGridY)
|| ((seg1SecGridY == seg1DomGridY)
&& cmp(seg1SecPreciseY, seg1DomPreciseY) < 0))
{
if (seg1.IsLeftDomPoint())
return -1;
return 1;
}
}
} else {
if (v2) {
//~s~ is vertical
if ((seg2SecGridY > seg2DomGridY)
|| ((seg2SecGridY == seg2DomGridY)
&& cmp(seg2SecPreciseY, seg2DomPreciseY) > 0))
//the y-value of the second
//point of ~s~ is greater than
//the dominating point of ~s~
{
if (seg1.IsLeftDomPoint())
return -1;
return 1;
} else if ((seg2SecGridY < seg2DomGridY)
|| ((seg2SecGridY == seg2DomGridY)
&& cmp(seg2SecPreciseY, seg2DomPreciseY) < 0)) {
//the y-value of the second
//point of ~s~ is greater than
//the dominating point of ~s~
if (seg1.IsLeftDomPoint())
return 1;
return -1;
}
} else {
mpq_class xd = seg1DomPreciseX + seg1DomGridX;
mpq_class yd = seg1DomPreciseY + seg1DomGridX;
mpq_class xs = seg1SecPreciseX + seg1SecGridX;
mpq_class ys = seg1SecPreciseY + seg1SecGridY;
mpq_class Xd = seg2DomPreciseX + seg2DomGridX;
mpq_class Yd = seg2DomPreciseY + seg2DomGridY;
mpq_class Xs = seg2SecPreciseX + seg2SecGridX;
mpq_class Ys = seg2SecPreciseY + seg2SecGridY;
mpq_class seg1Slope = (yd - ys) / (xd - xs);
mpq_class seg2Slope = (Yd - Ys) / (Xd - Xs);
int cmpSlope = cmp(seg1Slope, seg2Slope);
if (cmpSlope < 0) {
return -1;
}
if (cmpSlope > 0) {
return 1;
}
int cmpSecPreciseX = cmp(seg1SecPreciseX, seg2SecPreciseX);
if ((seg1SecGridX < seg2SecGridX)
|| ((seg1SecGridX == seg2SecGridX) && (cmpSecPreciseX < 0))
|| ((seg1SecGridX == seg2SecGridX) && (cmpSecPreciseX == 0)
&& (seg1SecGridY < seg2SecGridY))
|| ((seg1SecGridX == seg2SecGridX) && (cmpSecPreciseX == 0)
&& (seg1SecGridY == seg2SecGridY)
&& (cmp(seg1SecPreciseX, seg2SecPreciseX) < 0))) {
//The second point of ~this~ is
//less than
//the second point of ~s~
return -1;
}
if ((seg1SecGridX > seg2SecGridX)
|| ((seg1SecGridX == seg2SecGridX) && (cmpSecPreciseX > 0))
|| ((seg1SecGridX == seg2SecGridX) && (cmpSecPreciseX == 0)
&& (seg1SecGridY > seg2SecGridY))
|| ((seg1SecGridX == seg2SecGridX) && (cmpSecPreciseX == 0)
&& (seg1SecGridY == seg2SecGridY)
&& (cmp(seg1SecPreciseX, seg2SecPreciseX) > 0))) {
//The second point of ~this~ is
//greater than
//the second point of ~s~
return 1;
}
return 0;
}
}
}
}
assert(false); // This code should never be reached
return 0;
}
/*
3.4.1 ~Sort~
Sorts the segments with Mergesort using the function CompareSegment
*/
void Line2::Sort() {
assert(!IsOrdered());
int sz = segmentData.Size();
if (sz > 1) {
MergeSort(0, sz - 1);
}
ordered = true;
}
/*
3.4.1 ~MergeSort~
*/
void Line2::MergeSort(int startindex, int endindex) {
if (startindex < endindex) {
int divide = floor(((double) (startindex + endindex)) / 2.0);
MergeSort(startindex, divide);
MergeSort(divide + 1, endindex);
Merge(startindex, divide, endindex);
}
}
/*
3.4.1 ~Merge~
This function merges 2 sorted sequences stored in the DbArray ~segentData~.
The first sequence starts with ~startindex~ and ends with ~divide~ and the
second sequence starts with ~divide~+1 and ends with ~endindex~. Both
sequences will be edited in parallel and the sorted result will be
stored in the DbArray starting at index ~startindex~.
*/
void Line2::Merge(int startindex, int divide, int endindex) {
int startL = startindex;
int startR = divide + 1;
SegmentData seg1, seg2;
// The number of elements in both sequences:
int elemNo = (endindex - startindex) + 1;
SegmentData result[elemNo];
int index = 0;
segmentData.Get(startL, &seg1);
segmentData.Get(startR, &seg2);
while (index <= elemNo) {
if (CompareSegment(seg1, seg2) <= 0) {
// The current element in the first sequence is less
// than or equal to the current element in the second
// sequence and will be stored in result.
result[index] = seg1;
index++;
startL++;
if (startL <= divide) {
segmentData.Get(startL, &seg1);
} else {
// the first sequence is completely stored
// in result.
break;
}
} else {
// The current element in the first sequence is greater
// than the current element in the second sequence.
// The element of the second sequence will be stored
// in result.
result[index] = seg2;
index++;
startR++;
if (startR <= endindex) {
segmentData.Get(startR, &seg2);
} else {
// the second sequence is completely stored
// in result.
break;
}
}
}
while (startL <= divide) {
// the second sequence is completely stored in result,
// but there are
// still some elements in the first sequence.
segmentData.Get(startL, &seg1);
result[index] = seg1;
index++;
startL++;
}
while (startR <= endindex) {
// the first sequence is completely stored in
// result, but there are
// still some elements in the second sequence.
segmentData.Get(startR, &seg2);
result[index] = seg2;
index++;
startR++;
}
// Storing the merged sequences in the DbArray.
for (int i = 0; i < elemNo; i++) {
segmentData.Put(startindex + i, result[i]);
}
}
/*
3.4.1 ~SetPartnerNo~
*/
void Line2::SetPartnerNo() {
if (!IsDefined() || segmentData.Size() == 0) {
return;
}
// reserve a slot for each edgeno
int tmpsize = (segmentData.Size() + 1) / 2;
DbArray<int> TMP(tmpsize);
// initialize the array (it's only needed for
// wrong sorted halfsegments)
for (int i = 0; i < tmpsize + 1; i++) {
TMP.Put(i, -1);
}
SegmentData seg1;
SegmentData seg2;
int lpp;
for (int i = 0; i < segmentData.Size(); i++) {
segmentData.Get(i, seg1);
TMP.Get(seg1.GetEdgeno(), lpp);
if (seg1.IsLeftDomPoint()) {
if (lpp >= 0) {
int leftpos = lpp;
SegmentData right = seg1;
right.SetPartnerno(leftpos);
right.SetInsideAbove(false);
right.SetCoverageno(0);
right.SetCycleno(0);
right.SetFaceno(0);
segmentData.Get(leftpos, seg2);
SegmentData left = seg2;
left.SetPartnerno(i);
left.SetInsideAbove(false);
left.SetCoverageno(0);
left.SetCycleno(0);
left.SetFaceno(0);
segmentData.Put(i, right);
segmentData.Put(leftpos, left);
} else {
// normal case, put number to tmp
TMP.Put(seg1.GetEdgeno(), i);
}
} else { // RightDomPoint
if (lpp < 0) {
TMP.Put(seg1.GetEdgeno(), i);
} else {
int leftpos = lpp;
SegmentData right = seg1;
right.SetPartnerno(leftpos);
right.SetInsideAbove(false);
right.SetCoverageno(0);
right.SetCycleno(0);
right.SetFaceno(0);
segmentData.Get(leftpos, seg2);
SegmentData left = seg2;
left.SetPartnerno(i);
left.SetInsideAbove(false);
left.SetCoverageno(0);
left.SetCycleno(0);
left.SetFaceno(0);
segmentData.Put(i, right);
segmentData.Put(leftpos, left);
}
}
}
TMP.Destroy();
}
/*
3.5 Set operations
*/
/*
3.5.1 ~unionOp~
*/
void Line2::unionOP(Line2& l2, Line2& result, const Geoid* geoid/*=0*/) {
p2d::SetOp(*this, l2, result, union_op, geoid);
}
void Line2::unionWithScaling(Line2& l2, Line2& result,
const Geoid* geoid/*=0*/) {
p2d::SetOpWithScaling(*this, l2, result, union_op, geoid);
}
/*
3.5.1 ~intersection~
*/
void Line2::intersection(Line2& l2, Line2& result, const Geoid* geoid/*=0*/) {
p2d::SetOp(*this, l2, result, intersection_op, geoid);
}
void Line2::intersectionWithScaling(Line2& l2, Line2& result,
const Geoid* geoid/*=0*/) {
p2d::SetOpWithScaling(*this, l2, result, intersection_op, geoid);
}
/*
3.5.1 ~minus~
*/
void Line2::minus(Line2& l2, Line2& result, const Geoid* geoid/*=0*/) {
p2d::SetOp(*this, l2, result, difference_op, geoid);
}
void Line2::minusWithScaling(Line2& l2, Line2& result,
const Geoid* geoid/*=0*/) {
p2d::SetOpWithScaling(*this, l2, result, difference_op, geoid);
}
/*
3.6 ~intersects~
*/
bool Line2::intersects(Line2& l2, const Geoid* geoid/*=0*/) {
return p2d::intersects(*this, l2, geoid);
}
bool Line2::intersectsWithScaling(Line2& l2, const Geoid* geoid/*=0*/) {
return p2d::intersectsWithScaling(*this, l2, geoid);
}
/*
3.6 ~crossings~
*/
void Line2::crossings(Line2& l2, Points2& result, const Geoid* geoid/*=0*/) {
p2d::crossings(*this, l2, result, geoid);
}
void Line2::crossingsWithScaling(Line2& l2, Points2& result,
const Geoid* geoid/*=0*/) {
p2d::crossingsWithScaling(*this, l2, result, geoid);
}
/*
3.7 Functions requires by Secondo and virtual functions
of the StandardSpatialAttribute
*/
/*
3.7.1 ~Sizeof~
*/
inline size_t Line2::Sizeof() const {
return (sizeof(*this));
}
/*
3.7.1 ~HashValue~
*/
inline size_t Line2::HashValue() const {
if (IsEmpty()) {
return 0;
}
size_t h = 0;
SegmentData seg;
int x1, y1, x2, y2;
for (int i = 0; i < Size() && i < 5; i++) {
segmentData.Get(i, seg);
x1 = seg.GetDomGridXCoord();
y1 = seg.GetDomGridYCoord();
x2 = seg.GetSecGridXCoord();
y2 = seg.GetSecGridYCoord();
h += (size_t)((5 * x1 + y1) + (5 * x2 + y2));
}
return h;
}
/*
3.7.1 ~CopyFrom~
*/
inline void Line2::CopyFrom(const Attribute* right) {
*this = *((const Line2 *) right);
}
/*
3.7.1 ~Compare~
*/
inline int Line2::Compare(const Attribute *arg) const {
const Line2 &l = *((const Line2*) arg);
if (!IsDefined() && !l.IsDefined()) {
return 0;
}
if (!IsDefined()) {
return -1;
}
if (!l.IsDefined()) {
return 1;
}
if (Size() > l.Size())
return 1;
if (Size() < l.Size())
return -1;
int index = 0;
int result = 0;
while (index < Size()) {
SegmentData sd1;
SegmentData sd2;
segmentData.Get(index, sd1);
l.get(index, sd2);
result = CompareSegment2(sd1, sd2, *(l.getPreciseCoordinates()));
if (result != 0) {
return result;
}
index++;
}
return 0;
}
/*
3.7.1 ~Adjacent~
*/
bool Line2::Adjacent(const Attribute *arg) const {
return false;
}
/*
3.7.1 ~Clone~
*/
Line2* Line2::Clone() const {
return new Line2(*this);
}
/*
3.7.1 ~CloneLine2~
*/
Word Line2::CloneLine2(const ListExpr typeInfo, const Word& w) {
return SetWord(new Line2(*((Line2 *) w.addr)));
}
/*
3.7.1 ~CastLine2~
*/
void* Line2::CastLine2(void* addr) {
return (new (addr) Line2());
}
/*
3.7.1 ~SizeOfLine2~
*/
int Line2::SizeOfLine2() {
return sizeof(Line2);
}
/*
3.7.1 ~CreateLine2~
*/
Word Line2::CreateLine2(const ListExpr typeInfo) {
return SetWord(new Line2(false));
}
/*
3.7.1 ~DeleteLine2~
*/
void Line2::DeleteLine2(const ListExpr typeInfo, Word& w) {
Line2 *l = (Line2 *) w.addr;
(l->GetFLOB(0))->destroy();
(l->GetFLOB(1))->destroy();
l->SetDefined(false);
delete l;
w.addr = 0;
}
/*
3.7.1 ~CloseLine2~
*/
void Line2::CloseLine2(const ListExpr typeInfo, Word& w) {
delete (Line2*) w.addr;
w.addr = 0;
}
/*
3.7.1 ~Line2Property~
*/
ListExpr Line2::Line2Property() {
ListExpr ListRepr = nl->TextAtom();
nl->AppendText(ListRepr, "(<segment>*), where <segment> is "
"((<xl> <xr> ( <pxl> <pyl>))(<xr> <yr> "
"( <pxr> <pyr>))))");
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("-> DATA"),
nl->StringAtom(Line2::BasicType()), ListRepr,
nl->StringAtom("(((1 1 ('1/4' '3/4'))(3 4 "
"('1/8' '1/10'))))")));
}
/*
3.7.1 ~CheckLine2~
*/
bool Line2::CheckLine2(ListExpr type, ListExpr& errorInfo) {
return (nl->IsEqual(type, Line2::BasicType()));
}
/*
3.4.1 ~BoundingBox~
*/
const Rectangle<2> Line2::BoundingBox(const Geoid* geoid /*=0*/) const {
if (geoid) {
cerr << ": Spherical geometry not implemented." << endl;
assert(false);
}
return bbox;
}
/*
3.7.1 ~Distance~
*/
double Line2::Distance(const Rectangle<2>& rect,
const Geoid* geoid/*=0*/) const {
//TODO Distance
return numeric_limits<double>::max();
}
/*
3.7.1 ~Empty~
*/
bool Line2::IsEmpty() const {
return ((!IsDefined()) || segmentData.Size() == 0);
}
/*
3.7.1 ~Intersects~
*/
bool Line2::Intersects(const Rectangle<2>& rect,
const Geoid* geoid/*=0*/) const {
assert( !IsEmpty() ); // includes !undef
assert( this->ordered );
assert( rect.IsDefined() );
assert( !geoid || geoid->IsDefined() );
if(!BoundingBox().Intersects(rect,geoid)){
return false;
}
Line2* rectangle = new Line2(0);
Point2* p1;
Point2* p2;
Point2* p3;
Point2* p4;
createPoint2(rect.MinD(0), rect.MinD(1), &p1);
createPoint2(rect.MaxD(0), rect.MinD(1), &p2);
createPoint2(rect.MaxD(0), rect.MaxD(1), &p3);
createPoint2(rect.MinD(0), rect.MaxD(1), &p4);
rectangle->addSegment(true, p1, p2, 0);
rectangle->addSegment(false, p1, p2, 0);
rectangle->addSegment(true, p2, p3, 1);
rectangle->addSegment(false, p2, p3, 1);
rectangle->addSegment(true, p1, p4, 2);
rectangle->addSegment(false, p1, p4, 2);
rectangle->addSegment(true, p4, p3, 3);
rectangle->addSegment(false, p4, p3, 3);
bool intersects = p2d::intersects(*this, *rectangle, geoid);
delete p1;
delete p2;
delete p3;
delete p4;
delete rectangle;
return intersects;
}
/*
3 ~convertLineToLine2~
*/
void convertLineToLine2(Line& l, Line2& result) {
result.Clear();
if (!l.IsDefined()) {
result.SetDefined(false);
return;
}
HalfSegment hs;
int edgeNo = 0;
result.StartBulkLoad();
for (int i = 0; i < l.Size(); i++) {
l.Get(i, hs);
if (hs.IsLeftDomPoint()) {
int glx;
int gly;
mpq_class plx(0);
mpq_class ply(0);
createValue(hs.GetDomPoint().GetX(), glx, plx);
createValue(hs.GetDomPoint().GetY(), gly, ply);
int grx;
int gry;
mpq_class prx(0);
mpq_class pry(0);
createValue(hs.GetSecPoint().GetX(), grx, prx);
createValue(hs.GetSecPoint().GetY(), gry, pry);
result.addSegment(true, glx, gly, grx, gry, plx, ply, prx, pry, edgeNo);
result.addSegment(false, grx, gry, glx, gly, prx, pry, plx, ply, edgeNo);
edgeNo++;
}
}
result.EndBulkLoad(true, false);
assert(result.IsDefined() && result.BoundingBox().IsDefined());
}
} // end of namespace p2d
#endif /* _Line2_CPP*/