/* ---- This file is part of SECONDO. Copyright (C) 2014, 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 ---- This file provides auxiliary function dealing with precise halfsegments. */ #include "HsTools.h" #include "AvlTree.h" #include "PreciseHalfSegment.h" #include using namespace std; namespace hstools{ /* ~isSorted~ Checks whether ~v~ is sorted according to the halfsegment order. */ bool isSorted(const vector& v){ if(v.size()<2){ return true; } HalfSegmentComparator cmp; for(size_t i=0;i0){ return false; } } return true; } /* ~sort~ Sorts ~v~ using the halfsegment order. */ void sort(vector& v){ IsSmaller is; ::sort(v.begin(),v.end(),is); } /* ~isLogicalSorted~ Checks whether ~v~ is sorted using the logical order (faceno, cycleno, edgeno) */ bool isLogicalSorted(const vector& v){ if(v.size()<2){ return true; } LogicalHalfSegmentComparator cmp; for(size_t i=0;i0){ return false; } } return true; } /* ~sortLogical~ Sorts ~v~ according to the logical order of halfsegments (faceno, cycleno, edgeno) */ void sortLogical(vector& v){ IsSmaller is; ::sort(v.begin(),v.end(),is); } /* ~setCoverage~ Sets the coverage number of a set of halfsegments. This number is used in the accerelated computation of the point in region algorithm. The argument v must be sorted according to the halfsegment order. */ void setCoverage(vector& v){ int currCoverageNo = 0; for( size_t i = 0; i < v.size(); i++ ) { if( v[i].isLeftDomPoint() ){ currCoverageNo++; } else { currCoverageNo--; } v[i].attributes.coverageno = currCoverageNo; } } /* ~setPartnerNumbers~ This function sets the partner number of the contained halfsegments. Partners must have the same edge number. Non-partners must have different edge numbers. The edges must be numbered from 0 to n-1 where n is the number of contained segments ( v.size()/2). */ bool setPartnerNumbers(vector& v){ size_t s = v.size(); if((s & 1u) > 0u){ // odd number of halfsegments return false; } int s2 = s/2; int* tmp = new int[s/2]; for(size_t i=0;i=s2){ return false; } tmp[en] = i; } else { int en = v[i].attributes.edgeno; if(en>=s2){ return false; } int pn = tmp[en]; v[i].attributes.partnerno = pn; v[en].attributes.partnerno = i; } } delete[] tmp; return true; } bool checkRealm(const vector& v){ avltree::AVLTree > sss; MPrecHalfSegment * left; MPrecHalfSegment * right; for(unsigned int i=0;icheckRealm(current)){ return false; } if(right && !right->checkRealm(current)){ return false; } } else { // right endpoint if(!sss.removeN(current,left,right)){ return false; } if(left && right && !left->checkRealm(*right)){ return false; } } } return true; } ostream& print(const vector& v, ostream& o){ for(size_t i=0;i& res) { HalfSegmentComparator cmp; res.clear(); // compute coverage for common part int coverage = hs1.attributes.coverageno; if(hs2.attributes.insideAbove){ coverage++; } else { coverage--; } if(hs1.checkRealm(hs2)){ // hs1 and hs2 are already realminized if(cmp(hs1,hs2)<0){ res.push_back(hs1); res.push_back(hs2); return; } else { res.push_back(hs2); res.push_back(hs1); return; } } if(hs1==hs2){ // exact equality res.push_back(hs1); res[0].setOwner(BOTH); res[0].attributes.coverageno = coverage; return; } if(hs1.compareSlope(hs2)!=0){ // crossing or touching halfsegments if(hs1.crosses(hs2)){ // crossing halfsegments MPrecPoint* cp = hs1.crossPoint(hs2); res.push_back(MPrecHalfSegment (hs1.getLeftPoint(),*cp, true,hs1.attributes, hs1.getOwner())); res[res.size()-1].attributes.coverageno = hs1.attributes.coverageno; res.push_back(MPrecHalfSegment (hs2.getLeftPoint(),*cp, true,hs2.attributes, hs2.getOwner())); res[res.size()-1].attributes.coverageno = hs2.attributes.coverageno; res.push_back(MPrecHalfSegment (*cp,hs1.getRightPoint(), true,hs1.attributes, hs1.getOwner())); res[res.size()-1].attributes.coverageno = hs1.attributes.coverageno; res.push_back(MPrecHalfSegment (*cp,hs2.getRightPoint(), true,hs2.attributes, hs2.getOwner())); res[res.size()-1].attributes.coverageno = hs2.attributes.coverageno; delete cp; } else { // touching halfsegments if(hs1.innerContains(hs2.getLeftPoint())){ res.push_back(MPrecHalfSegment(hs1.getLeftPoint(), hs2.getLeftPoint(), true, hs1.attributes, hs1.getOwner())); res[res.size()-1].attributes.coverageno = hs1.attributes.coverageno; res.push_back(MPrecHalfSegment(hs2.getLeftPoint(), hs1.getRightPoint(), true, hs1.attributes, hs2.getOwner())); res[res.size()-1].attributes.coverageno = hs1.attributes.coverageno; res.push_back(hs2); } else if(hs1.innerContains(hs2.getRightPoint())){ res.push_back(MPrecHalfSegment(hs1.getLeftPoint(), hs2.getRightPoint(), true, hs1.attributes, hs1.getOwner())); res[res.size()-1].attributes.coverageno = hs1.attributes.coverageno; res.push_back(MPrecHalfSegment(hs2.getRightPoint(), hs1.getRightPoint(), true, hs1.attributes, hs1.getOwner())); res[res.size()-1].attributes.coverageno = hs1.attributes.coverageno; res.push_back(hs2); } else if(hs2.innerContains(hs1.getLeftPoint())){ res.push_back(MPrecHalfSegment(hs2.getLeftPoint(), hs1.getLeftPoint(), true, hs2.attributes, hs2.getOwner())); res[res.size()-1].attributes.coverageno = hs2.attributes.coverageno; res.push_back(MPrecHalfSegment(hs1.getLeftPoint(), hs2.getRightPoint(), true, hs2.attributes, hs2.getOwner())); res[res.size()-1].attributes.coverageno = hs2.attributes.coverageno; res.push_back(hs1); } else if(hs2.innerContains(hs1.getRightPoint())){ res.push_back(MPrecHalfSegment(hs2.getLeftPoint(), hs1.getRightPoint(), true, hs2.attributes, hs2.getOwner())); res[res.size()-1].attributes.coverageno = hs2.attributes.coverageno; res.push_back(MPrecHalfSegment(hs1.getRightPoint(), hs2.getRightPoint(), true, hs2.attributes, hs2.getOwner())); res[res.size()-1].attributes.coverageno = hs2.attributes.coverageno; res.push_back(hs1); } else { throw 1; // some error in computation or some forgotten case } } } else { // overlapping halfsegments // coverage number for common part int lcmp = hs1.getLeftPoint().compareTo(hs2.getLeftPoint()); int rcmp = hs1.getRightPoint().compareTo(hs2.getRightPoint()); // first part, single piece of hs1 or hs2 MPrecPoint firstCommonPoint(0,0); if(lcmp<0){ // first part belongs to hs1 res.push_back(MPrecHalfSegment( hs1.getLeftPoint(), hs2.getLeftPoint(), true, hs1.attributes, hs1.getOwner())); res[res.size()-1].attributes.coverageno = hs1.attributes.coverageno; firstCommonPoint = hs2.getLeftPoint(); } else if(lcmp>0) { // first part belongs to hs2 res.push_back(MPrecHalfSegment( hs2.getLeftPoint(), hs1.getLeftPoint(), true, hs2.attributes, hs2.getOwner())); res[res.size()-1].attributes.coverageno = hs2.attributes.coverageno; firstCommonPoint = hs1.getLeftPoint(); } else { // lcmp = 0 : both segments starts at the same point firstCommonPoint = hs1.getLeftPoint(); } // the common part and the last part if(rcmp==0){ // segments ends at the same point res.push_back(MPrecHalfSegment( firstCommonPoint, hs1.getRightPoint(), true, hs1.attributes, BOTH)); res[res.size()-1].attributes.coverageno = coverage; res[res.size()-1].attributes.insideAbove = hs1.attributes.insideAbove; } else if(rcmp < 0){ // last part belongs to hs2 res.push_back(MPrecHalfSegment( firstCommonPoint, hs1.getRightPoint(), true, hs1.attributes, BOTH)); res[res.size()-1].attributes.coverageno = coverage; res[res.size()-1].attributes.insideAbove = hs1.attributes.insideAbove; res.push_back(MPrecHalfSegment( hs1.getRightPoint(), hs2.getRightPoint(), true, hs2.attributes,hs2.getOwner())); res[res.size()-1].attributes.coverageno = hs2.attributes.coverageno; } else { // rcmp > 0 // last part belongs to hs1 res.push_back(MPrecHalfSegment( firstCommonPoint, hs2.getRightPoint(), true, hs2.attributes, BOTH)); res[res.size()-1].attributes.coverageno = coverage; res[res.size()-1].attributes.insideAbove = hs1.attributes.insideAbove; res.push_back(MPrecHalfSegment( hs2.getRightPoint(), hs1.getRightPoint(), true, hs1.attributes,hs1.getOwner())); res[res.size()-1].attributes.coverageno = hs1.attributes.coverageno; } } // sort IsSmaller is; sort(res.begin(),res.end(),is); } /* ~realminize~ The function computes a realminized version of ~v~ and stores it in ~res~. ~v~ has to be sorted according to the halfsegment order. */ void realminize(const vector& v, vector& res){ avltree::AVLTree > sss; priority_queue, IsGreater > es; MPrecHalfSegment * left; MPrecHalfSegment * right; res.clear(); HalfSegmentComparator cmp; vector realmRes; bool done = v.size()==0; size_t pos = 0; AttrType dummy(1); MPrecHalfSegment current(MPrecPoint(0,0),MPrecPoint(1,1), true, dummy); int edgeno = 0; MPrecCoordinate currentX(0); MPrecCoordinate lastX(0); bool first = true; while(!done){ if(poscheckRealm(current)){ makeRealm(current,*left,realmRes); sss.remove(*left); sss.remove(current); sss.insert(realmRes[0]); sss.insert(realmRes[1]); realmRes[0].setLDP(false); realmRes[1].setLDP(false); es.push(realmRes[0]); es.push(realmRes[1]); for(size_t i=2;icheckRealm(current)){ makeRealm(current,*right,realmRes); assert(sss.remove(*right)); assert(sss.remove(current)); sss.insert(realmRes[0]); sss.insert(realmRes[1]); realmRes[0].setLDP(false); realmRes[1].setLDP(false); es.push(realmRes[0]); es.push(realmRes[1]); for(size_t i=2;icheckRealm(*right)){ // cout << "realm neighbors" << endl; makeRealm(*left, *right, realmRes); sss.remove(*left); sss.remove(*right); sss.insert(realmRes[0]); sss.insert(realmRes[1]); realmRes[0].setLDP(false); realmRes[1].setLDP(false); es.push(realmRes[0]); es.push(realmRes[1]); for(size_t i=2;i& v1, const vector& v2, vector& res, SETOP op) { avltree::AVLTree > sss; EventStructure, vector > es(&v1,&v2); AttrType dummy; MPrecHalfSegment current (MPrecPoint(0,0), MPrecPoint(1,1), true, dummy); int source; MPrecHalfSegment * left; MPrecHalfSegment * right; res.clear(); vector realmRes; int edgeno = 0; while((source = es.next(current))){ if(current.isLeftDomPoint()) { MPrecHalfSegment* stored = sss.getMember(current); if(stored != 0){ // found overlapping part assert(stored->getOwner()!=BOTH); assert(stored->getOwner()!=current.getOwner()); if(current.getOwner()==FIRST){ makeRealm(current,*stored,realmRes); } else { makeRealm(*stored, current, realmRes); } sss.remove(*stored); sss.remove(current); sss.insert(realmRes[0]); // shorten realmRes[0].setLDP(false); es.push(realmRes[0]); for(size_t i=1;icheckRealm(current)){ makeRealm(current,*left,realmRes); sss.remove(*left); sss.remove(current); sss.insert(realmRes[0]); sss.insert(realmRes[1]); realmRes[0].setLDP(false); realmRes[1].setLDP(false); es.push(realmRes[0]); es.push(realmRes[1]); for(size_t i=2;icheckRealm(current)){ makeRealm(current,*right,realmRes); assert(sss.remove(*right)); assert(sss.remove(current)); sss.insert(realmRes[0]); sss.insert(realmRes[1]); realmRes[0].setLDP(false); realmRes[1].setLDP(false); es.push(realmRes[0]); es.push(realmRes[1]); for(size_t i=2;icheckRealm(*right)){ makeRealm(*left, *right, realmRes); sss.remove(*left); sss.remove(*right); sss.insert(realmRes[0]); sss.insert(realmRes[1]); realmRes[0].setLDP(false); realmRes[1].setLDP(false); es.push(realmRes[0]); es.push(realmRes[1]); for(size_t i=2;i& v){ if(v.empty()) { return true; } size_t num = 0; MPrecPoint lastDom(0,0); for(size_t pos =0;pos& v, vector& res); /* ~setInsideAbove~ This function will compute and set the insideAbove flag for each halfsegment in ~v~. ~v~ has to be sorted in halfsegment order. */ void setInsideAbove(vector& v); /* ~computeCycles~ This function computes the faceno, cycleno, edgeno for each halfsegment in ~v~. The halfsegments in v has to be sorted in halfsegment order , has to be realminized, and has to build only cycles. */ void computeCycles(vector& v); ostream& operator<<(ostream& o, const vector& v) { for(size_t i=0;i