;;;; geopoint-utils.scm ;;;; Kon Lovett, May '17 ;;;; Kon Lovett, Aug '17 (module geopoint-utils (;export geopoint-in-closed-polygon? intersects?-pnp intersects?-pip) (import scheme) (import chicken) (use numbers) (use geopoint geopolygon) (use type-checks) ;;; (define-type geopolygon (or (list-of (struct geopoint)) (vector-of (struct geopoint)))) ;; ;https://github.com/substack/point-in-polygon ;(: geopoint-in-closed-polygon? ((struct geopoint) geopolygon #!optional ((struct geopoint) (struct geopoint) number number --> boolean) --> boolean)) (: geopoint-in-closed-polygon? ((struct geopoint) geopolygon #!optional procedure --> boolean)) (define (geopoint-in-closed-polygon? gp gpoly #!optional (intersects? intersects?-pnp)) ;test for intersection of ray with every segment of the polygon ;start with the "closing" segment, then every [i-i],[i] segment (let ((gpoly (make-geopolygon gpoly))) (check-geopoint 'geopoint-in-closed-polygon? gp) (let ((len (vector-length (check-geopolygon 'geopoint-in-closed-polygon? gpoly)) ) (lat (geopoint-latitude gp) ) (lon (geopoint-longitude gp) ) ) ;assumes an open-poly is "closed" so a closed-poly must be treated as "open" (let ((len (if (geopolygon-closed? gpoly) (fx- len 1) len))) (let loop ((i 0) (j (fx- len 1)) (poly? #f)) (if (fx= i len) poly? (loop (fx+ i 1) i (if (intersects? (vector-ref gpoly i) (vector-ref gpoly j) lat lon) (not poly?) poly?)) ) ) ) ) ) ) ;; ;; Ray-casting algorithm (http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html) ;; (https://github.com/substack/point-in-polygon) (: intersects?-pnp ((struct geopoint) (struct geopoint) number number --> boolean)) (define (intersects?-pnp pi pj lat lon) (let ((lati (geopoint-latitude pi)) (loni (geopoint-longitude pi)) (latj (geopoint-latitude pj)) (lonj (geopoint-longitude pj)) ) (and (not (eq? (> loni lon) (> lonj lon))) (< lat (+ (/ (* (- latj lati) (- lon loni)) (- lonj loni)) lati))) ) ) ;; Ray-casting algorithm (http://en.wikipedia.org/wiki/Point_in_polygon) ;; (http://alienryderflex.com/polygon/) (: intersects?-pip ((struct geopoint) (struct geopoint) number number --> boolean)) (define (intersects?-pip pi pj lat lon) (let ((lati (geopoint-latitude pi)) (loni (geopoint-longitude pi)) (latj (geopoint-latitude pj)) (lonj (geopoint-longitude pj)) ) (and (or (and (< lati lat) (<= lat latj ) ) (and (< latj lat) (<= lat lati))) (or (<= loni lon) (<= lonj lon)) (< (+ loni (* (/ (- lat lati) (- latj lati)) (- lonj loni))) lon)) ) ) ) ;module geopoint-utils