Files
secondo/Algebras/TransportationMode/Partition.h

2194 lines
64 KiB
C
Raw Normal View History

2026-01-23 17:03:45 +08:00
/*
----
This file is part of SECONDO.
Copyright (C) 2004, University in Hagen, Department of Computer Science,
Database Systems for New Applications.
SECONDO is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
SECONDO is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with SECONDO; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
----
//paragraph [1] Title: [{\Large \bf \begin {center}] [\end {center}}]
//[TOC] [\tableofcontents]
[1] Header File of the Partition
March, 2010 Jianqiu xu
[TOC]
1 Overview
2 Defines and includes
*/
#ifndef Partition_H
#define Partition_H
#include "Algebra.h"
#include "Algebras/Spatial/Point.h"
#include "Algebras/Spatial/SpatialAlgebra.h"
#include "NestedList.h"
#include "QueryProcessor.h"
#include "Algebras/RTree/RTreeAlgebra.h"
#include "Algebras/BTree/BTreeAlgebra.h"
#include "Algebras/Temporal/TemporalAlgebra.h"
#include "StandardTypes.h"
#include "LogMsg.h"
#include "NList.h"
#include "Algebras/Relation-C++/RelationAlgebra.h"
#include "ListUtils.h"
#include "Algebras/Network/NetworkAlgebra.h"
#include <fstream>
#include <stack>
#include <vector>
#include <queue>
#include "Attribute.h"
#include "Tools/Flob/DbArray.h"
#include "Tools/Flob/Flob.h"
#include "WinUnix.h"
#include "AvlTree.h"
#include "Symbols.h"
#include "GeneralType.h"
/*
5 Auxiliary structures for plane sweep algorithms
5.1 Definition of ~ownertype~
This enumeration is used to indicate the source of an ~AVLSegment~.
*/
namespace myavlseg{
enum ownertype{none, first, second, both};
enum SetOperation{union_op, intersection_op, difference_op};
std::ostream& operator<<(std::ostream& o, const ownertype& owner);
const int LEFT = 1;
const int RIGHT = 2;
const int COMMON = 4;
/*
3.2 The Class ~AVLSegment~
This class is used for inserting into an avl tree during a plane sweep.
*/
class MyAVLSegment{
public:
/*
3.1.1 Constructors
~Standard Constructor~
*/
MyAVLSegment();
/*
~Constructor~
This constructor creates a new segment from the given HalfSegment.
As owner only __first__ and __second__ are the allowed values.
*/
MyAVLSegment(const HalfSegment& hs, ownertype owner);
/*
~Constructor~
Create a Segment only consisting of a single point.
*/
MyAVLSegment(const Point& p, ownertype owner);
/*
~Copy Constructor~
*/
MyAVLSegment(const MyAVLSegment& src);
/*
3.2.1 Destructor
*/
~MyAVLSegment() {}
/*
3.3.1 Operators
*/
MyAVLSegment& operator=(const MyAVLSegment& src);
bool operator==(const MyAVLSegment& s) const;
bool operator<(const MyAVLSegment& s) const;
bool operator>(const MyAVLSegment& s) const;
/*
3.3.1 Further Needful Functions
~Print~
This function writes this segment to __out__.
*/
void Print(std::ostream& out)const;
/*
~Equalize~
The value of this segment is taken from the argument.
*/
void Equalize( const MyAVLSegment& src);
/*
3.5.1 Geometric Functions
~crosses~
Checks whether this segment and __s__ have an intersection point of their
interiors.
*/
bool crosses(const MyAVLSegment& s) const;
/*
~crosses~
This function checks whether the interiors of the related
segments are crossing. If this function returns true,
the parameters ~x~ and ~y~ are set to the intersection point.
*/
bool crosses(const MyAVLSegment& s,double& x, double& y) const;
/*
~extends~
This function returns true, iff this segment is an extension of
the argument, i.e. if the right point of ~s~ is the left point of ~this~
and the slopes are equal.
*/
bool extends(const MyAVLSegment& s) const;
/*
~exactEqualsTo~
This function checks if s has the same geometry like this segment, i.e.
if both endpoints are equal.
*/
bool exactEqualsTo(const MyAVLSegment& s)const;
/*
~isVertical~
Checks whether this segment is vertical.
*/
bool isVertical() const;
/*
~isPoint~
Checks if this segment consists only of a single point.
*/
bool isPoint() const;
/*
~length~
Returns the length of this segment.
*/
double length();
/*
~InnerDisjoint~
This function checks whether this segment and s have at most a
common endpoint.
*/
bool innerDisjoint(const MyAVLSegment& s)const;
/*
~Intersects~
This function checks whether this segment and ~s~ have at least a
common point.
*/
bool intersects(const MyAVLSegment& s)const;
/*
~overlaps~
Checks whether this segment and ~s~ have a common segment.
*/
bool overlaps(const MyAVLSegment& s) const;
/*
~ininterior~
This function checks whether the point defined by (x,y) is
part of the interior of this segment.
*/
bool ininterior(const double x,const double y)const;
/*
~contains~
Checks whether the point defined by (x,y) is located anywhere on this
segment.
*/
bool contains(const double x,const double y)const;
/*
3.6.1 Comparison
Compares this with s. The x intervals must overlap.
*/
int compareTo(const MyAVLSegment& s) const;
/*
~SetOwner~
This function changes the owner of this segment.
*/
void setOwner(ownertype o);
/*
3.7.1 Some ~Get~ Functions
~getInsideAbove~
Returns the insideAbove value for such segments for which this value is unique,
e.g. for segments having owner __first__ or __second__.
*/
bool getInsideAbove() const;
inline double getX1() const { return x1; }
inline double getX2() const { return x2; }
inline double getY1() const { return y1; }
inline double getY2() const { return y2; }
inline ownertype getOwner() const { return owner; }
inline bool getInsideAbove_first() const { return insideAbove_first; }
inline bool getInsideAbove_second() const { return insideAbove_second; }
/*
3.8.1 Split Functions
~split~
This function splits two overlapping segments.
Preconditions:
1) this segment and ~s~ have to overlap.
2) the owner of this and ~s~ must be different
~left~, ~common~ and ~right~ will contain the
explicitely left part, a common part, and
an explecitely right part. The left and/or right part
my be empty. The existence can be checked using the return
value of this function. Let ret the return value. It holds:
__ret | LEFT__: the left part exists
__ret | COMMON__: the common part exist (always true)
__ret | RIGHT__: the right part exists
The constants LEFT, COMMON, and RIGHT have been defined
earlier.
*/
int split(const MyAVLSegment& s, MyAVLSegment& left, MyAVLSegment& common,
MyAVLSegment& right, const bool checkOwner = true) const;
/*
~splitAt~
This function divides a segment into two parts at the point
provided by (x, y). The point must be on the interior of this segment.
*/
void splitAt(const double x, const double y,
MyAVLSegment& left,
MyAVLSegment& right)const;
/*
~splitCross~
Splits two crossing segments into the 4 corresponding parts.
Both segments have to cross each other.
*/
void splitCross(const MyAVLSegment& s, MyAVLSegment& left1,
MyAVLSegment& right1, MyAVLSegment& left2,
MyAVLSegment& right2) const;
/*
3.9.1 Converting Functions
~ConvertToHs~
This functions creates a ~HalfSegment~ from this segment.
The owner must be __first__ or __second__.
*/
HalfSegment convertToHs(bool lpd, ownertype owner = both )const;
/*
3.10.1 Public Data Members
These members are not used in this class. So the user of
this class can change them without any problems within this
class itself.
*/
int con_below; // should be used as a coverage number
int con_above; // should be used as a coverage number
/*
3.11.1 Private Part
Here the data members as well as some auxiliary functions are
collected.
*/
private:
/* data members */
double x1,y1,x2,y2; // the geometry of this segment
bool insideAbove_first;
bool insideAbove_second;
ownertype owner; // who is the owner of this segment
/*
~pointequal~
This function checks if the points defined by (x1, y1) and
(x2,y2) are equals using the ~AlmostEqual~ function.
*/
static bool pointEqual(const double x1, const double y1,
const double x2, const double y2);
/*
~pointSmaller~
This function checks if the point defined by (x1, y1) is
smaller than the point defined by (x2, y2).
*/
static bool pointSmaller(const double x1, const double y1,
const double x2, const double y2);
/*
~comparePoints~
*/
static int comparePoints(const double x1,const double y1,
const double x2,const double y2);
/*
~compareSlopes~
compares the slopes of __this__ and __s__. The slope of a vertical
segment is greater than all other slopes.
*/
int compareSlopes(const MyAVLSegment& s) const;
/*
~XOverlaps~
Checks whether the x interval of this segment overlaps the
x interval of ~s~.
*/
bool xOverlaps(const MyAVLSegment& s) const;
/*
~XContains~
Checks if the x coordinate provided by the parameter __x__ is contained
in the x interval of this segment;
*/
bool xContains(const double x) const;
/*
~GetY~
Computes the y value for the specified __x__.
__x__ must be contained in the x-interval of this segment.
If the segment is vertical, the minimum y value of this
segment is returned.
*/
double getY(const double x) const;
};
std::ostream& operator<<(std::ostream& o, const MyAVLSegment& s);
};
/*
a smaller factor compared with original version of AlmostEqual
*/
inline bool MyAlmostEqual( const double d1, const double d2 )
{
// const double factor = 0.00001;
const double factor = 0.000001;
double diff = fabs(d1-d2);
return diff< factor;
}
/*
Moidfy the coordinate value of the point, change it into int value or
reduce the precision to be more practical
*/
#define GetCloser(a) fabs(floor(a)-a) > fabs(ceil(a)-a)? ceil(a):floor(a)
inline void ModifyPoint(Point& p)
{
double a, b;
int x, y;
a = p.GetX();
b = p.GetY();
x = static_cast<int>(GetCloser(a));
y = static_cast<int>(GetCloser(b));
p.Set(x,y);
/* double x, y;
x = p.GetX();
y = p.GetY();
x = ((int)(x*10000.0 + 0.5))/10000.0;
y = ((int)(y*10000.0 + 0.5))/10000.0;
p.Set(x,y);*/
}
inline void Modify_Point(Point& p)
{
double x,y;
x = p.GetX();
y = p.GetY();
// printf("%.10f %.10f\n",x, y);
x = ((int)(x*100.0 + 0.5))/100.0;
y = ((int)(y*100.0 + 0.5))/100.0;
// printf("%.10f %.10f\n",x, y);
p.Set(x,y);
}
/*
keep the number of digits after dot for float or double representation
*/
inline void Modify_Point2(Point& p)
{
double x,y;
x = p.GetX();
y = p.GetY();
// printf("%.10f %.10f\n",x, y);
// x = ((int)(x*1000.0 + 0.5))/1000.0;
// y = ((int)(y*1000.0 + 0.5))/1000.0;
double xx = (double)(int(x*1000.0 + 0.5))/1000;
double yy = (double)(int(y*1000.0 + 0.5))/1000;
// printf("%.10f %.10f\n",xx, yy);
p.Set(xx,yy);
}
inline void Modify_Point3(Point& p, double f)
{
double x, y;
x = p.GetX();
y = p.GetY();
// printf("%.10f %.10f\n",x, y);
// x = ((int)(x*1000.0 + 0.5))/1000.0;
// y = ((int)(y*1000.0 + 0.5))/1000.0;
double xx = (double)(int(x*f));
double yy = (double)(int(y*f));
// printf("%.10f %.10f\n",xx, yy);
p.Set(xx, yy);
}
template< template<typename T1> class Array1,
template<typename T2> class Array2,
template<typename T2> class Array3 >
void MySetOp(const RegionT<Array1>& reg1,
const RegionT<Array2>& reg2,
RegionT<Array3>& result,
myavlseg::SetOperation op);
void MySetOp(const Line& line, const Region& region, Line& result,
myavlseg::SetOperation op);
void MySetOp(const Line& line1, const Line& line2, Line& result,
myavlseg::SetOperation op);
template< template<typename T1> class Array1,
template<typename T2> class Array2,
template<typename T3> class Array3>
void MyMinus(const RegionT<Array1>& reg1,
const RegionT<Array2>& reg2,
RegionT<Array3>& result);
template< template<typename T1> class Array1,
template<typename T2> class Array2,
template<typename T3> class Array3>
void MyIntersection(const RegionT<Array1>& reg1,
const RegionT<Array2>& reg2,
RegionT<Array3>& result);
void MyIntersection(const Line& line, const Region& reg, Line& result);
void MyIntersection(const Line& l1, const Line& l2, Line& result);
template< template<typename T1> class Array1,
template<typename T2> class Array2,
template<typename T3> class Array3>
void MyUnion(const RegionT<Array1>& reg1,
const RegionT<Array2>& reg2,
RegionT<Array3>& result);
bool MyRegIntersects(const Region* reg1, const Region* reg2);
bool MyHSIntersects(const HalfSegment* hs1, const HalfSegment* hs2);
bool MyInside(Line*,Region*);
bool RegContainHS(Region* r, HalfSegment hs);
double PointOnSline(SimpleLine* sl, Point* loc, bool b);
/*
for storing line or sline in such a way:
mhs1.from---mhs1.to---mhs2.from---mhs2.to
*/
struct MyHalfSegment{
MyHalfSegment(){}
MyHalfSegment(bool d, const Point& p1, const Point& p2):def(d),
from(p1),to(p2){}
MyHalfSegment(const MyHalfSegment& mhs):def(mhs.def),
from(mhs.from),to(mhs.to){}
MyHalfSegment& operator=(const MyHalfSegment& mhs)
{
def = mhs.def;
from = mhs.from;
to = mhs.to;
return *this;
}
Point& GetLeftPoint(){return from;}
Point& GetRightPoint(){return to;}
void Print()
{
// cout<<"from "<<from<<" to "<<to<<endl;
printf("(%.8f %.8f) (%.8f %.8f)\n", from.GetX(), from.GetY(),
to.GetX(), to.GetY());
}
void Exchange()
{
Point temp = from;
from = to;
to = temp;
}
bool def;
Point from,to;
};
struct MySegDist:public MyHalfSegment{
double dist;
MySegDist(){dist=0.0;}
MySegDist(bool def, const Point& p1, const Point& p2, double d):
MyHalfSegment(def,p1,p2),dist(d){}
MySegDist(const MySegDist& msd):MyHalfSegment(msd),dist(msd.dist){}
MySegDist& operator=(const MySegDist& msd)
{
MyHalfSegment::operator=(msd);
dist = msd.dist;
return *this;
}
bool operator<(const MySegDist& msd) const
{
// cout<<"from1 "<<from<<" to1 "<<to<<endl;
// cout<<"from2 "<<msd.from<<" to2 "<<msd.to<<endl;
bool result = dist < msd.dist;
// cout<<"< "<<result<<endl;
return result;
}
bool operator==(const MySegDist& msd) const
{
// cout<<" == "<<endl;
if(AlmostEqual(from, msd.from) && AlmostEqual(to, msd.to) &&
AlmostEqual(dist, msd.dist)) return true;
if(AlmostEqual(to, msd.from) && AlmostEqual(from, msd.to) &&
AlmostEqual(dist, msd.dist)) return true;
return false;
}
};
std::ostream& operator<<(std::ostream& o, const MySegDist& seg);
/*
a point and a distance value to another point
*/
struct MyPoint{
MyPoint(){}
MyPoint(const Point& p, double d):loc(p), dist(d){}
MyPoint(const MyPoint& mp):loc(mp.loc),dist(mp.dist){}
MyPoint& operator=(const MyPoint& mp)
{
loc = mp.loc;
dist = mp.dist;
return *this;
}
bool operator<(const MyPoint& mp) const
{
return dist < mp.dist;
}
void Print()
{
cout<<"loc "<<loc<<" dist "<<dist<<endl;
}
Point loc;
double dist;
};
struct MyPoint_Ext:public MyPoint{
Point loc2;
double dist2;
MyPoint_Ext(){}
MyPoint_Ext(const Point& p1, const Point& p2, double d1, double d2):
MyPoint(p1,d1),loc2(p2),dist2(d2){}
MyPoint_Ext(const MyPoint_Ext& mpe):
MyPoint(mpe),loc2(mpe.loc2), dist2(mpe.dist2){}
MyPoint_Ext& operator=(const MyPoint_Ext& mpe)
{
MyPoint::operator=(mpe);
loc2 = mpe.loc2;
dist2 = mpe.dist2;
return *this;
}
void Print()
{
cout<<" loc1 " <<loc<<"loc2 "<<loc2
<<" dist1 "<<dist<<" dist2 "<<dist2<<endl;
}
};
/* structure for rotational plane sweep */
struct RPoint{
Point p;
double angle;
Point n1, n2;
double dist;
int regid;
RPoint(){}
RPoint(Point& q, double a, double d, int id):p(q),angle(a),dist(d),regid(id){}
RPoint(const RPoint& rp):p(rp.p),angle(rp.angle),
n1(rp.n1), n2(rp.n2), dist(rp.dist),regid(rp.regid){}
RPoint& operator=(const RPoint& rp)
{
p = rp.p;
angle = rp.angle;
n1 = rp.n1;
n2 = rp.n2;
dist = rp.dist;
regid = rp.regid;
return *this;
}
void SetNeighbor(Point& p1, Point& p2)
{
n1 = p1;
n2 = p2;
}
bool operator<(const RPoint& rp) const
{
if(AlmostEqual(angle,rp.angle)){
return dist > rp.dist;
}else
return angle > rp.angle;
}
void Print()
{
// cout<<" n1 "<<n1<<" n2 "<<n2<<endl;
// cout<<"p "<<p<<" angle "<<angle<<"dist "<<dist<<endl;
cout<<"p "<<p<<"angle "<<angle<<endl;
}
};
/*
a compressed version of junction
loc--position, rid1, rid2, and relative position in each route, len1, len2
*/
struct MyJun{
Point loc;
int rid1;
int rid2;
double len1;
double len2;
MyJun(Point p, int r1, int r2, double l1, double l2):
loc(p), rid1(r1), rid2(r2), len1(l1), len2(l2){}
MyJun(const MyJun& mj):
loc(mj.loc),rid1(mj.rid1),rid2(mj.rid2), len1(mj.len1), len2(mj.len2){}
MyJun(){}
MyJun& operator=(const MyJun& mj)
{
loc = mj.loc;
rid1 = mj.rid1;
rid2 = mj.rid2;
len1 = mj.len1;
len2 = mj.len2;
return *this;
}
bool operator<(const MyJun& mj) const
{
return loc < mj.loc;
}
void Print()
{
cout<<"loc "<<loc<<" r1 "<<rid1<<" r2 "<<rid2<<endl;
}
};
struct Region_Oid{
int oid;
Region reg;
Region_Oid(){}
Region_Oid(int id, Region& r):oid(id),reg(r){}
Region_Oid(const Region_Oid& ro):oid(ro.oid), reg(ro.reg){}
Region_Oid& operator=(const Region_Oid& ro)
{
oid = ro.oid;
reg = ro.reg;
return *this;
}
void Print()
{
cout<<"id "<<oid<<" reg "<<reg<<endl;
}
};
/*
struct for partition space
*/
struct SpacePartition{
Relation* l;
TupleType* resulttype;
unsigned int count;
std::vector<int> junid1;
std::vector<int> junid2;
std::vector<Region> outer_regions_s;
std::vector<Region> outer_regions1;
std::vector<Region> outer_regions2;
std::vector<Region> outer_regions_l;
std::vector<Region> outer_regions4;
std::vector<Region> outer_regions5;
std::vector<Region> outer_fillgap1;
std::vector<Region> outer_fillgap2;
std::vector<Region> outer_fillgap;
std::vector<Line> pave_line1;
std::vector<Line> pave_line2;
/////////////function implementation//////////////////////////////
SpacePartition();
SpacePartition(Relation* in_line);
//get the intersection value between a circle and a line function
void GetDeviation(Point, double, double, double&, double&, int);
//check the rotation from (p1-p0) to (p2-p0) is clock_wise or not
bool GetClockwise(Point& p0,Point& p1, Point& p2);
//get the angle of the rotation from (p1-p0) to (p2-p0)
double GetAngle(Point& p0,Point& p1, Point& p2);
//move the segment by a deviation to the left or right
void TransferSegment(MyHalfSegment&, std::vector<MyHalfSegment>&, int, bool);
//add the segment to line, but change its points coordinate to int value
void AddHalfSegmentResult(MyHalfSegment hs, Line* res, int& edgeno);
//for the given line stored in segs, get the line after transfer
void Gettheboundary(std::vector<MyHalfSegment>& segs,
std::vector<MyHalfSegment>& boundary, int delta,
bool clock_wise);
//get all the points forming the boundary for road region
void ExtendSeg1(std::vector<MyHalfSegment>& segs,int delta,
bool clock_wise,
std::vector<Point>& outer, std::vector<Point>& outer_half);
//get all the points forming the boundary for both road and pavement region
void ExtendSeg2(std::vector<MyHalfSegment>& segs,int delta,
bool clock_wise, std::vector<Point>& outer);
//translate a given line with a distance limitation
void ExtendSeg3(std::vector<MyHalfSegment>& segs,int delta,
bool clock_wise, std::vector<Point>& outer);
// order the segments so that the end point of last one connects to the start
// point of the next one, the result is stored as std::vector<MyHalfSegment>
void ReorderLine(SimpleLine*, std::vector<MyHalfSegment>&);
//create a region from the given set of ordered points
template<template<typename T> class Array>
void ComputeRegion(std::vector<Point>& outer_region,
std::vector<RegionT<Array> >& regs);
bool CheckRegionPS(std::vector<Point>& outer_region);
//extend each road to a region
void ExtendRoad(int attr_pos, int w);
//remove triangle area after cutting
void FilterDirtyRegion(std::vector<Region>& regs, Region* reg);
//cut the intersection region between pavement and road
void ClipPaveRegion(Region& reg,
std::vector<Region>& paves,int rid, Region* inborder);
//fill the gap between two pavements at some junction positions
void FillPave(network::Network* n, std::vector<Region>& pavements1,
std::vector<Region>& pavements2,
std::vector<double>& routes_length,
std::vector<Region>& paves1, std::vector<Region>& paves2);
//get the pavement beside each road
void Getpavement(network::Network* n, Relation* rel1, int attr_pos,
Relation* rel2, int attr_pos1, int attr_pos2, int w);
//get the closest point in hs to p and return the point and distance
double GetClosestPoint(HalfSegment& hs, Point& p, Point& cp);
double GetClosestPoint_New(HalfSegment& hs, Point& p, Point& cp);
//transfer the halfsegment by a deviation
void TransferHalfSegment(HalfSegment& hs, int delta, bool flag);
//for the given line, get its curve after transfer
template< template<typename T1> class Array1,
template<typename T2> class Array2>
void GetSubCurve(SimpleLineT<Array1>* curve,
LineT<Array2>* newcurve,
int roadwidth,
bool clock);
//build zebra crossing at junction position, called by GetZebraCrossing()
template< template<typename T1> class Array1,
template<typename T2> class Array2,
template<typename T3> class Array3,
template<typename T4> class Array4,
template<typename T5> class Array5>
bool BuildZebraCrossing(std::vector<MyPoint>& endpoints1,
std::vector<MyPoint>& endpoints2,
RegionT<Array1>* reg_pave1,
RegionT<Array2>* reg_pave2,
LineT<Array3>* pave1,
RegionT<Array4>* crossregion,
Point& junp,
RegionT<Array5>* last_zc);
//for the road line around the junction position, it creates the zebra crossing
template< template<typename T1> class Array1,
template<typename T2> class Array2,
template<typename T3> class Array3,
template<typename T4> class Array4,
template<typename T5> class Array5,
template<typename T6> class Array6>
void GetZebraCrossing(SimpleLineT<Array1>* subcurve,
RegionT<Array2>* reg_pave1, RegionT<Array3>* reg_pave2,
int roadwidth, LineT<Array4>* pave1, double delta_l,
Point p1, RegionT<Array5>* crossregion,
RegionT<Array6>* last_zc);
// Extend the line in decreasing direction
template< template<typename T1> class Array1,
template<typename T2> class Array2,
template<typename T3> class Array3,
template<typename T4> class Array4,
template<typename T5> class Array5,
template<typename T6> class Array6>
void Decrease(SimpleLineT<Array1>* curve, RegionT<Array2>* reg_pave1,
RegionT<Array3>* reg_pave2, double len,
LineT<Array4>* pave,
int roadwidth, RegionT<Array5>* crossregion,
RegionT<Array6>* last_zc);
//Extend the line in increasing direction
template< template<typename T1> class Array1,
template<typename T2> class Array2,
template<typename T3> class Array3,
template<typename T4> class Array4,
template<typename T5> class Array5,
template<typename T6> class Array6>
void Increase(SimpleLineT<Array1>* curve, RegionT<Array2>* reg_pave1,
RegionT<Array3>* reg_pave2, double len,
LineT<Array4>* pave,
int roadwidth, RegionT<Array5>* crossregion,
RegionT<Array6>* last_zc);
//create the pavement at each junction position
template< template<typename T1> class Array1,
template<typename T2> class Array2,
template<typename T3> class Array3,
template<typename T4> class Array4,
template<typename T5> class Array5,
template<typename T6> class Array6>
void CreatePavement(SimpleLineT<Array1>* curve, RegionT<Array2>* reg_pave1,
RegionT<Array3>* reg_pave2, double len,
int roadwidth, RegionT<Array4>* crossregion1,
RegionT<Array5>* crossregion2, RegionT<Array6>* last_zc);
//cut the common pavements of two roads at the junction position
void DecomposePave(Region* reg1, Region* reg2, std::vector<Region>& result);
void GetCommPave1(std::vector<Region_Oid>& pave1,
std::vector<Region_Oid>& pave2, int,int);
void GetCommPave2(Region* reg, int, std::vector<Region_Oid>& pave2);
void DecomposePavement1(network::Network* n, Relation* rel,
int attr_pos1, int attr_pos2, int attr_pos3);
void DecomposePavement2(int start_oid, Relation* rel,
int attr_pos1, int attr_pos2);
void GetPavementEdge1(network::Network*, Relation*, BTree*, int, int, int);
void GetPavementEdge2(Relation*, Relation*, BTree*, int, int, int);
bool RidPosExist(int rid, float pos,
std::vector<std::vector<float> >& rid_pos_list);
///////////cut the commone area between pavements and road regions///
void Junpavement(network::Network* n, Relation* rel, int attr_pos1,
int attr_pos2, int width, Relation* rel_road,int attr_pos3);
//Detect whether three points collineation
bool Collineation(Point& p1, Point& p2, Point& p3);
//Check that the pavement gap should not intersect the two roads
template< template<typename T1> class Array1,
template<typename T2> class Array2,
template<typename T3> class Array3>
bool SameSide1(RegionT<Array1>* reg1, RegionT<Array2>* reg2,
LineT<Array3>* r1r2,Point* junp);
//build a small region around the three halfsegments
template< template<typename T1> class Array1,
template<typename T2> class Array2,
template<typename T3> class Array3,
template<typename T4> class Array4>
bool SameSide2(RegionT<Array1>* reg1, RegionT<Array2>* reg2,
LineT<Array3>* r1r2,
Point* junp, MyHalfSegment thirdseg,
RegionT<Array4>& smallreg);
//the common area of two regions
template< template<typename T1> class Array1,
template<typename T2> class Array2>
inline bool PavementIntersection(RegionT<Array1>* reg1,
RegionT<Array2>* reg2);
//check the junction position rids.size() != 2 rids.size() != 6
void NewFillPavementDebug(Relation* rel, Relation* routes,
int id1, int id2,
Point* junp, int attr_pos1, int attr_pos2,
std::vector<int> rids);
// check for the junction where two road intersect
// rids.size() == 2, used by operator fillgap
void NewFillPavement1(Relation* rel, Relation* routes,
int id1, int id2,
Point* junp, int attr_pos1, int attr_pos2,
std::vector<int> rids);
//check for the junction where three roads intersect
//called by operator fillgap
void NewFillPavement2(Relation* rel, Relation* routes,
int id1, int id2,
Point* junp, int attr_pos1, int attr_pos2,
std::vector<int> rids);
//the same function as in NewFillPavement2, but with different input
//parameters called by function FillPave()
void NewFillPavement3(Relation* routes, int id1, int id2,
Point* junp, std::vector<Region>& paves1,
std::vector<Region>& paves2, std::vector<int> rids,
std::vector<Region>& newpaves1,
std::vector<Region>& newpaves2);
//the same function as NewFillPavement2, but with different input parameters
//called by function FillPave()
void NewFillPavement4(Relation* routes, int id1, int id2,
Point* junp, std::vector<Region>& paves1,
std::vector<Region>& paves2, std::vector<int> rids,
std::vector<Region>& newpaves1,
std::vector<Region>& newpaves2);
void NewFillPavement5(Relation* routes, int id1, int id2,
Point* junp, std::vector<Region>& paves1,
std::vector<Region>& paves2, std::vector<int> rids,
std::vector<Region>& newpaves1,
std::vector<Region>& newpaves2);
//for operator fillgap
void FillHoleOfPave(network::Network* n, Relation* rel, int attr_pos1,
int attr_pos2, int width);
};
/*
for each route, it returns all possible locations where interesting points
can locate
*/
struct StrRS{
network::Network* n;
Relation* r1;
Relation* r2;
unsigned int count;
TupleType* resulttype;
std::vector<int> rids;
std::vector<Line> lines;
std::vector<Point> interestps;
std::vector<Point> ps;
std::vector<bool> ps_type;
StrRS();
~StrRS();
StrRS(network::Network* net, Relation* rel1, Relation* rel2);
void GetSections(int attr_pos1, int attr_pos2, int attr_pos3);
void GenPoints1(int attr_pos1, int attr_pos2, int attr_pos3,
int attr_pos4, int no_ps);
void GenPoints2(R_Tree<2,TupleId>*, int attr_pos1, int attr_pos2,
unsigned int);
void DFTraverse(R_Tree<2,TupleId>*, SmiRecordId, Point*, int);
void GetInterestingPoints(HalfSegment hs, Point ip,
std::vector<MyPoint>& intersect_ps, Region*,
Region*);
};
#define TM_MYPI 3.1415927
/*
data clean process
*/
struct DataClean{
unsigned int count;
TupleType* resulttype;
DataClean(){ count = 0; resulttype = NULL;}
~DataClean(){if(resulttype != NULL) resulttype->DeleteIfAllowed();}
std::vector<SimpleLine> sl_list;
void ModifyLine(SimpleLine* in, SimpleLine* out);
void CheckRoads(Relation* r, R_Tree<2,TupleId>* rtree);
void DFTraverse(Relation* rel,R_Tree<2,TupleId>* rtree, SmiRecordId adr,
Line* sl, std::vector<int>& id_list, unsigned int id);
void DFTraverse2(Relation* rel,R_Tree<2,TupleId>* rtree, SmiRecordId adr,
Line* sl, std::vector<int>& id_list, unsigned int id);
};
/*
Implementation of template functions.
*/
void myinsertEvents(const myavlseg::MyAVLSegment& seg,
const bool createLeft,
const bool createRight,
std::priority_queue<HalfSegment,
std::vector<HalfSegment>,
std::greater<HalfSegment> >& q1,
std::priority_queue<HalfSegment,
std::vector<HalfSegment>,
std::greater<HalfSegment> >& q2);
bool MysplitByNeighbour(avltree::AVLTree<myavlseg::MyAVLSegment>& sss,
myavlseg::MyAVLSegment& current,
myavlseg::MyAVLSegment*& neighbour,
std::priority_queue<HalfSegment,
std::vector<HalfSegment>,
std::greater<HalfSegment> >& q1,
std::priority_queue<HalfSegment,
std::vector<HalfSegment>,
std::greater<HalfSegment> >& q2);
void MysplitNeighbours(avltree::AVLTree<myavlseg::MyAVLSegment>& sss,
myavlseg::MyAVLSegment *& leftN,
myavlseg::MyAVLSegment *& rightN,
std::priority_queue<HalfSegment,
std::vector<HalfSegment>,
std::greater<HalfSegment> >& q1,
std::priority_queue<HalfSegment,
std::vector<HalfSegment>,
std::greater<HalfSegment> >& q2);
/*
The first region minuses the seccond region and store the result as the third
*/
template< template<typename T1> class Array1,
template<typename T2> class Array2,
template<typename T3> class Array3>
void MyMinus(const RegionT<Array1>& reg1,
const RegionT<Array2>& reg2,
RegionT<Array3>& result)
{
MySetOp(reg1,reg2,result,myavlseg::difference_op);
}
/*
The first region unions the seccond region and store the result as the third
*/
template< template<typename T1> class Array1,
template<typename T2> class Array2,
template<typename T3> class Array3>
void MyUnion(const RegionT<Array1>& reg1,
const RegionT<Array2>& reg2,
RegionT<Array3>& result)
{
MySetOp(reg1,reg2,result,myavlseg::union_op);
}
template<template<typename T> class Array>
void SpacePartition:: ComputeRegion(std::vector<Point>& outer_region,
std::vector<RegionT<Array> >& regs)
{
/////////note that points are counter_clock_wise ordered///////////////
//for(unsigned i = 0;i < outer_region.size();i++)
// cout<<outer_region[i] << endl;
///////////////////////////////////////////////////////////////
//////////// check for overlapping segments///////////////////
//////////////////////////////////////////////////////////////
// CheckRegionPS(outer_region);
bool check = CheckRegionPS(outer_region);
if(check == false) return;
////////////////////////////////////////////////////////////
MMRegion* cr = new MMRegion( 0 );
cr->StartBulkLoad();
int fcno=-1;
int ccno=-1;
int edno= 0;
int partnerno = 0;
fcno++;
ccno++;
bool isCycle = true;
Point firstPoint = outer_region[0];
Point prevPoint = firstPoint;
//Starting to compute a new cycle
MMPoints *cyclepoints= new MMPoints( 8 );
MMRegion *rDir = new MMRegion(32);
rDir->StartBulkLoad();
Point currvertex = firstPoint;
cyclepoints->StartBulkLoad();
*cyclepoints += currvertex;
Point p1 = currvertex;
Point firstP = p1;
cyclepoints->EndBulkLoad();
for(unsigned int i = 1;i < outer_region.size();i++){
currvertex = outer_region[i];
// if(cyclepoints->Contains(currvertex))assert(false);
if(cyclepoints->Contains(currvertex))continue;
////////////////step -- 1/////////////////////////////
Point p2 = currvertex;
cyclepoints->StartBulkLoad();
*cyclepoints += currvertex;
cyclepoints->EndBulkLoad(true,false,false);
/////////////step --- 2 create halfsegment/////////////////////////
HalfSegment* hs = new HalfSegment(true, prevPoint, currvertex);
hs->attr.faceno=fcno;
hs->attr.cycleno=ccno;
hs->attr.edgeno=edno;
hs->attr.partnerno=partnerno;
partnerno++;
hs->attr.insideAbove = (hs->GetLeftPoint() == p1);
////////////////////////////////////////////////////////
p1 = p2;
edno++;
prevPoint= currvertex;
if(cr->InsertOk(*hs)){
*cr += *hs;
// cout<<"cr+1 "<<*hs<<endl;
if( hs->IsLeftDomPoint()){
*rDir += *hs;
// cout<<"rDr+1 "<<*hs<<endl;
hs->SetLeftDomPoint( false );
}else{
hs->SetLeftDomPoint( true );
// cout<<"rDr+2 "<<*hs<<endl;
(*rDir) += (*hs);
}
(*cr) += (*hs);
// cout<<"cr+2 "<<*hs<<endl;
delete hs;
}else assert(false);
}//end for
cyclepoints->DeleteIfAllowed();
// printf("(%.6f %.6f) (%.6f %.6f)\n", firstPoint.GetX(), firstPoint.GetY(),
// currvertex.GetX(), currvertex.GetY());
////////////////////last segment//////////////////////////
//edno++; // edgeno already increased
HalfSegment* hs = new HalfSegment(true, firstPoint, currvertex);
hs->attr.faceno=fcno;
hs->attr.cycleno=ccno;
hs->attr.edgeno=edno;
hs->attr.partnerno=partnerno;
hs->attr.insideAbove = (hs->GetRightPoint() == firstP);
partnerno++;
//////////////////////////////////////////////////////////
if (cr->InsertOk(*hs)){
// cout<<"insert last segment"<<endl;
*cr += *hs;
// cout<<"cr+3 "<<*hs<<endl;
if(hs->IsLeftDomPoint()){
*rDir += *hs;
// cout<<"rDr+3 "<<*hs<<endl;
hs->SetLeftDomPoint( false );
}else{
hs->SetLeftDomPoint( true );
// cout<<"rDr+4 "<<*hs<<endl;
*rDir += *hs;
}
*cr += *hs;
// cout<<"cr+4 "<<*hs<<endl;
delete hs;
rDir->EndBulkLoad(true, false, false, false);
//To calculate the inside above attribute
// bool direction = rDir->GetCycleDirection();
////explicitly define it for all regions, false -- area > 0////
bool direction = false;//counter_wise
// cout<<"direction "<<direction<<endl;
int h = cr->Size() - ( rDir->Size() * 2 );
while(h < cr->Size()){
//after each left half segment of the region is its
//correspondig right half segment
HalfSegment hsIA;
bool insideAbove;
cr->Get(h,hsIA);
if (direction == hsIA.attr.insideAbove)
insideAbove = false;
else
insideAbove = true;
if (!isCycle)
insideAbove = !insideAbove;
HalfSegment auxhsIA( hsIA );
auxhsIA.attr.insideAbove = insideAbove;
cr->UpdateAttr(h,auxhsIA.attr);
//Get right half segment
cr->Get(h+1,hsIA);
auxhsIA = hsIA;
auxhsIA.attr.insideAbove = insideAbove;
cr->UpdateAttr(h+1,auxhsIA.attr);
h+=2;
}
rDir->DeleteIfAllowed();
}else assert(false);
cr->SetNoComponents( fcno+1 );
cr->EndBulkLoad( true, true, true, false );
//regs.push_back(RegionT<Array>(*cr,false));
regs.push_back(*cr);
cr->DeleteIfAllowed();
}
/*
Check that the pavement gap should not intersect the two roads
*/
template< template<typename T1> class Array1,
template<typename T2> class Array2,
template<typename T3> class Array3>
bool SpacePartition::SameSide1(RegionT<Array1>* reg1,
RegionT<Array2>* reg2,
LineT<Array3>* r1r2,
Point* junp)
{
std::vector<MyPoint> mps1;
std::vector<MyPoint> mps2;
for(int i = 0;i < reg1->Size();i++){
HalfSegment hs;
reg1->Get(i,hs);
if(hs.IsLeftDomPoint()){
Point lp = hs.GetLeftPoint();
Point rp = hs.GetRightPoint();
MyPoint mp1(lp, lp.Distance(*junp));
MyPoint mp2(rp, rp.Distance(*junp));
mps1.push_back(mp1);
mps1.push_back(mp2);
}
}
for(int i = 0;i < reg2->Size();i++){
HalfSegment hs;
reg2->Get(i,hs);
if(hs.IsLeftDomPoint()){
Point lp = hs.GetLeftPoint();
Point rp = hs.GetRightPoint();
MyPoint mp1(lp, lp.Distance(*junp));
MyPoint mp2(rp, rp.Distance(*junp));
mps2.push_back(mp1);
mps2.push_back(mp2);
}
}
sort(mps1.begin(), mps1.end());
sort(mps2.begin(), mps2.end());
// cout<<mps1[0].loc<<mps2[0].loc<<mps1[2].loc<<mps2[2].loc<<endl;
if(mps1.size()<3) return false; // not a region
if(mps2.size()<3) return false; // not a region
std::vector<Point> border1;
border1.push_back(mps1[0].loc);
border1.push_back(mps1[2].loc);
border1.push_back(mps2[2].loc);
border1.push_back(mps2[0].loc);
std::vector<Point> border;
const double delta_dist = 0.1;
for(unsigned int i = 0;i < border1.size();i++){
unsigned int j = 0;
for(;j < border.size();j++){
if(border[j].Distance(border1[i]) < delta_dist) break;
}
if(j == border.size())
border.push_back(border1[i]);
}
// for(unsigned int i = 0;i < border.size();i++)
// cout<<border[i]<<endl;
if(border.size() < 3) return false; //not a region
if(border.size() == 3){
unsigned int count = 0;
unsigned int index = 0;
while(count < 3){
HalfSegment hs;
hs.Set(true, border[index], border[(index + 1)%border.size()]);
Line* temp = new Line(0);
int edgeno = 0;
hs.attr.edgeno = edgeno++;
*temp += hs;
hs.SetLeftDomPoint(!hs.IsLeftDomPoint());
*temp += hs;
if(temp->Intersects(*r1r2)){
temp->DeleteIfAllowed();
return false;
}
count++;
index++;
temp->DeleteIfAllowed();
}
//three points collineation
if(Collineation(border[0], border[1], border[2])) return false;
std::vector<Point> ps;
if(GetClockwise(border[0], border[1], border[2])){
ps.push_back(border[1]);
ps.push_back(border[0]);
ps.push_back(border[2]);
}else{
ps.push_back(border[2]);
ps.push_back(border[0]);
ps.push_back(border[1]);
}
//should be counter clock wise
std::vector<Region> gap;
ComputeRegion(ps, gap);
assert(gap.size() > 0);
outer_fillgap.push_back(gap[0]);
return true;
////////////////////////////////////////////
}else{ // four points construct a region
HalfSegment hs;
hs.Set(true, border[0], border[3]);
Line* temp = new Line(0);
int edgeno = 0;
hs.attr.edgeno = edgeno++;
*temp += hs;
hs.SetLeftDomPoint(!hs.IsLeftDomPoint());
*temp += hs;
if(temp->Intersects(*r1r2)){
temp->DeleteIfAllowed();
return false;
}else{
temp->DeleteIfAllowed();
std::vector<Point> ps;
// cout<<border[3]<< border[0]<< border[2]<<endl;
if(GetClockwise(border[3], border[0], border[2])){
ps.push_back(border[0]);
ps.push_back(border[3]);
ps.push_back(border[2]);
ps.push_back(border[1]);
}else{
ps.push_back(border[2]);
ps.push_back(border[3]);
ps.push_back(border[0]);
ps.push_back(border[1]);
}
/* for(unsigned int i = 0;i < ps.size();i++)
cout<<ps[i]<<endl; */
unsigned int i = 0;
for(;i < ps.size();i++){
unsigned int index1 = i;
unsigned int index2 = (i + 1)%ps.size();
unsigned int index3 = (i + 2)%ps.size();
/* cout<<i<<" "<<ps[index1]<<" "<<ps[index2]
<<" "<<ps[index3]<<endl;*/
////////////the special case that three points collineartion///
if(Collineation(ps[index1], ps[index2], ps[index3]))continue;
if(GetClockwise(ps[index2], ps[index1], ps[index3]))break;
std::vector<Point> temp_ps;
for(int j = ps.size() - 1;j >= 0;j--)
temp_ps.push_back(ps[j]);
ps.clear();
for(unsigned int j = 0;j < temp_ps.size();j++)
ps.push_back(temp_ps[j]);
break;
}
////////old checking////////////////
// assert( i < ps.size());
// //should be counter clock wise
// std::vector<Region> gap;
// ComputeRegion(ps, gap);
// outer_fillgap.push_back(gap[0]);
// return true;
/////four points can also be collineartion/////////
if(i < ps.size()){
std::vector<Region> gap;
ComputeRegion(ps, gap);
assert(gap.size() > 0);
outer_fillgap.push_back(gap[0]);
return true;
}else{
return false;
}
/////////////////////////////////////////////////
/* cout<<"four points"<<endl;
for(unsigned int j = 0;j < ps.size();j++){
std::vector<Point> ps1;
int index = (j + 1) % ps.size();
for(int i = 0 ; i < ps.size() ;i++){
Point p = ps[index];
ps1.push_back(p);
index = (index + 1) % ps.size();
}
std::vector<Region> result1;
ComputeRegion(ps1, result1);
if(result1[0].GetCycleDirection()){
outer_fillgap.push_back(result1[0]);
return true;
}
}
assert(false);*/
//////////////////////////////////////////////////
}
}
}
/*
build a small region around the three halfsegments
the pavement gap should not intersect the small region
*/
template< template<typename T1> class Array1,
template<typename T2> class Array2,
template<typename T3> class Array3,
template<typename T4> class Array4>
bool SpacePartition::SameSide2(RegionT<Array1>* reg1,
RegionT<Array2>* reg2,
LineT<Array3>* r1r2,
Point* junp, MyHalfSegment thirdseg,
RegionT<Array4>& smallreg)
{
if(reg1->Size() < 3 || reg2->Size() < 3){
return false;
}
std::vector<MyPoint> mps1;
std::vector<MyPoint> mps2;
for(int i = 0;i < reg1->Size();i++){
HalfSegment hs;
reg1->Get(i,hs);
if(hs.IsLeftDomPoint()){
Point lp = hs.GetLeftPoint();
Point rp = hs.GetRightPoint();
MyPoint mp1(lp, lp.Distance(*junp));
MyPoint mp2(rp, rp.Distance(*junp));
mps1.push_back(mp1);
mps1.push_back(mp2);
}
}
for(int i = 0;i < reg2->Size();i++){
HalfSegment hs;
reg2->Get(i,hs);
if(hs.IsLeftDomPoint()){
Point lp = hs.GetLeftPoint();
Point rp = hs.GetRightPoint();
MyPoint mp1(lp, lp.Distance(*junp));
MyPoint mp2(rp, rp.Distance(*junp));
mps2.push_back(mp1);
mps2.push_back(mp2);
}
}
sort(mps1.begin(), mps1.end());
sort(mps2.begin(), mps2.end());
// cout<<mps1[0].loc<<mps2[0].loc<<mps1[2].loc<<mps2[2].loc<<endl;
std::vector<Point> border1;
border1.push_back(mps1[0].loc);
border1.push_back(mps1[2].loc);
border1.push_back(mps2[2].loc);
border1.push_back(mps2[0].loc);
std::vector<Point> border;
const double delta_dist = 0.1;
for(unsigned int i = 0;i < border1.size();i++){
unsigned int j = 0;
for(;j < border.size();j++){
if(border[j].Distance(border1[i]) < delta_dist) break;
}
if(j == border.size())
border.push_back(border1[i]);
}
// for(unsigned int i = 0;i < border.size();i++)
// cout<<border[i]<<endl;
if(border.size() < 3) return false; //not a region
if(border.size() == 3){
// cout<<"3"<<endl;
unsigned int count = 0;
unsigned int index = 0;
while(count < 3){
HalfSegment hs;
hs.Set(true, border[index], border[(index + 1)%border.size()]);
Line* temp = new Line(0);
int edgeno = 0;
hs.attr.edgeno = edgeno++;
*temp += hs;
hs.SetLeftDomPoint(!hs.IsLeftDomPoint());
*temp += hs;
bool flag = true;
if(border[index].Inside(smallreg) == false)
flag = true;
else
flag = false;
if(temp->Intersects(*r1r2) || flag == false){
temp->DeleteIfAllowed();
return false;
}
count++;
index++;
temp->DeleteIfAllowed();
}
if(Collineation(border[0], border[1], border[2])) return false;
std::vector<Point> ps;
if(GetClockwise(border[0], border[1], border[2])){
ps.push_back(border[1]);
ps.push_back(border[0]);
ps.push_back(border[2]);
}else{
ps.push_back(border[2]);
ps.push_back(border[0]);
ps.push_back(border[1]);
}
//should be counter clock wise
std::vector<Region> gap;
ComputeRegion(ps, gap);
assert(gap.size() > 0);
outer_fillgap.push_back(gap[0]);
return true;
}else{ // four points construct a region
// cout<<"4"<<endl;
HalfSegment hs;
hs.Set(true, border[0], border[3]);
Line* temp = new Line(0);
int edgeno = 0;
hs.attr.edgeno = edgeno++;
*temp += hs;
hs.SetLeftDomPoint(!hs.IsLeftDomPoint());
*temp += hs;
bool flag = true;
if(border[0].Inside(smallreg) == false &&
border[3].Inside(smallreg) == false)
flag = true;
else
flag = false;
if(temp->Intersects(*r1r2) || flag == false){
temp->DeleteIfAllowed();
return false;
}else{
temp->DeleteIfAllowed();
std::vector<Point> ps;
if(GetClockwise(border[3], border[0], border[2])){
ps.push_back(border[0]);
ps.push_back(border[3]);
ps.push_back(border[2]);
ps.push_back(border[1]);
}else{
ps.push_back(border[2]);
ps.push_back(border[3]);
ps.push_back(border[0]);
ps.push_back(border[1]);
}
unsigned int i = 0;
for(;i < ps.size();i++){
unsigned int index1 = i;
unsigned int index2 = (i + 1)%ps.size();
unsigned int index3 = (i + 2)%ps.size();
////////////the special case that three points collineartion///
if(Collineation(ps[index1], ps[index2], ps[index3]))continue;
if(GetClockwise(ps[index2], ps[index1], ps[index3]))break;
std::vector<Point> temp_ps;
for(int j = ps.size() - 1;j >= 0;j--)
temp_ps.push_back(ps[j]);
ps.clear();
for(unsigned int j = 0;j < temp_ps.size();j++)
ps.push_back(temp_ps[j]);
break;
}
assert( i < ps.size());
//should be counter clock wise
std::vector<Region> gap;
ComputeRegion(ps, gap);
assert(gap.size() > 0);
outer_fillgap.push_back(gap[0]);
return true;
}
}
}
/*
the common area of two regions
*/
template< template<typename T1> class Array1,
template<typename T2> class Array2>
inline bool SpacePartition::PavementIntersection(RegionT<Array1>* reg1,
RegionT<Array2>* reg2)
{
if(reg1->Intersects(*reg2) == false)
return false;
Region* reg = new Region(0);
MyIntersection(*reg1, *reg2, *reg);
double regarea = reg->Area();
// cout<<"intersection area "<<regarea<<endl;
reg->DeleteIfAllowed();
if(MyAlmostEqual(regarea,0.0)) return false;
return true;
}
/*
Intersection, union and minus between two regions
*/
template< template<typename T1> class Array1,
template<typename T2> class Array2,
template<typename T3> class Array3>
void MySetOp(const RegionT<Array1>& reg1,
const RegionT<Array2>& reg2,
RegionT<Array3>& result,
myavlseg::SetOperation op){
result.Clear();
if(!reg1.IsDefined() || !reg2.IsDefined()){
result.SetDefined(false);
return;
}
result.SetDefined(true);
if(reg1.Size()==0){
switch(op){
case myavlseg::union_op : result = reg2;
return;
case myavlseg::intersection_op : return; // empty region
case myavlseg::difference_op : return; // empty region
default : assert(false);
}
}
if(reg2.Size()==0){
switch(op){
case myavlseg::union_op: result = reg1;
return;
case myavlseg::intersection_op: return;
case myavlseg::difference_op: result = reg1;
return;
default : assert(false);
}
}
if(!reg1.BoundingBox().Intersects(reg2.BoundingBox())){
switch(op){
case myavlseg::union_op: {
result.StartBulkLoad();
int edgeno=0;
int s = reg1.Size();
HalfSegment hs;
for(int i=0;i<s;i++){
reg1.Get(i,hs);
if(hs.IsLeftDomPoint()){
HalfSegment HS(hs);
HS.attr.edgeno = edgeno;
result += HS;
HS.SetLeftDomPoint(false);
result += HS;
edgeno++;
}
}
s = reg2.Size();
for(int i=0;i<s;i++){
reg2.Get(i,hs);
if(hs.IsLeftDomPoint()){
HalfSegment HS(hs);
HS.attr.edgeno = edgeno;
result += HS;
HS.SetLeftDomPoint(false);
result += HS;
edgeno++;
}
}
result.EndBulkLoad();
return;
} case myavlseg::difference_op: {
result = reg1;
return;
} case myavlseg::intersection_op:{
return;
} default: assert(false);
}
}
std::priority_queue<HalfSegment, std::vector<HalfSegment>,
std::greater<HalfSegment> > q1;
std::priority_queue<HalfSegment, std::vector<HalfSegment>,
std::greater<HalfSegment> > q2;
avltree::AVLTree<myavlseg::MyAVLSegment> sss;
myavlseg::ownertype owner;
int pos1 = 0;
int pos2 = 0;
HalfSegment nextHs;
int src = 0;
myavlseg::MyAVLSegment* member = 0;
myavlseg::MyAVLSegment* leftN = 0;
myavlseg::MyAVLSegment* rightN = 0;
myavlseg::MyAVLSegment left1,right1,common1,
left2,right2;
int edgeno =0;
myavlseg::MyAVLSegment tmpL,tmpR;
result.StartBulkLoad();
while( (owner=myselectNext(reg1,pos1,
reg2,pos2,
q1,q2,nextHs,src))!=myavlseg::none){
myavlseg::MyAVLSegment current(nextHs,owner);
member = sss.getMember(current,leftN,rightN);
// cout<<"current "<<current <<"owner "<<owner<<endl;
// sss.Print(cout);
if(leftN){
tmpL = *leftN;
leftN = &tmpL;
}
if(rightN){
tmpR = *rightN;
rightN = &tmpR;
}
if(nextHs.IsLeftDomPoint()){
if(member){ // overlapping segment found
if((member->getOwner()==myavlseg::both) ||
(member->getOwner()==owner)){
std::cerr << "overlapping segments detected "
"within a single region"
<< endl;
std::cerr << "the argument is "
<< (owner==myavlseg::first?"first":"second")
<< endl;
std::cerr.precision(16);
std::cerr << "stored is " << *member << endl;
std::cerr << "current = " << current << endl;
myavlseg::MyAVLSegment tmp_left, tmp_common, tmp_right;
member->split(current,tmp_left, tmp_common, tmp_right, false);
std::cerr << "The common part is " << tmp_common << endl;
std::cerr << "The lenth = " << tmp_common.length() << endl;
assert(false);
}
int parts = member->split(current,left1,common1,right1);
sss.remove(*member);
if(parts & myavlseg::LEFT){
if(!left1.isPoint()){
// cout<<"left1 "<<left1<<endl;
sss.insert(left1);
myinsertEvents(left1,false,true,q1,q2);
}
}
assert(parts & myavlseg::COMMON);
// update coverage numbers
if(current.getInsideAbove()){
common1.con_above++;
} else {
common1.con_above--;
}
if(!common1.isPoint()){
// cout<<"comm1 "<<common1<<endl;
sss.insert(common1);
myinsertEvents(common1,false,true,q1,q2);
}
if(parts & myavlseg::RIGHT){
myinsertEvents(right1,true,true,q1,q2);
}
} else { // there is no overlapping segment
// try to split segments if required
MysplitByNeighbour(sss, current, leftN, q1, q2);
MysplitByNeighbour(sss, current, rightN,q1, q2);
// cout<<"current "<<current<<endl;
// update coverage numbers
bool iac = current.getOwner()== myavlseg::first
?current.getInsideAbove_first()
:current.getInsideAbove_second();
/* iac = current.getOwner()== myavlseg::first
?current.getInsideAbove_first()
:current.getInsideAbove_second();*/
if(leftN){
// cout<<"leftN "<<leftN->con_below<<" "<<leftN->con_above<<endl;
// cout<<*leftN<<endl;
}
if(leftN && current.extends(*leftN)){
current.con_below = leftN->con_below;
current.con_above = leftN->con_above;
}else{
if(leftN && leftN->isVertical()){
current.con_below = leftN->con_below;
} else if(leftN){
current.con_below = leftN->con_above;
} else {
current.con_below = 0;
}
if(iac){
current.con_above = current.con_below+1;
} else {
current.con_above = current.con_below-1;
}
}
// insert element
if(!current.isPoint()){
// cout<<"current2 "<<current<<endl;
sss.insert(current);
myinsertEvents(current,false,true,q1,q2);
}
}
} else{ // nextHs.IsRightDomPoint
if(member && member->exactEqualsTo(current)){
switch(op){
case myavlseg::union_op :{
if( (member->con_above==0) || (member->con_below==0)) {
HalfSegment hs1 = member->getOwner()==myavlseg::both
?member->convertToHs(true,myavlseg::first)
:member->convertToHs(true);
hs1.attr.edgeno = edgeno;
result += hs1;
hs1.SetLeftDomPoint(false);
result += hs1;
edgeno++;
}
break;
}
case myavlseg::intersection_op: {
if(member->con_above==2 || member->con_below==2){
HalfSegment hs1 = member->getOwner()==myavlseg::both
?member->convertToHs(true,myavlseg::first)
:member->convertToHs(true);
hs1.attr.edgeno = edgeno;
hs1.attr.insideAbove = (member->con_above==2);
result += hs1;
hs1.SetLeftDomPoint(false);
result += hs1;
edgeno++;
}
break;
}
case myavlseg::difference_op : {
switch(member->getOwner()){
case myavlseg::first:{
if(member->con_above + member->con_below == 1){
HalfSegment hs1 = member->getOwner()==myavlseg::both
?member->convertToHs(true,myavlseg::first)
:member->convertToHs(true);
hs1.attr.edgeno = edgeno;
result += hs1;
hs1.SetLeftDomPoint(false);
result += hs1;
edgeno++;
}
break;
}
case myavlseg::second:{
if(member->con_above + member->con_below == 3){
HalfSegment hs1 = member->getOwner()==myavlseg::both
?member->convertToHs(true,myavlseg::second)
:member->convertToHs(true);
hs1.attr.insideAbove = ! hs1.attr.insideAbove;
hs1.attr.edgeno = edgeno;
result += hs1;
hs1.SetLeftDomPoint(false);
result += hs1;
edgeno++;
}
break;
}
case myavlseg::both: {
if((member->con_above==1) && (member->con_below== 1)){
HalfSegment hs1 = member->getOwner()==myavlseg::both
?member->convertToHs(true,myavlseg::first)
:member->convertToHs(true);
hs1.attr.insideAbove = member->getInsideAbove_first();
hs1.attr.edgeno = edgeno;
result += hs1;
hs1.SetLeftDomPoint(false);
result += hs1;
edgeno++;
}
break;
}
default : assert(false);
} // switch member->getOwner
break;
} // case difference
default : assert(false);
} // end of switch
sss.remove(*member);
MysplitNeighbours(sss,leftN,rightN,q1,q2);
} // current found in sss
} // right endpoint
}
if(result.Size() > 0 && result.Size() < 6){////its not a region
result.Clear();
result.EndBulkLoad(false, false, false, false);
}
else{
result.EndBulkLoad();
////////////////////////////////
/* Region* reg = new Region(0);
reg->StartBulkLoad();
int edgeno = 0;
for(int i = 0;i < result.Size();i++){
HalfSegment hs1;
result.Get(i, hs1);
if(!hs1.IsLeftDomPoint()) continue;
HalfSegment hs2(hs1);
Point lp = hs1.GetLeftPoint();
Point rp = hs1.GetRightPoint();
ModifyPoint(lp);
ModifyPoint(rp);
hs2.Set(true, lp, rp);
hs2.attr.edgeno = edgeno++;
*reg += hs2;
hs2.SetLeftDomPoint(!hs2.IsLeftDomPoint());
*reg += hs2;
}
reg->SetNoComponents(result.NoComponents());
reg->EndBulkLoad();
result.Clear();
result = *reg;
delete reg; */
///////////////////////////////
}
} // setOP region x region -> region
/*
The first region intersects the seccond region and store the result as the third
*/
template< template<typename T1> class Array1,
template<typename T2> class Array2,
template<typename T3> class Array3>
void MyIntersection(const RegionT<Array1>& reg1,
const RegionT<Array2>& reg2,
RegionT<Array3>& result)
{
MySetOp(reg1,reg2,result,myavlseg::intersection_op);
}
#endif