September 2017 Update

This commit is contained in:
Ingy döt Net 2017-09-23 10:01:46 +02:00
parent bba7bfd280
commit ba8067c3b7
14570 changed files with 153136 additions and 63871 deletions

View file

@ -0,0 +1,58 @@
/**
* @return {boolean} true if (lng, lat) is in bounds
*/
function contains(bounds, lat, lng) {
//https://rosettacode.org/wiki/Ray-casting_algorithm
var count = 0;
for (var b = 0; b < bounds.length; b++) {
var vertex1 = bounds[b];
var vertex2 = bounds[(b + 1) % bounds.length];
if (west(vertex1, vertex2, lng, lat))
++count;
}
return count % 2;
/**
* @return {boolean} true if (x,y) is west of the line segment connecting A and B
*/
function west(A, B, x, y) {
if (A.y <= B.y) {
if (y <= A.y || y > B.y ||
x >= A.x && x >= B.x) {
return false;
} else if (x < A.x && x < B.x) {
return true;
} else {
return (y - A.y) / (x - A.x) > (B.y - A.y) / (B.x - A.x);
}
} else {
return west(B, A, x, y);
}
}
}
var square = {name: 'square', bounds: [{x: 0, y: 0}, {x: 20, y: 0}, {x: 20, y: 20}, {x: 0, y: 20}]};
var squareHole = {
name: 'squareHole',
bounds: [{x: 0, y: 0}, {x: 20, y: 0}, {x: 20, y: 20}, {x: 0, y: 20}, {x: 5, y: 5}, {x: 15, y: 5}, {x: 15, y: 15}, {x: 5, y: 15}]
};
var strange = {
name: 'strange',
bounds: [{x: 0, y: 0}, {x: 5, y: 5}, {x: 0, y: 20}, {x: 5, y: 15}, {x: 15, y: 15}, {x: 20, y: 20}, {x: 20, y: 0}]
};
var hexagon = {
name: 'hexagon',
bounds: [{x: 6, y: 0}, {x: 14, y: 0}, {x: 20, y: 10}, {x: 14, y: 20}, {x: 6, y: 20}, {x: 0, y: 10}]
};
var shapes = [square, squareHole, strange, hexagon];
var testPoints = [{lng: 10, lat: 10}, {lng: 10, lat: 16}, {lng: -20, lat: 10},
{lng: 0, lat: 10}, {lng: 20, lat: 10}, {lng: 16, lat: 10}, {lng: 20, lat: 20}];
for (var s = 0; s < shapes.length; s++) {
var shape = shapes[s];
for (var tp = 0; tp < testPoints.length; tp++) {
var testPoint = testPoints[tp];
console.log(JSON.stringify(testPoint) + '\tin ' + shape.name + '\t' + contains(shape.bounds, testPoint.lat, testPoint.lng));
}
}

View file

