;;;; -*- mode:lisp;coding:utf-8 -*-
;;;;**************************************************************************
;;;;FILE:               geometry.lisp
;;;;LANGUAGE:           Common-Lisp
;;;;SYSTEM:             Common-Lisp
;;;;USER-INTERFACE:     NONE
;;;;DESCRIPTION
;;;;
;;;;    This package exports geometry functions.
;;;;    Literally, Earth measuring ones, coordinates, distances, etc.
;;;;
;;;;AUTHORS
;;;;    <PJB> Pascal J. Bourguignon <pjb@ogamita.com>
;;;;MODIFICATIONS
;;;;    2011-04-10 <PJB> Created.
;;;;BUGS
;;;;LEGAL
;;;;    GPL
;;;;
;;;;    Copyright Pascal J. Bourguignon 2011 - 2011
;;;;
;;;;    This program is free software; you can redistribute it and/or
;;;;    modify it under the terms of the GNU General Public License
;;;;    as published by the Free Software Foundation; either version
;;;;    2 of the License, or (at your option) any later version.
;;;;
;;;;    This program is distributed in the hope that it will be
;;;;    useful, but WITHOUT ANY WARRANTY; without even the implied
;;;;    warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
;;;;    PURPOSE.  See the GNU General Public License for more details.
;;;;
;;;;    You should have received a copy of the GNU General Public
;;;;    License along with this program; if not, write to the Free
;;;;    Software Foundation, Inc., 59 Temple Place, Suite 330,
;;;;    Boston, MA 02111-1307 USA
;;;;**************************************************************************

(defpackage "COM.OGAMITA.FGFS.GEOMETRY"
  (:use "COMMON-LISP")
  (:export

   "AVERAGE" "SQUARE" "DEG2RAD" "+MEAN-EARTH-RADIUS+"
   "+NAUTICAL-MILE+" "+2*EARTH-RADIUS/NAUTICAL-MILES+"
   "ORTHODROMIC-DISTANCE/NAUTICAL-MILES"

   )
  (:documentation "
This package exports geometry functions.
Literally, Earth measuring ones, coordinates, distances, etc.
GPL
Copyright Pascal J. Bourguignon 2011 - 2011
"))
(in-package "COM.OGAMITA.FGFS.GEOMETRY")

(declaim (inline average))
(defun average (seq)
  (if (listp seq)
      #+clisp
      (/ (reduce (function +) seq)
         (length seq))
      #-clisp
      (loop
         :for i :in seq
         :count 1 :into n
         :sum i :into s
         :finally (return (/ s n)))
      (/ (reduce (function +) seq)
         (length seq))))

(declaim (inline square))
(defun square (x) (* x x))

(declaim (inline deg2rad))
(defun deg2rad (degrees) (* degrees #.(/ pi 180.0d0)))

(defconstant +mean-earth-radius+           6371.01d0    "km")
(defconstant +nautical-mile+                  1.85200d0 "km")
(defconstant +2*earth-radius/nautical-miles+  (* 2.0d0 (/ +mean-earth-radius+ +nautical-mile+)) "nautical miles")

(defun orthodromic-distance/nautical-miles (lon1 lat1 lon2 lat2)
  ;; http://en.wikipedia.org/wiki/Great-circle_distance
  ;; Haversine formula:
  (let* ((lon1 (deg2rad lon1))
         (lat1 (deg2rad lat1))
         (lon2 (deg2rad lon2))
         (lat2 (deg2rad lat2))
         (dlon  (- lon1 lon2))
         (dlat  (- lat1 lat2)))
    (* +2*earth-radius/nautical-miles+
       (asin (sqrt (+ (square (sin (/ dlat 2.0d0)))
                      (* (cos lat1) (cos lat2) (square (sin (/ dlon 2.0d0))))))))))


;;;; THE END ;;;;
ViewGit