Skip to content

Commit b246350

Browse files
committed
merged
2 parents e99191f + 2aad7c9 commit b246350

File tree

4 files changed

+85
-16
lines changed

4 files changed

+85
-16
lines changed

content/geometry/Point.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
*/
1010
#pragma once
1111

12-
template <typename T> int sgn(T x) { return (x > 0) - (x < 0);}
12+
template <class T> int sgn(T x) { return (x > 0) - (x < 0); }
1313
template<class T>
1414
struct Point {
1515
typedef Point P;

content/geometry/SegmentIntersection.h

+12-14
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,13 @@
66
* Description:\\
77
\begin{minipage}{75mm}
88
If a unique intersection point between the line segments going from s1 to e1 and from s2 to e2 exists then it is returned.
9+
<<<<<<< HEAD
910
If no intersection point exists an empty vector is returned. If infinitely many exist a vector with 2 elements is returned.
1011
The wrong position will be returned if P is Point<int> and the intersection point does not have integer coordinates.
12+
=======
13+
If no intersection point exists an empty vector is returned. If infinitely many exist a vector with 2 elements is returned, containing the endpoints of the common line segment.
14+
The wrong position will be returned if P is Point<ll> and the intersection point does not have integer coordinates.
15+
>>>>>>> true/master
1116
Products of three coordinates are used in intermediate steps so watch out for overflow if using int or long long.
1217
\end{minipage}
1318
\begin{minipage}{15mm}
@@ -16,31 +21,24 @@ Products of three coordinates are used in intermediate steps so watch out for ov
1621
* Status: Well tested with fuzz-test and with Kattis problem intersection.
1722
* Usage:
1823
* vector<P> inter = segInter(s1,e1,s2,e2);
19-
* if (inter.size()==1)
24+
* if (sz(inter)==1)
2025
* cout << "segments intersect at " << inter[0] << endl;
2126
*/
2227
#pragma once
2328

2429
#include "Point.h"
2530
#include "onSegment.h"
2631

27-
template <class P>
28-
bool segInterProper(P a, P b, P c, P d, P& out) {
29-
double oa = c.cross(d, a), ob = c.cross(d, b),
30-
oc = a.cross(b, c), od = a.cross(b, d);
31-
if (sgn(oa) * sgn(ob) < 0 && sgn(oc) * sgn(od) < 0) {
32-
out = (a * ob - b * oa) / (ob - oa);
33-
return true;
34-
}
35-
return false;
36-
}
3732
template<class P> vector<P> segInter(P a, P b, P c, P d) {
38-
P out;
39-
if (segInterProper(a, b, c, d, out)) return {out};
33+
auto oa = c.cross(d, a), ob = c.cross(d, b),
34+
oc = a.cross(b, c), od = a.cross(b, d);
35+
// Checks if intersection is single non-endpoint point.
36+
if (sgn(oa) * sgn(ob) < 0 && sgn(oc) * sgn(od) < 0)
37+
return {(a * ob - b * oa) / (ob - oa)};
4038
set<P> s;
4139
if (onSegment(c, d, a)) s.insert(a);
4240
if (onSegment(c, d, b)) s.insert(b);
4341
if (onSegment(a, b, c)) s.insert(c);
4442
if (onSegment(a, b, d)) s.insert(d);
45-
return vector<P>(all(s));
43+
return {all(s)};
4644
}

content/geometry/onSegment.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,5 @@
1111
#include "Point.h"
1212

1313
template <class P> bool onSegment(P s, P e, P p) {
14-
return s.cross(e, p) == 0 && (s - p).dot(e - p) <= 0;
14+
return p.cross(s, e) == 0 && (s - p).dot(e - p) <= 0;
1515
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
#include <bits/stdc++.h>
2+
using namespace std;
3+
4+
#define rep(i, a, b) for(int i = a; i < int(b); ++i)
5+
#define trav(a, v) for(auto& a : v)
6+
#define all(x) x.begin(), x.end()
7+
#define sz(x) (int)(x).size()
8+
9+
typedef long long ll;
10+
typedef pair<int, int> pii;
11+
typedef vector<int> vi;
12+
13+
14+
#include "../content/geometry/SegmentIntersection.h"
15+
namespace oldImpl {
16+
template<class P>
17+
int segmentIntersection(const P& s1, const P& e1,
18+
const P& s2, const P& e2, P& r1, P& r2) {
19+
if (e1==s1) {
20+
if (e2==s2) {
21+
if (e1==e2) { r1 = e1; return 1; } //all equal
22+
else return 0; //different point segments
23+
} else return segmentIntersection(s2,e2,s1,e1,r1,r2);//swap
24+
}
25+
//segment directions and separation
26+
P v1 = e1-s1, v2 = e2-s2, d = s2-s1;
27+
auto a = v1.cross(v2), a1 = v1.cross(d), a2 = v2.cross(d);
28+
if (a == 0) { //if parallel
29+
auto b1=s1.dot(v1), c1=e1.dot(v1),
30+
b2=s2.dot(v1), c2=e2.dot(v1);
31+
if (a1 || a2 || max(b1,min(b2,c2))>min(c1,max(b2,c2)))
32+
return 0;
33+
r1 = min(b2,c2)<b1 ? s1 : (b2<c2 ? s2 : e2);
34+
r2 = max(b2,c2)>c1 ? e1 : (b2>c2 ? s2 : e2);
35+
return 2-(r1==r2);
36+
}
37+
if (a < 0) { a = -a; a1 = -a1; a2 = -a2; }
38+
if (0<a1 || a<-a1 || 0<a2 || a<-a2)
39+
return 0;
40+
r1 = s1-v1*a2/a;
41+
return 1;
42+
}
43+
}
44+
typedef Point<double> P;
45+
ostream &operator<<(ostream &os, P p) { return cout << "(" << p.x << "," << p.y << ")"; }
46+
bool eq(P a, P b) {
47+
return (a-b).dist()<1e-8;
48+
}
49+
int main() {
50+
rep(t,0,1000000) {
51+
const int GRID=6;
52+
P a(rand()%GRID, rand()%GRID), b(rand()%GRID, rand()%GRID), c(rand()%GRID, rand()%GRID), d(rand()%GRID, rand()%GRID);
53+
P tmp1, tmp2;
54+
auto res = oldImpl::segmentIntersection(a,b,c,d, tmp1, tmp2);
55+
auto res2 = segInter(a,b,c,d);
56+
if (res != sz(res2)) {
57+
cout<<a<<' '<<b<<' '<<c<<' '<<d<<endl;
58+
cout<<"old: "<<res<<" new: "<<sz(res2)<<endl;
59+
}
60+
assert(res==sz(res2));
61+
if (res==1) {
62+
assert(eq(*res2.begin(), tmp1));
63+
} else if (res==2) {
64+
vector<P> a(res2.begin(), res2.end());
65+
vector<P> b({tmp1, tmp2});
66+
sort(all(b));
67+
assert(eq(a[0], b[0]) && eq(a[1],b[1]));
68+
}
69+
}
70+
cout<<"Tests passed!"<<endl;
71+
}

0 commit comments

Comments
 (0)