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

6031 lines
178 KiB
C++

/*
----
This file is part of SECONDO.
Copyright (C) 2004, University in Hagen, Department of Computer Science,
Database Systems for New Applications.
SECONDO is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
SECONDO is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with SECONDO; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
----
//paragraph [1] Title: [{\Large \bf \begin {center}] [\end {center}}]
//[TOC] [\tableofcontents]
[1] Source File of the Transportation Mode Algebra
March, 2010 Jianqiu Xu
[TOC]
1 Overview
This source file essentially contains the necessary implementations for
partitioning space.
*/
#include "Partition.h"
/*
~Shift~ Operator for ~ownertype~
*/
using namespace std;
using namespace network;
ostream& myavlseg::operator<<(ostream& o, const myavlseg::ownertype& owner){
switch(owner){
case myavlseg::none : o << "none" ; break;
case myavlseg::first : o << "first"; break;
case myavlseg::second : o << "second"; break;
case myavlseg::both : o << "both"; break;
default : assert(false);
}
return o;
}
/*
3.1 Constructors
~Standard Constructor~
*/
myavlseg::MyAVLSegment::MyAVLSegment()
{
x1 = 0;
x2 = 0;
y1 = 0;
y2 = 0;
owner = none;
insideAbove_first = false;
insideAbove_second = false;
con_below = 0;
con_above = 0;
}
/*
~Constructor~
This constructor creates a new segment from the given HalfSegment.
As owner only __first__ and __second__ are the allowed values.
*/
myavlseg::MyAVLSegment::MyAVLSegment(const HalfSegment& hs, ownertype owner){
x1 = hs.GetLeftPoint().GetX();
y1 = hs.GetLeftPoint().GetY();
x2 = hs.GetRightPoint().GetX();
y2 = hs.GetRightPoint().GetY();
// if( (MyAlmostEqual(x1,x2) && (y2<y2) ) || (x2<x2) ){// swap the entries
if( (MyAlmostEqual(x1,x2) && (y2< y1) ) || (x2<x1) ){// swap the entries
double tmp = x1;
x1 = x2;
x2 = tmp;
tmp = y1;
y1 = y2;
y2 = tmp;
}
this->owner = owner;
switch(owner){
case first: {
insideAbove_first = hs.GetAttr().insideAbove;
insideAbove_second = false;
break;
} case second: {
insideAbove_second = hs.GetAttr().insideAbove;
insideAbove_first = false;
break;
} default: {
assert(false);
}
}
con_below = 0;
con_above = 0;
}
/*
~Constructor~
Create a Segment only consisting of a single point.
*/
myavlseg::MyAVLSegment::MyAVLSegment(const Point& p, ownertype owner)
{
x1 = p.GetX();
x2 = x1;
y1 = p.GetY();
y2 = y1;
this->owner = owner;
insideAbove_first = false;
insideAbove_second = false;
con_below = 0;
con_above = 0;
}
/*
~Copy Constructor~
*/
myavlseg::MyAVLSegment::MyAVLSegment(const MyAVLSegment& src){
Equalize(src);
}
/*
3.3 Operators
*/
myavlseg::MyAVLSegment& myavlseg::MyAVLSegment::operator=(
const myavlseg::MyAVLSegment& src){
Equalize(src);
return *this;
}
bool myavlseg::MyAVLSegment::operator==(const myavlseg::MyAVLSegment& s)const{
return compareTo(s)==0;
}
bool myavlseg::MyAVLSegment::operator<(const myavlseg::MyAVLSegment& s) const{
return compareTo(s)<0;
}
bool myavlseg::MyAVLSegment::operator>(const myavlseg::MyAVLSegment& s) const{
return compareTo(s)>0;
}
/*
3.3 Further Needful Functions
~Print~
This function writes this segment to __out__.
*/
void myavlseg::MyAVLSegment::Print(ostream& out)const{
out << "Segment("<<x1<<", " << y1 << ") -> (" << x2 << ", " << y2 <<") "
<< owner << " [ " << insideAbove_first << ", "
<< insideAbove_second << "] con("
<< con_below << ", " << con_above << ")";
}
/*
~Equalize~
The value of this segment is taken from the argument.
*/
void myavlseg::MyAVLSegment::Equalize( const myavlseg::MyAVLSegment& src){
x1 = src.x1;
x2 = src.x2;
y1 = src.y1;
y2 = src.y2;
owner = src.owner;
insideAbove_first = src.insideAbove_first;
insideAbove_second = src.insideAbove_second;
con_below = src.con_below;
con_above = src.con_above;
}
/*
3.5 Geometric Functions
~crosses~
Checks whether this segment and __s__ have an intersection point of their
interiors.
*/
bool myavlseg::MyAVLSegment::crosses(const myavlseg::MyAVLSegment& s) const{
double x,y;
return crosses(s,x,y);
}
/*
~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 myavlseg::MyAVLSegment::crosses(const myavlseg::MyAVLSegment& s,
double& x, double& y) const{
if(isPoint() || s.isPoint()){
return false;
}
if(!xOverlaps(s)){
return false;
}
if(overlaps(s)){ // a common line
return false;
}
if(compareSlopes(s)==0){ // parallel or disjoint lines
return false;
}
if(isVertical()){
x = x1; // compute y for s
y = s.y1 + ((x-s.x1)/(s.x2-s.x1))*(s.y2 - s.y1);
return !MyAlmostEqual(y1,y) && !MyAlmostEqual(y2,y) &&
(y>y1) && (y<y2)
&& !MyAlmostEqual(s.x1,x) && !MyAlmostEqual(s.x2,x) ;
}
if(s.isVertical()){
x = s.x1;
y = y1 + ((x-x1)/(x2-x1))*(y2-y1);
return !MyAlmostEqual(y,s.y1) && !MyAlmostEqual(y,s.y2) &&
(y>s.y1) && (y<s.y2) &&
!MyAlmostEqual(x1,x) && !MyAlmostEqual(x2,x);
}
// avoid problems with rounding errors during computation of
// the intersection point
if(pointEqual(x1,y1,s.x1,s.y1)){
return false;
}
if(pointEqual(x2,y2,s.x1,s.y1)){
return false;
}
if(pointEqual(x1,y1,s.x2,s.y2)){
return false;
}
if(pointEqual(x2,y2,s.x2,s.y2)){
return false;
}
// both segments are non vertical
double m1 = (y2-y1)/(x2-x1);
double m2 = (s.y2-s.y1)/(s.x2-s.x1);
double c1 = y1 - m1*x1;
double c2 = s.y1 - m2*s.x1;
double xs = (c2-c1) / (m1-m2); // x coordinate of the intersection point
x = xs;
y = y1 + ((x-x1)/(x2-x1))*(y2-y1);
return !MyAlmostEqual(x1,xs) && !MyAlmostEqual(x2,xs) && // not an endpoint
!MyAlmostEqual(s.x1,xs) && !MyAlmostEqual(s.x2,xs) && //of any segment
(x1<xs) && (xs<x2) && (s.x1<xs) && (xs<s.x2);
}
/*
~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 myavlseg::MyAVLSegment::extends(const myavlseg::MyAVLSegment& s)const{
return pointEqual(x1,y1,s.x2,s.y2) &&
compareSlopes(s)==0;
}
/*
~exactEqualsTo~
This function checks if s has the same geometry like this segment, i.e.
if both endpoints are equal.
*/
bool myavlseg::MyAVLSegment::exactEqualsTo(const myavlseg::MyAVLSegment& s)
const{
return pointEqual(x1,y1,s.x1,s.y1) &&
pointEqual(x2,y2,s.x2,s.y2);
}
/*
~isVertical~
Checks whether this segment is vertical.
*/
bool myavlseg::MyAVLSegment::isVertical() const{
return MyAlmostEqual(x1,x2);
}
/*
~isPoint~
Checks if this segment consists only of a single point.
*/
bool myavlseg::MyAVLSegment::isPoint() const{
return MyAlmostEqual(x1,x2) && MyAlmostEqual(y1,y2);
}
/*
~length~
Returns the length of this segment.
*/
double myavlseg::MyAVLSegment::length(){
return sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1));
}
/*
~InnerDisjoint~
This function checks whether this segment and s have at most a
common endpoint.
*/
bool myavlseg::MyAVLSegment::innerDisjoint(const myavlseg::MyAVLSegment& s)
const{
if(pointEqual(x1,y1,s.x2,s.y2)){ // common endpoint
return true;
}
if(pointEqual(s.x1,s.y1,x2,y2)){ // common endpoint
return true;
}
if(overlaps(s)){ // a common line
return false;
}
if(compareSlopes(s)==0){ // parallel or disjoint lines
return true;
}
if(ininterior(s.x1,s.y1)){
return false;
}
if(ininterior(s.x2,s.y2)){
return false;
}
if(s.ininterior(x1,y1)){
return false;
}
if(s.ininterior(x2,y2)){
return false;
}
if(crosses(s)){
return false;
}
return true;
}
/*
~Intersects~
This function checks whether this segment and ~s~ have at least a
common point.
*/
bool myavlseg::MyAVLSegment::intersects(const myavlseg::MyAVLSegment& s)const{
if(pointEqual(x1,y1,s.x2,s.y2)){ // common endpoint
return true;
}
if(pointEqual(s.x1,s.y1,x2,y2)){ // common endpoint
return true;
}
if(overlaps(s)){ // a common line
return true;
}
if(compareSlopes(s)==0){ // parallel or disjoint lines
return false;
}
if(isVertical()){
double x = x1; // compute y for s
double y = s.y1 + ((x-s.x1)/(s.x2-s.x1))*(s.y2 - s.y1);
return ( (contains(x,y) && s.contains(x,y) ) );
}
if(s.isVertical()){
double x = s.x1;
double y = y1 + ((x-x1)/(x2-x1))*(y2-y1);
return ((contains(x,y) && s.contains(x,y)));
}
// both segments are non vertical
double m1 = (y2-y1)/(x2-x1);
double m2 = (s.y2-s.y1)/(s.x2-s.x1);
double c1 = y1 - m1*x1;
double c2 = s.y1 - m2*s.x1;
double x = (c2-c1) / (m1-m2); // x coordinate of the intersection point
double y = y1 + ((x-x1)/(x2-x1))*(y2-y1);
return ( (contains(x,y) && s.contains(x,y) ) );
}
/*
~overlaps~
Checks whether this segment and ~s~ have a common segment.
*/
bool myavlseg::MyAVLSegment::overlaps(const myavlseg::MyAVLSegment& s) const{
if(isPoint() || s.isPoint()){
return false;
}
if(compareSlopes(s)!=0){
return false;
}
// one segment is an extension of the other one
if(pointEqual(x1,y1,s.x2,s.y2)){
return false;
}
if(pointEqual(x2,y2,s.x1,s.y1)){
return false;
}
return contains(s.x1,s.y1) || contains(s.x2,s.y2);
}
/*
~ininterior~
This function checks whether the point defined by (x,y) is
part of the interior of this segment.
*/
bool myavlseg::MyAVLSegment::ininterior(const double x,const double y)const{
if(isPoint()){ // a point has no interior
return false;
}
if(pointEqual(x,y,x1,y1) || pointEqual(x,y,x2,y2)){ // an endpoint
return false;
}
if(!MyAlmostEqual(x,x1) && x < x1){ // (x,y) left of this
return false;
}
if(!MyAlmostEqual(x,x2) && x > x2){ // (X,Y) right of this
return false;
}
if(isVertical()){
return (!MyAlmostEqual(y,y1) && (y>y1) &&
!MyAlmostEqual(y,y2) && (y<y2));
}
double ys = getY(x);
return MyAlmostEqual(y,ys);
}
/*
~contains~
Checks whether the point defined by (x,y) is located anywhere on this
segment.
*/
bool myavlseg::MyAVLSegment::contains(const double x,const double y)const{
if(pointEqual(x,y,x1,y1) || pointEqual(x,y,x2,y2)){
return true;
}
if(isPoint()){
return false;
}
if(MyAlmostEqual(x1,x2)){ // vertical segment
return (y>=y1) && (y <= y2);
}
// check if (x,y) is located on the line
double res1 = (x-x1)*(y2-y1);
double res2 = (y-y1)*(x2-x1);
if(!MyAlmostEqual(res1,res2)){
return false;
}
return ((x>x1) && (x<x2)) ||
MyAlmostEqual(x,x1) ||
MyAlmostEqual(x,x2);
}
/*
3.6 Comparison
Compares this with s. The x intervals must overlap.
*/
int myavlseg::MyAVLSegment::compareTo(const myavlseg::MyAVLSegment& s) const{
if(!xOverlaps(s)){
cerr << "Warning: compare MyAVLSegments with disjoint x intervals" << endl;
cerr << "This may be a problem of roundig errors!" << endl;
cerr << "*this = " << *this << endl;
cerr << " s = " << s << endl;
}
if(isPoint()){
if(s.isPoint()){
return comparePoints(x1,y1,s.x1,s.y1);
} else {
if(s.contains(x1,y1)){
return 0;
} else {
double y = s.getY(x1);
if(y1<y){
return -1;
} else {
return 1;
}
}
}
}
if(s.isPoint()){
if(contains(s.x1,s.y1)){
return 0;
} else {
double y = getY(s.x1);
if(y<s.y1){
return -1;
} else {
return 1;
}
}
}
if(overlaps(s)){
return 0;
}
bool v1 = isVertical();
bool v2 = s.isVertical();
if(!v1 && !v2){
double x = max(x1,s.x1); // the right one of the left coordinates
double y_this = getY(x);
double y_s = s.getY(x);
if(!MyAlmostEqual(y_this,y_s)){
if(y_this<y_s){
return -1;
} else {
return 1;
}
} else {
int cmp = compareSlopes(s);
if(cmp!=0){
return cmp;
}
// if the segments are connected, the left segment
// is the smaller one
if(MyAlmostEqual(x2,s.x1)){
return -1;
}
if(MyAlmostEqual(s.x2,x1)){
return 1;
}
// the segments have an proper overlap
return 0;
}
} else if(v1 && v2){ // both are vertical
if(MyAlmostEqual(y1,s.y2) || (y1>s.y2)){ // this is above s
return 1;
}
if(MyAlmostEqual(s.y1,y2) || (s.y1>y2)){ // s above this
return 1;
}
// proper overlapping part
return 0;
} else { // one segment is vertical
double x = v1? x1 : s.x1; // x coordinate of the vertical segment
double y1 = getY(x);
double y2 = s.getY(x);
if(MyAlmostEqual(y1,y2)){
return v1?1:-1; // vertical segments have the greatest slope
} else if(y1<y2){
return -1;
} else {
return 1;
}
}
}
/*
~SetOwner~
This function changes the owner of this segment.
*/
void myavlseg::MyAVLSegment::setOwner(myavlseg::ownertype o){
this->owner = o;
}
/*
3.7 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 myavlseg::MyAVLSegment::getInsideAbove() const{
switch(owner){
case first : return insideAbove_first;
case second: return insideAbove_second;
default : assert(false);
}
}
/*
3.8 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 myavlseg::MyAVLSegment::split(const myavlseg::MyAVLSegment& s,
myavlseg::MyAVLSegment& left,
myavlseg::MyAVLSegment& common,
myavlseg::MyAVLSegment& right,
const bool checkOwner/* = true*/) const{
assert(overlaps(s));
if(checkOwner){
assert( (this->owner==first && s.owner==second) ||
(this->owner==second && s.owner==first));
}
int result = 0;
int cmp = comparePoints(x1,y1,s.x1,s.y1);
if(cmp==0){
left.x1 = x1;
left.y1 = y1;
left.x2 = x1;
left.y2 = y1;
} else { // there is a left part
result = result | myavlseg::LEFT;
if(cmp<0){ // this is smaller
left.x1 = x1;
left.y1 = y1;
left.x2 = s.x1;
left.y2 = s.y1;
left.owner = this->owner;
left.con_above = this->con_above;
left.con_below = this->con_below;
left.insideAbove_first = this->insideAbove_first;
left.insideAbove_second = this->insideAbove_second;
} else { // s is smaller than this
left.x1 = s.x1;
left.y1 = s.y1;
left.x2 = this->x1;
left.y2 = this->y1;
left.owner = s.owner;
left.con_above = s.con_above;
left.con_below = s.con_below;
left.insideAbove_first = s.insideAbove_first;
left.insideAbove_second = s.insideAbove_second;
}
}
// there is an overlapping part
result = result | COMMON;
cmp = comparePoints(x2,y2,s.x2,s.y2);
common.owner = both;
common.x1 = left.x2;
common.y1 = left.y2;
if(this->owner==first){
common.insideAbove_first = insideAbove_first;
common.insideAbove_second = s.insideAbove_second;
} else {
common.insideAbove_first = s.insideAbove_first;
common.insideAbove_second = insideAbove_second;
}
common.con_above = this->con_above;
common.con_below = this->con_below;
if(cmp<0){
common.x2 = x2;
common.y2 = y2;
} else {
common.x2 = s.x2;
common.y2 = s.y2;
}
if(cmp==0){ // common right endpoint
return result;
}
result = result | myavlseg::RIGHT;
right.x1 = common.x2;
right.y1 = common.y2;
if(cmp<0){ // right part comes from s
right.owner = s.owner;
right.x2 = s.x2;
right.y2 = s.y2;
right.insideAbove_first = s.insideAbove_first;
right.insideAbove_second = s.insideAbove_second;
right.con_below = s.con_below;
right.con_above = s.con_above;
} else { // right part comes from this
right.owner = this->owner;
right.x2 = this->x2;
right.y2 = this->y2;
right.insideAbove_first = this->insideAbove_first;
right.insideAbove_second = this->insideAbove_second;
right.con_below = this->con_below;
right.con_above = this->con_above;
}
return result;
}
/*
~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 myavlseg::MyAVLSegment::splitAt(const double x, const double y,
myavlseg::MyAVLSegment& left,
myavlseg::MyAVLSegment& right)const{
/*
// debug::start
if(!ininterior(x,y)){
cout << "ininterior check failed (may be an effect"
<< " of rounding errors !!!" << endl;
cout << "The segment is " << *this << endl;
cout << "The point is (" << x << " , " << y << ")" << endl;
}
// debug::end
*/
left.x1=x1;
left.y1=y1;
left.x2 = x;
left.y2 = y;
left.owner = owner;
left.insideAbove_first = insideAbove_first;
left.insideAbove_second = insideAbove_second;
left.con_below = con_below;
left.con_above = con_above;
right.x1=x;
right.y1=y;
right.x2 = x2;
right.y2 = y2;
right.owner = owner;
right.insideAbove_first = insideAbove_first;
right.insideAbove_second = insideAbove_second;
right.con_below = con_below;
right.con_above = con_above;
}
/*
~splitCross~
Splits two crossing segments into the 4 corresponding parts.
Both segments have to cross each other.
*/
void myavlseg::MyAVLSegment::splitCross(const myavlseg::MyAVLSegment& s,
myavlseg::MyAVLSegment& left1,
myavlseg::MyAVLSegment& right1,
myavlseg::MyAVLSegment& left2,
myavlseg::MyAVLSegment& right2) const{
double x,y;
bool cross = crosses(s,x,y);
assert(cross);
splitAt(x, y, left1, right1);
s.splitAt(x, y, left2, right2);
}
/*
3.9 Converting Functions
~ConvertToHs~
This functions creates a ~HalfSegment~ from this segment.
The owner must be __first__ or __second__.
*/
HalfSegment myavlseg::MyAVLSegment::convertToHs(bool lpd,
myavlseg::ownertype owner/* = both*/)const{
assert( owner!=both || this->owner==first || this->owner==second);
assert( owner==both || owner==first || owner==second);
bool insideAbove;
if(owner==both){
insideAbove = this->owner==first?insideAbove_first
:insideAbove_second;
} else {
insideAbove = owner==first?insideAbove_first
:insideAbove_second;
}
Point p1(true,x1,y1);
Point p2(true,x2,y2);
HalfSegment hs(lpd, p1, p2);
hs.attr.insideAbove = insideAbove;
return hs;
}
/*
~pointequal~
This function checks if the points defined by (x1, y1) and
(x2,y2) are equals using the ~MyAlmostEqual~ function.
*/
bool myavlseg::MyAVLSegment::pointEqual(const double x1, const double y1,
const double x2, const double y2){
return MyAlmostEqual(x1,x2) && MyAlmostEqual(y1,y2);
}
/*
~pointSmaller~
This function checks if the point defined by (x1, y1) is
smaller than the point defined by (x2, y2).
*/
bool myavlseg::MyAVLSegment::pointSmaller(const double x1, const double y1,
const double x2, const double y2){
return comparePoints(x1,y1,x2,y2) < 0;
}
/*
~comparePoints~
*/
int myavlseg::MyAVLSegment::comparePoints(const double x1,const double y1,
const double x2,const double y2){
if(MyAlmostEqual(x1,x2)){
if(MyAlmostEqual(y1,y2)){
return 0;
} else if(y1<y2){
return -1;
} else {
return 1;
}
} else if(x1<x2){
return -1;
} else {
return 1;
}
}
/*
~compareSlopes~
compares the slopes of __this__ and __s__. The slope of a vertical
segment is greater than all other slopes.
*/
int myavlseg::MyAVLSegment::compareSlopes(const myavlseg::MyAVLSegment& s)
const{
assert(!isPoint() && !s.isPoint());
bool v1 = MyAlmostEqual(x1,x2);
bool v2 = MyAlmostEqual(s.x1,s.x2);
if(v1 && v2){ // both segments are vertical
return 0;
}
if(v1){
return 1; // this is vertical, s not
}
if(v2){
return -1; // s is vertical
}
// both segments are non-vertical
double res1 = (y2-y1)/(x2-x1);
double res2 = (s.y2-s.y1)/(s.x2-s.x1);
int result = -3;
if( MyAlmostEqual(res1,res2)){
result = 0;
} else if(res1<res2){
result = -1;
} else { // res1>res2
result = 1;
}
return result;
}
/*
~XOverlaps~
Checks whether the x interval of this segment overlaps the
x interval of ~s~.
*/
bool myavlseg::MyAVLSegment::xOverlaps(const myavlseg::MyAVLSegment& s) const{
if(!MyAlmostEqual(x1,s.x2) && x1 > s.x2){ // left of s
return false;
}
if(!MyAlmostEqual(x2,s.x1) && x2 < s.x1){ // right of s
return false;
}
return true;
}
/*
~XContains~
Checks if the x coordinate provided by the parameter __x__ is contained
in the x interval of this segment;
*/
bool myavlseg::MyAVLSegment::xContains(const double x) const{
if(!MyAlmostEqual(x1,x) && x1>x){
return false;
}
if(!MyAlmostEqual(x2,x) && x2<x){
return false;
}
return true;
}
/*
~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 myavlseg::MyAVLSegment::getY(const double x) const{
if(!xContains(x)){
cerr << "Warning: compute y value for a x outside the x interval!"
<< endl;
double diff1 = x1 - x;
double diff2 = x - x2;
double diff = (diff1>diff2?diff1:diff2);
cerr << "difference to x is " << diff << endl;
cerr << "The segment is " << *this << endl;
//assert(diff < 1.0);
}
if(isVertical()){
return y1;
}
double d = (x-x1)/(x2-x1);
return y1 + d*(y2-y1);
}
/*
3.12 Shift Operator
*/
ostream& myavlseg::operator<<(ostream& o, const myavlseg::MyAVLSegment& s){
s.Print(o);
return o;
}
/*
~selectNext~
Selects the minimum halfsegment from ~v~1, ~v~2, ~q~1, and ~q~2.
If no values are available, the return value will be __none__.
In this case, __result__ remains unchanged. Otherwise, __result__
is set to the minimum value found. In this case, the return value
will be ~first~ or ~second~.
If some halfsegments are equal, the one
from ~v~1 is selected.
Note: ~pos~1 and ~pos~2 are increased automatically. In the same way,
the topmost element of the selected queue is deleted.
The template parameter can be instantiated with ~Region~ or ~Line~
*/
template<class T1, class T2>
myavlseg::ownertype myselectNext(const T1& v1,
int& pos1,
const T2& v2,
int& pos2,
priority_queue<HalfSegment,
vector<HalfSegment>,
greater<HalfSegment> >& q1,
priority_queue<HalfSegment,
vector<HalfSegment>,
greater<HalfSegment> >& q2,
HalfSegment& result,
int& src
){
const HalfSegment* values[4];
HalfSegment hs0, hs1, hs2, hs3;
int number = 0; // number of available values
// read the available elements
if(pos1<v1.Size()){
v1.Get(pos1,hs0);
values[0] = &hs0;
number++;
} else {
values[0]=0;
}
if(q1.empty()){
values[1] = 0;
} else {
values[1] = &q1.top();
number++;
}
if(pos2<v2.Size()){
v2.Get(pos2,hs2);
values[2] = &hs2;
number++;
} else {
values[2] = 0;
}
if(q2.empty()){
values[3]=0;
} else {
values[3] = &q2.top();
number++;
}
// no halfsegments found
if(number == 0){
return myavlseg::none;
}
// search for the minimum.
int index = -1;
for(int i=0;i<4;i++){
if(values[i]){
if(index<0 || (result > *values[i])){
result = *values[i];
index = i;
}
}
}
src = index + 1;
switch(index){
case 0: pos1++; return myavlseg::first;
case 1: q1.pop(); return myavlseg::first;
case 2: pos2++; return myavlseg::second;
case 3: q2.pop(); return myavlseg::second;
default: assert(false);
}
return myavlseg::none;
}
/*
Instantiation of the ~selectNext~ Function.
*/
myavlseg::ownertype myselectNext(const Region& reg1,
int& pos1,
const Region& reg2,
int& pos2,
priority_queue<HalfSegment,
vector<HalfSegment>,
greater<HalfSegment> >& q1,
priority_queue<HalfSegment,
vector<HalfSegment>,
greater<HalfSegment> >& q2,
HalfSegment& result,
int& src // for debugging only
){
return myselectNext<Region,Region>(reg1,pos1,reg2,pos2,q1,q2,result,src);
}
/*
~insertEvents~
Creates events for the ~AVLSegment~ and insert them into ~q1~ and/ or ~q1~.
The target queue(s) is (are) determined by the owner of ~seg~.
The flags ~createLeft~ and ~createRight~ determine
whether the left and / or the right events should be created.
*/
void myinsertEvents(const myavlseg::MyAVLSegment& seg,
const bool createLeft,
const bool createRight,
priority_queue<HalfSegment,
vector<HalfSegment>,
greater<HalfSegment> >& q1,
priority_queue<HalfSegment,
vector<HalfSegment>,
greater<HalfSegment> >& q2){
if(seg.isPoint()){
return;
}
switch(seg.getOwner()){
case myavlseg::first: {
if(createLeft){
q1.push(seg.convertToHs(true, myavlseg::first));
}
if(createRight){
q1.push(seg.convertToHs(false, myavlseg::first));
}
break;
} case myavlseg::second:{
if(createLeft){
q2.push(seg.convertToHs(true, myavlseg::second));
}
if(createRight){
q2.push(seg.convertToHs(false, myavlseg::second));
}
break;
} case myavlseg::both : {
if(createLeft){
q1.push(seg.convertToHs(true, myavlseg::first));
q2.push(seg.convertToHs(true, myavlseg::second));
}
if(createRight){
q1.push(seg.convertToHs(false, myavlseg::first));
q2.push(seg.convertToHs(false, myavlseg::second));
}
break;
} default: {
assert(false);
}
}
}
/*
~splitByNeighbour~
~neighbour~ has to be an neighbour from ~current~ within ~sss~.
The return value is true, if current was changed.
*/
bool MysplitByNeighbour(avltree::AVLTree<myavlseg::MyAVLSegment>& sss,
myavlseg::MyAVLSegment& current,
myavlseg::MyAVLSegment*& neighbour,
priority_queue<HalfSegment,
vector<HalfSegment>,
greater<HalfSegment> >& q1,
priority_queue<HalfSegment,
vector<HalfSegment>,
greater<HalfSegment> >& q2){
myavlseg::MyAVLSegment left1, right1, left2, right2;
if(neighbour && !neighbour->innerDisjoint(current)){
if(neighbour->ininterior(current.getX1(),current.getY1())){
neighbour->splitAt(current.getX1(),current.getY1(),left1,right1);
sss.remove(*neighbour);
if(!left1.isPoint()){
neighbour = sss.insert2(left1);
myinsertEvents(left1,false,true,q1,q2);
}
myinsertEvents(right1,true,true,q1,q2);
return false;
} else if(neighbour->ininterior(current.getX2(),current.getY2())){
neighbour->splitAt(current.getX2(),current.getY2(),left1,right1);
sss.remove(*neighbour);
if(!left1.isPoint()){
neighbour = sss.insert2(left1);
myinsertEvents(left1,false,true,q1,q2);
}
myinsertEvents(right1,true,true,q1,q2);
return false;
} else if(current.ininterior(neighbour->getX2(),neighbour->getY2())){
current.splitAt(neighbour->getX2(),neighbour->getY2(),left1,right1);
current = left1;
myinsertEvents(left1,false,true,q1,q2);
myinsertEvents(right1,true,true,q1,q2);
return true;
} else if(current.crosses(*neighbour)){
neighbour->splitCross(current,left1,right1,left2,right2);
sss.remove(*neighbour);
if(!left1.isPoint()){
neighbour = sss.insert2(left1);
}
current = left2;
myinsertEvents(left1,false,true,q1,q2);
myinsertEvents(right1,true,true,q1,q2);
myinsertEvents(left2,false,true,q1,q2);
myinsertEvents(right2,true,true,q1,q2);
return true;
} else { // forgotten case or wrong order of halfsegments
cerr.precision(16);
cerr << "Warning wrong order in halfsegment array detected" << endl;
cerr << "current" << current << endl
<< "neighbour " << (*neighbour) << endl;
if(current.overlaps(*neighbour)){ // a common line
cerr << "1 : The segments overlaps" << endl;
}
if(neighbour->ininterior(current.getX1(),current.getY1())){
cerr << "2 : neighbour->ininterior(current.x1,current.y1)"
<< endl;
}
if(neighbour->ininterior(current.getX2(),current.getY2())){
cerr << "3 : neighbour->ininterior(current.getX2()"
<< ",current.getY2()" << endl;
}
if(current.ininterior(neighbour->getX1(),neighbour->getY1())){
cerr << " case 4 : current.ininterior(neighbour->getX1(),"
<< "neighbour.getY1()" << endl;
cerr << "may be an effect of rounding errors" << endl;
cerr << "remove left part from current" << endl;
current.splitAt(neighbour->getX1(),neighbour->getY1(),
left1,right1);
cerr << "removed part is " << left1 << endl;
current = right1;
myinsertEvents(current,false,true,q1,q2);
return true;
}
if(current.ininterior(neighbour->getX2(),neighbour->getY2())){
cerr << " 5 : current.ininterior(neighbour->getX2(),"
<< "neighbour->getY2())" << endl;
}
if(current.crosses(*neighbour)){
cerr << "6 : crosses" << endl;
}
assert(false);
return true;
}
} else {
return false;
}
}
/*
~splitNeighbours~
Checks if the left and the right neighbour are intersecting in their
interiors and performs the required actions.
*/
void MysplitNeighbours(avltree::AVLTree<myavlseg::MyAVLSegment>& sss,
myavlseg::MyAVLSegment *& leftN,
myavlseg::MyAVLSegment *& rightN,
priority_queue<HalfSegment,
vector<HalfSegment>,
greater<HalfSegment> >& q1,
priority_queue<HalfSegment,
vector<HalfSegment>,
greater<HalfSegment> >& q2){
if(leftN && rightN && !leftN->innerDisjoint(*rightN)){
myavlseg::MyAVLSegment left1, right1, left2, right2;
if(leftN->ininterior(rightN->getX2(),rightN->getY2())){
leftN->splitAt(rightN->getX2(),rightN->getY2(),left1,right1);
sss.remove(*leftN);
if(!left1.isPoint()){
leftN = sss.insert2(left1);
myinsertEvents(left1,false,true,q1,q2);
}
myinsertEvents(right1,true,true,q1,q2);
} else if(rightN->ininterior(leftN->getX2(),leftN->getY2())){
rightN->splitAt(leftN->getX2(),leftN->getY2(),left1,right1);
sss.remove(*rightN);
if(!left1.isPoint()){
rightN = sss.insert2(left1);
myinsertEvents(left1,false,true,q1,q2);
}
myinsertEvents(right1,true,true,q1,q2);
} else if (rightN->crosses(*leftN)){
leftN->splitCross(*rightN,left1,right1,left2,right2);
sss.remove(*leftN);
sss.remove(*rightN);
if(!left1.isPoint()) {
leftN = sss.insert2(left1);
}
if(!left2.isPoint()){
rightN = sss.insert2(left2);
}
myinsertEvents(left1,false,true,q1,q2);
myinsertEvents(left2,false,true,q1,q2);
myinsertEvents(right1,true,true,q1,q2);
myinsertEvents(right2,true,true,q1,q2);
} else { // forgotten case or overlapping segments (rounding errors)
if(leftN->overlaps(*rightN)){
cerr << "Overlapping neighbours found" << endl;
cerr << "leftN = " << *leftN << endl;
cerr << "rightN = " << *rightN << endl;
myavlseg::MyAVLSegment left;
myavlseg::MyAVLSegment common;
myavlseg::MyAVLSegment right;
int parts = leftN->split(*rightN, left,common,right,false);
sss.remove(*leftN);
sss.remove(*rightN);
if(parts & avlseg::LEFT){
if(!left.isPoint()){
cerr << "insert left part" << left << endl;
leftN = sss.insert2(left);
myinsertEvents(left,false,true,q1,q2);
}
}
if(parts & avlseg::COMMON){
if(!common.isPoint()){
cerr << "insert common part" << common << endl;
rightN = sss.insert2(common);
myinsertEvents(common,false,true,q1,q2);
}
}
if(parts & avlseg::RIGHT){
if(!right.isPoint()){
cerr << "insert events for the right part" << right << endl;;
myinsertEvents(right,true,true,q1,q2);
}
}
} else {
assert(false);
}
}
} // intersecting neighbours
}
void MyIntersection(const Line& line, const Region& reg, Line& result)
{
MySetOp(line, reg, result, myavlseg::intersection_op);
}
/*
Intersection, union and minus between a line and a region
*/
void MySetOp(const Line& line,
const Region& region,
Line& result,
myavlseg::SetOperation op){
assert(op==myavlseg::intersection_op || op == myavlseg::difference_op);
result.Clear();
if(!line.IsDefined() || !region.IsDefined()){
result.SetDefined(false);
return;
}
result.SetDefined(true);
if(line.Size()==0){ // empty line -> empty result
switch(op){
case myavlseg::intersection_op : return; // empty region
case myavlseg::difference_op : return; // empty region
default : assert(false);
}
}
if(region.Size()==0){
switch(op){
case myavlseg::intersection_op: return;
case myavlseg::difference_op: result = line;
return;
default : assert(false);
}
}
priority_queue<HalfSegment, vector<HalfSegment>, greater<HalfSegment> > q1;
priority_queue<HalfSegment, vector<HalfSegment>, greater<HalfSegment> > q2;
avltree::AVLTree<myavlseg::MyAVLSegment> sss;
myavlseg::ownertype owner;
int pos1 = 0;
int pos2 = 0;
int size1= line.Size();
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;
bool done = false;
result.StartBulkLoad();
// perform a planesweeo
while( ((owner=myselectNext(line,pos1,
region,pos2,
q1,q2,nextHs,src))!= myavlseg::none)
&& ! done){
myavlseg::MyAVLSegment current(nextHs,owner);
member = sss.getMember(current,leftN,rightN);
if(leftN){
tmpL = *leftN;
leftN = &tmpL;
}
if(rightN){
tmpR = *rightN;
rightN = &tmpR;
}
if(nextHs.IsLeftDomPoint()){
if(member){ // there is an overlapping segment in sss
if(member->getOwner()==owner ||
member->getOwner()==myavlseg::both ){
if(current.ininterior(member->getX2(),member->getY2())){
current.splitAt(member->getX2(),member->getY2(),left1,right1);
myinsertEvents(right1,true,true,q1,q2);
}
} else { // member and source come from difference sources
int parts = member->split(current,left1,common1,right1);
sss.remove(*member);
member = &common1;
if(parts & myavlseg::LEFT){
if(!left1.isPoint()){
sss.insert(left1);
myinsertEvents(left1,false,true,q1,q2);
}
}
assert(parts & myavlseg::COMMON);
if(owner==myavlseg::second) { // the region
if(current.getInsideAbove()){
common1.con_above++;
} else {
common1.con_above--;
}
} // for a line is nothing to do
if(!common1.isPoint()){
sss.insert(common1);
myinsertEvents(common1,false,true,q1,q2);
}
if(parts & myavlseg::RIGHT){
myinsertEvents(right1,true,true,q1,q2);
}
}
} else { // no overlapping segment in sss found
MysplitByNeighbour(sss,current,leftN,q1,q2);
MysplitByNeighbour(sss,current,rightN,q1,q2);
// update coverage numbers
if(owner==myavlseg::second){ // the region
bool iac = current.getInsideAbove();
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;
}
}
} else { // the line
if(leftN){
if(leftN->isVertical()){
current.con_below = leftN->con_below;
} else {
current.con_below = leftN->con_above;
}
}
current.con_above = current.con_below;
}
// insert element
if(!current.isPoint()){
sss.insert(current);
myinsertEvents(current,false,true,q1,q2);
}
}
} else { // nextHs.IsRightDomPoint()
if(member && member->exactEqualsTo(current)){
switch(op){
case myavlseg::intersection_op: {
if( (member->getOwner()==myavlseg::both) ||
(member->getOwner()==myavlseg::first && member->con_above>0)){
HalfSegment hs1 = member->convertToHs(true,myavlseg::first);
hs1.attr.edgeno = edgeno;
result += hs1;
hs1.SetLeftDomPoint(false);
result += hs1;
edgeno++;
}
break;
}
case myavlseg::difference_op: {
if( (member->getOwner()==myavlseg::first) &&
(member->con_above==0)){
HalfSegment hs1 = member->convertToHs(true,myavlseg::first);
hs1.attr.edgeno = edgeno;
result += hs1;
hs1.SetLeftDomPoint(false);
result += hs1;
edgeno++;
}
break;
}
default : assert(false);
}
sss.remove(*member);
MysplitNeighbours(sss,leftN,rightN,q1,q2);
}
if(pos1>=size1 && q1.empty()){ // line is processed
done = true;
}
}
}
result.EndBulkLoad();
} // setOP(line x region -> line)
void MyIntersection(const Line& l1, const Line& l2, Line& result)
{
MySetOp(l1, l2, result, myavlseg::intersection_op);
}
/*
Intersection, union and minus between two lines
*/
void MySetOp(const Line& line1,
const Line& line2,
Line& result,
myavlseg::SetOperation op){
result.Clear();
if(!line1.IsDefined() || !line2.IsDefined()){
result.SetDefined(false);
return;
}
result.SetDefined(true);
if(line1.Size()==0){
switch(op){
case myavlseg::union_op : result = line2;
return;
case myavlseg::intersection_op : return; // empty line
case myavlseg::difference_op : return; // empty line
default : assert(false);
}
}
if(line2.Size()==0){
switch(op){
case myavlseg::union_op: result = line1;
return;
case myavlseg::intersection_op: return;
case myavlseg::difference_op: result = line1;
return;
default : assert(false);
}
}
priority_queue<HalfSegment, vector<HalfSegment>, greater<HalfSegment> > q1;
priority_queue<HalfSegment, vector<HalfSegment>, 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(line1,pos1,
line2,pos2,
q1,q2,nextHs,src))!= myavlseg::none){
myavlseg::MyAVLSegment current(nextHs,owner);
member = sss.getMember(current,leftN,rightN);
if(leftN){
tmpL = *leftN;
leftN = &tmpL;
}
if(rightN){
tmpR = *rightN;
rightN = &tmpR;
}
if(nextHs.IsLeftDomPoint()){
if(member){ // found an overlapping segment
if(member->getOwner()==current.getOwner() ||
member->getOwner()== myavlseg::both){ // same source
double xm = member->getX2();
double xc = current.getX2();
if(!AlmostEqual(xm,xc) && (xm<xc)){ // current extends member
current.splitAt(xm,member->getY2(),left1,right1);
myinsertEvents(right1,true,true,q1,q2);
}
} else { // member and current come from different sources
int parts = member->split(current,left1,common1,right1);
sss.remove(*member);
member = &common1;
if(parts & myavlseg::LEFT){
if(!left1.isPoint()){
sss.insert(left1);
myinsertEvents(left1,false,true,q1,q2);
}
}
assert(parts & myavlseg::COMMON);
if(!common1.isPoint()){
sss.insert(common1);
myinsertEvents(common1,false,true,q1,q2);
}
if(parts & myavlseg::RIGHT){
myinsertEvents(right1,true,true,q1,q2);
}
}
} else { // no overlapping segment found
MysplitByNeighbour(sss,current,leftN,q1,q2);
MysplitByNeighbour(sss,current,rightN,q1,q2);
if(!current.isPoint()){
sss.insert(current);
myinsertEvents(current,false,true,q1,q2);
}
}
} else { // nextHS rightDomPoint
if(member && member->exactEqualsTo(current)){
// insert the segments into the result
switch(op){
case myavlseg::union_op : {
HalfSegment hs1 = member->convertToHs(true,myavlseg::first);
hs1.attr.edgeno = edgeno;
result += hs1;
hs1.SetLeftDomPoint(false);
result += hs1;
edgeno++;
break;
} case myavlseg::intersection_op : {
if(member->getOwner()== myavlseg::both){
HalfSegment hs1 =
member->convertToHs(true, myavlseg::first);
hs1.attr.edgeno = edgeno;
result += hs1;
hs1.SetLeftDomPoint(false);
result += hs1;
edgeno++;
}
break;
} case myavlseg::difference_op :{
if(member->getOwner()== myavlseg::first){
HalfSegment hs1 =
member->convertToHs(true, myavlseg::first);
hs1.attr.edgeno = edgeno;
result += hs1;
hs1.SetLeftDomPoint(false);
result += hs1;
edgeno++;
}
break;
} default : {
assert(false);
}
}
sss.remove(*member);
MysplitNeighbours(sss,leftN,rightN,q1,q2);
}
}
}
result.EndBulkLoad(true,false);
} // setop line x line -> line
/*
correct version of detecting the intersects of two halfsegments
*/
bool MyHSIntersects(const HalfSegment* hs1, const HalfSegment* hs2)
{
double k, a, K, A;
if( !hs1->BoundingBox().Intersects( hs2->BoundingBox() ) )
return false;
Coord xl = hs1->GetLeftPoint().GetX(),
yl = hs1->GetLeftPoint().GetY(),
xr = hs1->GetRightPoint().GetX(),
yr = hs1->GetRightPoint().GetY(),
Xl = hs2->GetLeftPoint().GetX(),
Yl = hs2->GetLeftPoint().GetY(),
Xr = hs2->GetRightPoint().GetX(),
Yr = hs2->GetRightPoint().GetY();
if( AlmostEqual( xl, xr ) &&
AlmostEqual( Xl, Xr ) )
// both segments are vertical
{
if( AlmostEqual( xl, Xl ) &&
( AlmostEqual( yl, Yl ) || AlmostEqual( yl, Yr ) ||
AlmostEqual( yr, Yl ) || AlmostEqual( yr, Yr ) ||
( yl > Yl && yl < Yr ) || ( yr > Yl && yr < Yr ) ||
( Yl > yl && Yl < yr ) || ( Yr > yl && Yr < yr ) ) )
return true;
return false;
}
if( !AlmostEqual( xl, xr ) )
// this segment is not vertical
{
k = (yr - yl) / (xr - xl);
a = yl - k * xl;
}
if( !AlmostEqual( Xl, Xr ) )
// hs is not vertical
{
K = (Yr - Yl) / (Xr - Xl);
A = Yl - K * Xl;
}
if( AlmostEqual( Xl, Xr ) )
//only hs is vertical
{
Coord y0 = k * Xl + a;
if( ( Xl > xl || AlmostEqual( Xl, xl ) ) &&
( Xl < xr || AlmostEqual( Xl, xr ) ) )
{
if( ( ( y0 > Yl || AlmostEqual( y0, Yl ) ) &&
( y0 < Yr || AlmostEqual( y0, Yr ) ) ) ||
( ( y0 > Yr || AlmostEqual( y0, Yr ) ) &&
( y0 < Yl || AlmostEqual( y0, Yl ) ) ) )
// (Xl, y0) is the intersection point
return true;
}
return false;
}
if( AlmostEqual( xl, xr ) )
// only this segment is vertical
{
Coord Y0 = K * xl + A;
if( ( xl > Xl || AlmostEqual( xl, Xl ) ) &&
( xl < Xr || AlmostEqual( xl, Xr ) ) )
{
if( ( ( Y0 > yl || AlmostEqual( Y0, yl ) ) &&
( Y0 < yr || AlmostEqual( Y0, yr ) ) ) ||
( ( Y0 > yr || AlmostEqual( Y0, yr ) ) &&
( Y0 < yl || AlmostEqual( Y0, yl ) ) ) )
// (xl, Y0) is the intersection point
return true;
}
return false;
}
// both segments are non-vertical
if( AlmostEqual( k, K ) )
// both segments have the same inclination
{
/*the original halfsegment::intersects function has a small bug, see
if( AlmostEqual( A, a ) &&
( ( xl > Xl || AlmostEqual( xl, Xl ) ) &&
( xl < Xr || AlmostEqual( xl, Xr ) ) ) ||
( ( Xl > xl || AlmostEqual( xl, Xl ) ) &&
( Xl < xr || AlmostEqual( xr, Xl ) ) ) ){
return true;
}
it should be
if( AlmostEqual( A, a ) &&
(( ( xl > Xl || AlmostEqual( xl, Xl ) ) &&
( xl < Xr || AlmostEqual( xl, Xr ) ) ) ||
( ( Xl > xl || AlmostEqual( xl, Xl ) ) &&
( Xl < xr || AlmostEqual( xr, Xl ) ) )) ){
return true;
}*/
if( AlmostEqual( A, a ) &&
(( ( xl > Xl || AlmostEqual( xl, Xl ) ) &&
( xl < Xr || AlmostEqual( xl, Xr ) ) ) ||
( ( Xl > xl || AlmostEqual( xl, Xl ) ) &&
( Xl < xr || AlmostEqual( xr, Xl ) ) )) )
// the segments are in the same straight line
return true;
}
else
{
Coord x0 = (A - a) / (k - K);
// y0 = x0 * k + a;
if( ( x0 > xl || AlmostEqual( x0, xl ) ) &&
( x0 < xr || AlmostEqual( x0, xr ) ) &&
( x0 > Xl || AlmostEqual( x0, Xl ) ) &&
( x0 < Xr || AlmostEqual( x0, Xr ) ) )
// the segments intersect at (x0, y0)
return true;
}
return false;
}
/*
detect whether two regions intersect, by the correct intersection function
between two halfsegments
*/
bool MyRegIntersects(const Region* reg1, const Region* reg2)
{
assert( reg1->IsDefined() );
assert( reg2->IsDefined() );
if( reg1->IsEmpty() || reg2->IsEmpty() )
return false;
if( !reg1->BoundingBox().Intersects( reg2->BoundingBox() ) )
return false;
assert( reg1->IsOrdered() );
assert( reg2->IsOrdered() );
if( reg1->Inside( *reg2 ) || reg2->Inside( *reg1 ) )
return true;
HalfSegment hs1, hs2;
for( int i = 0; i < reg1->Size(); i++ )
{
reg1->Get( i, hs1 );
if( hs1.IsLeftDomPoint() )
{
for( int j = 0; j < reg2->Size(); j++ )
{
reg2->Get( j, hs2 );
if( hs2.IsLeftDomPoint() &&
MyHSIntersects(&hs1, &hs2))
return true;
}
}
}
return false;
}
/*
It checks wheter the region contains the halfsegment.
for the intersection point which is not the endpoint of the halfsegment, it
should also check the middle point.
*/
bool RegContainHS(Region* r, HalfSegment hs)
{
BBox<2> bbox = r->BoundingBox();
if( !hs.GetLeftPoint().Inside(bbox) ||
!hs.GetRightPoint().Inside(bbox) )
return false;
if( !r->Contains(hs.GetLeftPoint()) ||
!r->Contains(hs.GetRightPoint()) )
return false;
HalfSegment auxhs;
bool checkMidPoint = false;
vector<Point> intersection_points;
//now we know that both endpoints of hs is inside region
for( int i = 0; i < r->Size(); i++ ){
r->Get(i, auxhs);
if( auxhs.IsLeftDomPoint() ){
if( hs.Crosses(auxhs) ){
return false;
}
else if( hs.Inside(auxhs) )
//hs is part of the border
return true;
else if( hs.Intersects(auxhs)){
if(auxhs.Contains(hs.GetLeftPoint()) ||
auxhs.Contains(hs.GetRightPoint()) ||
hs.Contains(auxhs.GetLeftPoint()) ||
hs.Contains(auxhs.GetRightPoint())){
checkMidPoint = true;
//the intersection point that is not the endpoint
Point temp_p;
if(hs.Intersection(auxhs,temp_p))
intersection_points.push_back(temp_p);
HalfSegment temp_hs;
if(hs.Intersection(auxhs, temp_hs)){
intersection_points.push_back(temp_hs.GetLeftPoint());
intersection_points.push_back(temp_hs.GetRightPoint());
}
}
}
}
}
if( checkMidPoint )
{
Point midp( true,
( hs.GetLeftPoint().GetX() + hs.GetRightPoint().GetX() ) / 2,
( hs.GetLeftPoint().GetY() + hs.GetRightPoint().GetY() ) / 2 );
if( !r->Contains( midp ) )
return false;
}
// cout<<"hs "<<hs<<endl;
for(unsigned int i = 0;i < intersection_points.size();i++){
Point p = intersection_points[i];
double x1 = (hs.GetLeftPoint().GetX() + p.GetX())/2;
double y1 = (hs.GetLeftPoint().GetY() + p.GetY())/2;
double x2 = (hs.GetRightPoint().GetX() + p.GetX())/2;
double y2 = (hs.GetRightPoint().GetY() + p.GetY())/2;
Point midp1(true, x1, y1);
Point midp2(true, x2, y2);
// cout<<"midp1 "<<midp1<<" midp2 "<<midp2<<endl;
if(!r->Contains(midp1)) return false;
if(!r->Contains(midp2)) return false;
}
return true;
}
/*
it checks whether a line is inside a region
*/
bool MyInside(Line* l, Region* r)
{
if(l->IsEmpty()) return false;
if(r->IsEmpty()) return false;
if(!r->BoundingBox().Contains(l->BoundingBox()))
return false;
assert(l->IsOrdered());
assert(r->IsOrdered());
for(int i = 0;i < l->Size();i++){
HalfSegment hs;
l->Get(i, hs);
if(!hs.IsLeftDomPoint()) continue;
if(!RegContainHS(r, hs)) return false;
}
return true;
}
/*
The following is the implementation of structure for space partition
*/
/*
Default constructor function
*/
SpacePartition::SpacePartition()
{
l = NULL;
resulttype = NULL;
count = 0;
}
SpacePartition::SpacePartition(Relation* in_line):l(in_line),count(0){}
/*
take the input point as the center and delta as the radius
a line function represented by a and b
it returns the intersection point (only x value) for the circle and line
function
*/
void SpacePartition::GetDeviation(Point center, double a, double b,double& x1,
double& x2, int delta)
{
double x0 = center.GetX();
double y0 = center.GetY();
double A = 1 + a*a;
double B = 2*a*(b-y0)-2*x0;
// double C = x0*x0 + (b-y0)*(b-y0) - 1;
double C = x0*x0 + (b-y0)*(b-y0) - delta*delta;
x1 = (-B - sqrt(B*B-4*A*C))/(2*A);
x2 = (-B + sqrt(B*B-4*A*C))/(2*A);
}
/*
It checks whether the rotation from segment (p1-p0) to segment (p2-p0) is
counterclockwise or clockwise
TRUE--clockwise false--couterclockwise
we define if three points are collinear, it is counter-clockwise
*/
bool SpacePartition::GetClockwise(Point& p0,Point& p1, Point& p2)
{
double x0 = p0.GetX();
double y0 = p0.GetY();
double x1 = p1.GetX();
double y1 = p1.GetY();
double x2 = p2.GetX();
double y2 = p2.GetY();
bool result;
if(AlmostEqual(x0,x1)){
if(y1 >= y0){
// if(x2 < x0) result = false;
if(x2 < x0 || AlmostEqual(x2,x0)) result = false;
else result = true;
}else{
if(x2 < x0) result = true;
else result = false;
}
}else{
double slope = (y1-y0)/(x1-x0);
/* if(AlmostEqual(y1,y0))
slope = 0;
else
slope = (y1-y0)/(x1-x0);*/
double intercept = y1-slope*x1;
if(x1 < x0){
if(y2 < (slope*x2 + intercept)) result = false;
else result = true;
}else{
if(y2 < (slope*x2 + intercept)) result = true;
else result = false;
}
}
// if(result) cout<<"clockwise "<<endl;
// else cout<<"counterclokwise "<<endl;
return result;
}
/*
It gets the angle of the rotation from segment (p1-p0) to segment (p2-p0)
*/
double SpacePartition::GetAngle(Point& p0,Point& p1, Point& p2)
{
/////cosne theorem ///
double angle; //radian [0-pi]
double b = p0.Distance(p1);
double c = p0.Distance(p2);
double a = p1.Distance(p2);
assert(AlmostEqual(b*c,0.0) == false);
double value = (b*b+c*c-a*a)/(2*b*c);
if(AlmostEqual(value,-1.0)) value = -1;
if(AlmostEqual(value,1.0)) value = 1;
angle = acos(value);
// cout<<"angle "<<angle<<" degree "<<angle*180.0/pi<<endl;
assert(0.0 <= angle && angle <= 3.1416);
return angle;
}
/*
Given a halfsegment, transfer it by a deviation (delta) to the left or right
side (up or down), determined by clockflag.
Put the transfered halfsegment into structure boundary
for example, (2, 2)--(3, 2), delta = 1
it return (2, 1)---(3,1) or (2,3)--(3,3)
*/
void SpacePartition::TransferSegment(MyHalfSegment& mhs,
vector<MyHalfSegment>& boundary, int delta, bool clock_flag)
{
Point from = mhs.GetLeftPoint();
Point to = mhs.GetRightPoint();
Point next_from1;
Point next_to1;
Point p1,p2,p3,p4;
if(AlmostEqual(from.GetX(),to.GetX())){
p1.Set(from.GetX() - delta,from.GetY());
p2.Set(from.GetX() + delta,from.GetY());
p3.Set(to.GetX() - delta, to.GetY());
p4.Set(to.GetX() + delta, to.GetY());
}
else if(AlmostEqual(from.GetY(), to.GetY())){
p1.Set(from.GetX(), from.GetY() - delta);
p2.Set(from.GetX(), from.GetY() + delta);
p3.Set(to.GetX(), to.GetY() - delta);
p4.Set(to.GetX(), to.GetY() + delta);
}else{
double k1 = (from.GetY() - to.GetY())/(from.GetX() - to.GetX());
double k2 = -1/k1;
double b1 = from.GetY() - k2*from.GetX();
double x1,x2;
GetDeviation(from,k2,b1,x1,x2,delta);
double y1 = x1*k2 + b1;
double y2 = x2*k2 + b1;
double x3,x4;
double b2 = to.GetY() - k2*to.GetX();
GetDeviation(to,k2,b2,x3,x4,delta);
double y3 = x3*k2 + b2;
double y4 = x4*k2 + b2;
p1.Set(x1,y1);
p2.Set(x2,y2);
p3.Set(x3,y3);
p4.Set(x4,y4);
// cout<<"k1: "<<k1<<" k2: "<<k2<<endl;
// cout<<p3<<" "<<p4<<endl;
}
vector<Point> clock_wise;
vector<Point> counterclock_wise;
if(GetClockwise(from,to,p1)) clock_wise.push_back(p1);
else counterclock_wise.push_back(p1);
if(GetClockwise(from,to,p2)) clock_wise.push_back(p2);
else counterclock_wise.push_back(p2);
if(GetClockwise(from,to,p3)) clock_wise.push_back(p3);
else counterclock_wise.push_back(p3);
if(GetClockwise(from,to,p4)) clock_wise.push_back(p4);
else counterclock_wise.push_back(p4);
// cout<<"clock size "<<clock_wise.size()
// <<" counter clock size "<<counterclock_wise.size()<<endl;
// cout<<"from "<<from<<" to "<<to
// <<" p1 "<<p1<<" p2 "<<p2<<" p3 "<<p3<<" p4 "<<p4<<endl;
/* if(!(clock_wise.size() == 2 && counterclock_wise.size() == 2)){
cout<<"from "<<from<<" to "<<to<<endl;
cout<<" p1 "<<p1<<" p2 "<<p2<<" p3 "<<p3<<" p4 "<<p4<<endl;
}*/ ////////// y value of two points are too close
assert(clock_wise.size() == 2 && counterclock_wise.size() == 2);
if(clock_flag){
next_from1 = clock_wise[0];
next_to1 = clock_wise[1];
}else{
next_from1 = counterclock_wise[0];
next_to1 = counterclock_wise[1];
}
MyHalfSegment* seg = new MyHalfSegment(true,next_from1,next_to1);
boundary.push_back(*seg);
delete seg;
}
/*
Add one segment to line, but change the point value to int
*/
void SpacePartition::AddHalfSegmentResult(MyHalfSegment hs, Line* res,
int& edgeno)
{
const double delta_dist = 0.1;
double a1,b1,a2,b2;
int x1,y1,x2,y2;
a1 = hs.GetLeftPoint().GetX();
b1 = hs.GetLeftPoint().GetY();
a2 = hs.GetRightPoint().GetX();
b2 = hs.GetRightPoint().GetY();
x1 = static_cast<int>(GetCloser(a1));
y1 = static_cast<int>(GetCloser(b1));
x2 = static_cast<int>(GetCloser(a2));
y2 = static_cast<int>(GetCloser(b2));
HalfSegment hs2;
Point p1,p2;
p1.Set(x1,y1);
p2.Set(x2,y2);
if(p1.Distance(p2) > delta_dist){//////////////final check
hs2.Set(true,p1,p2);
hs2.attr.edgeno = edgeno++;
*res += hs2;
hs2.SetLeftDomPoint(!hs2.IsLeftDomPoint());
*res += hs2;
}
}
/*
for the given line stored in segs, it gets its left or right side line after
transfer by a deviation given by delta
*/
void SpacePartition::Gettheboundary(vector<MyHalfSegment>& segs,
vector<MyHalfSegment>& boundary, int delta,
bool clock_wise)
{
const double delta_dist = 0.1;
for(unsigned int i = 0;i < segs.size();i++){
TransferSegment(segs[i], boundary, delta, clock_wise);
}
//////// connect the new boundary ////////////////////////
for(unsigned int i = 0;i < boundary.size() - 1; i++){
Point p1_1 = boundary[i].GetLeftPoint();
Point p1_2 = boundary[i].GetRightPoint();
Point p2_1 = boundary[i+1].GetLeftPoint();
Point p2_2 = boundary[i+1].GetRightPoint();
// cout<<p1_1<<" "<<p1_2<<" "<<p2_1<<" "<<p2_2<<endl;
if(p1_2.Distance(p2_1) < delta_dist) continue;
if(AlmostEqual(p1_1.GetX(),p1_2.GetX())){
assert(!AlmostEqual(p2_1.GetX(),p2_2.GetX()));
double a2 = (p2_2.GetY()-p2_1.GetY()) /(p2_2.GetX()-p2_1.GetX());
double b2 = p2_2.GetY() - a2*p2_2.GetX();
double x = p1_1.GetX();
double y = a2*x + b2;
boundary[i].to.Set(x,y);
boundary[i+1].from.Set(x,y);
}else{
if(AlmostEqual(p2_1.GetX(),p2_2.GetX())){
assert(!AlmostEqual(p1_1.GetX(),p1_2.GetX()));
double a1 = (p1_2.GetY()-p1_1.GetY()) /(p1_2.GetX()-p1_1.GetX());
double b1 = p1_2.GetY() - a1*p1_2.GetX();
double x = p2_1.GetX();
double y = a1*x + b1;
boundary[i].to.Set(x,y);
boundary[i+1].from.Set(x,y);
}else{
double a1 = (p1_2.GetY()-p1_1.GetY()) /(p1_2.GetX()-p1_1.GetX());
double b1 = p1_2.GetY() - a1*p1_2.GetX();
double a2 = (p2_2.GetY()-p2_1.GetY()) /(p2_2.GetX()-p2_1.GetX());
double b2 = p2_2.GetY() - a2*p2_2.GetX();
// assert(!AlmostEqual(a1,a2));
// cout<<"a1 "<<a1<<" a2 "<<a2<<endl;
if(AlmostEqual(a1,a2)) assert(AlmostEqual(b1,b2));
double x = (b2-b1)/(a1-a2);
double y = a1*x + b1;
////////////process speical case angle too small////////////
Point q1;
q1.Set(x,y);
Point q2 = segs[i].GetRightPoint();
if(q1.Distance(q2) > 5*delta){//reason: two roads points (y) too close
// cout<<"special case: (needs to be processed)"<<endl;
// cout<<"q1 "<<q1<<" q2 "<<q2<<endl;
// assert(false);
}
/////////////////////////////////////////////////////
boundary[i].to.Set(x,y);
boundary[i+1].from.Set(x,y);
}
// cout<<boundary[i].to<<" "<<boundary[i+1].from<<endl;
}// end if
}//end for
}
/*
For the given line, it gets all the points forming its boundary where delta
defines the deviation of the left or right side line for transfer.
outer does not include points from road, but outerhalf includes
It is to create the region for road
*/
void SpacePartition::ExtendSeg1(vector<MyHalfSegment>& segs,int delta,
bool clock_wise,
vector<Point>& outer, vector<Point>& outer_half)
{
const double delta_dist = 0.1;
for(unsigned int i = 0;i < segs.size();i++){
// cout<<"start "<<segs[i].GetLeftPoint()<<" to "
// <<segs[i].GetRightPoint()<<endl;
if(i < segs.size() - 1){
Point to1 = segs[i].GetRightPoint();
Point from2 = segs[i+1].GetLeftPoint();
assert(to1.Distance(from2) < delta_dist);
}
}
vector<MyHalfSegment> boundary;
Gettheboundary(segs, boundary, delta, clock_wise);
///////////////////////add two more segments ///////////////////////
Point old_start = segs[0].GetLeftPoint();
Point old_end = segs[segs.size() - 1].GetRightPoint();
Point new_start = boundary[0].GetLeftPoint();
Point new_end = boundary[boundary.size() - 1].GetRightPoint();
MyHalfSegment* mhs = new MyHalfSegment(true, old_start, new_start);
boundary.push_back(*mhs);
for(int i = boundary.size() - 2; i >= 0;i --)
boundary[i+1] = boundary[i];
boundary[0] = *mhs;
delete mhs;
mhs = new MyHalfSegment(true,new_end,old_end);
boundary.push_back(*mhs);
delete mhs;
if(clock_wise){
for(unsigned int i = 0;i < boundary.size();i++){
///////////////outer segments////////////////////////////////
Point p = boundary[i].GetLeftPoint();
ModifyPoint(p);
if(i == 0){
outer.push_back(boundary[i].GetLeftPoint());
outer_half.push_back(boundary[i].GetLeftPoint());
}
else{
outer.push_back(p);
outer_half.push_back(p);
}
}
for(int i = segs.size() - 1; i >= 0; i--)
outer_half.push_back(segs[i].GetRightPoint());
}else{
for(unsigned int i = 0; i < segs.size(); i++)
outer_half.push_back(segs[i].GetLeftPoint());
for(int i = boundary.size() - 1;i >= 0;i--){
/////////////////////////////////////////////////////////////
Point p = boundary[i].GetRightPoint();
ModifyPoint(p);
/////////////////////////////////////////////////////////////
if((unsigned)i == boundary.size() - 1){
outer.push_back(boundary[i].GetRightPoint());
outer_half.push_back(boundary[i].GetRightPoint());
}else{
outer.push_back(p);
outer_half.push_back(p);
}
}
}
}
/*
For the given line, it gets all the points forming its boundary where delta
defines the deviation of the left or right side line for transfer.
It is to create the region covering both road and pavement so that the original
road line is not used. This region is larger than the one created by function
ExtendSeg1 because it contains pavements.
*/
void SpacePartition::ExtendSeg2(vector<MyHalfSegment>& segs,int delta,
bool clock_wise, vector<Point>& outer)
{
const double delta_dist = 0.1;
for(unsigned int i = 0;i < segs.size();i++){
// cout<<"start "<<segs[i].GetLeftPoint()<<" to "
// <<segs[i].GetRightPoint()<<endl;
if(i < segs.size() - 1){
Point to1 = segs[i].GetRightPoint();
Point from2 = segs[i+1].GetLeftPoint();
assert(to1.Distance(from2) < delta_dist);
}
}
vector<MyHalfSegment> boundary;
Gettheboundary(segs, boundary, delta, clock_wise);
///////////////////////add two more segments ///////////////////////
Point old_start = segs[0].GetLeftPoint();
Point old_end = segs[segs.size() - 1].GetRightPoint();
Point new_start = boundary[0].GetLeftPoint();
Point new_end = boundary[boundary.size() - 1].GetRightPoint();
MyHalfSegment* mhs = new MyHalfSegment(true,old_start,new_start);
boundary.push_back(*mhs);
for(int i = boundary.size() - 2; i >= 0;i --)
boundary[i+1] = boundary[i];
boundary[0] = *mhs;
delete mhs;
mhs = new MyHalfSegment(true,new_end,old_end);
boundary.push_back(*mhs);
delete mhs;
if(clock_wise){
for(unsigned int i = 0;i < boundary.size();i++){
///////////////outer segments////////////////////////////////
Point p = boundary[i].GetLeftPoint();
ModifyPoint(p);
/////////////////////////////////////////////////////////
if(i == 0){
outer.push_back(boundary[i].GetLeftPoint());
}
else{
outer.push_back(p);
}
}
}else{
for(int i = boundary.size() - 1;i >= 0;i--){
/////////////////////////////////////////////////////////////
Point p = boundary[i].GetRightPoint();
ModifyPoint(p);
/////////////////////////////////////////////////////////////
if((unsigned)i == boundary.size() - 1){
outer.push_back(boundary[i].GetRightPoint());
}else{
outer.push_back(p);
}
}
}
}
/*
For the given line, it gets all the points forming its boundary where delta
defines the deviation of the left or right side line for transfer.
*/
void SpacePartition::ExtendSeg3(vector<MyHalfSegment>& segs,int delta,
bool clock_wise, vector<Point>& outer)
{
const double delta_dist = 0.1;
for(unsigned int i = 0;i < segs.size();i++){
// cout<<"start "<<segs[i].GetLeftPoint()<<" to "
// <<segs[i].GetRightPoint()<<endl;
if(i < segs.size() - 1){
Point to1 = segs[i].GetRightPoint();
Point from2 = segs[i+1].GetLeftPoint();
assert(to1.Distance(from2) < delta_dist);
}
}
// cout<<"segs size "<<segs.size()<<endl;
vector<MyHalfSegment> boundary;
Gettheboundary(segs, boundary, delta, clock_wise);
// cout<<"boundary size "<<boundary.size()<<endl;
for(unsigned int i = 0;i < boundary.size();i++){
///////////////outer segments////////////////////////////////
Point p = boundary[i].GetLeftPoint();
outer.push_back(p);
}
outer.push_back(boundary[boundary.size() - 1].GetRightPoint());
// cout<<"outer size "<<outer.size()<<endl;
}
/*
for the given line, order it in such a way that segi.to = seg{i+1}.from
store the result in vector<MyHalfSegment>, with higher precision
*/
void SpacePartition::ReorderLine(SimpleLine* sline,
vector<MyHalfSegment>& seq_halfseg)
{
if(!(sline->Size() > 0)){
cout<<__FILE__<<" "<<__LINE__<<" line empty "<<endl;
assert(false);
}
Point sp;
assert(sline->AtPosition(0.0,true,sp));
vector<MyHalfSegment> copyline;
for(int i = 0;i < sline->Size();i++){
HalfSegment hs;
sline->Get(i,hs);
if(hs.IsLeftDomPoint()){
Point lp = hs.GetLeftPoint();
Point rp = hs.GetRightPoint();
MyHalfSegment* mhs = new MyHalfSegment(true,lp,rp);
copyline.push_back(*mhs);
delete mhs;
}
}
////////////////reorder /////////////////////////////////////
/*for(unsigned i = 0;i < copyline.size();i++)
copyline[i].Print();*/
const double delta_dist = 0.00001;
unsigned int count = 0;
while(count < copyline.size()){
vector<int> pos;
vector<double> dist;
for(unsigned int index = 0;index < copyline.size();index++){
if(copyline[index].def == false)continue;
Point lp = copyline[index].GetLeftPoint();
Point rp = copyline[index].GetRightPoint();
double d1 = lp.Distance(sp);
double d2 = rp.Distance(sp);
if(d1 > delta_dist && d2 > delta_dist)
continue;
if(d1 < delta_dist){
pos.push_back(index);
dist.push_back(d1);
}
if(d2 < delta_dist){
pos.push_back(index);
dist.push_back(d2);
}
}
assert(pos.size() > 0 && dist.size() > 0);
double threshold_dist = numeric_limits<double>::max();
int pos_index = -1;
for(unsigned int i = 0;i < dist.size();i++){
if(dist[i] < threshold_dist){
pos_index = i;
threshold_dist = dist[i];
}
}
assert(pos_index != -1);
int find_pos = pos[pos_index];
Point from = copyline[find_pos].GetLeftPoint();
Point to = copyline[find_pos].GetRightPoint();
double dist1 = from.Distance(sp);
double dist2 = to.Distance(sp);
assert(dist1 < delta_dist || dist2 < delta_dist);
if(dist1 < dist2){
sp = to;
count++;
copyline[find_pos].def = false;
MyHalfSegment* mhs = new MyHalfSegment(true,from,to);
seq_halfseg.push_back(*mhs);
delete mhs;
continue;
}else{
sp = from;
count++;
copyline[find_pos].def = false;
MyHalfSegment* mhs = new MyHalfSegment(true,to,from);
seq_halfseg.push_back(*mhs);
delete mhs;
continue;
}
assert(false);
}
}
/*
for the given set of ordered points, it creates a region
*/
bool SpacePartition::CheckRegionPS(vector<Point>& outer_region)
{
////////////whether two points are equal or segments overlapping ////
if(outer_region.size() < 3){
return false;
}
//assert(outer_region.size() >= 3);
vector<bool> flag_list;
vector<Point> ps_list;
for(unsigned int i = 0;i < outer_region.size();i++){
flag_list.push_back(true);
ps_list.push_back(outer_region[i]);
}
for(unsigned int i = 0;i < outer_region.size() - 2;i++){
unsigned int j = i + 1;
unsigned int k = j + 1;
Point p1 = outer_region[i];
Point p2 = outer_region[j];
Point p3 = outer_region[k];
// cout<<"p1 "<<p1<<" p2 "<<p2<<" p3 "<<p3<<endl;
// HalfSegment hs1(true, p1, p2);
// HalfSegment hs2(true, p2, p3);
// HalfSegment hs_res;
// if(hs1.Intersection(hs2, hs_res)){
// if(hs_res.Length() > 0.0)
// cout<<"wrong overlapping segment"<<endl;
// }
if(!AlmostEqual(p1,p2) && !AlmostEqual(p2,p3)){
HalfSegment hs1(true, p1, p2);
HalfSegment hs2(true, p2, p3);
HalfSegment hs_res;
if(hs1.Intersection(hs2, hs_res)){
if(hs_res.Length() > 0.0){
// cout<<"wrong overlapping segments"<<endl;//delete p2
// cout<<hs1<<" "<<hs2<<endl;
flag_list[j] = false;
}
}
}
}
outer_region.clear();
for(unsigned int i = 0;i < ps_list.size();i++){
if(flag_list[i]){
outer_region.push_back(ps_list[i]);
}
}
//////////////////////////////////////////////////
/////////check crossing segment//////////////////
/////////////////////////////////////////////////
vector<MyHalfSegment> mhs;
for(unsigned int i = 0;i < outer_region.size() - 1;i++){
Point from = outer_region[i];
unsigned int j = i + 1;
while(j < outer_region.size()){
Point to = outer_region[j];
if(!AlmostEqual(from, to)){
MyHalfSegment my_hs(true, from, to);
mhs.push_back(my_hs);
break;
}else
j++;
}
}
// cout<<"mhs size "<<mhs.size()<<endl;
for(unsigned int i = 0;i < mhs.size() - 2;i++){
unsigned int j = i + 1;
unsigned int k = j + 1;
// cout<<"i "<<i<<" k "<<k<<endl;
HalfSegment hs1(true, mhs[i].from, mhs[i].to);
HalfSegment hs2(true, mhs[k].from, mhs[k].to);
if(hs1.Crosses(hs2)){
// cout<<"crossing segments"<<endl;
// cout<<"hs1 "<<hs1<<" hs2 "<<hs2<<endl;
Point res;
assert(hs1.Intersection(hs2,res));
if(res.IsDefined()){
mhs[i].to = res;
mhs[j].from = mhs[j].to = res;
mhs[k].from = res;
i++;
}
}
}
////////////////////////////////////////////////////////////
////////////debuging, detecting/////////////////////////////
////////////delete roundant segment////////////////////////
///////////////////////////////////////////////////////////
// vector<MyHalfSegment> temp_mhs;
// for(unsigned int i = 0;i < mhs.size() - 1;i++){
// unsigned int j = i + 1;
// if(j == mhs.size()) break;
// if(AlmostEqual(mhs[i].from, mhs[j].from) &&
// AlmostEqual(mhs[i].to, mhs[j].to)){
// cout<<"wrong"<<endl;
// cout<<mhs[i].from<<" "<<mhs[i].to<<endl;
// cout<<mhs[j].from<<" "<<mhs[j].to<<endl;
// temp_mhs.push_back(mhs[i]);
// i++;
// }else{
// temp_mhs.push_back(mhs[i]);
// temp_mhs.push_back(mhs[j]);
// }
//
// }
// mhs.clear();
// for(unsigned int i = 0;i < temp_mhs.size();i++)
// mhs.push_back(temp_mhs[i]);
///////////////////////////////////////////////////////////
outer_region.clear();
for(unsigned int i = 0;i < mhs.size();i++){
if(i == 0)outer_region.push_back(mhs[i].from);
else{
Point last_p = outer_region[outer_region.size() - 1];
Point cur_p = mhs[i].from;
if(!AlmostEqual(last_p, cur_p)) outer_region.push_back(cur_p);
if(i == mhs.size() - 1){
last_p = outer_region[outer_region.size() - 1];
cur_p = mhs[i].to;
// if(!AlmostEqual(last_p,cur_p)) outer_region.push_back(cur_p);
if(!AlmostEqual(last_p, cur_p) &&
!AlmostEqual(outer_region[0], cur_p))//the first, the last
outer_region.push_back(cur_p);
}
}
}
// assert(outer_region.size() >= 3);
if(outer_region.size() >= 3) return true;
else return false;
}
/*
this function is called by operator segment2region.
It is to create the region for the road and pavement for each input route
w is defined as the deviation
*/
void SpacePartition::ExtendRoad(int attr_pos, int w)
{
if(w < 3){
cout<<"road width should be larger than 2"<<endl;
return;
}
for(int i = 1;i <= l->GetNoTuples();i++){
// Tuple* t = l->GetTuple(i);
Tuple* t = l->GetTuple(i,false);
SimpleLine* sline = (SimpleLine*)t->GetAttribute(attr_pos);
vector<MyHalfSegment> seq_halfseg; //reorder it from start to end
ReorderLine(sline, seq_halfseg);
int delta1;//width of road on each side, depend on the road length
int delta2;
delta1 = w;
int delta = w/2;
if(delta < 2) delta = 2;
delta2 = delta1 + delta;
vector<Point> outer_s;
vector<Point> outer1;
vector<Point> outer2;
vector<Point> outer4;
vector<Point> outer_l;
vector<Point> outer5;
assert(delta1 != delta2);
// cout<<"i "<<i<<endl;
// cout<<"small1"<<endl;
ExtendSeg1(seq_halfseg, delta1, true, outer_s,outer1);
// cout<<"large1"<<endl;
ExtendSeg2(seq_halfseg, delta2, true, outer_l);
/////////////////////////////////////////////////////////////
outer_l.push_back(outer_s[1]);
for(int j = outer_l.size() - 1;j > 0;j--)
outer_l[j] = outer_l[j-1];
outer_l[1] = outer_s[1];
outer_l.push_back(outer_s[outer_s.size() - 1]);
int point_count1 = outer_s.size();
int point_count2 = outer_l.size();
//////////////////paveroad--larger/////////////////////////////////
for(unsigned int j = 0;j < outer_l.size();j++)
outer4.push_back(outer_l[j]);
for(int j = seq_halfseg.size() - 1; j >= 0; j--)
outer4.push_back(seq_halfseg[j].GetRightPoint());
//////////////////////////////////////////////////////////
ExtendSeg1(seq_halfseg, delta1, false, outer_s, outer2);
ExtendSeg2(seq_halfseg, delta2, false,outer_l);
////////////////////////////////////////////////////////////
outer_l.push_back(outer_s[point_count1+1]);
for(int j = outer_l.size() - 1;j > point_count2;j--)
outer_l[j] = outer_l[j-1];
outer_l[point_count2 + 1] = outer_s[point_count1 + 1];
outer_l.push_back(outer_s[outer_s.size() - 1]);
//////////////////paveroad---larger////////////////////////////
for(unsigned int j = 0; j < seq_halfseg.size(); j++)
outer5.push_back(seq_halfseg[j].GetLeftPoint());
for(unsigned int j = point_count2; j < outer_l.size();j++)
outer5.push_back(outer_l[j]);
/////////////////////////////////////////////////////////////
t->DeleteIfAllowed();
/////////////get the boundary//////////////////
ComputeRegion(outer_s, outer_regions_s);
assert(outer_regions_s.size() > 0);
ComputeRegion(outer1, outer_regions1);
assert(outer_regions1.size() > 0);
ComputeRegion(outer2, outer_regions2);
assert(outer_regions2.size() > 0);
ComputeRegion(outer_l, outer_regions_l);
assert(outer_regions_l.size() > 0);
ComputeRegion(outer4, outer_regions4);
assert(outer_regions4.size() > 0);
ComputeRegion(outer5, outer_regions5);
assert(outer_regions5.size() > 0);
////////////////////////////////////////////////////////////////
///////////////////////debuging////////////////////////////////
///////////////////////////////////////////////////////////////
// Region* res1 = new Region(0);
// Region* res2 = new Region(0);
// int reg_id = outer_regions_s.size() - 1;
// outer_regions4[reg_id].Minus(outer_regions1[reg_id],*res1);
// outer_regions5[reg_id].Minus(outer_regions2[reg_id],*res2);
//
// delete res1;
// delete res2;
}
}
/*
cut the intersection region between pavement and road, especailly at junction
*/
void SpacePartition::ClipPaveRegion(Region& reg,
vector<Region>& paves,int rid, Region* inborder)
{
Region* comm_reg = new Region(0);
// reg.Intersection(*inborder,*comm_reg);
MyIntersection(reg,*inborder,*comm_reg);
Region* result = new Region(0);
// reg.Minus(*comm_reg,*result);
MyMinus(reg,*comm_reg,*result);
paves[rid - 1] = *result;
result->DeleteIfAllowed();
comm_reg->DeleteIfAllowed();
}
/*
fill the gap between two pavements at some junction positions
*/
void SpacePartition::FillPave(Network* n, vector<Region>& pavements1,
vector<Region>& pavements2,
vector<double>& routes_length,
vector<Region>& paves1, vector<Region>& paves2)
{
Relation* routes = n->GetRoutes();
Relation* juns = n->GetJunctions();
vector<MyJun> myjuns;
for(int i = 1;i <= n->GetNoJunctions();i++){
Tuple* jun_tuple = juns->GetTuple(i,false);
CcInt* rid1 = (CcInt*)jun_tuple->GetAttribute(JUNCTION_ROUTE1_ID);
CcInt* rid2 = (CcInt*)jun_tuple->GetAttribute(JUNCTION_ROUTE2_ID);
int id1 = rid1->GetIntval();
int id2 = rid2->GetIntval();
Point* junp = (Point*)jun_tuple->GetAttribute(JUNCTION_POS);
CcReal* meas1 = (CcReal*)jun_tuple->GetAttribute(JUNCTION_ROUTE1_MEAS);
CcReal* meas2 = (CcReal*)jun_tuple->GetAttribute(JUNCTION_ROUTE2_MEAS);
double len1 = meas1->GetRealval();
double len2 = meas2->GetRealval();
MyJun mj(*junp, id1, id2, len1, len2);
myjuns.push_back(mj);
jun_tuple->DeleteIfAllowed();
}
juns->Delete();
sort(myjuns.begin(), myjuns.end());
bool global_flag = false;
const double delta_dist = 0.1;
for(unsigned int i = 0 ;i < myjuns.size();i++){
Point loc = myjuns[i].loc;
int rid1 = myjuns[i].rid1;
int rid2 = myjuns[i].rid2;
// cout<<"rid1 "<<rid1<<" rid2 "<<rid2<<endl;
// if(!(rid1 == 2397 && rid2 == 2398)) continue;
if((MyAlmostEqual(myjuns[i].len1, 0.0)||
MyAlmostEqual(myjuns[i].len1, routes_length[rid1 - 1])) &&
(MyAlmostEqual(myjuns[i].len2, 0.0)||
MyAlmostEqual(myjuns[i].len2, routes_length[rid2 - 1]))){
vector<int> rids;
int j1 = i - 1;
while(j1 >= 0 && loc.Distance(myjuns[j1].loc) < delta_dist){
rids.push_back(myjuns[j1].rid1);
rids.push_back(myjuns[j1].rid2);
j1--;
}
unsigned int j2 = i;
while(j2 < myjuns.size() && loc.Distance(myjuns[j2].loc)< delta_dist){
rids.push_back(myjuns[j2].rid1);
rids.push_back(myjuns[j2].rid2);
j2++;
}
if(rids.size() == 2){
NewFillPavement3(routes, rid1, rid2, &loc,
pavements1, pavements2, rids, paves1, paves2);
}
if(rids.size() == 6){
NewFillPavement4(routes, rid1, rid2, &loc,
pavements1, pavements2, rids, paves1, paves2);
}
////////a special case for junction rid 2549--2550 ///////////////////
//////////////////for Berlin Network ////////////////////////////////
/////////////not so good, but it does not have to check every case////
if(rids.size() == 12 && global_flag == false){
bool flag1 = false;
bool flag2 = false;
for(unsigned int k1 = 0;k1 < rids.size();k1++){
if(rids[k1] == 2549) flag1 = true;
if(rids[k1] == 2550) flag2 = true;
}
if(flag1 && flag2){
/* for(unsigned int k1= 0; k1 < rids.size();k1++)
cout<<rids[k1]<<endl;*/
rids.clear();
rid1 = 2549;
rid2 = 2550;
rids.push_back(rid1);
rids.push_back(rid2);
NewFillPavement5(routes, rid1, rid2, &loc,
pavements1, pavements2, rids, paves1, paves2);
// cout<<"come here"<<endl;
global_flag = true;
}
}
////////////////////////////////////////////////////////////////
rids.clear();
}
}
}
/*
remove triangle area after cutting
*/
void SpacePartition::FilterDirtyRegion(vector<Region>& regs, Region* reg)
{
vector<Region> subregions;
int no_faces = reg->NoComponents();
// cout<<"no_faces "<<no_faces<<endl;
for(int i = 0;i < no_faces;i++){
Region* temp = new Region(0);
subregions.push_back(*temp);
temp->DeleteIfAllowed();
subregions[i].StartBulkLoad();
}
for(int i = 0;i < reg->Size();i++){
HalfSegment hs;
reg->Get(i,hs);
int face = hs.attr.faceno;
subregions[face] += hs;
}
for(int i = 0;i < no_faces;i++)
subregions[i].EndBulkLoad(false,false,false,false);
//////////////////////////new method//////////////////////////////
Region* result = new Region(0);
int count = 0;
for(unsigned int i = 0;i < subregions.size();i++){
// if(subregions[i].Size() <= 6 || subregions[i].Area() < 3.0)continue;
if(subregions[i].Size() <= 6 || fabs(subregions[i].Area()) < 3.0)continue;
Region* temp = new Region(0);
subregions[i].Union(*result, *temp);
*result = *temp;
temp->DeleteIfAllowed();
count++;
}
// cout<<"count "<<count<<endl;
assert(count <= no_faces);//faceno in halfsegment is not modified
result->SetNoComponents(count);
regs.push_back(*result);
result->DeleteIfAllowed();
}
/*
Create the pavement beside each road
*/
void SpacePartition::Getpavement(Network* n, Relation* rel1, int attr_pos,
Relation* rel2, int attr_pos1, int attr_pos2, int w)
{
//cut the pavement for each junction
vector<Region> pavements1;
vector<Region> pavements2;
Relation* routes = n->GetRoutes();
vector<double> routes_length;
for(int i = 1;i <= rel2->GetNoTuples();i++){
Tuple* tuple = rel2->GetTuple(i, false);
Region* reg1 = (Region*)tuple->GetAttribute(attr_pos1);
Region* reg2 = (Region*)tuple->GetAttribute(attr_pos2);
pavements1.push_back(Region(*reg1,false));
pavements2.push_back(Region(*reg2,false));
tuple->DeleteIfAllowed();
Tuple* route_tuple = routes->GetTuple(i, false);
CcReal* len = (CcReal*)route_tuple->GetAttribute(ROUTE_LENGTH);
double length = len->GetRealval();
route_tuple->DeleteIfAllowed();
routes_length.push_back(length);
}
//////////////////////////////////////////////////////////////
Relation* juns = n->GetJunctions();
for(int i = 1;i <= n->GetNoJunctions();i++){
Tuple* jun_tuple = juns->GetTuple(i, false);
CcInt* rid1 = (CcInt*)jun_tuple->GetAttribute(JUNCTION_ROUTE1_ID);
CcInt* rid2 = (CcInt*)jun_tuple->GetAttribute(JUNCTION_ROUTE2_ID);
int id1 = rid1->GetIntval();
int id2 = rid2->GetIntval();
// Point* junp = (Point*)jun_tuple->GetAttribute(JUNCTION_POS);
// if(!(id1 == 2043 || id2 == 2043)) {
// jun_tuple->DeleteIfAllowed();
// continue;
// }
// cout<<"rid1 "<<id1<<" rid2 "<<id2<<endl;
// CcReal* meas1 = (CcReal*)jun_tuple->GetAttribute(JUNCTION_ROUTE1_MEAS);
// CcReal* meas2 = (CcReal*)jun_tuple->GetAttribute(JUNCTION_ROUTE2_MEAS);
// double len1 = meas1->GetRealval();
// double len2 = meas2->GetRealval();
Region rid1_pave1 = pavements1[id1 - 1];
Region rid1_pave2 = pavements2[id1 - 1];
Region rid2_pave1 = pavements1[id2 - 1];
Region rid2_pave2 = pavements2[id2 - 1];
Tuple* inborder_tuple1 = rel1->GetTuple(id1, false);
Tuple* inborder_tuple2 = rel1->GetTuple(id2, false);
Region* reg1 = (Region*)inborder_tuple1->GetAttribute(attr_pos);
Region* reg2 = (Region*)inborder_tuple2->GetAttribute(attr_pos);
ClipPaveRegion(rid1_pave1,pavements1,id1,reg2);
ClipPaveRegion(rid1_pave2,pavements2,id1,reg2);
ClipPaveRegion(rid2_pave1,pavements1,id2,reg1);
ClipPaveRegion(rid2_pave2,pavements2,id2,reg1);
inborder_tuple1->DeleteIfAllowed();
inborder_tuple2->DeleteIfAllowed();
jun_tuple->DeleteIfAllowed();
}
juns->Delete();
//////////////fill the hole of pavement/////////////////////
vector<Region> newpave1;
vector<Region> newpave2;
for(unsigned int i = 0;i < pavements1.size();i++){
Region* reg = new Region(0);
newpave1.push_back(*reg);
newpave2.push_back(*reg);
reg->DeleteIfAllowed();
}
FillPave(n, pavements1, pavements2, routes_length, newpave1, newpave2);
for(unsigned int i = 0;i < pavements1.size();i++){
Region* reg1 = new Region(0);
MyUnion(pavements1[i], newpave1[i], *reg1);
pavements1[i] = *reg1;
reg1->DeleteIfAllowed();
Region* reg2 = new Region(0);
MyUnion(pavements2[i], newpave2[i], *reg2);
pavements2[i] = *reg2;
reg2->DeleteIfAllowed();
}
/////////////////////////////////////////////////////////////
for(unsigned int i = 0;i < pavements1.size();i++){
// outer_regions1.push_back(pavements1[i]);
// outer_regions2.push_back(pavements2[i]);
// cout<<"id "<<i + 1<<endl;
FilterDirtyRegion(outer_regions1, &pavements1[i]);
FilterDirtyRegion(outer_regions2, &pavements2[i]);
}
}
/*
For the Given halfsegment, transfer it by a deviation.
Similar as the function TransferSegment()
*/
void SpacePartition::TransferHalfSegment(HalfSegment& hs, int delta, bool flag)
{
// cout<<"before hs "<<hs<<endl;
Point lp = hs.GetLeftPoint();
Point rp = hs.GetRightPoint();
// cout<<"delta "<<delta<<endl;
if(MyAlmostEqual(lp.GetY(), rp.GetY())){
Point p1, p2;
if(flag){
p1.Set(lp.GetX(), lp.GetY() + delta);
p2.Set(rp.GetX(), rp.GetY() + delta);
}else{
p1.Set(lp.GetX(), lp.GetY() - delta);
p2.Set(rp.GetX(), rp.GetY() - delta);
}
hs.Set(true,p1,p2);
}else if(MyAlmostEqual(lp.GetX(), rp.GetX())){
Point p1, p2;
if(flag){
p1.Set(lp.GetX() + delta, lp.GetY());
p2.Set(rp.GetX() + delta, rp.GetY());
}else{
p1.Set(lp.GetX() - delta, lp.GetY());
p2.Set(rp.GetX() - delta, rp.GetY());
}
hs.Set(true,p1,p2);
}else{
double k1 = (lp.GetY() - rp.GetY())/(lp.GetX() - rp.GetX());
double k2 = -1/k1;
double c1 = lp.GetY() - lp.GetX()*k2;
double c2 = rp.GetY() - rp.GetX()*k2;
double x1 , x2;
x1 = 0.0; x2 = 0.0;
GetDeviation(lp, k2, c1, x1, x2, delta);
double y1 = x1*k2 + c1;
double y2 = x2*k2 + c1;
double x3, x4;
x3 = 0.0; x4 = 0.0;
GetDeviation(rp, k2, c2, x3, x4, delta);
double y3 = x3*k2 + c2;
double y4 = x4*k2 + c2;
Point p1,p2;
// cout<<"x1 "<<x1<<" x2 "<<x2<<" y1 "<<y1<<" y2 "<<y2<<endl;
if(flag){
p1.Set(x1, y1);
p2.Set(x3, y3);
}else{
p1.Set(x2, y2);
p2.Set(x4, y4);
}
hs.Set(true, p1, p2);
}
// cout<<"after hs "<<hs<<endl;
}
/*
for the given sline, get its left or right line after transfer
Similar as Gettheboundary()
*/
// void SpacePartition::GetSubCurve(SimpleLine* curve, Line* newcurve,
// int roadwidth, bool clock)
// {
// newcurve->StartBulkLoad();
// for(int i = 0; i < curve->Size();i++){
// HalfSegment hs;
// curve->Get(i,hs);
// // cout<<"old "<<hs<<endl;
// TransferHalfSegment(hs, roadwidth, clock);
// // cout<<"new "<<hs<<endl;
// *newcurve += hs;
// }
// newcurve->EndBulkLoad();
// }
template< template<typename T1> class Array1,
template<typename T2> class Array2>
void SpacePartition::GetSubCurve(
SimpleLineT<Array1>* curve,
LineT<Array2>* newcurve,
int roadwidth, bool clock)
{
newcurve->StartBulkLoad();
int edgeno = 0;
for(int i = 0; i < curve->Size();i++){
HalfSegment hs;
curve->Get(i, hs);
if(hs.IsLeftDomPoint() == false) continue;
// cout<<"old "<<hs<<endl;
TransferHalfSegment(hs, roadwidth, clock);
// cout<<"new "<<hs<<endl;
HalfSegment newhs(true, hs.GetLeftPoint(), hs.GetRightPoint());
newhs.attr.edgeno = edgeno++;
*newcurve += newhs;
newhs.SetLeftDomPoint(!newhs.IsLeftDomPoint());
*newcurve += newhs;
}
newcurve->EndBulkLoad();
}
/*
build the zebracrossing at the junction position.
The main determined input parameters are endpoints1 and endpoints2.
If the four points can construct a zebra, returns true, otherwise return false
*/
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 SpacePartition::BuildZebraCrossing(
vector<MyPoint>& endpoints1,
vector<MyPoint>& endpoints2,
RegionT<Array1>* reg_pave1,
RegionT<Array2>* reg_pave2,
LineT<Array3>* pave1,
RegionT<Array4>* crossregion,
Point& junp,
RegionT<Array5>* last_zc)
{
if(endpoints1.size() > 0 && endpoints2.size() > 0){
MyPoint lp = endpoints1[0];
MyPoint rp = endpoints2[0];
MMLine* pave = new MMLine(0);
pave->StartBulkLoad();
HalfSegment hs;
hs.Set(true,lp.loc,rp.loc);
int edgeno = 0;
hs.attr.edgeno = edgeno++;
*pave += hs;
hs.SetLeftDomPoint(!hs.IsLeftDomPoint());
*pave += hs;
pave->EndBulkLoad();
//////////////extend it to a region/////////////////////////////
HalfSegment hs1 = hs;
HalfSegment hs2 = hs;
TransferHalfSegment(hs1, 2, true);
TransferHalfSegment(hs2, 2, false);
vector<Point> outer_ps;
vector<MMRegion> result;
Point lp1 = hs1.GetLeftPoint();
Point rp1 = hs1.GetRightPoint();
Point lp2 = hs2.GetLeftPoint();
Point rp2 = hs2.GetRightPoint();
Point mp1, mp2;
mp1.Set((lp1.GetX() + rp1.GetX())/2, (lp1.GetY() + rp1.GetY())/2);
mp2.Set((lp2.GetX() + rp2.GetX())/2, (lp2.GetY() + rp2.GetY())/2);
if(mp1.Distance(junp) > mp2.Distance(junp)){
lp1 = hs.GetLeftPoint();
rp1 = hs.GetRightPoint();
lp2 = hs1.GetLeftPoint();
rp2 = hs1.GetRightPoint();
}else{
lp1 = hs.GetLeftPoint();
rp1 = hs.GetRightPoint();
lp2 = hs2.GetLeftPoint();
rp2 = hs2.GetRightPoint();
}
/* if((lp2.Inside(*reg_pave1) && rp2.Inside(*reg_pave2)) ||
(lp2.Inside(*reg_pave2) && rp2.Inside(*reg_pave1)) ){
if(GetClockwise(lp2, lp1, rp2)){
outer_ps.push_back(lp2);
outer_ps.push_back(rp2);
outer_ps.push_back(rp1);
outer_ps.push_back(lp1);
}else{
outer_ps.push_back(lp1);
outer_ps.push_back(rp1);
outer_ps.push_back(rp2);
outer_ps.push_back(lp2);
}
ComputeRegion(outer_ps, result);
*crossregion = result[0];
*pave1 = *pave;
delete pave;
return true;
}*/
// cout<<"lp2 "<<lp2<<" rp2 "<<rp2<<endl;
if((lp2.Inside(*reg_pave1) && rp2.Inside(*reg_pave2)) ||
(lp2.Inside(*reg_pave2) && rp2.Inside(*reg_pave1)) ){
if(GetClockwise(lp2, lp1, rp2)){
outer_ps.push_back(lp2);
outer_ps.push_back(rp2);
outer_ps.push_back(rp1);
outer_ps.push_back(lp1);
}else{
outer_ps.push_back(lp1);
outer_ps.push_back(rp1);
outer_ps.push_back(rp2);
outer_ps.push_back(lp2);
}
//////order points in counter clock-wise /////////////////
for(unsigned int j = 0;j < outer_ps.size();j++){
vector<Point> outer_ps1;
int index = (j + 1) % outer_ps.size();
for(unsigned int i = 0 ; i < outer_ps.size() ;i++){
Point p = outer_ps[index];
outer_ps1.push_back(p);
index = (index + 1) % outer_ps.size();
////////////////////2012.3.9////////////////////
if(outer_ps1.size() >= 2){
if(p.Distance(outer_ps1[outer_ps1.size() - 2]) < 0.001){
outer_ps1.clear();
break;
}
}
///////////////////////////////////////////////////
}
vector<MMRegion> result1;
// ComputeRegion(outer_ps1, result1);
if(outer_ps1.size() >= 3)/////////2012.3.9
ComputeRegion(outer_ps1, result1);
// if(result1[0].GetCycleDirection() &&
if(result1.size() > 0 && result1[0].GetCycleDirection() &&
result1[0].Intersects(*last_zc) == false){
*crossregion = result1[0];
*pave1 = *pave;
pave->DeleteIfAllowed();
return true;
}
}
}
pave->DeleteIfAllowed();
///////////////////////////////////////////////////////////////
}
endpoints1.clear();
endpoints2.clear();
return false;
}
/*
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 SpacePartition::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)
{
vector<MyPoint> endpoints1;
vector<MyPoint> endpoints2;
double delta = 1.0;
MMLine* subline1 = new MMLine(0);
MMLine* subline2 = new MMLine(0);
Point junp = p1;
GetSubCurve(subcurve, subline1, roadwidth + 1, true);
GetSubCurve(subcurve, subline2, roadwidth + 1, false);
// *pave1 = *subline1;
Point p2;
double l;
/* if(flag)
l = delta;
else
l = subcurve->Length() - delta;*/
//////////////////////////////////////////////////////
Point startp, endp;
assert(subcurve->AtPosition(0.0, true, startp));
assert(subcurve->AtPosition(subcurve->Length(), true, endp));
bool flag1;
if(startp.Distance(p1) < endp.Distance(p1)){
flag1 = true;
l = delta;
}
else{
l = subcurve->Length() - delta;
flag1 = false;
}
// cout<<"flag1 "<<flag1<<endl;
// cout<<"subcurve length "<<subcurve->Length()<<endl;
// cout<<"l "<<l<<endl;
// cout<<"p1 "<<p1<<" startp "<<startp<<"endp "<<endp<<endl;
///////////////////////////////////////////////////////
bool find = false;
while(find == false){
if(flag1){
l = l + delta;
if(l > subcurve->Length() || AlmostEqual(l, subcurve->Length())) break;
}
else{
l = l - delta;
if(l < 0.0 || AlmostEqual(l, 0.0)) break;
}
assert(subcurve->AtPosition(l,true,p2));
if(MyAlmostEqual(p1.GetX(), p2.GetX())){
double y = p2.GetY();
double x1 = p2.GetX() - (roadwidth + 2);
double x2 = p2.GetX() + (roadwidth + 2);
MMLine* line1 = new MMLine(0);
line1->StartBulkLoad();
HalfSegment hs;
Point lp,rp;
lp.Set(x1, y);
rp.Set(x2, y);
hs.Set(true,lp,rp);
int edgeno = 0;
hs.attr.edgeno = edgeno++;
*line1 += hs;
hs.SetLeftDomPoint(!hs.IsLeftDomPoint());
*line1 += hs;
line1->EndBulkLoad();
MMPoints* ps1 = new MMPoints(0);
MMPoints* ps2 = new MMPoints(0);
subline1->Crossings(*line1, *ps1);
subline2->Crossings(*line1, *ps2);
if(ps1->Size() > 0 && ps2->Size() > 0 &&
((ps1->Inside(*reg_pave1) && ps2->Inside(*reg_pave2)) ||
(ps1->Inside(*reg_pave2) && ps2->Inside(*reg_pave1)))){
// if(ps1->Size() > 0 && ps2->Size() > 0){
// cout<<"1 "<<p2<<endl;
for(int i = 0;i < ps1->Size();i++){
Point p;
ps1->Get(i,p);
MyPoint mp(p,p.Distance(p2));
endpoints1.push_back(mp);
}
for(int i = 0;i < ps2->Size();i++){
Point p;
ps2->Get(i,p);
MyPoint mp(p, p.Distance(p2));
endpoints2.push_back(mp);
}
sort(endpoints1.begin(),endpoints1.end());
sort(endpoints2.begin(),endpoints2.end());
// find = true;
find=BuildZebraCrossing(endpoints1, endpoints2,
reg_pave1, reg_pave2, pave1, crossregion, junp,last_zc);
}
p1 = p2;
ps1->DeleteIfAllowed();
ps2->DeleteIfAllowed();
line1->DeleteIfAllowed();
}else if(MyAlmostEqual(p1.GetY(), p2.GetY())){
double y1 = p2.GetY() - (roadwidth + 2);
double y2 = p2.GetY() + (roadwidth + 2);
double x = p2.GetX();
MMLine* line1 = new MMLine(0);
line1->StartBulkLoad();
HalfSegment hs;
Point lp,rp;
lp.Set(x, y1);
rp.Set(x, y2);
hs.Set(true,lp,rp);
int edgeno = 0;
hs.attr.edgeno = edgeno++;
*line1 += hs;
hs.SetLeftDomPoint(!hs.IsLeftDomPoint());
*line1 += hs;
line1->EndBulkLoad();
MMPoints* ps1 = new MMPoints(0);
MMPoints* ps2 = new MMPoints(0);
subline1->Crossings(*line1,*ps1);
subline2->Crossings(*line1,*ps2);
if(ps1->Size() > 0 && ps2->Size() > 0 &&
((ps1->Inside(*reg_pave1) && ps2->Inside(*reg_pave2)) ||
(ps1->Inside(*reg_pave2) && ps2->Inside(*reg_pave1)))){
// if(ps1->Size() > 0 && ps2->Size() > 0){
// cout<<"2 "<<p2<<endl;
for(int i = 0;i < ps1->Size();i++){
Point p;
ps1->Get(i,p);
MyPoint mp(p,p.Distance(p2));
endpoints1.push_back(mp);
}
for(int i = 0;i < ps2->Size();i++){
Point p;
ps2->Get(i,p);
MyPoint mp(p, p.Distance(p2));
endpoints2.push_back(mp);
}
sort(endpoints1.begin(),endpoints1.end());
sort(endpoints2.begin(),endpoints2.end());
// find = true;
find=BuildZebraCrossing(endpoints1, endpoints2,
reg_pave1, reg_pave2, pave1, crossregion, junp,last_zc);
}
p1 = p2;
ps1->DeleteIfAllowed();
ps2->DeleteIfAllowed();
line1->DeleteIfAllowed();
}else{//not vertical
double k1 = (p2.GetY() - p1.GetY())/(p2.GetX() - p1.GetX());
double k2 = -1/k1;
double c2 = p2.GetY() - p2.GetX()*k2;
double x1 = p2.GetX() - (roadwidth + 2);
double x2 = p2.GetX() + (roadwidth + 2);
MMLine* line1 = new MMLine(0);
line1->StartBulkLoad();
HalfSegment hs;
Point lp,rp;
lp.Set(x1, x1*k2 + c2);
rp.Set(x2, x2*k2 + c2);
hs.Set(true,lp,rp);
int edgeno = 0;
hs.attr.edgeno = edgeno++;
*line1 += hs;
hs.SetLeftDomPoint(!hs.IsLeftDomPoint());
*line1 += hs;
line1->EndBulkLoad();
MMPoints* ps1 = new MMPoints(0);
MMPoints* ps2 = new MMPoints(0);
subline1->Crossings(*line1,*ps1);
subline2->Crossings(*line1,*ps2);
if(ps1->Size() > 0 && ps2->Size() > 0 &&
((ps1->Inside(*reg_pave1) && ps2->Inside(*reg_pave2)) ||
(ps1->Inside(*reg_pave2) && ps2->Inside(*reg_pave1)))){
// if(ps1->Size() > 0 && ps2->Size() > 0){
// cout<<"3 "<<p2<<endl;
for(int i = 0;i < ps1->Size();i++){
Point p;
ps1->Get(i,p);
MyPoint mp(p, p.Distance(p2));
endpoints1.push_back(mp);
}
for(int i = 0;i < ps2->Size();i++){
Point p;
ps2->Get(i,p);
MyPoint mp(p, p.Distance(p2));
endpoints2.push_back(mp);
}
sort(endpoints1.begin(),endpoints1.end());
sort(endpoints2.begin(),endpoints2.end());
// find = true;
find=BuildZebraCrossing(endpoints1, endpoints2,
reg_pave1, reg_pave2, pave1, crossregion, junp,last_zc);
}
p1 = p2;
ps1->DeleteIfAllowed();
ps2->DeleteIfAllowed();
line1->DeleteIfAllowed();
}
}
subline1->DeleteIfAllowed();
subline2->DeleteIfAllowed();
}
/*
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 SpacePartition::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)
{
double l = len;
double delta_l = 20.0;
Point p1;
assert(curve->AtPosition(l, true, p1));
while(1){
MMSimpleLine* subcurve = new MMSimpleLine(0);
if(l - delta_l > 0.0)
curve->SubLine(l - delta_l, l, true, *subcurve);
else
curve->SubLine(0.0, l, true, *subcurve);
GetZebraCrossing(subcurve, reg_pave1,
reg_pave2, roadwidth, pave, delta_l, p1,
crossregion, last_zc);
subcurve->DeleteIfAllowed();
if(pave->Size() > 0 || delta_l >= curve->Length()) break;
delta_l += delta_l;
}
}
/*
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 SpacePartition::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)
{
double route_length = curve->Length();
double l = len;
double delta_l = 20.0;
Point p1;
assert(curve->AtPosition(l, true, p1));
// cout<<"increase p1 "<<p1<<endl;
while(1){
MMSimpleLine* subcurve = new MMSimpleLine(0);
if(l + delta_l < route_length)
curve->SubLine(l, l+delta_l, true, *subcurve);
else
curve->SubLine(l, route_length, true, *subcurve);
// cout<<*subcurve<<endl;
GetZebraCrossing(subcurve, reg_pave1,
reg_pave2, roadwidth, pave, delta_l, p1,
crossregion, last_zc);
subcurve->DeleteIfAllowed();
if(pave->Size() > 0 || delta_l >= route_length) break;
delta_l += delta_l;
}
// cout<<"increase "<<*crossregion<<endl;
}
/*
Create the pavement for each junction position, called by function Junpavement()
cross1 does not intersect cross2
*/
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 SpacePartition::CreatePavement(
SimpleLineT<Array1>* curve,
RegionT<Array2>* reg_pave1,
RegionT<Array3>* reg_pave2,
double len,
int roadwidth,
RegionT<Array4>* cross1,
RegionT<Array5>* cross2,
RegionT<Array6>* last_zc)
{
MMLine* pave1 = new MMLine(0);
MMLine* pave2 = new MMLine(0);
if(MyAlmostEqual(curve->Length(), len))
Decrease(curve, reg_pave1, reg_pave2, len, pave2,
roadwidth, cross2, last_zc);//--
else if(MyAlmostEqual(len, 0.0))
Increase(curve, reg_pave1, reg_pave2, len, pave1,
roadwidth, cross1, last_zc);//++
else{
Increase(curve, reg_pave1, reg_pave2, len, pave1,
roadwidth, cross1, last_zc);
/////////////////////////////////////////////////
MMRegion* temp = new MMRegion(0);
cross1->Union(*last_zc, *temp);
*last_zc = *temp;
temp->DeleteIfAllowed();
/////////////////////////////////////////////////
Decrease(curve, reg_pave1, reg_pave2, len, pave2,
roadwidth, cross2, last_zc);
}
pave1->DeleteIfAllowed();
pave2->DeleteIfAllowed();
}
/*
check the existence of a road network position
*/
bool SpacePartition::RidPosExist(int rid, float pos,
vector<vector<float> >& rid_pos_list)
{
if(rid_pos_list[rid - 1].size() == 0){
rid_pos_list[rid - 1].push_back(pos);
return false;
}
for(unsigned int i = 0;i < rid_pos_list[rid - 1].size();i++){
if(fabs(rid_pos_list[rid - 1][i] - pos) < EPSDIST)return true;
}
rid_pos_list[rid - 1].push_back(pos);
return false;
}
/*
called by operator junregion
*/
void SpacePartition::Junpavement(Network* n, Relation* rel, int attr_pos1,
int attr_pos2, int width, Relation* rel_road, int attr_pos3)
{
Flob::resetStatistics();
//get the pavement for each junction
Relation* routes = n->GetRoutes();
vector<MMRegion*> zc_reg;
vector<vector<float> > rid_pos_list;
MMRegion* temp = new MMRegion(0);
MMRegion* crossregion1 = new MMRegion(0);
MMRegion* crossregion2 = new MMRegion(0);
MMRegion* temp_reg = new MMRegion(0);
MMRegion* crossregion3 = new MMRegion(0);
MMRegion* crossregion4 = new MMRegion(0);
MMRegion* cross12 = new MMRegion(0);
for(int i = 0;i < routes->GetNoTuples();i++){
MMRegion* reg = new MMRegion(0);
zc_reg.push_back(reg);
vector<float> real_list;
rid_pos_list.push_back(real_list);
}
Relation* juns = n->GetJunctions();
for(int i = 1;i <= n->GetNoJunctions();i++){
Tuple* jun_tuple = juns->GetTuple(i, false);
CcInt* rid1 = (CcInt*)jun_tuple->GetAttribute(JUNCTION_ROUTE1_ID);
CcInt* rid2 = (CcInt*)jun_tuple->GetAttribute(JUNCTION_ROUTE2_ID);
int id1 = rid1->GetIntval();
int id2 = rid2->GetIntval();
CcReal* meas1 = (CcReal*)jun_tuple->GetAttribute(JUNCTION_ROUTE1_MEAS);
CcReal* meas2 = (CcReal*)jun_tuple->GetAttribute(JUNCTION_ROUTE2_MEAS);
double len1 = meas1->GetRealval();
double len2 = meas2->GetRealval();
// cout<<"len1 "<<len1<<" len2 "<<len2<<endl;
Tuple* inborder_tuple1 = rel->GetTuple(id1, false);
Tuple* inborder_tuple2 = rel->GetTuple(id2, false);
Region* reg1_in = (Region*)inborder_tuple1->GetAttribute(attr_pos1);
Region* reg1_out = (Region*)inborder_tuple1->GetAttribute(attr_pos2);
Region* reg2_in = (Region*)inborder_tuple2->GetAttribute(attr_pos1);
Region* reg2_out = (Region*)inborder_tuple2->GetAttribute(attr_pos2);
////////////////////////////////////////////////////////
Tuple* route_tuple1 = routes->GetTuple(id1, false);
SimpleLine* curve1 = (SimpleLine*)route_tuple1->GetAttribute(ROUTE_CURVE);
if(RidPosExist(id1, len1, rid_pos_list) == false){//not expand yet
CreatePavement(curve1, reg1_in, reg1_out, len1, width,
crossregion1, crossregion2, temp_reg);
if(zc_reg[id1 - 1]->Intersects(*crossregion1) == false){
zc_reg[id1 - 1]->Union(*crossregion1, *temp);
MMRegion* rp = zc_reg[id1-1];
zc_reg[id1 - 1] = temp;
temp = rp;
}
if(zc_reg[id1 - 1]->Intersects(*crossregion2) == false){
zc_reg[id1 - 1]->Union(*crossregion2, *temp);
MMRegion* rp = zc_reg[id1 - 1];
zc_reg[id1 - 1] = temp;
temp = rp;
}
}
temp_reg->Clear();
Tuple* route_tuple2 = routes->GetTuple(id2, false);
SimpleLine* curve2 = (SimpleLine*)route_tuple2->GetAttribute(ROUTE_CURVE);
crossregion1->Union(*crossregion2, *cross12);
/////////////////a special case, for the triangle area////////////////
if(id1 == 1402 && id2 == 1406){
*cross12 = *crossregion3;
}
if(RidPosExist(id2, len2, rid_pos_list) == false){//not expand yet.
CreatePavement(curve2, reg2_in, reg2_out, len2,
width, crossregion3, crossregion4, cross12);
if(zc_reg[id2 - 1]->Intersects(*crossregion3) == false){
zc_reg[id2 - 1]->Union(*crossregion3, *temp);
MMRegion* rp = zc_reg[id2 - 1];
zc_reg[id2 - 1] = temp;
temp = rp;
}
if(zc_reg[id2 - 1]->Intersects(*crossregion4) == false){
zc_reg[id2 - 1]->Union(*crossregion4, *temp);
MMRegion* rp = zc_reg[id2 - 1];
zc_reg[id2 - 1] = temp;
temp = rp;
}
}
cross12->Clear();
crossregion1->Clear();
crossregion2->Clear();
crossregion3->Clear();
crossregion4->Clear();
route_tuple1->DeleteIfAllowed();
route_tuple2->DeleteIfAllowed();
inborder_tuple1->DeleteIfAllowed();
inborder_tuple2->DeleteIfAllowed();
jun_tuple->DeleteIfAllowed();
}
juns->Delete();
cout << "before copying regions, the statistic is " << endl;
Flob::printStatistics(cout);
cout << "----------------------" << endl << endl;
size_t sum=0;
for(unsigned int i = 0;i < zc_reg.size();i++){
junid1.push_back(i + 1);
outer_regions1.push_back(*zc_reg[i]);
cout << "region " << i << " has a size of " << zc_reg[i]->Size() << endl;
sum += zc_reg[i]->Size();
zc_reg[i]->DeleteIfAllowed();
}
cout << "result's size summarized is " << sum << endl;
cout << "temporarly data has sizes " << endl;
cout << "temp : " << temp->Size() << endl;
cout << "crossregion1: " << crossregion1->Size() << endl;
cout << "crossregion2: " << crossregion2->Size() << endl;
cout << "crossregion3: " << crossregion3->Size() << endl;
cout << "crossregion4: " << crossregion4->Size() << endl;
cout << "temp_reg: " << temp_reg->Size() << endl;
cout << "cross12: " << cross12->Size() << endl;
temp->DeleteIfAllowed();
crossregion1->DeleteIfAllowed();
crossregion2->DeleteIfAllowed();
temp_reg->DeleteIfAllowed();
crossregion3->DeleteIfAllowed();
crossregion4->DeleteIfAllowed();
cross12->DeleteIfAllowed();
Flob::printStatistics(cout);
}
/*
Detect whether three points collineation
*/
bool SpacePartition::Collineation(Point& p1, Point& p2, Point& p3)
{
if(MyAlmostEqual(p1.GetX(), p2.GetX())){
if(MyAlmostEqual(p2.GetX(), p3.GetX())) return true;
}
if(MyAlmostEqual(p1.GetY(), p2.GetY())){
if(MyAlmostEqual(p2.GetY(), p3.GetY())) return true;
}
double k1 = (p1.GetY() - p2.GetY())/(p1.GetX() - p2.GetX());
double k2 = (p2.GetY() - p3.GetY())/(p2.GetX() - p3.GetX());
if(MyAlmostEqual(k1, k2)) return true;
return false;
}
/*
check the junction position rids.size() != 2 rids.size() != 6
*/
void SpacePartition::NewFillPavementDebug(Relation* rel, Relation* routes,
int id1, int id2,
Point* junp, int attr_pos1, int attr_pos2,
vector<int> rids)
{
Line* r1r2 = new Line(0);
int edgeno = 0;
double delta_dist = 0.1;
r1r2->StartBulkLoad();
for(unsigned int i = 0;i < rids.size();i++){
// Tuple* route_tuple = routes->GetTuple(rids[i]);
Tuple* route_tuple = routes->GetTuple(rids[i], false);
SimpleLine* route = (SimpleLine*)route_tuple->GetAttribute(ROUTE_CURVE);
for(int j = 0;j < route->Size();j++){
HalfSegment hs;
route->Get(j,hs);
if(hs.IsLeftDomPoint()){
Point lp = hs.GetLeftPoint();
Point rp = hs.GetRightPoint();
if(lp.Distance(*junp) < delta_dist ||
rp.Distance(*junp) < delta_dist){
HalfSegment newhs;
newhs.Set(true,lp,rp);
newhs.attr.edgeno = edgeno++;
*r1r2 += newhs;
newhs.SetLeftDomPoint(!newhs.IsLeftDomPoint());
*r1r2 += newhs;
}
}
}
route_tuple->DeleteIfAllowed();
}
r1r2->EndBulkLoad();
// Tuple* pave_tuple1 = rel->GetTuple(id1);
// Tuple* pave_tuple2 = rel->GetTuple(id2);
Tuple* pave_tuple1 = rel->GetTuple(id1, false);
Tuple* pave_tuple2 = rel->GetTuple(id2, false);
Region* reg1_pave1 = (Region*)pave_tuple1->GetAttribute(attr_pos1);
Region* reg1_pave2 = (Region*)pave_tuple1->GetAttribute(attr_pos2);
Region* reg2_pave1 = (Region*)pave_tuple2->GetAttribute(attr_pos1);
Region* reg2_pave2 = (Region*)pave_tuple2->GetAttribute(attr_pos2);
if(reg1_pave1->Intersects(*reg2_pave1) == false){
junid1.push_back(id1);
junid2.push_back(id2);
pave_line1.push_back(*r1r2);
outer_fillgap1.push_back(*reg1_pave1);
outer_fillgap2.push_back(*reg2_pave1);
Region* result1 = new Region(0);
assert(reg1_pave1->GetCycleDirection());
assert(reg2_pave1->GetCycleDirection());
outer_fillgap.push_back(*result1);
result1->DeleteIfAllowed();
}
if(reg1_pave1->Intersects(*reg2_pave2) == false){
junid1.push_back(id1);
junid2.push_back(id2);
pave_line1.push_back(*r1r2);
outer_fillgap1.push_back(*reg1_pave1);
outer_fillgap2.push_back(*reg2_pave2);
assert(reg1_pave1->GetCycleDirection());
assert(reg2_pave2->GetCycleDirection());
Region* result1 = new Region(0);
outer_fillgap.push_back(*result1);
result1->DeleteIfAllowed();
}
if(reg1_pave2->Intersects(*reg2_pave1) == false ){
junid1.push_back(id1);
junid2.push_back(id2);
pave_line1.push_back(*r1r2);
outer_fillgap1.push_back(*reg1_pave2);
outer_fillgap2.push_back(*reg2_pave1);
assert(reg1_pave2->GetCycleDirection());
assert(reg2_pave1->GetCycleDirection());
Region* result1 = new Region(0);
outer_fillgap.push_back(*result1);
result1->DeleteIfAllowed();
}
if(reg1_pave2->Intersects(*reg2_pave2) == false){
junid1.push_back(id1);
junid2.push_back(id2);
pave_line1.push_back(*r1r2);
outer_fillgap1.push_back(*reg1_pave2);
outer_fillgap2.push_back(*reg2_pave2);
assert(reg1_pave2->GetCycleDirection());
assert(reg2_pave2->GetCycleDirection());
Region* result1 = new Region(0);
outer_fillgap.push_back(*result1);
result1->DeleteIfAllowed();
}
pave_tuple1->DeleteIfAllowed();
pave_tuple2->DeleteIfAllowed();
r1r2->DeleteIfAllowed();
}
/*
check for the junction where two road intersect
rids.size() == 2, used by operator fillgap
*/
void SpacePartition::NewFillPavement1(Relation* rel, Relation* routes,
int id1, int id2,
Point* junp, int attr_pos1, int attr_pos2,
vector<int> rids)
{
Line* r1r2 = new Line(0);
int edgeno = 0;
double delta_dist = 0.1;
r1r2->StartBulkLoad();
for(unsigned int i = 0;i < rids.size();i++){
// Tuple* route_tuple = routes->GetTuple(rids[i]);
Tuple* route_tuple = routes->GetTuple(rids[i], false);
SimpleLine* route = (SimpleLine*)route_tuple->GetAttribute(ROUTE_CURVE);
for(int j = 0;j < route->Size();j++){
HalfSegment hs;
route->Get(j,hs);
if(hs.IsLeftDomPoint()){
Point lp = hs.GetLeftPoint();
Point rp = hs.GetRightPoint();
if(lp.Distance(*junp) < delta_dist ||
rp.Distance(*junp) < delta_dist){
HalfSegment newhs;
newhs.Set(true,lp,rp);
newhs.attr.edgeno = edgeno++;
*r1r2 += newhs;
newhs.SetLeftDomPoint(!newhs.IsLeftDomPoint());
*r1r2 += newhs;
}
}
}
route_tuple->DeleteIfAllowed();
}
r1r2->EndBulkLoad();
// Tuple* pave_tuple1 = rel->GetTuple(id1);
// Tuple* pave_tuple2 = rel->GetTuple(id2);
Tuple* pave_tuple1 = rel->GetTuple(id1, false);
Tuple* pave_tuple2 = rel->GetTuple(id2, false);
Region* reg1_pave1 = (Region*)pave_tuple1->GetAttribute(attr_pos1);
Region* reg1_pave2 = (Region*)pave_tuple1->GetAttribute(attr_pos2);
Region* reg2_pave1 = (Region*)pave_tuple2->GetAttribute(attr_pos1);
Region* reg2_pave2 = (Region*)pave_tuple2->GetAttribute(attr_pos2);
// if(reg1_pave1->Intersects(*reg2_pave1) == false &&
if(PavementIntersection(reg1_pave1, reg2_pave1) == false &&
SameSide1(reg1_pave1, reg2_pave1, r1r2, junp)){
junid1.push_back(id1);
junid2.push_back(id2);
pave_line1.push_back(*r1r2);
outer_fillgap1.push_back(*reg1_pave1);
outer_fillgap2.push_back(*reg2_pave1);
Region* result1 = new Region(0);
assert(reg1_pave1->GetCycleDirection());
assert(reg2_pave1->GetCycleDirection());
// cout<<outer_fillgap[outer_fillgap.size() - 1].GetCycleDirection()<<endl;
// cout<<*reg1_pave1<<endl;
// cout<<outer_fillgap[outer_fillgap.size() - 1]<<endl;
MyUnion(*reg1_pave1, outer_fillgap[outer_fillgap.size() - 1], *result1);
// outer_fillgap1.push_back(*result1);
// outer_fillgap2.push_back(*reg2_pave1);
result1->DeleteIfAllowed();
}
// if(reg1_pave1->Intersects(*reg2_pave2) == false &&
if(PavementIntersection(reg1_pave1, reg2_pave2) == false &&
SameSide1(reg1_pave1, reg2_pave2, r1r2, junp)){
junid1.push_back(id1);
junid2.push_back(id2);
pave_line1.push_back(*r1r2);
outer_fillgap1.push_back(*reg1_pave1);
outer_fillgap2.push_back(*reg2_pave2);
assert(reg1_pave1->GetCycleDirection());
assert(reg2_pave2->GetCycleDirection());
Region* result1 = new Region(0);
MyUnion(*reg1_pave1, outer_fillgap[outer_fillgap.size() - 1], *result1);
// outer_fillgap1.push_back(*result1);
// outer_fillgap2.push_back(*reg2_pave1);
result1->DeleteIfAllowed();
}
// if(reg1_pave2->Intersects(*reg2_pave1) == false &&
if(PavementIntersection(reg1_pave2, reg2_pave1) == false &&
SameSide1(reg1_pave2, reg2_pave1, r1r2, junp)){
junid1.push_back(id1);
junid2.push_back(id2);
pave_line1.push_back(*r1r2);
outer_fillgap1.push_back(*reg1_pave2);
outer_fillgap2.push_back(*reg2_pave1);
assert(reg1_pave2->GetCycleDirection());
assert(reg2_pave1->GetCycleDirection());
Region* result1 = new Region(0);
MyUnion(*reg1_pave2, outer_fillgap[outer_fillgap.size() - 1], *result1);
// outer_fillgap1.push_back(*result1);
// outer_fillgap2.push_back(*reg2_pave1);
result1->DeleteIfAllowed();
}
// if(reg1_pave2->Intersects(*reg2_pave2) == false &&
if(PavementIntersection(reg1_pave2, reg2_pave2) == false &&
SameSide1(reg1_pave2, reg2_pave2, r1r2, junp)){
junid1.push_back(id1);
junid2.push_back(id2);
pave_line1.push_back(*r1r2);
outer_fillgap1.push_back(*reg1_pave2);
outer_fillgap2.push_back(*reg2_pave2);
assert(reg1_pave2->GetCycleDirection());
assert(reg2_pave2->GetCycleDirection());
Region* result1 = new Region(0);
MyUnion(*reg1_pave2, outer_fillgap[outer_fillgap.size() - 1], *result1);
// outer_fillgap1.push_back(*result1);
// outer_fillgap2.push_back(*reg2_pave1);
result1->DeleteIfAllowed();
}
pave_tuple1->DeleteIfAllowed();
pave_tuple2->DeleteIfAllowed();
r1r2->DeleteIfAllowed();
}
/*
check for the junction where three roads intersect
called by operator fillgap
*/
void SpacePartition:: NewFillPavement2(Relation* rel, Relation* routes,
int id1, int id2,
Point* junp, int attr_pos1, int attr_pos2,
vector<int> rids)
{
Line* r1r2 = new Line(0);
int edgeno = 0;
double delta_dist = 0.1;
r1r2->StartBulkLoad();
MyHalfSegment firstseg;
MyHalfSegment secondseg;
MyHalfSegment thirdseg;
int third_seg = 0;
for(unsigned int i = 0;i < rids.size();i++){
// Tuple* route_tuple = routes->GetTuple(rids[i]);
Tuple* route_tuple = routes->GetTuple(rids[i], false);
SimpleLine* route = (SimpleLine*)route_tuple->GetAttribute(ROUTE_CURVE);
for(int j = 0;j < route->Size();j++){
HalfSegment hs;
route->Get(j,hs);
if(hs.IsLeftDomPoint()){
Point lp = hs.GetLeftPoint();
Point rp = hs.GetRightPoint();
if(lp.Distance(*junp) < delta_dist ||
rp.Distance(*junp) < delta_dist){
HalfSegment newhs;
newhs.Set(true,lp,rp);
newhs.attr.edgeno = edgeno++;
*r1r2 += newhs;
newhs.SetLeftDomPoint(!newhs.IsLeftDomPoint());
*r1r2 += newhs;
if(rids[i] != id1 && rids[i] != id2){
third_seg++;
if(lp.Distance(*junp) < delta_dist){
thirdseg.def = true;
thirdseg.from = lp;
thirdseg.to = rp;
}else{
thirdseg.def = true;
thirdseg.from = rp;
thirdseg.to = lp;
}
}
if(rids[i] == id1){
if(lp.Distance(*junp) < delta_dist){
firstseg.def = true;
firstseg.from = lp;
firstseg.to = rp;
}else{
firstseg.def = true;
firstseg.from = rp;
firstseg.to = lp;
}
}
if(rids[i] == id2){
if(lp.Distance(*junp) < delta_dist){
secondseg.def = true;
secondseg.from = lp;
secondseg.to = rp;
}else{
secondseg.def = true;
secondseg.from = rp;
secondseg.to = lp;
}
}
}
}
}
route_tuple->DeleteIfAllowed();
}
r1r2->EndBulkLoad();
if(third_seg > 2){
r1r2->DeleteIfAllowed();
return;
}
////////////////////////////////
double angle1 = GetAngle(firstseg.from, firstseg.to, thirdseg.to);
double angle2 = GetAngle(firstseg.from, firstseg.to, secondseg.to);
bool clock1 = GetClockwise(firstseg.from, firstseg.to, thirdseg.to);
bool clock2 = GetClockwise(firstseg.from, firstseg.to, secondseg.to);
if(clock2){
if(clock1){
if(angle1 > angle2){
r1r2->DeleteIfAllowed();
return;
}
}else{
r1r2->DeleteIfAllowed();
return;
}
}else{
if(clock1 == false){
if(angle1 > angle2){
r1r2->DeleteIfAllowed();
return;
}
}else{
r1r2->DeleteIfAllowed();
return;
}
}
//////////////////////////////
vector<Point> ps;
vector<Region> smallreg;
ps.push_back(firstseg.from);
ps.push_back(firstseg.to);
ps.push_back(thirdseg.to);
ps.push_back(secondseg.to);
ComputeRegion(ps, smallreg);
assert(smallreg.size() > 0);
//////////////////////////////
Tuple* pave_tuple1 = rel->GetTuple(id1, false);
Tuple* pave_tuple2 = rel->GetTuple(id2, false);
Region* reg1_pave1 = (Region*)pave_tuple1->GetAttribute(attr_pos1);
Region* reg1_pave2 = (Region*)pave_tuple1->GetAttribute(attr_pos2);
Region* reg2_pave1 = (Region*)pave_tuple2->GetAttribute(attr_pos1);
Region* reg2_pave2 = (Region*)pave_tuple2->GetAttribute(attr_pos2);
if(PavementIntersection(reg1_pave1, reg2_pave2) == false &&
SameSide2(reg1_pave1, reg2_pave1, r1r2, junp, thirdseg, smallreg[0])){
/* if(third_seg > 2){
cout<<"1"<<endl;
cout<<"id1 "<<id1<<"id2 "<<id2<<endl;
} */
junid1.push_back(id1);
junid2.push_back(id2);
pave_line1.push_back(*r1r2);
outer_fillgap1.push_back(*reg1_pave1);
outer_fillgap2.push_back(*reg2_pave1);
Region* result1 = new Region(0);
assert(reg1_pave1->GetCycleDirection());
assert(reg2_pave1->GetCycleDirection());
MyUnion(*reg1_pave1, outer_fillgap[outer_fillgap.size() - 1], *result1);
result1->DeleteIfAllowed();
}
if(PavementIntersection(reg1_pave1, reg2_pave2) == false &&
SameSide2(reg1_pave1, reg2_pave2, r1r2, junp, thirdseg, smallreg[0])){
// if(third_seg > 2){
// cout<<"2"<<endl;
// cout<<"id1 "<<id1<<"id2 "<<id2<<endl;
// }
junid1.push_back(id1);
junid2.push_back(id2);
pave_line1.push_back(*r1r2);
outer_fillgap1.push_back(*reg1_pave1);
outer_fillgap2.push_back(*reg2_pave2);
assert(reg1_pave1->GetCycleDirection());
assert(reg2_pave2->GetCycleDirection());
Region* result1 = new Region(0);
MyUnion(*reg1_pave1, outer_fillgap[outer_fillgap.size() - 1], *result1);
result1->DeleteIfAllowed();
}
if(PavementIntersection(reg1_pave2, reg2_pave1) == false &&
SameSide2(reg1_pave2, reg2_pave1, r1r2, junp, thirdseg, smallreg[0])){
// if(third_seg > 2){
// cout<<"3"<<endl;
// cout<<"id1 "<<id1<<"id2 "<<id2<<endl;
// }
junid1.push_back(id1);
junid2.push_back(id2);
pave_line1.push_back(*r1r2);
outer_fillgap1.push_back(*reg1_pave2);
outer_fillgap2.push_back(*reg2_pave1);
assert(reg1_pave2->GetCycleDirection());
assert(reg2_pave1->GetCycleDirection());
Region* result1 = new Region(0);
MyUnion(*reg1_pave2, outer_fillgap[outer_fillgap.size() - 1], *result1);
result1->DeleteIfAllowed();
}
if(PavementIntersection(reg1_pave2, reg2_pave2) == false &&
SameSide2(reg1_pave2, reg2_pave2, r1r2, junp, thirdseg, smallreg[0])){
// if(third_seg > 2){
// cout<<"4"<<endl;
// cout<<"id1 "<<id1<<"id2 "<<id2<<endl;
// }
junid1.push_back(id1);
junid2.push_back(id2);
pave_line1.push_back(*r1r2);
outer_fillgap1.push_back(*reg1_pave2);
outer_fillgap2.push_back(*reg2_pave2);
assert(reg1_pave2->GetCycleDirection());
assert(reg2_pave2->GetCycleDirection());
Region* result1 = new Region(0);
MyUnion(*reg1_pave2, outer_fillgap[outer_fillgap.size() - 1], *result1);
result1->DeleteIfAllowed();
}
pave_tuple1->DeleteIfAllowed();
pave_tuple2->DeleteIfAllowed();
r1r2->DeleteIfAllowed();
}
/*
the same function as in NewFillPavement2, but with different input parameters
called by function FillPave()
*/
void SpacePartition::NewFillPavement3(Relation* routes, int id1, int id2,
Point* junp, vector<Region>& paves1,
vector<Region>& paves2, vector<int> rids,
vector<Region>& newpaves1, vector<Region>& newpaves2)
{
Line* r1r2 = new Line(0);
int edgeno = 0;
double delta_dist = 0.1;
r1r2->StartBulkLoad();
for(unsigned int i = 0;i < rids.size();i++){
// Tuple* route_tuple = routes->GetTuple(rids[i]);
Tuple* route_tuple = routes->GetTuple(rids[i], false);
SimpleLine* route = (SimpleLine*)route_tuple->GetAttribute(ROUTE_CURVE);
for(int j = 0;j < route->Size();j++){
HalfSegment hs;
route->Get(j,hs);
if(hs.IsLeftDomPoint()){
Point lp = hs.GetLeftPoint();
Point rp = hs.GetRightPoint();
if(lp.Distance(*junp) < delta_dist ||
rp.Distance(*junp) < delta_dist){
HalfSegment newhs;
newhs.Set(true,lp,rp);
newhs.attr.edgeno = edgeno++;
*r1r2 += newhs;
newhs.SetLeftDomPoint(!newhs.IsLeftDomPoint());
*r1r2 += newhs;
}
}
}
route_tuple->DeleteIfAllowed();
}
r1r2->EndBulkLoad();
Region* reg1_pave1 = &paves1[id1 - 1];
Region* reg1_pave2 = &paves2[id1 - 1];
Region* reg2_pave1 = &paves1[id2 - 1];
Region* reg2_pave2 = &paves2[id2 - 1];
if(PavementIntersection(reg1_pave1, reg2_pave1) == false &&
SameSide1(reg1_pave1, reg2_pave1, r1r2, junp)){
Region* result = new Region(0);
assert(reg1_pave1->GetCycleDirection());
assert(reg2_pave1->GetCycleDirection());
MyUnion(newpaves1[id1 - 1], outer_fillgap[outer_fillgap.size() - 1],
*result);
newpaves1[id1 - 1] = *result;
result->DeleteIfAllowed();
}
if(PavementIntersection(reg1_pave1, reg2_pave2) == false &&
SameSide1(reg1_pave1, reg2_pave2, r1r2, junp)){
assert(reg1_pave1->GetCycleDirection());
assert(reg2_pave2->GetCycleDirection());
Region* result = new Region(0);
MyUnion(newpaves1[id1 - 1], outer_fillgap[outer_fillgap.size() - 1],
*result);
newpaves1[id1 - 1] = *result;
result->DeleteIfAllowed();
}
if(PavementIntersection(reg1_pave2, reg2_pave1) == false &&
SameSide1(reg1_pave2, reg2_pave1, r1r2, junp)){
assert(reg1_pave2->GetCycleDirection());
assert(reg2_pave1->GetCycleDirection());
Region* result = new Region(0);
MyUnion(newpaves2[id1 - 1], outer_fillgap[outer_fillgap.size() - 1],
*result);
newpaves2[id1 - 1] = *result;
result->DeleteIfAllowed();
}
if(PavementIntersection(reg1_pave2, reg2_pave2) == false &&
SameSide1(reg1_pave2, reg2_pave2, r1r2, junp)){
assert(reg1_pave2->GetCycleDirection());
assert(reg2_pave2->GetCycleDirection());
Region* result = new Region(0);
MyUnion(newpaves2[id1 - 1], outer_fillgap[outer_fillgap.size() - 1],
*result);
newpaves2[id1 - 1] = *result;
result->DeleteIfAllowed();
}
r1r2->DeleteIfAllowed();
}
/*
the same function as NewFillPavement2, but with different input parameters
called by function FillPave()
*/
void SpacePartition::NewFillPavement4(Relation* routes, int id1, int id2,
Point* junp, vector<Region>& paves1,
vector<Region>& paves2, vector<int> rids,
vector<Region>& newpaves1, vector<Region>& newpaves2)
{
Line* r1r2 = new Line(0);
int edgeno = 0;
double delta_dist = 0.1;
r1r2->StartBulkLoad();
MyHalfSegment firstseg;
MyHalfSegment secondseg;
MyHalfSegment thirdseg;
int third_seg = 0;
for(unsigned int i = 0;i < rids.size();i++){
// Tuple* route_tuple = routes->GetTuple(rids[i]);
Tuple* route_tuple = routes->GetTuple(rids[i], false);
SimpleLine* route = (SimpleLine*)route_tuple->GetAttribute(ROUTE_CURVE);
for(int j = 0;j < route->Size();j++){
HalfSegment hs;
route->Get(j,hs);
if(hs.IsLeftDomPoint()){
Point lp = hs.GetLeftPoint();
Point rp = hs.GetRightPoint();
if(lp.Distance(*junp) < delta_dist ||
rp.Distance(*junp) < delta_dist){
HalfSegment newhs;
newhs.Set(true,lp,rp);
newhs.attr.edgeno = edgeno++;
*r1r2 += newhs;
newhs.SetLeftDomPoint(!newhs.IsLeftDomPoint());
*r1r2 += newhs;
if(rids[i] != id1 && rids[i] != id2){
third_seg++;
if(lp.Distance(*junp) < delta_dist){
thirdseg.def = true;
thirdseg.from = lp;
thirdseg.to = rp;
}else{
thirdseg.def = true;
thirdseg.from = rp;
thirdseg.to = lp;
}
}
if(rids[i] == id1){
if(lp.Distance(*junp) < delta_dist){
firstseg.def = true;
firstseg.from = lp;
firstseg.to = rp;
}else{
firstseg.def = true;
firstseg.from = rp;
firstseg.to = lp;
}
}
if(rids[i] == id2){
if(lp.Distance(*junp) < delta_dist){
secondseg.def = true;
secondseg.from = lp;
secondseg.to = rp;
}else{
secondseg.def = true;
secondseg.from = rp;
secondseg.to = lp;
}
}
}
}
}
route_tuple->DeleteIfAllowed();
}
r1r2->EndBulkLoad();
if(third_seg > 2){
r1r2->DeleteIfAllowed();
return;
}
////////////////////////////////
double angle1 = GetAngle(firstseg.from, firstseg.to, thirdseg.to);
double angle2 = GetAngle(firstseg.from, firstseg.to, secondseg.to);
bool clock1 = GetClockwise(firstseg.from, firstseg.to, thirdseg.to);
bool clock2 = GetClockwise(firstseg.from, firstseg.to, secondseg.to);
if(clock2){
if(clock1){
if(angle1 > angle2){
r1r2->DeleteIfAllowed();
return;
}
}else{
r1r2->DeleteIfAllowed();
return;
}
}else{
if(clock1 == false){
if(angle1 > angle2){
r1r2->DeleteIfAllowed();
return;
}
}else{
r1r2->DeleteIfAllowed();
return;
}
}
//////////////////////////////
vector<Point> ps;
vector<Region> smallreg;
ps.push_back(firstseg.from);
ps.push_back(firstseg.to);
ps.push_back(thirdseg.to);
ps.push_back(secondseg.to);
ComputeRegion(ps, smallreg);
assert(smallreg.size() > 0);
//////////////////////////////
Region* reg1_pave1 = &paves1[id1 - 1];
Region* reg1_pave2 = &paves2[id1 - 1];
Region* reg2_pave1 = &paves1[id2 - 1];
Region* reg2_pave2 = &paves2[id2 - 1];
// if(PavementIntersection(reg1_pave1, reg2_pave2) == false &&
if(PavementIntersection(reg1_pave1, reg2_pave1) == false &&
SameSide2(reg1_pave1, reg2_pave1, r1r2, junp, thirdseg, smallreg[0])){
Region* result = new Region(0);
assert(reg1_pave1->GetCycleDirection());
assert(reg2_pave1->GetCycleDirection());
MyUnion(newpaves1[id1 - 1], outer_fillgap[outer_fillgap.size() - 1],
*result);
newpaves1[id1 - 1] = *result;
result->DeleteIfAllowed();
}
if(PavementIntersection(reg1_pave1, reg2_pave2) == false &&
SameSide2(reg1_pave1, reg2_pave2, r1r2, junp, thirdseg, smallreg[0])){
assert(reg1_pave1->GetCycleDirection());
assert(reg2_pave2->GetCycleDirection());
Region* result = new Region(0);
MyUnion(newpaves1[id1 - 1], outer_fillgap[outer_fillgap.size() - 1],
*result);
newpaves1[id1 - 1] = *result;
result->DeleteIfAllowed();
}
if(PavementIntersection(reg1_pave2, reg2_pave1) == false &&
SameSide2(reg1_pave2, reg2_pave1, r1r2, junp, thirdseg, smallreg[0])){
assert(reg1_pave2->GetCycleDirection());
assert(reg2_pave1->GetCycleDirection());
Region* result = new Region(0);
MyUnion(newpaves2[id1 - 1], outer_fillgap[outer_fillgap.size() - 1],
*result);
newpaves2[id1 - 1] = *result;
result->DeleteIfAllowed();
}
if(PavementIntersection(reg1_pave2, reg2_pave2) == false &&
SameSide2(reg1_pave2, reg2_pave2, r1r2, junp, thirdseg, smallreg[0])){
assert(reg1_pave2->GetCycleDirection());
assert(reg2_pave2->GetCycleDirection());
Region* result = new Region(0);
MyUnion(newpaves2[id1 - 1], outer_fillgap[outer_fillgap.size() - 1],
*result);
newpaves2[id1 - 1] = *result;
result->DeleteIfAllowed();
}
r1r2->DeleteIfAllowed();
}
/*
a special function for junction- rid 2549 and 2550
*/
void SpacePartition::NewFillPavement5(Relation* routes, int id1, int id2,
Point* junp, vector<Region>& paves1,
vector<Region>& paves2, vector<int> rids,
vector<Region>& newpaves1, vector<Region>& newpaves2)
{
Line* r1r2 = new Line(0);
int edgeno = 0;
double delta_dist = 0.1;
r1r2->StartBulkLoad();
for(unsigned int i = 0;i < rids.size();i++){
// Tuple* route_tuple = routes->GetTuple(rids[i]);
Tuple* route_tuple = routes->GetTuple(rids[i], false);
SimpleLine* route = (SimpleLine*)route_tuple->GetAttribute(ROUTE_CURVE);
for(int j = 0;j < route->Size();j++){
HalfSegment hs;
route->Get(j,hs);
if(hs.IsLeftDomPoint()){
Point lp = hs.GetLeftPoint();
Point rp = hs.GetRightPoint();
if(lp.Distance(*junp) < delta_dist ||
rp.Distance(*junp) < delta_dist){
HalfSegment newhs;
newhs.Set(true,lp,rp);
newhs.attr.edgeno = edgeno++;
*r1r2 += newhs;
newhs.SetLeftDomPoint(!newhs.IsLeftDomPoint());
*r1r2 += newhs;
}
}
}
route_tuple->DeleteIfAllowed();
}
r1r2->EndBulkLoad();
Region* reg1_pave1 = &paves1[id1 - 1];
Region* reg2_pave1 = &paves1[id2 - 1];
if(PavementIntersection(reg1_pave1, reg2_pave1) == false &&
SameSide1(reg1_pave1, reg2_pave1, r1r2, junp)){
Region* result = new Region(0);
assert(reg1_pave1->GetCycleDirection());
assert(reg2_pave1->GetCycleDirection());
MyUnion(newpaves1[id1 - 1], outer_fillgap[outer_fillgap.size() - 1],
*result);
newpaves1[id1 - 1] = *result;
result->DeleteIfAllowed();
}
r1r2->DeleteIfAllowed();
}
/*
for operator fillgap
*/
void SpacePartition::FillHoleOfPave(Network* n, Relation* rel, int attr_pos1,
int attr_pos2, int width)
{
Relation* routes = n->GetRoutes();
Relation* juns = n->GetJunctions();
vector<double> routes_length;
double min_length = numeric_limits<double>::max();
double max_length = numeric_limits<double>::min();
for(int i = 1;i <= routes->GetNoTuples();i++){
Tuple* route_tuple = routes->GetTuple(i, false);
CcReal* len = (CcReal*)route_tuple->GetAttribute(ROUTE_LENGTH);
double length = len->GetRealval();
if(length < min_length) min_length = length;
if(length > max_length) max_length = length;
route_tuple->DeleteIfAllowed();
routes_length.push_back(length);
}
//////////////////////////////////////////////////////////////////
// vector<Region> pavements1;
// vector<Region> pavements2;
// for(int i = 1;i <= rel->GetNoTuples();i++){
// Tuple* pave_tuple = rel->GetTuple(i, false);
// Region* reg1 = (Region*)pave_tuple->GetAttribute(attr_pos1);
// Region* reg2 = (Region*)pave_tuple->GetAttribute(attr_pos2);
// pavements1.push_back(*reg1);
// pavements2.push_back(*reg2);
// pave_tuple->DeleteIfAllowed();
// }
//
// vector<Region> newpave1;
// vector<Region> newpave2;
// for(unsigned int i = 0;i < pavements1.size();i++){
// Region* reg = new Region(0);
// newpave1.push_back(*reg);
// newpave2.push_back(*reg);
// delete reg;
// }
// FillPave(n, pavements1, pavements2, routes_length, newpave1, newpave2);
// for(unsigned int i = 0;i < pavements1.size();i++){
// // cout<<"i "<<i<<endl;
//
// Region* reg1 = new Region(0);
// MyUnion(pavements1[i], newpave1[i], *reg1);
// pavements1[i] = *reg1;
// delete reg1;
//
// Region* reg2 = new Region(0);
// MyUnion(pavements2[i], newpave2[i], *reg2);
// pavements2[i] = *reg2;
// delete reg2;
// }
vector<MyJun> myjuns;
for(int i = 1;i <= n->GetNoJunctions();i++){
Tuple* jun_tuple = juns->GetTuple(i, false);
CcInt* rid1 = (CcInt*)jun_tuple->GetAttribute(JUNCTION_ROUTE1_ID);
CcInt* rid2 = (CcInt*)jun_tuple->GetAttribute(JUNCTION_ROUTE2_ID);
int id1 = rid1->GetIntval();
int id2 = rid2->GetIntval();
Point* junp = (Point*)jun_tuple->GetAttribute(JUNCTION_POS);
// cout<<"rid1 "<<id1<<" rid2 "<<id2<<endl;
CcReal* meas1 = (CcReal*)jun_tuple->GetAttribute(JUNCTION_ROUTE1_MEAS);
CcReal* meas2 = (CcReal*)jun_tuple->GetAttribute(JUNCTION_ROUTE2_MEAS);
double len1 = meas1->GetRealval();
double len2 = meas2->GetRealval();
MyJun mj(*junp, id1, id2, len1, len2);
myjuns.push_back(mj);
jun_tuple->DeleteIfAllowed();
}
juns->Delete();
sort(myjuns.begin(), myjuns.end());
// for(unsigned int i = 0;i < myjuns.size();i++)
// myjuns[i].Print();
const double delta_dist = 0.1;
for(unsigned int i = 0 ;i < myjuns.size();i++){
Point loc = myjuns[i].loc;
int rid1 = myjuns[i].rid1;
int rid2 = myjuns[i].rid2;
// cout<<"rid1 "<<rid1<<" rid2 "<<rid2<<endl;
if((MyAlmostEqual(myjuns[i].len1, 0.0)||
MyAlmostEqual(myjuns[i].len1, routes_length[rid1 - 1])) &&
(MyAlmostEqual(myjuns[i].len2, 0.0)||
MyAlmostEqual(myjuns[i].len2, routes_length[rid2 - 1]))){
vector<int> rids;
int j1 = i - 1;
while(j1 >= 0 && loc.Distance(myjuns[j1].loc) < delta_dist){
rids.push_back(myjuns[j1].rid1);
rids.push_back(myjuns[j1].rid2);
j1--;
}
unsigned int j2 = i;
while(j2 < myjuns.size() && loc.Distance(myjuns[j2].loc) < delta_dist){
rids.push_back(myjuns[j2].rid1);
rids.push_back(myjuns[j2].rid2);
j2++;
}
// cout<<" rids size "<<rids.size()<<endl;
// cout<<"rid1 "<<rid1<<" rid2 "<<rid2<<endl;
if(rids.size() == 2){
NewFillPavement1(rel, routes, rid1, rid2, &loc,
attr_pos1, attr_pos2, rids);
}
if(rids.size() == 6){
NewFillPavement2(rel, routes, rid1, rid2, &loc,
attr_pos1, attr_pos2, rids);
}
if(rids.size() != 2 && rids.size() != 6 && rids.size() != 12){
NewFillPavementDebug(rel, routes, rid1, rid2, &loc,
attr_pos1, attr_pos2, rids);
}
rids.clear();
}
}
}
/*
a class to collect all possible sections of a route where the interesting
points can locate
*/
StrRS::StrRS()
{
r1 = NULL;
r2 = NULL;
count = 0;
resulttype = NULL;
}
StrRS::~StrRS()
{
if(resulttype != NULL) resulttype->DeleteIfAllowed();
}
StrRS::StrRS(Network* net,Relation* rel1, Relation* rel2):n(net), r1(rel1),
r2(rel2), count(0),resulttype(NULL)
{
}
/*
for each route, it creates a set of sections from that route where the
intersecting places can locate. It is according to the position of each
junction. The sections should not intersect the junction area
(zebra crossing). For each junction position,
w meters before it and w meters after it, these places are available.
*/
void StrRS::GetSections(int attr_pos1, int attr_pos2, int attr_pos3)
{
const double dist_delta = 10.0;
for(int i = 1;i <= r2->GetNoTuples();i++){
Tuple* cross_tuple = r2->GetTuple(i, false);
CcInt* rid = (CcInt*)cross_tuple->GetAttribute(attr_pos2);
Region* cross_reg = (Region*)cross_tuple->GetAttribute(attr_pos3);
// cout<<"rid "<<rid<<" cross "<<*cross_reg<<endl;
// cout<<"rid "<<rid->GetIntval()<<endl;
Tuple* route_tuple = r1->GetTuple(rid->GetIntval(), false);
SimpleLine* sl = (SimpleLine*)route_tuple->GetAttribute(attr_pos1);
vector<JunctionSortEntry> xjuns;
n->GetJunctionsOnRoute(rid, xjuns);
// cout<<*l<<endl;
vector<float> cross_pos;
////////////collect intersection points and the position///////
for(unsigned int j = 0;j < xjuns.size();j++){
double meas = xjuns[j].GetRouteMeas();
// cout<<"meas "<<meas<<endl;
if(j == 0){
if(!AlmostEqual(meas, 0.0)) cross_pos.push_back(0.0);
}
cross_pos.push_back(meas);
}
/* for(int j = 0;j < cross_pos.size();j++)
cout<<cross_pos[j]<<" ";
cout<<endl; */
for(unsigned int j = 0;j < cross_pos.size();j++){
if(j == 0){
if(cross_pos.size() == 1){
double pos1 = cross_pos[j] + dist_delta;
double pos2 = sl->Length() - dist_delta;
while(pos1 < pos2){
SimpleLine* sub_sl = new SimpleLine(0);
sl->SubLine(pos1, pos2, true, *sub_sl);
Line* l = new Line(0);
sub_sl->toLine(*l);
if(l->Intersects(*cross_reg) == false){
rids.push_back(rid->GetIntval());
lines.push_back(*l);
l->DeleteIfAllowed();
sub_sl->DeleteIfAllowed();
break;
}else{
pos1 += dist_delta;
pos2 -= dist_delta;
}
l->DeleteIfAllowed();
sub_sl->DeleteIfAllowed();
}
}else{
double pos1 = cross_pos[j];
double pos2 = cross_pos[j + 1] - dist_delta;
while(pos1 < pos2){
SimpleLine* sub_sl = new SimpleLine(0);
sl->SubLine(pos1, pos2, true, *sub_sl);
Line* l = new Line(0);
sub_sl->toLine(*l);
if(l->Intersects(*cross_reg) == false){
rids.push_back(rid->GetIntval());
lines.push_back(*l);
l->DeleteIfAllowed();
sub_sl->DeleteIfAllowed();
break;
}else{
pos1 += dist_delta;
pos2 -= dist_delta;
}
l->DeleteIfAllowed();
sub_sl->DeleteIfAllowed();
}
}
}else{
double pos1 = cross_pos[j - 1] + dist_delta;
double pos2 = cross_pos[j] - dist_delta;
while(pos1 < pos2){
SimpleLine* sub_sl = new SimpleLine(0);
sl->SubLine(pos1, pos2, true, *sub_sl);
Line* l = new Line(0);
sub_sl->toLine(*l);
if(l->Intersects(*cross_reg) == false){
rids.push_back(rid->GetIntval());
lines.push_back(*l);
l->DeleteIfAllowed();
sub_sl->DeleteIfAllowed();
break;
}else{
pos1 += dist_delta;
pos2 -= dist_delta;
}
l->DeleteIfAllowed();
sub_sl->DeleteIfAllowed();
}
/////////////process the last part/////////////////
if(j == cross_pos.size() - 1){
double pos1 = cross_pos[j] + dist_delta;
double pos2 = sl->Length() - dist_delta;
while(pos1 < pos2){
SimpleLine* sub_sl = new SimpleLine(0);
sl->SubLine(pos1, pos2, true, *sub_sl);
Line* l = new Line(0);
sub_sl->toLine(*l);
if(l->Intersects(*cross_reg) == false){
rids.push_back(rid->GetIntval());
lines.push_back(*l);
l->DeleteIfAllowed();
sub_sl->DeleteIfAllowed();
break;
}else{
pos1 += dist_delta;
pos2 -= dist_delta;
}
l->DeleteIfAllowed();
sub_sl->DeleteIfAllowed();
}
}
}
}
//////////////////////////////////////////////////////////////////////
cross_tuple->DeleteIfAllowed();
route_tuple->DeleteIfAllowed();
}
}
/*
get the interesting points locate on both sides of a road region
*/
void StrRS::GetInterestingPoints(HalfSegment hs, Point ip,
vector<MyPoint>& intersect_ps,
Region* reg1, Region* reg2)
{
Point p1 = hs.GetLeftPoint();
Point p2 = hs.GetRightPoint();
const double delta_dist = 10.0;
Line* line1 = new Line(0);
if(MyAlmostEqual(p1.GetX(), p2.GetX())){
double y = ip.GetY();
double x1 = ip.GetX() - delta_dist;
double x2 = ip.GetX() + delta_dist;
line1->StartBulkLoad();
HalfSegment hs;
Point lp,rp;
lp.Set(x1, y);
rp.Set(x2, y);
hs.Set(true,lp,rp);
int edgeno = 0;
hs.attr.edgeno = edgeno++;
*line1 += hs;
hs.SetLeftDomPoint(!hs.IsLeftDomPoint());
*line1 += hs;
line1->EndBulkLoad();
}else if(MyAlmostEqual(p1.GetY(), p2.GetY())){
double y1 = ip.GetY() - delta_dist;
double y2 = ip.GetY() + delta_dist;
double x = ip.GetX();
line1->StartBulkLoad();
HalfSegment hs;
Point lp,rp;
lp.Set(x, y1);
rp.Set(x, y2);
hs.Set(true,lp,rp);
int edgeno = 0;
hs.attr.edgeno = edgeno++;
*line1 += hs;
hs.SetLeftDomPoint(!hs.IsLeftDomPoint());
*line1 += hs;
line1->EndBulkLoad();
}else{//not vertical
double k1 = (p2.GetY() - p1.GetY())/(p2.GetX() - p1.GetX());
double k2 = -1/k1;
double c2 = ip.GetY() - ip.GetX()*k2;
double x1 = ip.GetX() - delta_dist;
double x2 = ip.GetX() + delta_dist;
line1->StartBulkLoad();
HalfSegment hs;
Point lp,rp;
lp.Set(x1, x1*k2 + c2);
rp.Set(x2, x2*k2 + c2);
hs.Set(true,lp,rp);
int edgeno = 0;
hs.attr.edgeno = edgeno++;
*line1 += hs;
hs.SetLeftDomPoint(!hs.IsLeftDomPoint());
*line1 += hs;
line1->EndBulkLoad();
}
vector<MyPoint> temp;
// cout<<"ip "<<ip<<" created line "<<*line1<<endl;
Line* l1 = new Line(0);
Line* l2 = new Line(0);
line1->Intersection(*reg1, *l1);
line1->Intersection(*reg2, *l2);
// cout<<l1->Size()<<" "<<l2->Size()<<endl;
if(l1->Size() >= 2 && l2->Size() >= 2){
Point lp, rp;
for(int i = 0;i < l1->Size();i++){
HalfSegment hs;
l1->Get(i, hs);
if(!hs.IsLeftDomPoint())continue;
lp = hs.GetLeftPoint();
rp = hs.GetRightPoint();
// cout<<"lp1 "<<lp<<" rp1 "<<rp<<endl;
MyPoint mp_l(lp, lp.Distance(ip));
temp.push_back(mp_l);
MyPoint mp_r(rp, rp.Distance(ip));
temp.push_back(mp_r);
}
for(int i = 0;i < l2->Size();i++){
HalfSegment hs;
l2->Get(i, hs);
if(!hs.IsLeftDomPoint())continue;
lp = hs.GetLeftPoint();
rp = hs.GetRightPoint();
// cout<<"lp2 "<<lp<<" rp2 "<<rp<<endl;
MyPoint mp_l(lp, lp.Distance(ip));
temp.push_back(mp_l);
MyPoint mp_r(rp, rp.Distance(ip));
temp.push_back(mp_r);
}
sort(temp.begin(),temp.end());
assert(temp.size() >= 4);
for(unsigned int i = 0;i < 4;i++){
intersect_ps.push_back(temp[i]);
}
l1->DeleteIfAllowed();
l2->DeleteIfAllowed();
line1->DeleteIfAllowed();
}
}
/*
Generate Interesting points on pavement
*/
void StrRS::GenPoints1(int attr_pos1, int attr_pos2, int attr_pos3,
int attr_pos4, int no_ps)
{
const double dist_deta = 2.0;
// cout<<"generating no_ps points "<<no_ps<<endl;
int no_sub_sec = r1->GetNoTuples();
struct timeval tval;
struct timezone tzone;
gettimeofday(&tval, &tzone);
srand48(tval.tv_sec);
while(no_ps > 0){
//randomly selects a section
// int m = lrand48() % no_sub_sec + 1;
int m = GetRandom() % no_sub_sec + 1;
Tuple* tuple_sec = r1->GetTuple(m, false);
int rid = ((CcInt*)tuple_sec->GetAttribute(attr_pos1))->GetIntval();
Line* l = (Line*)tuple_sec->GetAttribute(attr_pos2);
//randomly selects a halfsegment in the section
int no_hs = l->Size();
// int hs_index = lrand48()% no_hs;
int hs_index = GetRandom()% no_hs;
HalfSegment hs;
l->Get(hs_index, hs);
double length = hs.Length();
if(length > dist_deta){
// int pos = lrand48()% ((int)floor(length));
int pos = GetRandom() % ((int)floor(length));
assert(0 <= pos && pos <= length);
// cout<<"rid "<<rid<<" length "<<length<<" pos "<<pos<<endl;
Point ip;
ip = hs.AtPosition(pos);
vector<MyPoint> intersect_ps;
Tuple* tuple_pave = r2->GetTuple(rid, false);
Region* pave_reg1 = (Region*)tuple_pave->GetAttribute(attr_pos3);
Region* pave_reg2 = (Region*)tuple_pave->GetAttribute(attr_pos4);
GetInterestingPoints(hs, ip, intersect_ps, pave_reg1, pave_reg2);
tuple_pave->DeleteIfAllowed();
for(unsigned int i = 0;i < intersect_ps.size();i++){
rids.push_back(rid);
ps.push_back(ip);
if(i == 0 || i == 1)
ps_type.push_back(false);
else
ps_type.push_back(true);
interestps.push_back(intersect_ps[i].loc);
}
no_ps -= intersect_ps.size();
}
tuple_sec->DeleteIfAllowed();
}
}
/*
traverse the Rtree to find which triangle contains the point
*/
void StrRS::DFTraverse(R_Tree<2,TupleId>* rtree, SmiRecordId adr, Point* p,
int attr_pos)
{
R_TreeNode<2,TupleId>* node = rtree->GetMyNode(adr,false,
rtree->MinEntries(0), rtree->MaxEntries(0));
for(int j = 0;j < node->EntryCount();j++){
if(node->IsLeaf()){
R_TreeLeafEntry<2,TupleId> e =
(R_TreeLeafEntry<2,TupleId>&)(*node)[j];
Tuple* dg_tuple2 = r2->GetTuple(e.info, false);
Region* candi_reg =
(Region*)dg_tuple2->GetAttribute(attr_pos);
if(candi_reg->Contains(*p)){
for(int i = 0;i < candi_reg->Size();i++){
HalfSegment hs;
candi_reg->Get(i, hs);
if(!hs.IsLeftDomPoint())continue;
if(hs.Contains(*p)){
rids.push_back(e.info);
BBox<2> bbox = candi_reg->BoundingBox();
Coord x = p->GetX() - bbox.MinD(0);
Coord y = p->GetY() - bbox.MinD(1);
Point new_p(true, x, y);
interestps.push_back(new_p);
ps.push_back(*p);
break;
}
}
}
dg_tuple2->DeleteIfAllowed();
}else{
R_TreeInternalEntry<2> e =
(R_TreeInternalEntry<2>&)(*node)[j];
if(p->Inside(e.box)){
DFTraverse(rtree, e.pointer, p, attr_pos);
}
}
}
delete node;
}
/*
mapping the point into a triangle
*/
void StrRS::GenPoints2(R_Tree<2,TupleId>* rtree, int attr_pos1,
int attr_pos2, unsigned int no_ps)
{
SmiRecordId adr = rtree->RootRecordId();
for(int i = 1;i <= r1->GetNoTuples();i++){
Tuple* point_tuple = r1->GetTuple(i, false);
Point* p1 = (Point*)point_tuple->GetAttribute(attr_pos1);
DFTraverse(rtree, adr, p1, attr_pos2);
point_tuple->DeleteIfAllowed();
if(rids.size() == no_ps)break;
}
if(rids.size() < no_ps){
cout<<"WARNING!!! not enough points found"<<endl;
}
}
//////////////////////////////////////////////////////////////////////////////
///////////////////data cleaning process/////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
/*
modify the coordinates of a line value, not so many numbers after dot
*/
void DataClean::ModifyLine(SimpleLine* in, SimpleLine* out)
{
// *out = *in;
out->Clear();
out->StartBulkLoad();
int edgeno = 0;
static int line_id = 1;
const double delta_dist = 0.001;
for(int i = 0;i < in->Size();i++){
HalfSegment hs1;
in->Get(i, hs1);
if(!hs1.IsLeftDomPoint()) continue;
Point lp = hs1.GetLeftPoint();
Point rp = hs1.GetRightPoint();
// Modify_Point2(lp);
// Modify_Point2(rp);
HalfSegment hs2(true, lp, rp);
hs2.attr.edgeno = edgeno++;
*out += hs2;
hs2.SetLeftDomPoint(!hs2.IsLeftDomPoint());
*out += hs2;
if(lp.Distance(rp) < delta_dist){
cout<<line_id<<endl;
line_id++;
}
}
out->EndBulkLoad();
}
/*
check the coordinates; data clean for roads data
it checks whether two roads have overlapping. if it is, then delete the two
old roads, and create a new one by doing union on them
using traverse rtree to improve efficiency
much faster than navie algorithm (two loops)
*/
void DataClean::CheckRoads(Relation* rel, R_Tree<2,TupleId>* rtree)
{
/*vector<Line> new_line_list;
for(unsigned int i = 0;i < line_list.size();i++){
Line* l1 = &(line_list[i]);
//////////////////////naive method///////////////////////////
for(unsigned int j = i + 1;j < line_list.size();j++){
Line* l2 = &line_list[j];
Line* res = new Line(0);
l1->Intersection(*l2, *res);
if(res->IsDefined() && res->Length() > 0.0){
flag_list[i] = false;
flag_list[j] = false;
cout<<"len "<<res->Length()
<<" l1 "<<line_id_list[i]<<" l2 "<<line_id_list[j]<<endl;
Line* res2 = new Line(0);
l1->Union(*l2, *res2);
new_line_list.push_back(*res2);
delete res2;
}
delete res;
}
}
for(unsigned int i = 0;i < flag_list.size();i++){
if(flag_list[i] == false) continue;
SimpleLine* sl = new SimpleLine(0);
sl->fromLine(line_list[i]);
sl_list.push_back(*sl);
delete sl;
}
//////new generated line/////
for(unsigned int i = 0;i < new_line_list.size();i++){
SimpleLine* sl = new SimpleLine(0);
sl->fromLine(new_line_list[i]);
sl_list.push_back(*sl);
delete sl;
}*/
/* vector<bool> flag_list;
vector<Line> line_list;
vector<SimpleLine> sline_list;
vector<int> line_id_list;
for(int i = 1;i <= rel->GetNoTuples();i++){
flag_list.push_back(true);
Tuple* road_tuple = rel->GetTuple(i, false);
SimpleLine* sl = (SimpleLine*)road_tuple->GetAttribute(ROUTE_CURVE);
line_id_list.push_back(i);
Line* l = new Line(0);
sl->toLine(*l);
line_list.push_back(*l);
sline_list.push_back(*sl);
delete l;
road_tuple->DeleteIfAllowed();
}*/
// const double delta_len = 0.001;
//
// for(unsigned int i = 0;i < line_list.size();i++){
// Line* l1 = &(line_list[i]);
//
// vector<int> oid_list;
// DFTraverse(rel,rtree,rtree->RootRecordId(),l1, oid_list, i + 1);
// for(unsigned int j = 0;j < oid_list.size();j++){
// int index = oid_list[j] - 1;
// Line* l2 = &line_list[index];
//
// if(flag_list[index] == false) continue;
//
// if(l1->Inside(*l2)){
// flag_list[i] = false;//delete this line
// break;
// }
// if(l2->Inside(*l1)){
// flag_list[index] = false;
// }else {
//
// Line* res1 = new Line(0);
// l1->Intersection(*l2, *res1);
// if(res1->IsDefined() && res1->Length() > 0.0){
// double len1 = l1->Length();
// double len2 = l2->Length();
// cout<<"id1 "<<i + 1<<" id2 "<<j + 1<<" ";
// cout<<"len1 "<<len1<<" len2 "<<len2
// <<" comm "<<res1->Length()<<endl;
// assert(res1->Length() > delta_len);
// assert(len1 - res1->Length() > delta_len);
// assert(len2 - res1->Length() > delta_len);
//
// if(len1 > len2){
// Line* res = new Line(0);
// l1->Minus(*res1,*res);
// line_list[i] = *res;
// delete res;
// l1 = &(line_list[i]);
// }else{
// Line* res = new Line(0);
// l2->Minus(*res1,*res);
// line_list[index] = *res;
// delete res;
// }
// }
// delete res1;
// }
//
// }
//
// }
//
//
// for(unsigned int i = 0;i < flag_list.size();i++){
// if(flag_list[i] == false) continue;
//
// SimpleLine* sl = new SimpleLine(0);
// sl->fromLine(line_list[i]);
// if(sl->IsDefined() && sl->Length() > 0.0)
// sl_list.push_back(*sl);
// else
// cout<<"id "<<i+1<<endl;
//
// delete sl;
// }
//////////////////////////////////////////////////////////////////////////
/////////////// delete cycle ///////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
// for(int i = 1;i <= rel->GetNoTuples();i++){
// Tuple* road_tuple = rel->GetTuple(i, false);
// SimpleLine* sl = (SimpleLine*)road_tuple->GetAttribute(ROUTE_CURVE);
// if(sl->IsCycle() == false)
// sl_list.push_back(*sl);
// else{
// SpacePartition* sp = new SpacePartition();
// vector<MyHalfSegment> seq_halfseg; //reorder it from start to end
// sp->ReorderLine(sl, seq_halfseg);
//
//
// // double sum = 0;
// // for(int j = 0;j < seq_halfseg.size();j++){
// // Point p1 = seq_halfseg[j].from;
// // Point p2 = seq_halfseg[j].to;
// // sum += p1.Distance(p2);
// // }
// // cout<<sl->Length()<<" "<<sum<<endl;
// SimpleLine* sl1 = new SimpleLine(0);
// SimpleLine* sl2 = new SimpleLine(0);
// sl1->StartBulkLoad();
// sl2->StartBulkLoad();
// int half = seq_halfseg.size()/2;
// int edgeno = 0;
// for(int j = 0;j < half;j++){
// Point p1 = seq_halfseg[j].from;
// Point p2 = seq_halfseg[j].to;
// HalfSegment hs(true, p1, p2);
// hs.attr.edgeno = edgeno++;
// *sl1 += hs;
// hs.SetLeftDomPoint(!hs.IsLeftDomPoint());
// *sl1 += hs;
//
// }
// edgeno = 0;
// for(int j = half; j < seq_halfseg.size();j++){
// Point p1 = seq_halfseg[j].from;
// Point p2 = seq_halfseg[j].to;
// HalfSegment hs(true, p1, p2);
// hs.attr.edgeno = edgeno++;
// *sl2 += hs;
// hs.SetLeftDomPoint(!hs.IsLeftDomPoint());
// *sl2 += hs;
// }
//
//
// sl1->EndBulkLoad();
// sl2->EndBulkLoad();
//
//
// sl_list.push_back(*sl1);
// sl_list.push_back(*sl2);
//
// delete sl2;
// delete sl1;
//
// delete sp;
// }
//
//
// road_tuple->DeleteIfAllowed();
// }
// return;
////////////////////////////////////////////////////////////////////////////
/* for(int i = 1;i <= rel->GetNoTuples();i++){
Tuple* road_tuple1 = rel->GetTuple(i, false);
int id1 = ((CcInt*)road_tuple1->GetAttribute(ROUTE_ID))->GetIntval();
SimpleLine* sl1 = (SimpleLine*)road_tuple1->GetAttribute(ROUTE_CURVE);
bool s1 =
((CcBool*)road_tuple1->GetAttribute(ROUTE_STARTSSMALLER))->GetBoolval();
Line* l1 = new Line(0);
sl1->toLine(*l1);
vector<int> oid_list;
// DFTraverse(rel,rtree,rtree->RootRecordId(), l1, oid_list, i);
DFTraverse(rel,rtree,rtree->RootRecordId(), l1, oid_list, id1);
delete l1;
for(unsigned int index = 0;index < oid_list.size();index++){
int j = oid_list[index];
Tuple* road_tuple2 = rel->GetTuple(j, false);
int id2 = ((CcInt*)road_tuple2->GetAttribute(ROUTE_ID))->GetIntval();
SimpleLine* sl2 = (SimpleLine*)road_tuple2->GetAttribute(ROUTE_CURVE);
bool s2 =
((CcBool*)road_tuple2->GetAttribute(ROUTE_STARTSSMALLER))->GetBoolval();
Points* ps = new Points(0);
sl1->Crossings( *sl2, *ps);
if(ps->Size() == 0){
delete ps;
road_tuple2->DeleteIfAllowed();
continue;
}
// cout<<ps->Size()<<endl;
if(ps->Size() >= 3){
cout<<"id1 "<<id1<<" id2 "<<id2<<" no "<<ps->Size()<<endl;
}
// cout<<"id1 "<<id1<<" id2 "<<id2<<endl;
for(int k = 0;k < ps->Size();k++){
Point loc;
ps->Get(k, loc);
double pos1, pos2;
// cout<<"loc "<<loc<<endl;
if(sl1->AtPoint(loc, s1, pos1) == false){
cout<<"not find on simpleline1 "<<id1<<" loc "<<loc<<endl;
cout<<"id2 "<<id2<<endl;
}
if(sl2->AtPoint(loc, s2, pos2) == false){
cout<<"not find on simpleline2 "<<id2<<" loc "<<loc<<endl;
cout<<"id1 "<<id1<<endl;
}
}
delete ps;
road_tuple2->DeleteIfAllowed();
}
road_tuple1->DeleteIfAllowed();
} */
for(int i = 1;i <= rel->GetNoTuples();i++){
Tuple* road_tuple = rel->GetTuple(i, false);
int id = ((CcInt*)road_tuple->GetAttribute(ROUTE_ID))->GetIntval();
SimpleLine* sl = (SimpleLine*)road_tuple->GetAttribute(ROUTE_CURVE);
Line* l = new Line(0);
sl->toLine(*l);
vector<int> oid_list;
DFTraverse2(rel,rtree,rtree->RootRecordId(), l, oid_list, id);
l->DeleteIfAllowed();
road_tuple->DeleteIfAllowed();
if(oid_list.size() == 0){
cout<<"rid "<<id<<endl;
}
}
}
/*
traverse rtree to find lines intersect the input line
*/
void DataClean::DFTraverse(Relation* rel,
R_Tree<2,TupleId>* rtree, SmiRecordId adr,
Line* sl, vector<int>& id_list, unsigned int id)
{
R_TreeNode<2,TupleId>* node = rtree->GetMyNode(adr,false,
rtree->MinEntries(0), rtree->MaxEntries(0));
for(int j = 0;j < node->EntryCount();j++){
if(node->IsLeaf()){
R_TreeLeafEntry<2,TupleId> e =
(R_TreeLeafEntry<2,TupleId>&)(*node)[j];
Tuple* dg_tuple = rel->GetTuple(e.info, false);
SimpleLine* sline =
(SimpleLine*)dg_tuple->GetAttribute(ROUTE_CURVE);
unsigned int r_id =
((CcInt*)dg_tuple->GetAttribute(ROUTE_ID))->GetIntval();
if(r_id == id){
dg_tuple->DeleteIfAllowed();
continue;
}
if(sl->BoundingBox().Intersects(sline->BoundingBox())){
if(e.info != id)
id_list.push_back(e.info);
}
dg_tuple->DeleteIfAllowed();
}else{
R_TreeInternalEntry<2> e =
(R_TreeInternalEntry<2>&)(*node)[j];
if(sl->BoundingBox().Intersects(e.box)){
DFTraverse(rel,rtree, e.pointer, sl, id_list, id);
}
}
}
delete node;
}
void DataClean::DFTraverse2(Relation* rel,
R_Tree<2,TupleId>* rtree, SmiRecordId adr,
Line* sl, vector<int>& id_list, unsigned int id)
{
R_TreeNode<2,TupleId>* node = rtree->GetMyNode(adr,false,
rtree->MinEntries(0), rtree->MaxEntries(0));
for(int j = 0;j < node->EntryCount();j++){
if(node->IsLeaf()){
R_TreeLeafEntry<2,TupleId> e =
(R_TreeLeafEntry<2,TupleId>&)(*node)[j];
Tuple* dg_tuple = rel->GetTuple(e.info, false);
SimpleLine* sline =
(SimpleLine*)dg_tuple->GetAttribute(ROUTE_CURVE);
if(sl->BoundingBox().Intersects(sline->BoundingBox())){
Line* temp_l = new Line(0);
sline->toLine(*temp_l);
if(e.info != id && sl->Intersects(*temp_l)){
id_list.push_back(e.info);
}
temp_l->DeleteIfAllowed();
}
dg_tuple->DeleteIfAllowed();
}else{
R_TreeInternalEntry<2> e =
(R_TreeInternalEntry<2>&)(*node)[j];
if(sl->BoundingBox().Intersects(e.box)){
DFTraverse2(rel,rtree, e.pointer, sl, id_list, id);
}
}
}
delete node;
}
/////////////////////////////////////////////////////////////////////
////////a robust method to get the position of a point on a sline///
/////////////////////////////////////////////////////////////////////
double PointOnSline(SimpleLine* sl, Point* loc, bool b)
{
double res = -1.0;
double min_dist = 0.001;
SpacePartition* sp = new SpacePartition();
vector<MyHalfSegment> mhs_temp;
sp->ReorderLine(sl, mhs_temp);
delete sp;
Point start;
sl->AtPosition(0.0, b, start);
vector<MyHalfSegment> mhs;
if(mhs_temp[0].from.Distance(start) < min_dist){
for(unsigned int i = 0;i < mhs_temp.size();i++)
mhs.push_back(mhs_temp[i]);
}else{
for(int i = mhs_temp.size() - 1;i >= 0;i--){
MyHalfSegment seg = mhs_temp[i];
seg.Print();
seg.Exchange();
seg.Print();
mhs.push_back(seg);
}
}
double l = 0.0;
for(unsigned int i = 0;i < mhs.size();i++){
HalfSegment hs(true, mhs[i].from, mhs[i].to);
if(hs.Contains(*loc)){
l += loc->Distance(mhs[i].from);
res = l;
break;
}else
l += hs.Length();
}
if(fabs(res) < 0.000001) res = 0.0;
if(fabs(res - sl->Length()) < 0.000001) res = sl->Length();
double result;
if(sl->AtPoint(*loc, b, result) == false){
cout<<"error"<<endl;
}
if(fabs(res - result) > 0.001){
cout<<"too large deviation "<<endl;
cout<<"res "<<res<<" atpoint "<<result<<endl;
}
if(res < 0.0){
cout<<"error:not found on the sline "<<endl;
}
return res;
}