@ -1,7 +1,6 @@
package ray_casting
import java.lang.Double.*
import java.lang.Math.*
import java.lang.Double.MAX_VALUE
import java.lang.Double.MIN_VALUE
import java.lang.Math.abs
data class Point(val x: Double, val y: Double)
@ -9,8 +8,8 @@ data class Edge(val s: Point, val e: Point) {
operator fun invoke(p: Point) : Boolean = when {
s.y > e.y -> Edge(e, s).invoke(p)
p.y == s.y || p.y == e.y -> invoke(Point(p.x, p.y + epsilon))
p.y > e.y || p.y < s.y || p.x > max(s.x, e.x) -> false
p.x < min(s.x, e.x) -> true
p.y > e.y || p.y < s.y || p.x > Math.max(s.x, e.x) -> false
p.x < Math.min(s.x, e.x) -> true
else -> {
val blue = if (abs(s.x - p.x) > MIN_VALUE) (p.y - s.y) / (p.x - s.x) else MAX_VALUE
val red = if (abs(s.x - e.x) > MIN_VALUE) (e.y - s.y) / (e.x - s.x) else MAX_VALUE

View file

@ -1,5 +1,3 @@
package ray_casting
fun main(args: Array<String>) {
val figures = arrayOf(Figure("Square", arrayOf(Edge(Point(0.0, 0.0), Point(10.0, 0.0)), Edge(Point(10.0, 0.0), Point(10.0, 10.0)),
Edge(Point(10.0, 10.0), Point(0.0, 10.0)),Edge(Point(0.0, 10.0), Point(0.0, 0.0)))),

View file

@ -1,75 +0,0 @@
#lang racket
(module pip racket
(require racket/contract)
(provide point)
(provide seg)
(provide (contract-out [point-in-polygon? (->
point?
list?
boolean?)]))
(struct point (x y) #:transparent)
(struct seg (Ax Ay Bx By))
(define ε 0.000001)
(define (neq? x y) (not (eq? x y)))
(define (ray-cross-seg? r s)
(let* ([Ax (seg-Ax s)] [Ay (seg-Ay s)]
[Bx (seg-Bx s)] [By (seg-By s)]
[Px (point-x r)] [Pyo (point-y r)]
[Py (+ Pyo (if (or (eq? Pyo Ay)
(eq? Pyo By))
ε 0))])
(cond [(or (< Py Ay) (> Py 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))])))
(define (point-in-polygon? point polygon)
(odd?
(for/fold ([c 0]) ([seg polygon])
(+ c (if (ray-cross-seg? point seg) 1 0))))))
(require 'pip)
(define test-point-list
(list
(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)))
(define square
(list (seg 0.0 0.0 10.0 0.0)
(seg 10.0 0.0 10.0 10.0)
(seg 10.0 10.0 0.0 10.0)
(seg 0.0 0.0 0.0 10.0)))
(define exagon
(list (seg 3.0 0.0 7.0 0.0)
(seg 7.0 0.0 10.0 5.0)
(seg 10.0 5.0 7.0 10.0)
(seg 7.0 10.0 3.0 10.0)
(seg 0.0 5.0 3.0 10.0)
(seg 3.0 0.0 0.0 5.0)))
(define (test-figure fig name)
(printf "\ntesting ~a: \n" name)
(for ([p test-point-list])
(printf "testing ~v: ~a\n" p (point-in-polygon? p fig))))
(test-figure square "square")
(test-figure exagon "exagon")

View file

@ -1,17 +0,0 @@
testing square:
testing (point 5.0 5.0): #t
testing (point 5.0 8.0): #t
testing (point -10.0 5.0): #f
testing (point 0.0 5.0): #f
testing (point 10.0 5.0): #t
testing (point 8.0 5.0): #t
testing (point 10.0 10.0): #f
testing exagon:
testing (point 5.0 5.0): #t
testing (point 5.0 8.0): #t
testing (point -10.0 5.0): #f
testing (point 0.0 5.0): #f
testing (point 10.0 5.0): #t
testing (point 8.0 5.0): #t
testing (point 10.0 10.0): #f

View file

@ -0,0 +1,119 @@
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)]
struct Point {
x: f64,
y: f64
}
#[derive(Debug, Clone)]
struct Edge {
pt1: 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} }
}
}
#[derive(Debug)]
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
}
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;
}
if pt.y == a.y || pt.y == b.y {
pt = Point {x: pt.x, y: 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;
} 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;
}
}
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)];
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))
]
};
let poly_square_hole = 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((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))
]
};
let poly_strange = Polygon {
edges: vec![
Edge::new((0.0, 0.0), (2.5, 2.5)),
Edge::new((2.5, 2.5), (0.0, 10.0)),
Edge::new((0.0, 10.0), (2.5, 7.5)),
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))
]
};
let poly_hexagon = Polygon {
edges: vec![
Edge::new((3.0, 0.0), (7.0, 0.0)),
Edge::new((7.0, 0.0), (10.0, 5.0)),
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))
]
};
print!("\nSquare :");
for pt in testpoints.iter() {
print!(" {:?}", pt_in_polygon(pt, &poly_square));
}
print!("\nSquare with hole:");
for pt in testpoints.iter() {
print!(" {:?}", pt_in_polygon(pt, &poly_square_hole));
}
print!("\nStrange polygon :");
for pt in testpoints.iter() {
print!(" {:?}", pt_in_polygon(pt, &poly_strange));
}
print!("\nHexagon :");
for pt in testpoints.iter() {
print!(" {:?}", pt_in_polygon(pt, &poly_hexagon));
}
print!("\n");
}

