/* ---- 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& used) { set 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& 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 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 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, "(*), where is " "(( ( ))( " "( ))))"); 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::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*/