Elisp: Earth Coordinate to Google Map Link

By Xah Lee. Date: . Last updated: .

This page shows a command to turn earth coordinate into Google Map link.

Problem

Suppose you have a earth coordinate under cursor, like this:

40°42′46″N 74°00′21″W

or

40.71277777777778 -74.00583333333333

Press a button, and it becomes a Google Map link, like this:

<a class="ggMap" href="http://maps.google.com/maps?q=40.71277777777778%2C-74.00583333333333">Location</a>

Solution

Here's the emacs lisp command to do it.

Alt+x xah-google-map-linkify

put this in your Emacs Init File:

;; -*- coding: utf-8; lexical-binding: t; -*-

(defun xah-latitude-longitude-decimalize (CoordYX)
  "Convert latitude longitude string CoordYX in minutes second format to decimal.
Return a vector.
For example, string
37°26′36.42″N 06°15′14.28″W
becomes
[37.44345 -6.253966666666667]

URL `http://xahlee.info/emacs/emacs/elisp_make_google-map_link.html'
Version: 2015-02-08 2023-07-23"
  (let ((xtmpPair
         (split-string
          (replace-regexp-in-string
           "'" "′"
           (replace-regexp-in-string
            "\"" "″"
            (replace-regexp-in-string "''" "″" CoordYX t t) t t) t t)
          " +"))
        xlatStr xlatNum xlonStr xlonNum xdeg xmin xsec xsign (xc (/ 1.0 60.0)))
    (when (not (equal (length xtmpPair) 2)) (user-error "Error: input can contain only one space"))
    (setq xlatStr (elt xtmpPair 0) xlonStr (elt xtmpPair 1))
    (if (string-match "\\`\\([0-9]+\\)°\\([0-9]+\\)′\\([.0-9]+\\)″\\(.?\\)\\'" xlatStr)
        (progn
          (setq xdeg (string-to-number (match-string 1 xlatStr)))
          (setq xmin (string-to-number (match-string 2 xlatStr)))
          (setq xsec (string-to-number (match-string 3 xlatStr)))
          (setq xsign (match-string 4 xlatStr))
          (setq xlatNum (+ xdeg (* (+ xmin (* xsec xc)) xc)))
          (cond
           ((string-equal (downcase xsign) "n") nil)
           ((string-equal xsign "") nil)
           ((string-equal (downcase xsign) "s") (setq xlatNum (* -1 xlatNum)))
           (t (user-error "Input is malformed. Your latitude ends with a char that's not N or S"))))
      (progn (user-error "Latitude is malformed")))

    (if (string-match "\\`\\([0-9]+\\)°\\([0-9]+\\)′\\([.0-9]+\\)″\\(.?\\)\\'" xlonStr)
        (progn
          (setq xdeg (string-to-number (match-string 1 xlonStr)))
          (setq xmin (string-to-number (match-string 2 xlonStr)))
          (setq xsec (string-to-number (match-string 3 xlonStr)))
          (setq xsign (match-string 4 xlonStr))
          (setq xlonNum (+ xdeg (* (+ xmin (* xsec xc)) xc)))
          (cond
           ((string-equal (downcase xsign) "e") nil)
           ((string-equal xsign "") nil)
           ((string-equal (downcase xsign) "w") (setq xlonNum (* -1 xlonNum)))
           (t (user-error "Input is malformed. Your longitude ends with a char that's not E or W"))))
      (progn (user-error "Longitude is malformed")))
    (vector xlatNum xlonNum)))

(defun xah-coord-to-google-map-link (CoordYX &optional Title)
  "Return a HTML link to Google Map.

Title is the title attribute for the HTML link.
CoordYX is a vector [y x] where y is latitude, x is longitude. Each must be a decimal number.

Sample output:
<a class=\"ggMap\" href=\"http://maps.google.com/maps?q=40.71277777777778%2C-74.00583333333333\">Location</a>

URL `http://xahlee.info/emacs/emacs/elisp_make_google-map_link.html'
Version: 2015-05-12 2021-05-02 2022-01-27"
  (let (xtitle xy xx)
    (setq xtitle (if Title Title ""))
    (if CoordYX
        (setq xy (elt CoordYX 0) xx (elt CoordYX 1))
      (setq xy "y▮" xx "x▮"))
    ;; (insert "<a href=\"http://maps.google.com/maps?q=" (number-to-string xy) "%2C" (number-to-string xx) "\" title=\"" xtitle "\">Google Map</a>\n")
    (format
      "<a class=\"ggMap\" href=\"http://maps.google.com/maps?q=%s%s%s\">%s</a>\n"
      (number-to-string xy)
      "%2C"
      (number-to-string xx)
      xtitle
      )))

(defun xah-google-map-linkify ()
  "Change coordinate under cursor into a Google Map link.

If there's a text selection, use that as input.

The current line must be one of the following format:

40°42′46″N 74°00′21″W
40.71277777777778 -74.00583333333333

(New York City coordinate.)

Note, by convention, earth coordinates are given in this order:
‹latitude› ‹longitude›
(latitude is like  y axis, longitude is like x axis)

Sample result:

<a class=\"ggMap\" href=\"http://maps.google.com/maps?q=40.71277777777778%2C-74.00583333333333\">Location</a>

URL `http://xahlee.info/emacs/emacs/elisp_make_google-map_link.html'
Version: 2016-07-12 2022-01-27 2023-07-23"
  (interactive)
  (let (xp1 xp2 xinput xcoord-x xcoord-y xcoord-y-x)
    (if (use-region-p)
        (setq xp1 (region-beginning) xp2 (region-end))
      (setq xp1 (line-beginning-position) xp2 (line-end-position)))

    (setq xinput (buffer-substring-no-properties xp1 xp2))
    (if (string-match-p "°" xinput)
        (progn
          (setq xcoord-y-x (xah-latitude-longitude-decimalize xinput)
                xcoord-y (aref xcoord-y-x 0)
                xcoord-x (aref xcoord-y-x 1)))
      (progn
        (let ((xxx (split-string xinput  " " "OMIT-NULLS")))
          (setq xcoord-y (string-to-number (nth 0 xxx))
                xcoord-x (string-to-number (nth 1 xxx))
                xcoord-y-x (vector xcoord-y xcoord-x)))))
    (delete-region xp1 xp2)
    (insert (xah-coord-to-google-map-link xcoord-y-x "Location"))))