-
Notifications
You must be signed in to change notification settings - Fork 0
/
segment.cpp
144 lines (128 loc) · 4.39 KB
/
segment.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#include <cmath>
#include <stdio.h>
using std::abs;
double ep = 1e-10;
struct Point{
double x,y;
Point(double x,double y){
this->x =x;
this->y = y;
}
bool equals(Point o){
return abs(x-o.x)<ep && abs(y-o.y)<ep;
}
};
double crossProduct(Point start1, Point start2, Point end1, Point end2){
return (end1.x-start1.x)*(end2.y-start2.y)
-(end1.y-start1.y)*(end2.x-start2.x);
}
double triangleArea( Point a, Point b, Point c){
return abs(crossProduct(a, a, b, c));
}
bool arePointsCollinear(Point a, Point b, Point c){
return triangleArea(a, b, c)<ep;
}
struct Segment{
Point& start, &end;
Segment (Point &s,Point &e):start(s),end(e) {}
};
char doSegmentsIntersects(Segment one, Segment two);
bool containsPoint(Segment s, Point point){
return s.start.equals(point)|| s.end.equals(point);
}
bool doSegmentsIntersectExceptAtEnds(Segment one, Segment two){
char a = doSegmentsIntersects(one, two);
return a!='v' && a!='0' && a!='e';
}
bool doSegmentsIntersectAtEdge(Segment one, Segment two){
return doSegmentsIntersects(one, two) == 'e';
}
bool doSegmentsIntersectAtVertex(Segment one, Segment two){
char a = doSegmentsIntersects(one, two);
return a=='v';
}
bool doSegmentsIntersect(Segment one, Segment two){
return doSegmentsIntersects(one, two)!='0';
}
bool isPointBetweenSegment(Segment one, Point p){
if ( abs(one.start.x - one.end.x)>ep )
return ((one.start.x <= p.x) && (p.x <= one.end.x)) ||
((one.start.x >= p.x) && (p.x >= one.end.x) );
else
return ((one.start.y <= p.y) && (p.y <= one.end.y)) ||
((one.start.y >= p.y) && (p.y >= one.end.y));
}
//return 0 for no parallel intersection, e for if they overlap at an edge
char parallelSegmentIntersection(Segment one, Segment two){
if ( !arePointsCollinear( one.start, one.end, two.start) )
return '0';
if ( isPointBetweenSegment( one, two.start) ||
isPointBetweenSegment( one, two.end) ||
isPointBetweenSegment( two, one.start) ||
isPointBetweenSegment( two, one.end))
return 'e';
return '0';
}
char doSegmentsIntersects(Segment one, Segment two){
if(containsPoint(one,two.start) || containsPoint(one,two.end))
if(containsPoint(one,two.start) && containsPoint(one,two.end))
return 'e';
//else
//return 'v'; //Not quite correct. This potentially could be 'e'
double s,t;
double num, denom;
char code = '?';
denom = one.start.x * ( two.end.y - two.start.y ) +
one.end.x * ( two.start.y - two.end.y ) +
two.end.x * ( one.end.y - one.start.y ) +
two.start.x * ( one.start.y - one.end.y );
//Parallel
if(abs(denom) < ep)
return parallelSegmentIntersection(one, two);
num = one.start.x * ( two.end.y - two.start.y ) +
two.start.x * ( one.start.y - two.end.y ) +
two.end.x * ( two.start.y - one.start.y );
if( (abs(num) <ep) || (abs(num -denom)<ep) )
code = 'v';
s = num / denom;
num = -(one.start.x * ( two.start.y - one.end.y ) +
one.end.xi * ( one.start.y - two.start.y ) +
two.start.x * ( one.end.y - one.start.y ));
if( (abs(num) <ep) || (abs(num -denom)<ep) )
code = 'v';
t = num / denom;
if ( (0.0 < s) && (s < 1.0) &&
(0.0 < t) && (t < 1.0) )
code = '1';
else if ( (0.0 > s) || (s > 1.0) ||
(0.0 > t) || (t > 1.0) )
code = '0';
return code;
}
//Returns 0 for Sucess, -1 for parallel
int getIntersectionPoint(double x1, double y1, double x2, double y2,
double x3, double y3, double x4, double y4,
Point& ipt){
double s, num, denom;
denom = x1 * ( y4 - y3 ) +
x2 * ( y3 - y4 ) +
x4 * ( y2 - y1 ) +
x3 * ( y1 - y2 );
//Parallel
if(abs(denom) < ep)
return -1;
num = x1 * ( y4 - y3 ) +
x3 * ( y1 - y4 ) +
x4 * ( y3 - y1 );
s = num / denom;
num = -(x1 * ( y3 - y2 ) +
x2 * ( y1 - y3 ) +
x3 * ( y2 - y1 ));
ipt = Point( x1 + s * ( x2 - x1 ), y1 + s * ( y2 - y1 ));
return 0;
}
int getIntersectionPoint(Segment one, Segment two, Point& ipt){
return getIntersectionPoint(one.start.x,one.start.y,one.end.x,one.end.y,
two.start.x,two.start.y,two.end.x,two.end.y,
ipt);
}