June 2018 Update
This commit is contained in:
parent
ba8067c3b7
commit
22f33d4004
5278 changed files with 84726 additions and 14379 deletions
|
|
@ -47,7 +47,7 @@ An algorithm for the previous speech could be (if P is a point, Px is its x coor
|
|||
'''end''' '''if'''
|
||||
'''if''' Py < Ay '''or''' Py > By '''then'''
|
||||
'''return''' false
|
||||
'''else''' '''if''' Px > max(Ax, Bx) '''then'''
|
||||
'''else''' '''if''' Px >= max(Ax, Bx) '''then'''
|
||||
'''return''' false
|
||||
'''else'''
|
||||
'''if''' Px < min(Ax, Bx) '''then'''
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ public class RayCasting {
|
|||
if (P[1] == A[1] || P[1] == B[1])
|
||||
P[1] += 0.0001;
|
||||
|
||||
if (P[1] > B[1] || P[1] < A[1] || P[0] > max(A[0], B[0]))
|
||||
if (P[1] > B[1] || P[1] < A[1] || P[0] >= max(A[0], B[0]))
|
||||
return false;
|
||||
|
||||
if (P[0] < min(A[0], B[0]))
|
||||
|
|
|
|||
|
|
@ -0,0 +1,45 @@
|
|||
module RayCastings
|
||||
|
||||
export Point
|
||||
|
||||
struct Point{T}
|
||||
x::T
|
||||
y::T
|
||||
end
|
||||
Base.show(io::IO, p::Point) = print(io, "($(p.x), $(p.y))")
|
||||
|
||||
const Edge = Tuple{Point{T}, Point{T}} where T
|
||||
Base.show(io::IO, e::Edge) = print(io, "$(e[1]) ∘-∘ $(e[2])")
|
||||
|
||||
function rayintersectseg(p::Point{T}, edge::Edge{T}) where T
|
||||
a, b = edge
|
||||
if a.y > b.y
|
||||
a, b = b, a
|
||||
end
|
||||
if p.y ∈ (a.y, b.y)
|
||||
p = Point(p.x, p.y + eps(p.y))
|
||||
end
|
||||
|
||||
rst = false
|
||||
if (p.y > b.y || p.y < a.y) || (p.x > max(a.x, b.x))
|
||||
return false
|
||||
end
|
||||
|
||||
if p.x < min(a.x, b.x)
|
||||
rst = true
|
||||
else
|
||||
mred = (b.y - a.y) / (b.x - a.x)
|
||||
mblu = (p.y - a.y) / (p.x - a.x)
|
||||
rst = mblu ≥ mred
|
||||
end
|
||||
|
||||
return rst
|
||||
end
|
||||
|
||||
isinside(poly::Vector{Tuple{Point{T}, Point{T}}}, p::Point{T}) where T =
|
||||
isodd(count(edge -> rayintersectseg(p, edge), poly))
|
||||
|
||||
connect(a::Point{T}, b::Point{T}...) where T =
|
||||
[(a, b) for (a, b) in zip(vcat(a, b...), vcat(b..., a))]
|
||||
|
||||
end # module RayCastings
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
let A = Point(0.0, 0.0),
|
||||
B = Point(0.0, 10.0),
|
||||
C = Point(10.0, 10.0),
|
||||
D = Point(10.0, 0.0),
|
||||
E = Point(2.5, 2.5),
|
||||
F = Point(2.5, 7.5),
|
||||
G = Point(7.5, 7.5),
|
||||
H = Point(7.5, 2.5),
|
||||
I = Point(3.0, 0.0),
|
||||
J = Point(7.0, 0.0),
|
||||
K = Point(10.0, 5.0),
|
||||
L = Point(7.0, 10.0),
|
||||
M = Point(3.0, 10.0),
|
||||
N = Point(0.0, 5.0),
|
||||
testpts = (Point(5.0, 5.0), Point(5.0, 8.0), Point(-10.0, 5.0), Point(0.0, 5.0),
|
||||
Point(10.0, 5.0), Point(8.0, 5.0), Point(10.0, 10.0))
|
||||
|
||||
square = RayCastings.connect(A, B, C, D)
|
||||
square_withhole = vcat(square, RayCastings.connect(E, F, G, H))
|
||||
strange = RayCastings.connect(A, E, B, F, G, C, D, E)
|
||||
exagon = RayCastings.connect(I, J, K, L, M, N)
|
||||
|
||||
println("\n# TESTING WHETHER POINTS ARE WITHIN POLYGONS")
|
||||
for poly in (square, square_withhole, strange, exagon)
|
||||
println("\nEdges: \n - ", join(poly, "\n - "))
|
||||
println("Inside/outside:")
|
||||
for p in testpts
|
||||
@printf(" - %-12s is %s\n", p, RayCastings.isinside(poly, p) ? "inside" : "outside")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -7,45 +7,44 @@ call poly 0 0, A A, 0 10, A B, B B, 10 10, 10 0 ; call test 'ir
|
|||
call poly 3 0, 7 0, 10 5, 7 10, 3 10, 0 5 ; call test 'hexagon'
|
||||
exit /*stick a fork in it, we're all done. */
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
in$out: procedure expose point. poly.; parse arg p; #=0
|
||||
do side=1 to poly.0 by 2; #=#+intersect(p,side); end /*side*/
|
||||
in$out: procedure expose point. poly.; parse arg p; #=0
|
||||
do side=1 to poly.0 by 2; #=# +intersect(p, side); end /*side*/
|
||||
return # // 2 /*ODD is inside. EVEN is outside.*/
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
intersect: procedure expose point. poly.; parse arg ?,s; sp=s+1
|
||||
epsilon='1e' || (-digits()%2); infinity="1e" || (digits() *2)
|
||||
Px=point.?.x; Ax=poly.s.x; Ay=poly.s.y
|
||||
Py=point.?.y; Bx=poly.sp.x; By=poly.sp.y /* [↓] do a swap.*/
|
||||
intersect: procedure expose point. poly.; parse arg ?,s; sp=s + 1
|
||||
epsilon= '1e' || (-digits() %2); infinity= "1e" || (digits() *2)
|
||||
Px=point.?.x; Ax=poly.s.x; Bx=poly.sp.x
|
||||
Py=point.?.y; Ay=poly.s.y; By=poly.sp.y /* [↓] do a vertex swap*/
|
||||
if Ay>By then parse value Ax Ay Bx By with Bx By Ax Ay
|
||||
if Py=Ay | Py=By then Py=Py + epsilon
|
||||
if Py<Ay | Py>By | Px>max(Ax,Bx) then return 0
|
||||
if Px<min(Ax,Bx) then return 1
|
||||
if Ax\=Bx then m_red =(By-Ay) / (Bx-Ax)
|
||||
else m_red =infinity
|
||||
if Ax\=Px then m_blue=(Py-Ay) / (Px-Ax)
|
||||
else return 1
|
||||
return m_blue >= m_red
|
||||
if Py<Ay | Py>By | Px>max(Ax, Bx) then return 0
|
||||
if Px<min(Ax, Bx) then return 1
|
||||
if Ax\=Bx then red = (By-Ay) / (Bx-Ax)
|
||||
else red = infinity
|
||||
if Ax\=Px then return (Py-Ay) / (Px-Ax) >= red
|
||||
return 1
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
points: wx=0; wy=0; do j=1 for arg(); parse value arg(j) with xx yy
|
||||
wx=max(wx, length(xx) ); call value 'POINT.'j".X", xx
|
||||
wy=max(wy, length(yy) ); call value 'POINT.'j".Y", yy
|
||||
points: wx=0; wy=0; do j=1 for arg(); parse value arg(j) with xx yy
|
||||
wx=max(wx, length(xx) ); call value 'POINT.'j".X", xx
|
||||
wy=max(wy, length(yy) ); call value 'POINT.'j".Y", yy
|
||||
end /*j*/
|
||||
call value point.0, j-1 /*define the number of points. */
|
||||
return
|
||||
return /* [↑] adjust J (for DO loop)*/
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
poly: @='POLY.'; parse arg Fx Fy /* [↓] process the X,Y points.*/
|
||||
poly: @= 'POLY.'; parse arg Fx Fy /* [↓] process the X,Y points.*/
|
||||
n=0
|
||||
do j=1 for arg(); n=n+1; parse value arg(j) with xx yy
|
||||
call value @ || n'.X', xx ; call value @ || n".Y", yy
|
||||
if n//2 then iterate; n=n+1
|
||||
call value @ || n'.X', xx ; call value @ || n".Y", yy
|
||||
do j=1 for arg(); n=n + 1; parse value arg(j) with xx yy
|
||||
call value @ || n'.X', xx ; call value @ || n".Y", yy
|
||||
if n//2 then iterate; n=n + 1 /*Inside? Then skip this point.*/
|
||||
call value @ || n'.X', xx ; call value @ || n".Y", yy
|
||||
end /*j*/
|
||||
n=n+1
|
||||
call value @ || n'.X', Fx; call value @ || n".Y", Fy; call value @'0',n
|
||||
return /*POLY.0 is # segments(sides).*/
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
test: say; do k=1 for point.0; w=wx+wy+2
|
||||
say right(' ['arg(1)"] point:", 30),
|
||||
right( right(point.k.x, wx)', 'right(point.k.y, wy), w) " is ",
|
||||
right( word('outside inside', in$out(k)+1), 7)
|
||||
end /*k*/
|
||||
n=n + 1 /*POLY.0 is # segments(sides).*/
|
||||
call value @ || n'.X', Fx; call value @ || n".Y", Fy; call value @'0', n
|
||||
return
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
test: say; do k=1 for point.0; w=wx + wy + 2 /*W, WX, WY ≡are various widths*/
|
||||
say right(' ['arg(1)"] point:", 30),
|
||||
right( right(point.k.x, wx)', 'right(point.k.y, wy), w) " is ",
|
||||
right( word('outside inside', in$out(k) + 1), 7)
|
||||
end /*k*/
|
||||
return /* [↑] format the output nicely*/
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
boolean?)]))
|
||||
|
||||
(struct point (x y) #:transparent)
|
||||
(struct seg (Ax Ay Bx By))
|
||||
(struct seg (Ax Ay Bx By) #:transparent)
|
||||
(define ε 0.000001)
|
||||
(define (neq? x y) (not (eq? x y)))
|
||||
|
||||
|
|
@ -23,17 +23,23 @@
|
|||
(eq? Pyo By))
|
||||
ε 0))])
|
||||
|
||||
(cond [(or (< Py Ay) (> Py By)) #f]
|
||||
(define Ax2 (if (< Ay By) Ax Bx))
|
||||
(define Ay2 (if (< Ay By) Ay By))
|
||||
(define Bx2 (if (< Ay By) Bx Ax))
|
||||
(define By2 (if (< Ay By) By Ay))
|
||||
|
||||
(cond [(or (> Py (max Ay By)) (< Py (min Ay By))) #f]
|
||||
[(> Px (max Ax Bx)) #f]
|
||||
[(< Px (min Ax Bx)) #t]
|
||||
[else
|
||||
(let ([red (if (neq? Ax Px)
|
||||
(/ (- By Ay) (- Bx Ax))
|
||||
+inf.0)]
|
||||
[blue (if (neq? Ax Px)
|
||||
(/ (- Py Ax) (- Px Ax))
|
||||
+inf.0)])
|
||||
(if (>= blue red) #t #f))])))
|
||||
[else (cond
|
||||
[(< Px (min Ax Bx)) #t]
|
||||
[else
|
||||
(let ([red (if (neq? Ax2 Bx2)
|
||||
(/ (- By2 Ay2) (- Bx2 Ax2))
|
||||
+inf.0)]
|
||||
[blue (if (neq? Ax2 Px)
|
||||
(/ (- Py Ay2) (- Px Ax2))
|
||||
+inf.0)])
|
||||
(if (>= blue red) #t #f))])])))
|
||||
|
||||
(define (point-in-polygon? point polygon)
|
||||
(odd?
|
||||
|
|
|
|||
|
|
@ -1,71 +1,83 @@
|
|||
use std::f64;
|
||||
use std::clone::Clone;
|
||||
|
||||
const _EPS: f64 = 0.00001;
|
||||
const _MIN: f64 = f64::MIN_POSITIVE;
|
||||
const _MAX: f64 = f64::MAX;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Clone)]
|
||||
struct Point {
|
||||
x: f64,
|
||||
y: f64
|
||||
y: f64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Clone)]
|
||||
struct Edge {
|
||||
pt1: Point,
|
||||
pt2: Point
|
||||
pt2: Point,
|
||||
}
|
||||
|
||||
impl Edge {
|
||||
fn new(pt1: (f64, f64), pt2: (f64, f64)) -> Edge {
|
||||
Edge { pt1: Point {x: pt1.0, y: pt1.1}, pt2: Point {x: pt2.0, y: pt2.1} }
|
||||
Edge {
|
||||
pt1: Point { x: pt1.0, y: pt1.1 },
|
||||
pt2: Point { x: pt2.0, y: pt2.1 },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Polygon{
|
||||
edges: Vec<Edge> // Polygon has to be created with counter-clockwise coordinates
|
||||
struct Polygon {
|
||||
edges: Vec<Edge>, // Polygon has to be created with counter-clockwise coordinates
|
||||
}
|
||||
|
||||
fn pt_in_polygon(pt: &Point, poly: &Polygon) -> bool {
|
||||
poly.edges.iter()
|
||||
.map(|edge| ray_intersect_seg(pt, edge))
|
||||
.fold(0u8, |sum, val| sum + (val as u8)) % 2 == 1
|
||||
let count = poly.edges
|
||||
.iter()
|
||||
.filter(|edge| ray_intersect_seg(pt, edge))
|
||||
.count();
|
||||
|
||||
count % 2 == 1
|
||||
}
|
||||
|
||||
fn ray_intersect_seg(p: &Point, edge: &Edge) -> bool {
|
||||
let mut pt = p.clone();
|
||||
let (mut a, mut b): (&Point, &Point) = (&edge.pt1, &edge.pt2);
|
||||
if a.y > b.y {
|
||||
let t = a; a = b; b = t;
|
||||
std::mem::swap(&mut a, &mut b);
|
||||
}
|
||||
if pt.y == a.y || pt.y == b.y {
|
||||
pt = Point {x: pt.x, y: pt.y + _EPS};
|
||||
pt.y += _EPS;
|
||||
}
|
||||
|
||||
if (pt.y > b.y || pt.y < a.y) || pt.x > a.x.max(b.x) {
|
||||
return false;
|
||||
}
|
||||
if pt.x < a.x.min(b.x) {
|
||||
return true;
|
||||
false
|
||||
} else if pt.x < a.x.min(b.x) {
|
||||
true
|
||||
} else {
|
||||
let m_red = if (a.x - b.x).abs() > _MIN { (b.y - a.y) / (b.x - a.x) } else { _MAX };
|
||||
let m_blue = if (a.x - pt.x).abs() > _MIN { (pt.y - a.y) / (pt.x - a.x) } else { _MAX };
|
||||
return m_blue >= m_red;
|
||||
let m_red = if (a.x - b.x).abs() > _MIN {
|
||||
(b.y - a.y) / (b.x - a.x)
|
||||
} else {
|
||||
_MAX
|
||||
};
|
||||
let m_blue = if (a.x - pt.x).abs() > _MIN {
|
||||
(pt.y - a.y) / (pt.x - a.x)
|
||||
} else {
|
||||
_MAX
|
||||
};
|
||||
m_blue >= m_red
|
||||
}
|
||||
}
|
||||
|
||||
fn main(){
|
||||
let p = |x,y| Point {x: x, y: y};
|
||||
let testpoints = vec![p(5.0, 5.0), p(5.0, 8.0), p(-10.0, 5.0), p(0.0, 5.0), p(10.0, 5.0), p(8.0, 5.0), p(10.0, 10.0)];
|
||||
fn main() {
|
||||
let p = |x, y| Point { x, y };
|
||||
let testpoints = [p(5.0, 5.0), p(5.0, 8.0), p(-10.0, 5.0), p(0.0, 5.0), p(10.0, 5.0), p(8.0, 5.0), p(10.0, 10.0)];
|
||||
let poly_square = Polygon {
|
||||
edges: vec![
|
||||
Edge::new((0.0, 0.0), (10.0, 0.0)),
|
||||
Edge::new((10.0, 0.0), (10.0, 10.0)),
|
||||
Edge::new((10.0, 10.0), (0.0, 10.0)),
|
||||
Edge::new((0.0, 10.0), (0.0, 0.0))
|
||||
]
|
||||
};
|
||||
Edge::new((0.0, 10.0), (0.0, 0.0)),
|
||||
],
|
||||
};
|
||||
let poly_square_hole = Polygon {
|
||||
edges: vec![
|
||||
Edge::new((0.0, 0.0), (10.0, 0.0)),
|
||||
|
|
@ -75,8 +87,8 @@ fn main(){
|
|||
Edge::new((2.5, 2.5), (7.5, 2.5)),
|
||||
Edge::new((7.5, 2.5), (7.5, 7.5)),
|
||||
Edge::new((7.5, 7.5), (2.5, 7.5)),
|
||||
Edge::new((2.5, 7.5), (2.5, 2.5))
|
||||
]
|
||||
Edge::new((2.5, 7.5), (2.5, 2.5)),
|
||||
],
|
||||
};
|
||||
let poly_strange = Polygon {
|
||||
edges: vec![
|
||||
|
|
@ -86,8 +98,8 @@ fn main(){
|
|||
Edge::new((2.5, 7.5), (7.5, 7.5)),
|
||||
Edge::new((7.5, 7.5), (10.0, 10.0)),
|
||||
Edge::new((10.0, 10.0), (10.0, 0.0)),
|
||||
Edge::new((10.0, 0.0), (2.5, 2.5))
|
||||
]
|
||||
Edge::new((10.0, 0.0), (2.5, 2.5)),
|
||||
],
|
||||
};
|
||||
let poly_hexagon = Polygon {
|
||||
edges: vec![
|
||||
|
|
@ -96,24 +108,24 @@ fn main(){
|
|||
Edge::new((10.0, 5.0), (7.0, 10.0)),
|
||||
Edge::new((7.0, 10.0), (3.0, 10.0)),
|
||||
Edge::new((3.0, 10.0), (0.0, 5.0)),
|
||||
Edge::new((0.0, 5.0), (3.0, 0.0))
|
||||
]
|
||||
};
|
||||
Edge::new((0.0, 5.0), (3.0, 0.0)),
|
||||
],
|
||||
};
|
||||
print!("\nSquare :");
|
||||
for pt in testpoints.iter() {
|
||||
for pt in &testpoints {
|
||||
print!(" {:?}", pt_in_polygon(pt, &poly_square));
|
||||
}
|
||||
print!("\nSquare with hole:");
|
||||
for pt in testpoints.iter() {
|
||||
for pt in &testpoints {
|
||||
print!(" {:?}", pt_in_polygon(pt, &poly_square_hole));
|
||||
}
|
||||
print!("\nStrange polygon :");
|
||||
for pt in testpoints.iter() {
|
||||
for pt in &testpoints {
|
||||
print!(" {:?}", pt_in_polygon(pt, &poly_strange));
|
||||
}
|
||||
print!("\nHexagon :");
|
||||
for pt in testpoints.iter() {
|
||||
for pt in &testpoints {
|
||||
print!(" {:?}", pt_in_polygon(pt, &poly_hexagon));
|
||||
}
|
||||
print!("\n");
|
||||
println!();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,47 @@
|
|||
Imports System.Math
|
||||
|
||||
Module RayCasting
|
||||
|
||||
Private square As Integer()() = {New Integer() {0, 0}, New Integer() {20, 0}, New Integer() {20, 20}, New Integer() {0, 20}}
|
||||
Private squareHole As Integer()() = {New Integer() {0, 0}, New Integer() {20, 0}, New Integer() {20, 20}, New Integer() {0, 20}, New Integer() {5, 5}, New Integer() {15, 5}, New Integer() {15, 15}, New Integer() {5, 15}}
|
||||
Private strange As Integer()() = {New Integer() {0, 0}, New Integer() {5, 5}, New Integer() {0, 20}, New Integer() {5, 15}, New Integer() {15, 15}, New Integer() {20, 20}, New Integer() {20, 0}}
|
||||
Private hexagon As Integer()() = {New Integer() {6, 0}, New Integer() {14, 0}, New Integer() {20, 10}, New Integer() {14, 20}, New Integer() {6, 20}, New Integer() {0, 10}}
|
||||
Private shapes As Integer()()() = {square, squareHole, strange, hexagon}
|
||||
|
||||
Public Sub Main()
|
||||
Dim testPoints As Double()() = {New Double() {10, 10}, New Double() {10, 16}, New Double() {-20, 10}, New Double() {0, 10}, New Double() {20, 10}, New Double() {16, 10}, New Double() {20, 20}}
|
||||
|
||||
For Each shape As Integer()() In shapes
|
||||
For Each point As Double() In testPoints
|
||||
Console.Write(String.Format("{0} ", Contains(shape, point).ToString.PadLeft(7)))
|
||||
Next
|
||||
Console.WriteLine()
|
||||
Next
|
||||
End Sub
|
||||
|
||||
Private Function Contains(shape As Integer()(), point As Double()) As Boolean
|
||||
|
||||
Dim inside As Boolean = False
|
||||
Dim length As Integer = shape.Length
|
||||
|
||||
For i As Integer = 0 To length - 1
|
||||
If Intersects(shape(i), shape((i + 1) Mod length), point) Then
|
||||
inside = Not inside
|
||||
End If
|
||||
Next
|
||||
|
||||
Return inside
|
||||
End Function
|
||||
|
||||
Private Function Intersects(a As Integer(), b As Integer(), p As Double()) As Boolean
|
||||
|
||||
If a(1) > b(1) Then Return Intersects(b, a, p)
|
||||
If p(1) = a(1) Or p(1) = b(1) Then p(1) += 0.0001
|
||||
If p(1) > b(1) Or p(1) < a(1) Or p(0) > Max(a(0), b(0)) Then Return False
|
||||
If p(0) < Min(a(0), b(0)) Then Return True
|
||||
Dim red As Double = (p(1) - a(1)) / (p(0) - a(0))
|
||||
Dim blue As Double = (b(1) - a(1)) / (b(0) - a(0))
|
||||
|
||||
Return red >= blue
|
||||
End Function
|
||||
End Module
|
||||
Loading…
Add table
Add a link
Reference in a new issue