View file

@ -0,0 +1,17 @@
const E = 0.0001;
fcn rayHitsSeg([(Px,Py)],[(Ax,Ay)],[(Bx,By)]){ // --> Bool
if(Py==Ay or Py==By) Py+=E;
if(Py<Ay or Py>By or Px>Ax.max(Bx)) False
else if(Px<Ax.min(Bx)) True
else try{ ( (Py - Ay)/(Px - Ax) )>=( (By - Ay)/(Bx - Ax) ) } //blue>=red
catch(MathError){ Px==Ax } // divide by zero == ∞, only blue?
}
fcn pointInPoly(point, polygon){ // --> Bool, polygon is ( (a,b),(c,d).. )
polygon.filter('wrap([(ab,cd)]){ a,b:=ab; c,d:=cd;
if(b<=d) rayHitsSeg(point,ab,cd); // left point has smallest y coordinate
else rayHitsSeg(point,cd,ab);
})
.len().isOdd; // True if crossed an odd number of borders ie inside polygon
}

View file

@ -0,0 +1,50 @@
polys:=T( //(name,( ((a,b),(c,d)),((a,b),(c,d))... ), ... )==(nm,(ln,ln..) ..)
T("squared",
T(T(T( 0.0, 0.0), T(10.0, 0.0)),
T(T(10.0, 0.0), T(10.0, 10.0)),
T(T(10.0, 10.0), T( 0.0, 10.0)),
T(T( 0.0, 10.0), T( 0.0, 0.0)))),
T("squaredhole",
T(T(T( 0.0, 0.0), T(10.0, 0.0)),
T(T(10.0, 0.0), T(10.0, 10.0)),
T(T(10.0, 10.0), T( 0.0, 10.0)),
T(T( 0.0, 10.0), T( 0.0, 0.0)),
T(T( 2.5, 2.5), T( 7.5, 2.5)),
T(T( 7.5, 2.5), T( 7.5, 7.5)),
T(T( 7.5, 7.5), T( 2.5, 7.5)),
T(T( 2.5, 7.5), T( 2.5, 2.5)))),
T("strange",
T(T(T( 0.0, 0.0), T( 2.5, 2.5)),
T(T( 2.5, 2.5), T( 0.0, 10.0)),
T(T( 0.0, 10.0), T( 2.5, 7.5)),
T(T( 2.5, 7.5), T( 7.5, 7.5)),
T(T( 7.5, 7.5), T(10.0, 10.0)),
T(T(10.0, 10.0), T(10.0, 0.0)),
T(T(10.0, 0.0), T( 2.5, 2.5)),
T(T( 2.5, 2.5), T( 0.0, 0.0)))), # conjecturally close polygon
T("exagon",
T(T(T( 3.0, 0.0), T( 7.0, 0.0)),
T(T( 7.0, 0.0), T(10.0, 5.0)),
T(T(10.0, 5.0), T( 7.0, 10.0)),
T(T( 7.0, 10.0), T( 3.0, 10.0)),
T(T( 3.0, 10.0), T( 0.0, 5.0)),
T(T( 0.0, 5.0), T( 3.0, 0.0)))),
);
testPoints:=T(
T( 5.0, 5.0),
T( 5.0, 8.0),
T(-10.0, 5.0),
T( 0.0, 5.0),
T( 10.0, 5.0),
T( 8.0, 5.0),
T( 10.0, 10.0)
);
foreach name,polywanna in (polys){
name.println();
foreach testPoint in (testPoints){
println("\t(%6.1f,%6.1f)\t".fmt(testPoint.xplode()),
pointInPoly(testPoint,polywanna) and "IN" or "OUT");
}
}