branch: externals/osm commit 3208952f8d089cb39d68e72130b39647663067de Author: Daniel Mendler <m...@daniel-mendler.de> Commit: Daniel Mendler <m...@daniel-mendler.de>
Refactor, store map coordinates as latitude/longitude --- README.org | 7 +- osm.el | 348 ++++++++++++++++++++++++++++++------------------------------- 2 files changed, 174 insertions(+), 181 deletions(-) diff --git a/README.org b/README.org index 5ee62d7966..700b0a9234 100644 --- a/README.org +++ b/README.org @@ -106,14 +106,14 @@ Key bindings in =osm-mode= buffer: - ~C-<arrow>~, ~M-<arrow>~: Large step scrolling - ~+~, ~SPC~: =osm-zoom-in= - Zoom in - ~-~, ~S-SPC~: =osm-zoom-out= - Zoom out -- ~<mouse-1>~: =osm-center-click= - Center to point +- ~<mouse-1>~: =osm-transient-click= - Place transient pin at point - ~<mouse-2>~: =osm-org-link-click= - Store point as Org link - ~<mouse-3>~: =osm-bookmark-set-click= - Store point as bookmark - ~<osm-bookmark mouse-*>~: =osm-bookmark-delete-click= - Click on bookmark at point to delete - ~<down-mouse-*>~: =osm-mouse-drag= - Drag the map with the mouse - ~d~, ~DEL~: =osm-bookmark-delete= - Delete selected bookmark -- ~n~: =osm-bookmark-rename= - Rename selected bookmark - ~t~: =osm-goto= - Go to location +- ~c~: =osm-center= - Center to currently marked pin - ~h~: =osm-home= - Go to home location - ~s~: =osm-search= - Search for location - ~v~: =osm-server= - Select tile server @@ -122,9 +122,10 @@ Key bindings in =osm-mode= buffer: - ~l~: =org-store-link= - Store org link - ~e~: =osm-elisp-link= - Store Elisp link in the kill ring - ~b~: =osm-bookmark-set= - Set bookmark +- ~n~: =osm-bookmark-rename= - Rename selected bookmark - ~j~: =osm-bookmark-jump= - Jump to bookmark - ~q~: =quit-window= - Close buffer and window -- ~c~: =clone-buffer= - Clone buffer +- ~o~: =clone-buffer= - Clone buffer * Related projects diff --git a/osm.el b/osm.el index 423366b38c..23e1b03139 100644 --- a/osm.el +++ b/osm.el @@ -144,11 +144,12 @@ (defcustom osm-pin-colors '((osm-selected-bookmark "#e20" "#600") + (osm-selected-poi "#e20" "#600") (osm-bookmark "#f80" "#820") - (osm-center "#08f" "#028") + (osm-transient "#08f" "#028") (osm-home "#80f" "#208") (osm-poi "#88f" "#228") - (osm-org-link "#7a9" "#254")) + (osm-link "#7a9" "#254")) "Colors of pins." :type '(alist :key-type symbol :value-type (list string string))) @@ -239,9 +240,10 @@ Should be at least 7 days according to the server usage policies." (let ((map (make-sparse-keymap))) (define-key map [menu-bar osm--menu] (osm--menu-item osm--menu)) (define-key map [osm-home] #'ignore) - (define-key map [osm-org-link] #'ignore) - (define-key map [osm-center] #'ignore) + (define-key map [osm-link] #'ignore) + (define-key map [osm-transient] #'ignore) (define-key map [osm-selected-bookmark] #'ignore) + (define-key map [osm-selected-poi] #'ignore) (define-key map [osm-bookmark mouse-1] #'osm-bookmark-select-click) (define-key map [osm-bookmark mouse-2] #'osm-bookmark-select-click) (define-key map [osm-bookmark mouse-3] #'osm-bookmark-select-click) @@ -253,7 +255,7 @@ Should be at least 7 days according to the server usage policies." (define-key map "-" #'osm-zoom-out) (define-key map " " #'osm-zoom-in) (define-key map (kbd "S-SPC") #'osm-zoom-out) - (define-key map [mouse-1] #'osm-center-click) + (define-key map [mouse-1] #'osm-transient-click) (define-key map [mouse-2] #'osm-org-link-click) (define-key map [mouse-3] #'osm-bookmark-set-click) (define-key map [down-mouse-1] #'osm-mouse-drag) @@ -274,7 +276,8 @@ Should be at least 7 days according to the server usage policies." (define-key map "n" #'osm-bookmark-rename) (define-key map "d" #'osm-bookmark-delete) (define-key map "\d" #'osm-bookmark-delete) - (define-key map "c" #'clone-buffer) + (define-key map "c" #'osm-center) + (define-key map "o" #'clone-buffer) (define-key map "h" #'osm-home) (define-key map "t" #'osm-goto) (define-key map "s" #'osm-search) @@ -343,11 +346,11 @@ Should be at least 7 days according to the server usage policies." (defvar-local osm--zoom nil "Zoom level of the map.") -(defvar-local osm--x nil - "Y coordinate on the map in pixel.") +(defvar-local osm--lat nil + "Latitude coordinate.") -(defvar-local osm--y nil - "X coordinate on the map in pixel.") +(defvar-local osm--lon nil + "Longitude coordinate.") (defvar-local osm--overlay-table nil "Overlay hash table.") @@ -400,14 +403,6 @@ Should be at least 7 days according to the server usage policies." (setq y (* float-pi (- 1 (* 2 (/ y 256.0 (expt 2.0 zoom)))))) (/ (* 180 (atan (/ (- (exp y) (exp (- y))) 2))) float-pi)) -(defun osm--lon () - "Return longitude in degrees." - (osm--x-to-lon osm--x osm--zoom)) - -(defun osm--lat () - "Return latitude in degrees." - (osm--y-to-lat osm--y osm--zoom)) - (defun osm--lon-to-x (lon zoom) "Convert LON/ZOOM to x coordinate in pixel." (floor (* 256 (expt 2.0 zoom) (osm--lon-to-normalized-x lon)))) @@ -416,6 +411,22 @@ Should be at least 7 days according to the server usage policies." "Convert LAT/ZOOM to y coordinate in pixel." (floor (* 256 (expt 2.0 zoom) (osm--lat-to-normalized-y lat)))) +(defsubst osm--x () + "Return longitude in pixel of map center." + (osm--lon-to-x osm--lon osm--zoom)) + +(defsubst osm--y () + "Return latitude in pixel of map center." + (osm--lat-to-y osm--lat osm--zoom)) + +(defsubst osm--x0 () + "Return longitude in pixel of top left corner." + (- (osm--x) osm--wx)) + +(defsubst osm--y0 () + "Return latitude in pixel of top left corner." + (- (osm--y) osm--wy)) + (defun osm--server-property (prop &optional server) "Return server property PROP for SERVER." (or (plist-get (alist-get (or server osm-server) osm-server-list) prop) @@ -490,8 +501,8 @@ Should be at least 7 days according to the server usage policies." (pcase-let ((`(,sx . ,sy) (posn-x-y (event-start event))) (win (selected-window)) (map (make-sparse-keymap))) - (cl-incf sx osm--x) - (cl-incf sy osm--y) + (cl-incf sx (osm--x)) + (cl-incf sy (osm--y)) (define-key map [mouse-movement] (lambda (event) (interactive "e") @@ -504,8 +515,7 @@ Should be at least 7 days according to the server usage policies." (define-key map [drag-mouse-2] #'ignore) (define-key map [drag-mouse-3] #'ignore) (pcase-let ((`(,ex . ,ey) (posn-x-y event))) - (setq osm--x (- sx ex) - osm--y (- sy ey)) + (osm--move-to (- sx ex) (- sy ey)) (osm--update))))) (setq track-mouse 'dragging) (set-transient-map map @@ -516,71 +526,63 @@ Should be at least 7 days according to the server usage policies." "Zoom in with the mouse wheel." (pcase-let ((`(,x . ,y) (posn-x-y (event-start last-input-event)))) (when (< osm--zoom (osm--server-property :max-zoom)) - (cl-incf osm--x (/ (- x osm--wx) 2)) - (cl-incf osm--y (/ (- y osm--wy) 2)) + (osm--move-by (/ (- x osm--wx) 2) (/ (- y osm--wy) 2)) (osm-zoom-in)))) (defun osm--zoom-out-wheel (_n) "Zoom out with the mouse wheel." (pcase-let ((`(,x . ,y) (posn-x-y (event-start last-input-event)))) (when (> osm--zoom (osm--server-property :min-zoom)) - (cl-decf osm--x (- x osm--wx)) - (cl-decf osm--y (- y osm--wy)) + (osm--move-by (- osm--wx x) (- osm--wy y)) (osm-zoom-out)))) -(defun osm-center-click (event) - "Center to the location of the click EVENT." - (interactive "e") - (pcase-let ((`(,x . ,y) (posn-x-y (event-start event)))) - (when (< osm--zoom (osm--server-property :max-zoom)) - (cl-incf osm--x (- x osm--wx)) - (cl-incf osm--y (- y osm--wy)) - (osm--put-transient-pin 'osm-center osm--x osm--y "Center") - (osm--update)))) +(defun osm-center () + "Center to location of transient pin." + (interactive) + (when osm--transient-pin + (setq osm--lat (car osm--transient-pin) + osm--lon (cadr osm--transient-pin)) + (osm--update))) + +(defun osm-transient-click (event) + "Put a transient pin at location of the click EVENT." + (interactive "@e") + (osm--put-transient-pin-event event 'osm-transient "Transient") + (osm--update)) (defun osm-bookmark-set-click (event) "Create bookmark at position of click EVENT." (interactive "@e") - (pcase-let ((`(,x . ,y) (posn-x-y (event-start event)))) - (osm--put-transient-pin 'osm-selected-bookmark - (+ osm--x (- x osm--wx)) - (+ osm--y (- y osm--wy)) - "New bookmark") - (osm-bookmark-set))) + (osm--put-transient-pin-event event 'osm-selected-bookmark "New bookmark") + (osm-bookmark-set)) (defun osm-org-link-click (event) "Store link at position of click EVENT." (interactive "@e") - (pcase-let ((`(,x . ,y) (posn-x-y (event-start event)))) - (osm--put-transient-pin 'osm-org-link - (+ osm--x (- x osm--wx)) - (+ osm--y (- y osm--wy)) - "New Org Link") - (call-interactively 'org-store-link))) + (osm--put-transient-pin-event event 'osm-link "New Org Link") + (call-interactively 'org-store-link)) (defun osm--pin-at (type x y) "Get pin of TYPE at X/Y." - (let ((x (+ osm--x (- x osm--wx))) - (y (+ osm--y (- y osm--wy))) + (let ((x (+ (osm--x0) x)) + (y (+ (osm--y0) y)) (min most-positive-fixnum) found) (dolist (pin (car (osm--get-overlays (/ x 256) (/ y 256)))) - (pcase-let ((`(,p ,q ,id . ,_) pin)) + (pcase-let ((`(,p ,q ,_lat ,_lon ,id . ,_) pin)) (when (eq type id) (let ((d (+ (* (- p x) (- p x)) (* (- q y) (- q y))))) (when (and (>= q y) (< q (+ y 50)) (>= p (- x 20)) (< p (+ x 20)) (< d min)) (setq min d found pin)))))) - found)) + (cddr found))) (defun osm-bookmark-select-click (event) "Select bookmark at position of click EVENT." (interactive "@e") (pcase-let* ((`(,x . ,y) (posn-x-y (event-start event)))) (when-let (pin (osm--pin-at 'osm-bookmark x y)) + (osm--put-transient-pin 'osm-selected-bookmark (car pin) (cadr pin) (cdddr pin)) (message "%s" (cdddr pin)) - (osm--put-transient-pin 'osm-selected-bookmark - (car pin) (cadr pin) - (cdddr pin)) (osm--update)))) (defun osm-poi-click (event) @@ -588,38 +590,17 @@ Should be at least 7 days according to the server usage policies." (interactive "@e") (pcase-let* ((`(,x . ,y) (posn-x-y (event-start event)))) (when-let (pin (osm--pin-at 'osm-poi x y)) + (osm--put-transient-pin 'osm-selected-poi (car pin) (cadr pin) (cdddr pin)) (message "%s" (cdddr pin)) - (osm--goto - (list - (osm--y-to-lat (cadr pin) osm--zoom) - (osm--x-to-lon (car pin) osm--zoom) - osm--zoom) - nil)))) + (osm--update)))) (defun osm-zoom-in (&optional n) "Zoom N times into the map." (interactive "p") (osm--barf-unless-osm) - (setq n (- (max (osm--server-property :min-zoom) - (min (osm--server-property :max-zoom) - (+ osm--zoom (or n 1)))) - osm--zoom) - osm--zoom (+ osm--zoom n)) - (cond - ((< n 0) - (setq n (lsh 1 (- n))) - (when osm--transient-pin - (setf (car osm--transient-pin) (/ (car osm--transient-pin) n) - (cadr osm--transient-pin) (/ (cadr osm--transient-pin) n))) - (setq osm--x (/ osm--x n) - osm--y (/ osm--y n))) - ((> n 0) - (setq n (lsh 1 n)) - (when osm--transient-pin - (setf (car osm--transient-pin) (* (car osm--transient-pin) n) - (cadr osm--transient-pin) (* (cadr osm--transient-pin) n))) - (setq osm--x (* osm--x n) - osm--y (* osm--y n)))) + (setq osm--zoom (max (osm--server-property :min-zoom) + (min (osm--server-property :max-zoom) + (+ osm--zoom (or n 1))))) (osm--update)) (defun osm-zoom-out (&optional n) @@ -627,24 +608,27 @@ Should be at least 7 days according to the server usage policies." (interactive "p") (osm-zoom-in (- (or n 1)))) -(defun osm--move (dx dy step) - "Move by DX/DY with STEP size." +(defun osm--move-by (dx dy) + "Move by DX/DY." + (osm--move-to (+ (osm--x) dx) (+ (osm--y) dy))) + +(defun osm--move-to (x y) + "Move to X/Y." (osm--barf-unless-osm) - (setq osm--x (min (* 256 (1- (expt 2 osm--zoom))) - (max 0 (+ osm--x (* dx step)))) - osm--y (min (* 256 (1- (expt 2 osm--zoom))) - (max 0 (+ osm--y (* dy step))))) - (osm--update)) + (setq osm--lon (osm--x-to-lon x osm--zoom) + osm--lat (osm--y-to-lat y osm--zoom))) (defun osm-right (&optional n) "Move N small stepz to the right." (interactive "p") - (osm--move (or n 1) 0 osm-small-step)) + (osm--move-by (* (or n 1) osm-small-step) 0) + (osm--update)) (defun osm-down (&optional n) "Move N small stepz down." (interactive "p") - (osm--move 0 (or n 1) osm-small-step)) + (osm--move-by 0 (* (or n 1) osm-small-step)) + (osm--update)) (defun osm-up (&optional n) "Move N small stepz up." @@ -659,12 +643,14 @@ Should be at least 7 days according to the server usage policies." (defun osm-right-right (&optional n) "Move N large stepz to the right." (interactive "p") - (osm--move (or n 1) 0 osm-large-step)) + (osm--move-by (* (or n 1) osm-large-step) 0) + (osm--update)) (defun osm-down-down (&optional n) "Move N large stepz down." (interactive "p") - (osm--move 0 (or n 1) osm-large-step)) + (osm--move-by 0 (* (or n 1) osm-large-step)) + (osm--update)) (defun osm-up-up (&optional n) "Move N large stepz up." @@ -748,16 +734,21 @@ Should be at least 7 days according to the server usage policies." (unless (eq major-mode #'osm-mode) (error "Not an osm-mode buffer"))) -(defun osm--pin-inside-p (x y p q) - "Return non-nil if pin P/Q is inside tile X/Y." - (setq x (* x 256) y (* y 256)) - (and (>= p (- x 32)) (< p (+ x 256 32)) - (>= q y) (< q (+ y 256 64)))) +(defun osm--pin-inside-p (x y lat lon) + "Return non-nil if pin at LAT/LON is inside tile X/Y." + (let ((p (osm--lon-to-x lon osm--zoom)) + (q (osm--lat-to-y lat osm--zoom))) + (setq x (* x 256) y (* y 256)) + (and (>= p (- x 32)) (< p (+ x 256 32)) + (>= q y) (< q (+ y 256 64))))) -(defun osm--put-pin (pins id x y help) +(defun osm--put-pin (pins id lat lon help) "Put pin at X/Y with HELP and ID in PINS hash table." - (let ((x0 (/ x 256)) (y0 (/ y 256)) - (pin `(,x, y ,id . ,help))) + (let* ((x (osm--lon-to-x lon osm--zoom)) + (y (osm--lat-to-y lat osm--zoom)) + (x0 (/ x 256)) + (y0 (/ y 256)) + (pin `(,x ,y ,lat ,lon ,id . ,help))) (push pin (gethash (cons x0 y0) pins)) (cl-loop for i from -1 to 1 do @@ -771,24 +762,15 @@ Should be at least 7 days according to the server usage policies." (defun osm--compute-pins () "Compute pin hash table." (let ((pins (make-hash-table :test #'equal))) - (osm--put-pin pins 'osm-home - (osm--lon-to-x (cadr osm-home) osm--zoom) - (osm--lat-to-y (car osm-home) osm--zoom) - "Home") + (osm--put-pin pins 'osm-home (car osm-home) (cadr osm-home) "Home") (bookmark-maybe-load-default-file) (dolist (bm bookmark-alist) (when (eq (bookmark-prop-get bm 'handler) #'osm-bookmark-jump) (let ((coord (bookmark-prop-get bm 'coordinates))) - (osm--put-pin pins 'osm-bookmark - (osm--lon-to-x (cadr coord) osm--zoom) - (osm--lat-to-y (car coord) osm--zoom) - (car bm))))) + (osm--put-pin pins 'osm-bookmark (car coord) (cadr coord) (car bm))))) (dolist (file osm--gpx-files) (dolist (pt (cddr file)) - (osm--put-pin pins 'osm-poi - (osm--lon-to-x (cddr pt) osm--zoom) - (osm--lat-to-y (cadr pt) osm--zoom) - (car pt)))) + (osm--put-pin pins 'osm-poi (cadr pt) (cddr pt) (car pt)))) pins)) ;; TODO The Bresenham algorithm used here to add the line segments @@ -863,7 +845,7 @@ TPIN is an optional transient pin." (y0 (* 256 y)) (svg-pin (lambda (pin) - (pcase-let* ((`(,p ,q ,id . ,help) pin) + (pcase-let* ((`(,p ,q ,_lat ,_lon ,id . ,help) pin) (`(,_ ,bg ,fg) (assq id osm-pin-colors))) (setq p (- p x0) q (- q y0)) (push `((poly . [,p ,q ,(- p 20) ,(- q 40) ,p ,(- q 50) ,(+ p 20) ,(- q 40) ]) @@ -921,28 +903,32 @@ xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'> (defun osm--get-tile (x y) "Get tile at X/Y." - (if (pcase osm--transient-pin - (`(,p ,q . ,_) (osm--pin-inside-p x y p q))) - (osm--draw-tile x y osm--transient-pin) - (let* ((key `(,osm-server ,osm--zoom ,x . ,y)) - (tile (and osm--tile-cache (gethash key osm--tile-cache)))) - (if tile - (progn (setcar tile osm--tile-cookie) (cdr tile)) - (setq tile (osm--draw-tile x y nil)) - (when tile - (when osm-max-tiles - (unless osm--tile-cache - (setq osm--tile-cache (make-hash-table :test #'equal :size osm-max-tiles))) - (puthash key (cons osm--tile-cookie tile) osm--tile-cache)) - tile))))) + (pcase osm--transient-pin + ((and `(,lat ,lon . ,_) + (guard (osm--pin-inside-p x y lat lon))) + (osm--draw-tile x y `(,(osm--lon-to-x lon osm--zoom) + ,(osm--lat-to-y lat osm--zoom) + ,@osm--transient-pin))) + (_ + (let* ((key `(,osm-server ,osm--zoom ,x . ,y)) + (tile (and osm--tile-cache (gethash key osm--tile-cache)))) + (if tile + (progn (setcar tile osm--tile-cookie) (cdr tile)) + (setq tile (osm--draw-tile x y nil)) + (when tile + (when osm-max-tiles + (unless osm--tile-cache + (setq osm--tile-cache (make-hash-table :test #'equal :size osm-max-tiles))) + (puthash key (cons osm--tile-cookie tile) osm--tile-cache)) + tile)))))) (defun osm--display-tile (x y tile) "Display TILE at X/Y." - (let ((i (- x (/ (- osm--x osm--wx) 256))) - (j (- y (/ (- osm--y osm--wy) 256)))) + (let ((i (- x (/ (osm--x0) 256))) + (j (- y (/ (osm--y0) 256)))) (when (and (>= i 0) (< i osm--nx) (>= j 0) (< j osm--ny)) - (let* ((mx (if (= 0 i) (mod (- osm--x osm--wx) 256) 0)) - (my (if (= 0 j) (mod (- osm--y osm--wy) 256) 0)) + (let* ((mx (if (= 0 i) (mod (osm--x0) 256) 0)) + (my (if (= 0 j) (mod (osm--y0) 256) 0)) (pos (+ (point-min) (* j (1+ osm--nx)) i))) (unless tile (setq tile (cons 'image osm--placeholder))) @@ -994,7 +980,7 @@ xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'> (defun osm--update-header () "Update header line." - (let* ((meter-per-pixel (/ (* 156543.03 (cos (/ (osm--lat) (/ 180.0 float-pi)))) (expt 2 osm--zoom))) + (let* ((meter-per-pixel (/ (* 156543.03 (cos (/ osm--lat (/ 180.0 float-pi)))) (expt 2 osm--zoom))) (server (osm--server-property :name)) (meter 1) (idx 0) (factor '(2 2.5 2))) @@ -1004,8 +990,8 @@ xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'> (setq-local header-line-format (concat - (format #(" %7.2f°" 0 6 (face bold)) (osm--lat)) - (format #(" %7.2f°" 0 6 (face bold)) (osm--lon)) + (format #(" %7.2f°" 0 6 (face bold)) osm--lat) + (format #(" %7.2f°" 0 6 (face bold)) osm--lon) (propertize " " 'display '(space :align-to (- center 10))) (format "%3s " (if (>= meter 1000) (/ meter 1000) meter)) (if (>= meter 1000) "km " "m ") @@ -1096,30 +1082,33 @@ xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'> (dotimes (_j osm--ny) (insert (make-string osm--nx ?\s) "\n")) (goto-char (point-min)) - (dotimes (j osm--ny) - (dotimes (i osm--nx) - (let* ((x (+ i (/ (- osm--x osm--wx) 256))) - (y (+ j (/ (- osm--y osm--wy) 256))) - (tile (osm--get-tile x y))) - (osm--display-tile x y tile) - (unless tile (osm--enqueue-download x y))))))) + (let ((tx (/ (osm--x0) 256)) + (ty (/ (osm--y0) 256))) + (dotimes (j osm--ny) + (dotimes (i osm--nx) + (let* ((x (+ i tx)) + (y (+ j ty)) + (tile (osm--get-tile x y))) + (osm--display-tile x y tile) + (unless tile (osm--enqueue-download x y)))))))) (defun osm--process-download-queue () "Process the download queue." (setq osm--download-queue (sort - (cl-loop for job in osm--download-queue + (cl-loop with tx = (/ (osm--x0) 256) + with ty = (/ (osm--y0) 256) + for job in osm--download-queue for (x y . zoom) = job - for i = (- x (/ (- osm--x osm--wx) 256)) - for j = (- y (/ (- osm--y osm--wy) 256)) if (and (= zoom osm--zoom) - (>= i 0) (< i osm--nx) - (>= j 0) (< j osm--ny)) + (>= x tx) (< x (+ tx osm--nx)) + (>= y ty) (< y (+ ty osm--ny))) collect job) - (pcase-lambda (`(,x1 ,y1 . ,_z1) `(,x2 ,y2 . ,_z2)) - (setq x1 (- x1 (/ osm--x 256)) y1 (- y1 (/ osm--y 256)) - x2 (- x2 (/ osm--x 256)) y2 (- y2 (/ osm--y 256))) - (< (+ (* x1 x1) (* y1 y1)) (+ (* x2 x2) (* y2 y2)))))) + (let ((tx (/ (osm--x) 256)) + (ty (/ (osm--y) 256))) + (pcase-lambda (`(,x1 ,y1 . ,_z1) `(,x2 ,y2 . ,_z2)) + (setq x1 (- x1 tx) y1 (- y1 ty) x2 (- x2 tx) y2 (- y2 ty)) + (< (+ (* x1 x1) (* y1 y1)) (+ (* x2 x2) (* y2 y2))))))) (osm--download)) (defun osm--purge-tile-cache () @@ -1136,13 +1125,13 @@ xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'> "Make osm bookmark record with NAME at LAT/LON." (setq bookmark-current-bookmark nil) ;; Reset bookmark to use new name `(,(or name (osm--bookmark-name)) - (coordinates ,(or lat (osm--lat)) ,(or lon (osm--lon)) ,osm--zoom) + (coordinates ,(or lat osm--lat) ,(or lon osm--lon) ,osm--zoom) (server . ,osm-server) (handler . ,#'osm-bookmark-jump))) (defun osm--org-link-data () "Return Org link data." - (pcase-let ((`(,lat ,lon ,name) (osm--location-data 'osm-org-link "Org link"))) + (pcase-let ((`(,lat ,lon ,name) (osm--location-data 'osm-link "Org link"))) (setq name (string-remove-prefix "osm: " (osm--bookmark-name name))) (list lat lon osm--zoom (and (not (eq osm-server (default-value 'osm-server))) osm-server) @@ -1153,14 +1142,14 @@ xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'> (defun osm--buffer-name () "Return buffer name." (format "*osm: %.2f° %.2f° Z%s %s*" - (osm--lat) (osm--lon) osm--zoom + osm--lat osm--lon osm--zoom (osm--server-property :name))) (defun osm--bookmark-name (&optional loc) "Return bookmark name with optional LOC name." (format "osm: %s%.2f° %.2f° Z%s %s" (if loc (concat loc ", ") "") - (osm--lat) (osm--lon) osm--zoom + osm--lat osm--lon osm--zoom (osm--server-property :name))) (defun osm--goto (at server) @@ -1171,8 +1160,6 @@ xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'> (or (and (eq major-mode #'osm-mode) (current-buffer)) (pcase-let* ((`(,def-lat ,def-lon ,def-zoom) (or at osm-home)) - (def-x (osm--lon-to-x def-lon def-zoom)) - (def-y (osm--lat-to-y def-lat def-zoom)) (def-server (or server osm-server))) ;; Search for existing buffer (cl-loop @@ -1180,8 +1167,8 @@ xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'> (and (eq (buffer-local-value 'major-mode buf) #'osm-mode) (eq (buffer-local-value 'osm-server buf) def-server) (eq (buffer-local-value 'osm--zoom buf) def-zoom) - (eq (buffer-local-value 'osm--x buf) def-x) - (eq (buffer-local-value 'osm--y buf) def-y) + (eq (buffer-local-value 'osm--lat buf) def-lat) + (eq (buffer-local-value 'osm--lon buf) def-lon) buf))) (generate-new-buffer "*osm*")) (unless (eq major-mode #'osm-mode) @@ -1190,18 +1177,27 @@ xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'> (setq osm-server server osm--download-active nil osm--download-queue nil)) - (when (or (not (and osm--x osm--y)) at) + (when (or (not (and osm--lon osm--lat)) at) (setq at (or at osm-home) - osm--zoom (nth 2 at) - osm--x (osm--lon-to-x (nth 1 at) osm--zoom) - osm--y (osm--lat-to-y (nth 0 at) osm--zoom)) - (osm--put-transient-pin 'osm-center osm--x osm--y "Center")) + osm--lat (nth 0 at) + osm--lon (nth 1 at) + osm--zoom (nth 2 at)) + (osm--put-transient-pin 'osm-transient osm--lat osm--lon "Center")) (prog1 (pop-to-buffer (current-buffer)) (osm--update)))) -(defun osm--put-transient-pin (id x y help) - "Set transient pin at X/Y with ID and HELP." - (setq osm--transient-pin `(,x ,y ,id . ,help))) +(defun osm--put-transient-pin (id lat lon help) + "Set transient pin at LAT/LON with ID and HELP." + (setq osm--transient-pin `(,lat ,lon ,id . ,help))) + +(defun osm--put-transient-pin-event (event id help) + "Set transient pin with ID and HELP at location of EVENT." + (pcase-let ((`(,x . ,y) (posn-x-y (event-start event)))) + (osm--put-transient-pin + id + (osm--y-to-lat (+ (osm--y0) y) osm--zoom) + (osm--x-to-lon (+ (osm--x0) x) osm--zoom) + help))) ;;;###autoload (defun osm-goto (lat lon zoom) @@ -1232,8 +1228,7 @@ Optionally specify a SERVER and a COMMENT." "Jump to osm bookmark BM." (interactive (list (osm--bookmark-read))) (set-buffer (osm--goto (bookmark-prop-get bm 'coordinates) - (bookmark-prop-get bm 'server))) - (setq osm--transient-pin nil)) + (bookmark-prop-get bm 'server)))) ;;;###autoload (defun osm-bookmark-delete (bm) @@ -1249,8 +1244,7 @@ Optionally specify a SERVER and a COMMENT." (interactive (list (car (osm--bookmark-read)))) (let ((new-name (read-from-minibuffer "New name: " old-name nil nil 'bookmark-history old-name))) - (when osm--transient-pin - (setf (cdddr osm--transient-pin) new-name)) + (when osm--transient-pin (setf (cdddr osm--transient-pin) new-name)) (bookmark-rename old-name new-name) (osm--revert))) @@ -1258,9 +1252,7 @@ Optionally specify a SERVER and a COMMENT." "Read bookmark name." (bookmark-maybe-load-default-file) (or (assoc - (if (and osm--transient-pin - (eq (caddr osm--transient-pin) - 'osm-selected-bookmark)) + (if (eq (caddr osm--transient-pin) 'osm-selected-bookmark) (cdddr osm--transient-pin) (completing-read "Bookmark: " @@ -1289,9 +1281,9 @@ Optionally specify a SERVER and a COMMENT." (defun osm--location-data (id help) "Fetch location info for ID with HELP." (unless osm--transient-pin - (osm--put-transient-pin id osm--x osm--y help)) - (let ((lat (osm--y-to-lat (cadr osm--transient-pin) osm--zoom)) - (lon (osm--x-to-lon (car osm--transient-pin) osm--zoom))) + (osm--put-transient-pin id osm--lat osm--lon help)) + (let ((lat (car osm--transient-pin)) + (lon (cadr osm--transient-pin))) (message "%s: Fetching name of %.2f %.2f..." help lat lon) ;; Redisplay before slow fetching (osm--update) @@ -1468,7 +1460,7 @@ If the prefix argument LUCKY is non-nil take the first result and jump there." (defun osm-elisp-link () "Store coordinates as an Elisp link in the kill ring." (interactive) - (pcase-let* ((`(,lat ,lon ,name) (osm--location-data 'osm-org-link "Elisp link")) + (pcase-let* ((`(,lat ,lon ,name) (osm--location-data 'osm-link "Elisp link")) (link (format "(osm %.6f %.6f %s%s%s)" lat lon osm--zoom (if (eq osm-server (default-value 'osm-server)) @@ -1476,14 +1468,14 @@ If the prefix argument LUCKY is non-nil take the first result and jump there." (format " %s" osm-server)) (if name (format " %S" name) "")))) (kill-new link) - (message "Stored link in the kill ring"))) + (message "Stored in the kill ring: %s" link))) (dolist (sym (list #'osm-up #'osm-down #'osm-left #'osm-right #'osm-up-up #'osm-down-down #'osm-left-left #'osm-right-right #'osm-zoom-out #'osm-zoom-in #'osm-bookmark-set #'osm-gpx-hide #'osm-elisp-link)) (put sym 'command-modes '(osm-mode))) -(dolist (sym (list #'osm-mouse-drag #'osm-center-click #'osm-org-link-click +(dolist (sym (list #'osm-mouse-drag #'osm-transient-click #'osm-org-link-click #'osm-poi-click #'osm-bookmark-set-click #'osm-bookmark-select-click)) (put sym 'completion-predicate #'ignore))