;;;; geopolygon.scm -*- Scheme -*- ;;;; Kon Lovett, Jul '18 ;;;; Kon Lovett, Aug '17 ;;;; Kon Lovett, May '17 (module geopolygon (;export make-geopolygon geopolygon? check-geopolygon error-geopolygon geopolygon geopolygon-closed? geopolygon-open? geopolygon-bounding-box ) (import scheme (chicken base) (chicken type) vector-lib (only type-checks-basic define-check+error-type) geopoint geobox) (define-type geopoint (struct geopoint)) (define-type geopolygon (or (list-of geopoint) (vector-of geopoint))) (: make-geopolygon ((or geopolygon geopoint) #!rest (struct geopoint) --> geopolygon)) (: geopolygon? (* -> boolean : geopolygon)) (: geopolygon (#!rest --> geopolygon)) (: geopolygon-closed? (geopolygon --> boolean)) (: geopolygon-open? (geopolygon --> boolean)) (: geopolygon-bounding-box (geopolygon --> (struct geobox))) ;;; (include "geo-constants") ;; (define (ensure-vector gps) (if (list? gps) (list->vector gps) gps)) ;; ;not strict (define make-geopolygon (case-lambda ((gps) (cond ((vector? gps) (and (vector-every geopoint? gps) gps) ) ((list? gps) (make-geopolygon (ensure-vector gps)) ) (else (error 'make-geopolygon "unrecognized as geopolygon" gps) ) ) ) (rest (make-geopolygon rest) ) ) ) (define (geopolygon? obj) (and (vector? obj) (vector-every geopoint? obj))) (define-check+error-type geopolygon) (define (geopolygon . gps) (make-geopolygon gps)) ; explicitly closed means [0] = [n-1] ; (define (geopolygon-closed? gpoly) (let* ((gpoly (ensure-vector gpoly)) (len (vector-length gpoly)) ) (and (<= 2 len) (geopoint= (vector-ref gpoly 0) (vector-ref gpoly (- len 1))) ) ) ) ; explicitly open means [0] != [n-1] ; (define (geopolygon-open? gpoly) (not (geopolygon-closed? gpoly))) ;; (define (geopolygon-bounding-box gpoly) (let* ((gpoly (ensure-vector gpoly)) (len (vector-length (check-geopolygon 'geopolygon-bounding-box gpoly))) ) (let loop ((i (the fixnum 0)) (minLat 90) (maxLat -90) (minLon 180) (maxLon -180)) ;traced polygon? (if (= i len) ;then report (make-geobox minLat minLon maxLat maxLon) ;else next point in poly (let* ((pnt (vector-ref gpoly i)) (lat (geopoint-latitude pnt)) (lon (geopoint-longitude pnt)) ) (loop (+ i 1) (min lat minLat) (max lat maxLat) (min lon minLon) (max lon maxLon)) ) ) ) ) ) ) ;geopolygon