1 ;;; PHOROS -- Photogrammetric Road Survey
2 ;;; Copyright (C) 2010, 2011 Bert Burgemeister
4 ;;; This program is free software; you can redistribute it and/or modify
5 ;;; it under the terms of the GNU General Public License as published by
6 ;;; the Free Software Foundation; either version 2 of the License, or
7 ;;; (at your option) any later version.
9 ;;; This program is distributed in the hope that it will be useful,
10 ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
11 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 ;;; GNU General Public License for more details.
14 ;;; You should have received a copy of the GNU General Public License along
15 ;;; with this program; if not, write to the Free Software Foundation, Inc.,
16 ;;; 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 (hunchentoot:define-easy-handler
(phoros.js
) ()
21 "Serve some Javascript."
22 (when (hunchentoot:session-value
'authenticated-p
)
25 (setf debug-info
(@ *open-layers
*console info
))
27 (defmacro inner-html-with-id
(id)
28 "innerHTML of element with id=\"id\"."
29 `(chain document
(get-element-by-id ,id
) inner-h-t-m-l
))
31 (defmacro value-with-id
(id)
32 "Value of element with id=\"id\"."
33 `(chain document
(get-element-by-id ,id
) value
))
35 (defmacro checkbox-status-with-id
(id)
36 "Whether checkbox with id=\"id\" is checked or not."
37 `(chain document
(get-element-by-id ,id
) checked
))
43 (:p
"User role. \"Read\" can't write or modify anything.
44 \"Write\" may write user points and delete their own
45 ones. \"Admin\" may write user points and delete points
47 :presentation-project-name
49 (:p
"Presentation project name."))
50 :presentation-project-emptiness
52 (:p
"This presentation project is empty. You can't do much
56 (:p
"Phoros version.")
57 (:p
"In a version string A.B.C, changes in A denote
58 incompatible changes in data (you can't access a database
59 set up by a different version of Phoros); changes in B mean
60 user-visible changes in feature set; changes in C denote
61 bug fixes and minor improvements."))
64 (:p
"Current action."))
65 :multiple-points-phoros-controls
67 (:p
"Try reading the text under mouse pointer."))
70 (:p
"Store user point with its attribute,
71 numeric-description, description, and auxiliary data into
75 (:p
"Delete current point."))
76 :download-user-points-button
78 (:p
"Download all user points as GeoJSON-fomatted text
79 file. Do this regularly if you don't want to lose your
80 work due to server crashes or major Phoros updates.")
81 (:p
"Points saved this way can be fed back into your
82 project using the command line interface (on server or on
83 any other host where the database is reachable)."))
87 (:p
"The standard ones, polygon, polyline, and solitary are
88 rendered as asterisk, square, and triangle respectively.
89 Anything else is rendered as an X."))
92 (:h3
"\"description\"")
93 (:p
"Optional textual description of the set of user points
94 the current point belongs to."))
95 :point-numeric-description
97 (:h3
"\"numeric-description\"")
98 (:p
"Optional description of the current user point. It is
99 occasionally used to label representations of this point in
100 streetmap and in images.")
101 (:p
"If parts of it look like numbers, the leftmost such
102 part is automatically incremented during first click into
106 (:p
"Creation date of current user point. Will be updated
107 when you change this point."))
110 (:p
"Check this if the user point being created is to
111 include auxiliary data."))
114 (:p
"Select a set of auxiliary data, either by its distance
115 (in metres) from the current estimated position, or by
116 clicking its representation in streetmap."))
119 (:p
"Auxiliary data connected to this presentation project;
120 all the numeric values followed by all the text values if
124 (:p
"Creator of current user point. Will be updated when
125 you change this point."))
126 :remove-work-layers-button
128 (:p
"Discard the current, unstored user point or unselect
129 any selected user points. Zoom out all images. Keep
130 the rest of the workspace untouched."))
133 (:p
"View some info about Phoros."))
136 (:p
"Finish this session after storing current streetmap
137 zoom status and your cursor position.")
138 (:p
"Fresh login is required to continue."))
141 (:p
"Clicking into the streetmap fetches images which most
142 probably feature the clicked point.")
143 (:p
"To pan the map, drag the mouse. To zoom, spin the
144 mouse wheel, or hold shift down whilst dragging a box, or
145 double-click (shift double-click for larger zoom steps) a
146 point of interest."))
149 (:p
"Clicking into an image sets or resets the active point
150 there. Once a feature is marked by active points in more
151 than one image, the estimated position is calculated.")
152 (:p
"To pan an image, drag the mouse. To zoom, spin the
153 mouse wheel, or hold shift down whilst dragging a box, or
154 double-click (shift double-click for larger zoom steps) a
155 point of interest."))
156 ol-Control-Pan-West-Item-Inactive
158 (:p
"Move viewport left."))
159 ol-Control-Pan-East-Item-Inactive
161 (:p
"Move viewport right."))
162 ol-Control-Pan-North-Item-Inactive
164 (:p
"Move viewport up."))
165 ol-Control-Pan-South-Item-Inactive
167 (:p
"Move viewport down."))
168 ol-Control-Zoom-In-Item-Inactive
171 ol-Control-Zoom-Out-Item-Inactive
174 streetmap-Zoom-To-Max-Extent-Item-Inactive
176 (:p
"Zoom to the extent of presentation project."))
177 ol-Control-Zoom-To-Max-Extent-Item-Inactive
179 (:p
"Zoom out completely, restoring the original view."))
180 :zoom-images-to-max-extent
182 (:p
"Zoom all images out completely, restoring the original
186 (:p
"I haven't been able to display a set of images that
187 cover a common area because I couldn't find the necessary
188 information. As a fallback, I'm displaying a set of images
189 with points of view close to the point you selected.")
190 (:p
"The server is probably trying to remedy this problem
191 but this may take some time."))
194 (:p
"Check this to automatically zoom into images once they
195 get an estimated position."))
198 (:p
"Check this to snap your current position onto a line
199 along points of auxiliary data, and to keep streetmap
200 centered around current position."))
203 (:p
"Decrease step size. Double-click to decrease harder."))
206 (:p
"Step size in metres. Click to increase; double-click
207 to increase harder."))
210 (:p
"Increase step size. Double-click to increase harder."))
213 (:p
"Move your position by one step on a line along points
214 of auxiliary data. Double-click to change direction."))
215 :image-layer-switcher
217 (:p
"Toggle display of image."))
220 (:p
"No photogrammetric survey possible as there isn't any
221 usable calibration data available for this image.")
222 (:p
"This means no image footprints can be calculated
223 either which prevents me from selecting images covering a
227 (:p
"Time this image was taken."))
230 (:p
"Choose a background streetmap."))
233 (:p
"Toggle visibility of data layers."))
236 (:p
"Click to re-center streetmap, or drag the red
238 :streetmap-mouse-position
240 (:p
"Cursor position in geographic coordinates when cursor
244 (:p
"Hints on Phoros' displays and controls are shown here
245 while hovering over the respective elements."))))
247 (defun add-help-topic (topic element
)
248 "Add mouse events to DOM element that initiate display of a
251 (setf (@ element onmouseover
)
253 (lambda () (show-help x
)))
255 (setf (@ element onmouseout
) show-help
)))
257 (defun add-help-events ()
258 "Add mouse events to DOM elements that initiate display of a
261 (topic *help-topics
*)
262 (add-help-topic topic
(chain document
(get-element-by-id topic
)))
263 (dolist (element (chain document
(get-elements-by-class-name topic
)))
264 (add-help-topic topic element
))))
266 (defun show-help (&optional topic
)
267 "Put text on topic into help-display"
268 (setf (inner-html-with-id "help-display")
269 (let ((help-body (getprop *help-topics
* topic
)))
270 (if (undefined help-body
)
274 (defvar *click-control
*
278 (@ *open-layers
*control
)
286 (apply this arguments
))
287 (setf (@ this handler
)
288 (new (chain *open-layers
292 :click
(@ this trigger
)))))))))))
294 (defvar +unix-epoch
+ (lisp *unix-epoch
*)
295 "Seconds between Lisp epoch and UNIX epoch.")
297 (new (chain *open-layers
(*projection
"EPSG:4326"))))
298 (defvar +spherical-mercator
+
299 (new (chain *open-layers
(*projection
"EPSG:900913"))))
301 (defvar +user-name
+ (lisp (hunchentoot:session-value
'user-name
))
302 "User's (short) name.")
303 (defvar +user-role
+ (lisp (string-downcase (hunchentoot:session-value
305 "User's permissions.")
307 (defvar +presentation-project-bbox-text
+
308 (lisp (hunchentoot:session-value
'presentation-project-bbox
)))
310 (defvar +presentation-project-bounds
+
311 (chain (new (chain *open-layers
314 (or +presentation-project-bbox-text
+
315 "-180,-89,180,89"))))
316 (transform +geographic
+ +spherical-mercator
+))
317 "Bounding box of the entire presentation project.")
320 (lisp (hunchentoot:session-value
'aux-data-p
)))
322 (defvar *images
* (array) "Collection of the photos currently shown.")
324 (defvar *streetmap
* undefined
325 "The streetmap shown to the user.")
327 (defvar *point-attributes-select
* undefined
328 "The HTML element for selecting user point attributes.")
330 (defvar *aux-point-distance-select
* undefined
331 "The HTML element for selecting one of a few nearest
334 (defvar *global-position
* undefined
335 "Coordinates of the current estimated position")
337 (defvar *linestring-step-ratio
* 4
338 "Look for auxiliary points to include into linestring within
339 a radius of *linestring-step-ratio* multilied by multiplied by
342 (defvar *current-nearest-aux-point
*
343 (create attributes
(create aux-numeric undefined
345 "Attributes of currently selected point of auxiliary data.")
347 (defvar *bbox-strategy
* (@ *open-layers
*strategy
*bbox
*))
348 (setf (@ *bbox-strategy
* prototype ratio
) 1.5)
349 (setf (@ *bbox-strategy
* prototype res-factor
) 1.5)
351 (defvar *json-parser
* (new (chain *open-layers
*format
*json
*)))
353 (defvar *geojson-format
* (chain *open-layers
*format
*geo-j-s-o-n
))
354 (setf (@ *geojson-format
* prototype ignore-extra-dims
)
355 t
) ;doesn't handle height anyway
356 (setf (@ *geojson-format
* prototype external-projection
)
358 (setf (@ *geojson-format
* prototype internal-projection
)
362 (new (chain *open-layers
365 (create external-projection
+geographic
+
366 internal-projection
+spherical-mercator
+)))))
368 (defvar *http-protocol
* (chain *open-layers
*protocol
*http
*))
369 (setf (chain *http-protocol
* prototype format
) (new *geojson-format
*))
371 (defvar *pristine-images-p
* t
372 "T if none of the current images has been clicked into yet.")
374 (defvar *current-user-point
* undefined
375 "The currently selected user-point.")
377 (defun write-permission-p (&optional
(current-owner +user-name
+))
378 "Nil if current user can't edit stuff created by
379 current-owner or, without arguments, new stuff."
380 (or (equal +user-role
+ "admin")
381 (and (equal +user-role
+ "write")
382 (equal +user-name
+ current-owner
))))
385 "Anything necessary to deal with a photo."
391 (create projection
+spherical-mercator
+
393 controls
(array (new (chain *open-layers
395 (*navigation
)))))))))
396 (setf (@ this dummy
) false
) ;TODO why? (omitting splices map components directly into *image)
399 (setf (@ *image prototype delete-photo
)
401 (setf (@ *image prototype photop
)
403 (setf (@ *image prototype show-photo
)
405 (setf (@ *image prototype draw-epipolar-line
)
407 (setf (@ *image prototype draw-active-point
)
409 (setf (@ *image prototype draw-estimated-positions
)
410 draw-estimated-positions
)
412 (defun photo-path (photo-parameters)
413 "Create from stuff found in photo-parameters a path for use in
415 (+ "/phoros/lib/photo/" (@ photo-parameters directory
) "/"
416 (@ photo-parameters filename
) "/"
417 (@ photo-parameters byte-position
) ".png"
418 "?mounting-angle=" (@ photo-parameters mounting-angle
)
419 "&bayer-pattern=" (@ photo-parameters bayer-pattern
)
420 "&color-raiser=" (@ photo-parameters color-raiser
)))
422 (defun has-layer-p (map layer-name
)
423 "False if map doesn't have a layer called layer-name."
424 (chain map
(get-layers-by-name layer-name
) length
))
426 (defun some-active-point-p ()
427 "False if no image in *images* has an Active Point."
429 for i across
*images
*
430 sum
(has-layer-p (@ i map
) "Active Point")))
432 (defun remove-layer (map layer-name
)
433 "Destroy layer layer-name in map."
434 (when (has-layer-p map layer-name
)
435 (chain map
(get-layers-by-name layer-name
) 0 (destroy))))
437 (defun remove-any-layers (layer-name)
438 "Destroy in all *images* and in *streetmap* the layer named layer-name."
440 for i across
*images
* do
441 (remove-layer (@ i map
) layer-name
))
442 (remove-layer *streetmap
* layer-name
))
444 (defun reset-controls ()
445 (reveal-element-with-id "real-phoros-controls")
446 (hide-element-with-id "multiple-points-phoros-controls")
447 (disable-element-with-id "finish-point-button")
448 (disable-element-with-id "delete-point-button")
449 (disable-element-with-id "remove-work-layers-button")
450 (setf (inner-html-with-id "h2-controls") "Create Point")
451 (setf (inner-html-with-id "creator") nil
)
452 (setf (inner-html-with-id "point-creation-date") nil
)
453 (hide-aux-data-choice)
454 (setf (inner-html-with-id "aux-numeric-list") nil
)
455 (setf (inner-html-with-id "aux-text-list") nil
))
457 (defun disable-streetmap-nearest-aux-points-layer ()
458 "Get (@ *streetmap* nearest-aux-points-layer) out of the way,
459 I.e., remove features and disable feature select control so
460 it won't shadow any other control."
461 (chain *streetmap
* nearest-aux-points-layer
(remove-all-features))
462 (chain *streetmap
* nearest-aux-points-select-control
(deactivate))
463 (chain *streetmap
* user-points-select-control
(activate)))
465 (defun reset-layers-and-controls ()
466 "Destroy user-generated layers in *streetmap* and in all
467 *images*, and put controls into pristine state."
468 (remove-any-layers "Epipolar Line")
469 (remove-any-layers "Active Point")
470 (remove-any-layers "Estimated Position")
471 (remove-any-layers "User Point")
472 (chain *streetmap
* user-points-select-control
(unselect-all))
473 (disable-streetmap-nearest-aux-points-layer)
474 (when (and (not (equal undefined
*current-user-point
*))
475 (@ *current-user-point
* layer
))
477 user-points-select-control
478 (unselect *current-user-point
*)))
480 (setf *pristine-images-p
* t
)
481 (zoom-images-to-max-extent))
483 (defun enable-element-with-id (id)
484 "Activate HTML element with id=\"id\"."
485 (setf (chain document
(get-element-by-id id
) disabled
) nil
))
487 (defun disable-element-with-id (id)
488 "Grey out HTML element with id=\"id\"."
489 (setf (chain document
(get-element-by-id id
) disabled
) t
))
491 (defun hide-element-with-id (id)
492 "Hide HTML element wit id=\"id\"."
493 (setf (chain document
(get-element-by-id id
) style display
)
496 (defun reveal-element-with-id (id)
497 "Reveal HTML element wit id=\"id\"."
498 (setf (chain document
(get-element-by-id id
) style display
)
501 (defun hide-aux-data-choice ()
502 "Disable selector for auxiliary data."
503 ;;(disable-element-with-id "include-aux-data-p")
504 (hide-element-with-id "include-aux-data")
505 (hide-element-with-id "aux-point-distance")
506 (setf (chain document
507 (get-element-by-id "aux-point-distance")
512 (defun refresh-layer (layer)
513 "Have layer re-request and redraw features."
514 (chain layer
(refresh (create :force t
))))
516 (defun present-photos ()
517 "Handle the response triggered by request-photos-for-point."
518 (let ((photo-parameters
521 photo-request-response response-text
)))))
523 for i across
*images
*
524 do
(chain i
(delete-photo)))
525 (if (@ photo-parameters
0 footprintp
)
526 (hide-element-with-id "no-footprints-p")
527 (reveal-element-with-id "no-footprints-p"))
529 for p across photo-parameters
530 for i across
*images
*
532 (setf (@ i photo-parameters
) p
)
533 (chain i
(show-photo)))))
535 (defun consolidate-combobox (combobox-id)
536 "Help faking a combobox: copy selected option into input."
537 (let ((combobox-select (+ combobox-id
"-select"))
538 (combobox-input (+ combobox-id
"-input")))
539 (setf (value-with-id combobox-input
)
540 (getprop (chain document
541 (get-element-by-id combobox-select
)
544 (get-element-by-id combobox-select
)
548 (get-element-by-id combobox-input
)
551 (defun unselect-combobox-selection (combobox-id)
552 "Help faking a combobox: unset selected option so any
553 selection there will trigger an onchange event."
554 (let ((combobox-select (+ combobox-id
"-select")))
555 (setf (chain document
556 (get-element-by-id combobox-select
)
560 (defun stuff-combobox (combobox-id values
&optional
(selection -
1))
561 "Stuff combobox with values. If selection is a non-negative
562 integer, select the respective item."
563 (let ((combobox-select (+ combobox-id
"-select"))
564 (combobox-input (+ combobox-id
"-input")))
565 (setf (chain document
566 (get-element-by-id combobox-select
)
570 (loop for i in values do
572 (chain document
(create-element "option")))
573 (setf (@ combobox-item text
) i
)
575 (get-element-by-id combobox-select
)
576 (add combobox-item null
)))
577 (setf (chain document
578 (get-element-by-id combobox-select
)
581 (consolidate-combobox combobox-id
)))
583 (defun stuff-user-point-comboboxes (&optional selectp
)
584 "Stuff user point attribute comboboxes with sensible values.
585 If selectp it t, select the most frequently used one."
589 user-point-choice-response response-text
))))
591 (chain response attributes
(map (lambda (x)
594 (chain response descriptions
(map (lambda (x)
595 (@ x description
)))))
596 (best-used-attribute -
1)
597 (best-used-description -
1))
601 for i across
(@ response descriptions
)
603 do
(when (< maximum
(@ i count
))
604 (setf maximum
(@ i count
))
605 (setf best-used-description k
)))
608 for i across
(@ response attributes
)
610 do
(when (< maximum
(@ i count
))
611 (setf maximum
(@ i count
))
612 (setf best-used-attribute k
))))
614 "point-attribute" attributes best-used-attribute
)
616 "point-description" descriptions best-used-description
)))
618 (defun request-user-point-choice (&optional selectp
)
619 "Stuff user point attribute comboboxes with sensible values.
620 If selectp it t, select the most frequently used one."
621 (setf (@ *streetmap
* user-point-choice-response
)
626 (create :url
"/phoros/lib/user-point-attributes.json"
628 :headers
(create "Content-type" "text/plain")
630 (stuff-user-point-comboboxes selectp
)))))))
632 (defun request-photos-after-click (event)
633 "Handle the response to a click into *streetmap*; fetch photo
634 data. Set or update streetmap cursor."
635 (request-photos (chain *streetmap
*
636 (get-lon-lat-from-pixel (@ event xy
)))))
638 (defun request-photos (lonlat)
639 "Fetch photo data for a point near lonlat. Set or update
641 (setf (@ *streetmap
* clicked-lonlat
) lonlat
)
642 (if (checkbox-status-with-id "walk-p")
643 (request-aux-data-linestring-for-point
644 (@ *streetmap
* clicked-lonlat
))
645 (request-photos-for-point (@ *streetmap
* clicked-lonlat
))))
647 (defun request-aux-data-linestring-for-point (lonlat-spherical-mercator)
648 "Fetch a linestring along auxiyliary points near
649 lonlat-spherical-mercator."
650 (let ((lonlat-geographic
651 (chain lonlat-spherical-mercator
653 (transform +spherical-mercator
+ +geographic
+))))
654 (request-aux-data-linestring (@ lonlat-geographic lon
)
655 (@ lonlat-geographic lat
)
656 (* *linestring-step-ratio
*
658 (step-size-degrees))))
660 (defun request-photos-for-point (lonlat-spherical-mercator)
661 "Fetch photo data near lonlat-spherical-mercator; set or
662 update streetmap cursor."
663 (disable-element-with-id "finish-point-button")
664 (disable-element-with-id "remove-work-layers-button")
665 (remove-any-layers "Estimated Position")
666 (disable-streetmap-nearest-aux-points-layer)
668 (let* ((lonlat-geographic
669 (chain lonlat-spherical-mercator
671 (transform +spherical-mercator
+ +geographic
+)))
675 (create :longitude
(@ lonlat-geographic lon
)
676 :latitude
(@ lonlat-geographic lat
)
677 :zoom
(chain *streetmap
* (get-zoom))
678 :count
(lisp *number-of-images
*))))))
681 (remove-all-features))
685 (new (chain *open-layers
691 (*point
(@ lonlat-spherical-mercator
693 (@ lonlat-spherical-mercator
696 overview-cursor-layer
697 (remove-all-features))
699 overview-cursor-layer
701 (new (chain *open-layers
707 (*point
(@ lonlat-spherical-mercator
709 (@ lonlat-spherical-mercator
711 (setf (@ *streetmap
* photo-request-response
)
717 :url
"/phoros/lib/local-data"
719 :headers
(create "Content-type" "text/plain"
720 "Content-length" (@ content length
))
721 :success present-photos
))))))
723 (defun draw-epipolar-line ()
724 "Draw an epipolar line from response triggered by clicking
725 into a (first) photo."
726 (enable-element-with-id "remove-work-layers-button")
727 (let* ((epipolar-line
730 (@ this epipolar-request-response response-text
))))
734 (new (chain *open-layers
737 (@ x
:m
) (@ x
:n
))))))))
739 (new (chain *open-layers
745 (*line-string points
))))))))
746 (setf (@ feature render-intent
) "temporary")
747 (chain this epipolar-layer
748 (add-features feature
))))
749 ;; either *line-string or *multi-point are usable
751 (defun request-nearest-aux-points (global-position count
)
752 "Draw into streetmap the count nearest points of auxiliary
754 (let ((global-position-etc global-position
)
756 (setf (@ global-position-etc count
) count
)
757 (setf content
(chain *json-parser
*
758 (write global-position-etc
)))
759 (setf (@ *streetmap
* aux-local-data-request-response
)
763 (create :url
"/phoros/lib/aux-local-data"
765 :headers
(create "Content-type" "text/plain"
768 :success draw-nearest-aux-points
))))))
770 (defun request-aux-data-linestring (longitude latitude radius step-size
)
771 "Draw into streetmap a piece of linestring threaded along the
772 nearest points of auxiliary data inside radius."
773 (let* ((payload (create longitude longitude
777 azimuth
(@ *streetmap
*
778 linestring-central-azimuth
)))
779 (content (chain *json-parser
* (write payload
))))
780 (setf (@ *streetmap
* aux-data-linestring-request-response
)
784 (create :url
"/phoros/lib/aux-local-linestring.json"
786 :headers
(create "Content-type" "text/plain"
789 :success draw-aux-data-linestring
))))))
791 (defun draw-estimated-positions ()
792 "Draw into streetmap and into all images points at Estimated
793 Position. Estimated Position is the point returned so far
794 from photogrammetric calculations that are triggered by
795 clicking into another photo. Also draw into streetmap the
796 nearest auxiliary points to Estimated Position."
797 (when (write-permission-p)
798 (setf (chain document
799 (get-element-by-id "finish-point-button")
802 (enable-element-with-id "finish-point-button"))
803 (let* ((estimated-positions-request-response
807 estimated-positions-request-response
810 (aref estimated-positions-request-response
1))
811 (estimated-position-style
812 (create stroke-color
(chain *open-layers
815 style
"temporary" stroke-color
)
818 (setf *global-position
*
819 (aref estimated-positions-request-response
0))
826 (new (chain *open-layers
829 (@ *global-position
* longitude
)
830 (@ *global-position
* latitude
))))
831 (transform +geographic
+ +spherical-mercator
+)))))))
832 (setf (@ feature render-intent
) "temporary")
833 (setf (@ *streetmap
* estimated-position-layer
)
834 (new (chain *open-layers
838 (create display-in-layer-switcher nil
)))))
839 (setf (@ *streetmap
* estimated-position-layer style
)
840 estimated-position-style
)
841 (chain *streetmap
* estimated-position-layer
(add-features feature
))
843 (add-layer (@ *streetmap
* estimated-position-layer
))))
844 (request-nearest-aux-points *global-position
* 7)
847 for p in estimated-positions
849 (when p
;otherwise a photogrammetry error has occured
850 (setf (@ i estimated-position-layer
)
856 (create display-in-layer-switcher nil
)))))
857 (setf (@ i estimated-position-lonlat
)
858 (new (chain *open-layers
(*lon-lat
(@ p m
)
860 (setf (@ i estimated-position-layer style
)
861 estimated-position-style
)
864 (chain *open-layers
*geometry
(*point
(@ p m
)
868 (chain *open-layers
*feature
(*vector point
)))))
870 (add-layer (@ i estimated-position-layer
)))
871 (chain i estimated-position-layer
872 (add-features feature
))))))
873 (zoom-anything-to-point)
875 (get-element-by-id "finish-point-button")
878 (defun draw-nearest-aux-points ()
879 "Draw a few auxiliary points into streetmap."
880 (reveal-element-with-id "include-aux-data")
881 (reveal-element-with-id "aux-point-distance")
886 aux-local-data-request-response
889 (disable-streetmap-nearest-aux-points-layer)
890 (chain *streetmap
* user-points-select-control
(deactivate))
891 (chain *streetmap
* nearest-aux-points-select-control
(activate))
892 (chain *streetmap
* nearest-aux-points-hover-control
(activate))
893 (setf (@ *aux-point-distance-select
* options length
)
903 (*point
(@ i geometry coordinates
0)
904 (@ i geometry coordinates
1))))
905 (transform +geographic
+ +spherical-mercator
+)))
908 (chain *open-layers
*feature
(*vector point
)))))
909 (setf (@ feature attributes
)
911 (setf (@ feature fid
) ;this is supposed to correspond to
912 n
) ; option of *aux-point-distance-select*
914 nearest-aux-points-layer
915 (add-features feature
))
916 (setf aux-point-distance-item
917 (chain document
(create-element "option")))
918 (setf (@ aux-point-distance-item text
)
921 n
;let's hope add-features alway stores features in order of arrival
925 (format (@ i properties distance
) 3 ""))))
926 (chain *aux-point-distance-select
*
927 (add aux-point-distance-item null
))))
929 nearest-aux-points-select-control
932 (elt (@ *streetmap
* nearest-aux-points-layer features
)
934 (enable-element-with-id "aux-point-distance")))
936 (defun draw-aux-data-linestring ()
937 "Draw a piece of linestring along a few auxiliary points into
938 streetmap. Pan streetmap accordingly."
941 aux-data-linestring-request-response
944 (chain *json-parser
* (read data
) linestring
))
946 (chain *json-parser
* (read data
) current-point
))
948 (chain *json-parser
* (read data
) previous-point
))
950 (chain *json-parser
* (read data
) next-point
))
952 (chain *json-parser
* (read data
) azimuth
))
954 (chain *wkt-parser
* (read linestring-wkt
)))
956 (chain *wkt-parser
* (read current-point-wkt
)))
958 (chain *wkt-parser
* (read previous-point-wkt
)))
960 (chain *wkt-parser
* (read next-point-wkt
)))
961 (current-point-lonlat
962 (new (chain *open-layers
963 (*lon-lat
(@ current-point geometry x
)
964 (@ current-point geometry y
))))))
965 (chain *streetmap
* (pan-to current-point-lonlat
))
966 (setf (@ *streetmap
* linestring-central-azimuth
) azimuth
)
967 (request-photos-for-point current-point-lonlat
)
968 (setf (@ *streetmap
* step-back-point
) previous-point
)
969 (setf (@ *streetmap
* step-forward-point
) next-point
)
970 (chain *streetmap
* aux-data-linestring-layer
(remove-all-features))
972 aux-data-linestring-layer
973 (add-features linestring
))))
975 (defun step (&optional back-p
)
976 "Enable walk-mode if necessary, and do a step along
977 aux-data-linestring."
978 (if (checkbox-status-with-id "walk-p")
979 (let ((next-point-geometry
982 (if (< (- (@ *streetmap
* linestring-central-azimuth
) pi
) 0)
983 (setf (@ *streetmap
* linestring-central-azimuth
)
984 (+ (@ *streetmap
* linestring-central-azimuth
) pi
))
985 (setf (@ *streetmap
* linestring-central-azimuth
)
986 (- (@ *streetmap
* linestring-central-azimuth
) pi
)))
991 (transform +spherical-mercator
+ +geographic
+)))
996 (transform +spherical-mercator
+ +geographic
+)))))
997 (request-aux-data-linestring (@ next-point-geometry x
)
998 (@ next-point-geometry y
)
999 (* *linestring-step-ratio
*
1000 (step-size-degrees))
1001 (step-size-degrees)))
1003 (setf (checkbox-status-with-id "walk-p") t
) ;doesn't seem to trigger event
1004 (flip-walk-mode)))) ; so we have to do it explicitly
1006 (defun step-size-degrees ()
1007 "Return inner-html of element step-size (metres) converted
1008 into map units (degrees). You should be close to the
1010 (/ (inner-html-with-id "step-size") 1855.325 60))
1012 (defun decrease-step-size ()
1013 (when (> (inner-html-with-id "step-size") 0.5)
1014 (setf (inner-html-with-id "step-size")
1015 (/ (inner-html-with-id "step-size") 2))))
1017 (defun increase-step-size ()
1018 (when (< (inner-html-with-id "step-size") 100)
1019 (setf (inner-html-with-id "step-size")
1020 (* (inner-html-with-id "step-size") 2))))
1022 (defun user-point-style-map (label-property)
1023 "Create a style map where styles dispatch on feature property
1024 \"attribute\" and features are labelled after feature
1025 property label-property."
1026 (let* ((symbolizer-property "attribute")
1028 (new (chain *open-layers
1030 (*comparison
(create type
(chain *open-layers
1034 property symbolizer-property
1035 value
"solitary")))))
1037 (new (chain *open-layers
1039 (*comparison
(create type
(chain *open-layers
1043 property symbolizer-property
1044 value
"polyline")))))
1046 (new (chain *open-layers
1048 (*comparison
(create type
(chain *open-layers
1052 property symbolizer-property
1053 value
"polygon")))))
1055 (new (chain *open-layers
1057 filter solitary-filter
1059 graphic-name
"triangle"))))))
1061 (new (chain *open-layers
1063 filter polyline-filter
1065 graphic-name
"square"
1066 point-radius
4))))))
1068 (new (chain *open-layers
1070 filter polygon-filter
1072 graphic-name
"star"))))))
1074 (new (chain *open-layers
1078 graphic-name
"x"))))))
1079 (user-point-default-style
1082 (*style
(create stroke-color
"OrangeRed"
1083 fill-color
"OrangeRed"
1086 font-color
"OrangeRed"
1087 font-family
"'andale mono', 'lucida console', monospace"
1092 (create rules
(array solitary-rule
1096 (user-point-select-style
1099 (*style
(create stroke-opacity
1
1100 label label-property
)
1101 (create rules
(array solitary-rule
1105 (user-point-temporary-style
1108 (*style
(create fill-opacity
.5)
1109 (create rules
(array solitary-rule
1113 (new (chain *open-layers
1115 (create "default" user-point-default-style
1116 "temporary" user-point-temporary-style
1117 "select" user-point-select-style
))))))
1119 (defun draw-user-points ()
1120 "Draw currently selected user points into all images."
1121 (let* ((user-point-positions-response
1122 (chain *json-parser
*
1124 (@ *user-point-in-images-response
* response-text
))))
1125 (user-point-collections
1126 (chain user-point-positions-response image-points
))
1128 (chain user-point-positions-response user-point-count
))
1130 (when (> user-point-count
1) "${numericDescription}")))
1133 for user-point-collection in user-point-collections
1135 (when i
;otherwise a photogrammetry error has occured
1139 (@ user-point-collection features
)
1142 (@ raw-feature geometry coordinates
0))
1144 (@ raw-feature geometry coordinates
1))
1146 (new (chain *open-layers
1152 (@ raw-feature properties
))
1154 (new (chain *open-layers
1156 (*vector point attributes
)))))
1157 (setf (@ feature fid
) fid
)
1158 (setf (@ feature render-intent
) "select")
1161 (@ i user-point-layer
)
1162 (new (chain *open-layers
1166 (create display-in-layer-switcher nil
1167 style-map
(user-point-style-map
1169 (chain i map
(add-layer (@ i user-point-layer
)))
1170 (chain i user-point-layer
(add-features features
)))))))
1172 (defun finish-point ()
1173 "Send current *global-position* as a user point to the database."
1174 (let ((global-position-etc *global-position
*))
1175 (setf (@ global-position-etc attribute
)
1176 (value-with-id "point-attribute-input"))
1177 (setf (@ global-position-etc description
)
1178 (value-with-id "point-description-input"))
1179 (setf (@ global-position-etc numeric-description
)
1180 (value-with-id "point-numeric-description"))
1181 (when (checkbox-status-with-id "include-aux-data-p")
1182 (setf (@ global-position-etc aux-numeric
)
1183 (@ *current-nearest-aux-point
*
1186 (setf (@ global-position-etc aux-text
)
1187 (@ *current-nearest-aux-point
*
1191 (chain *json-parser
*
1192 (write global-position-etc
))))
1197 (create :url
"/phoros/lib/store-point"
1199 :headers
(create "Content-type" "text/plain"
1200 "Content-length" (@ content length
))
1203 (@ *streetmap
* user-point-layer
))
1204 (reset-layers-and-controls)
1205 (request-user-point-choice))))))))
1207 (defun increment-numeric-text (text)
1208 "Increment text if it looks like a number, and return it."
1209 (let* ((parts (chain (regex "(\\D*)(\\d*)(.*)") (exec text
)))
1210 (old-number (elt parts
2))
1211 (new-number (1+ (parse-int old-number
10)))))
1212 (if (is-finite new-number
)
1213 (+ (elt parts
1) new-number
(elt parts
3))
1216 (defun update-point ()
1217 "Send changes to currently selected user point to database."
1219 (create user-point-id
(@ *current-user-point
* fid
)
1221 (value-with-id "point-attribute-input")
1223 (value-with-id "point-description-input")
1225 (value-with-id "point-numeric-description")))
1227 (chain *json-parser
*
1228 (write point-data
))))
1232 (create :url
"/phoros/lib/update-point"
1234 :headers
(create "Content-type" "text/plain"
1235 "Content-length" (@ content
1239 (@ *streetmap
* user-point-layer
))
1240 (reset-layers-and-controls)
1241 (request-user-point-choice)))))))
1243 (defun delete-point ()
1244 "Purge currently selected user point from database."
1245 (let ((user-point-id (@ *current-user-point
* fid
)))
1247 (chain *json-parser
*
1248 (write user-point-id
)))
1252 (create :url
"/phoros/lib/delete-point"
1254 :headers
(create "Content-type" "text/plain"
1255 "Content-length" (@ content
1259 (@ *streetmap
* user-point-layer
))
1260 (reset-layers-and-controls)
1261 (request-user-point-choice true
)))))))
1263 (defun draw-active-point ()
1264 "Draw an Active Point, i.e. a point used in subsequent
1265 photogrammetric calculations."
1269 (new (chain *open-layers
1272 (new (chain *open-layers
1275 (@ this photo-parameters m
)
1276 (@ this photo-parameters n
))))))))))
1278 (defun image-click-action (clicked-image)
1280 "Do appropriate things when an image is clicked into."
1282 (chain clicked-image map
(get-lon-lat-from-view-port-px
1285 (@ clicked-image photo-parameters
))
1286 pristine-image-p content request
)
1287 (when (and (@ photo-parameters usable
)
1288 (chain clicked-image
(photop)))
1289 (setf (@ photo-parameters m
) (@ lonlat lon
)
1290 (@ photo-parameters n
) (@ lonlat lat
))
1291 (remove-layer (@ clicked-image map
) "Active Point")
1292 (remove-any-layers "Epipolar Line")
1293 (setf *pristine-images-p
* (not (some-active-point-p)))
1294 (setf (@ clicked-image active-point-layer
)
1295 (new (chain *open-layers
1297 (*vector
"Active Point"
1298 (create display-in-layer-switcher
1300 (chain clicked-image
1302 (add-layer (@ clicked-image active-point-layer
)))
1303 (chain clicked-image
(draw-active-point))
1307 (chain *streetmap
* user-points-select-control
(unselect-all))
1309 (setf (value-with-id "point-numeric-description")
1310 (increment-numeric-text
1311 (value-with-id "point-numeric-description")))
1312 (remove-any-layers "User Point") ;from images
1314 for i across
*images
* do
1315 (when (and (not (equal i clicked-image
))
1318 (@ i epipolar-layer
)
1319 (new (chain *open-layers
1321 (*vector
"Epipolar Line"
1323 display-in-layer-switcher nil
))))
1324 content
(chain *json-parser
*
1326 (append (array photo-parameters
)
1327 (@ i photo-parameters
))))
1328 (@ i epipolar-request-response
)
1332 (create :url
"/phoros/lib/epipolar-line"
1335 "Content-type" "text/plain"
1338 :success
(@ i draw-epipolar-line
)
1342 (add-layer (@ i epipolar-layer
))))))
1344 (remove-any-layers "Epipolar Line")
1345 (remove-any-layers "Estimated Position")
1346 (let* ((active-pointed-photo-parameters
1348 for i across
*images
*
1349 when
(has-layer-p (@ i map
) "Active Point")
1350 collect
(@ i photo-parameters
)))
1352 (chain *json-parser
*
1354 (list active-pointed-photo-parameters
1359 photo-parameters
)))))))))
1360 (setf (@ clicked-image estimated-positions-request-response
)
1364 (create :url
"/phoros/lib/estimated-positions"
1367 "Content-type" "text/plain"
1370 :success
(@ clicked-image
1371 draw-estimated-positions
)
1372 :scope clicked-image
)))))))))))
1374 (defun iso-time-string (lisp-time)
1375 "Return Lisp universal time formatted as ISO time string"
1376 (let* ((unix-time (- lisp-time
+unix-epoch
+))
1377 (js-date (new (*date
(* 1000 unix-time
)))))
1378 (chain *open-layers
*date
(to-i-s-o-string js-date
))))
1380 (defun delete-photo ()
1381 "Delete this object's photo."
1383 repeat
(chain this map
(get-num-layers))
1384 do
(chain this map layers
0 (destroy)))
1385 (hide-element-with-id (@ this usable-id
))
1386 (setf (@ this trigger-time-div inner-h-t-m-l
) nil
))
1389 "Check if this object contains a photo."
1390 (@ this trigger-time-div inner-h-t-m-l
))
1392 (defun show-photo ()
1393 "Show the photo described in this object's photo-parameters."
1394 (let ((image-div-width
1395 (parse-int (chain (get-computed-style (@ this map div
) nil
)
1398 (parse-int (chain (get-computed-style (@ this map div
) nil
)
1401 (@ this photo-parameters sensor-width-pix
))
1403 (@ this photo-parameters sensor-height-pix
)))
1413 (photo-path (@ this photo-parameters
))
1414 (new (chain *open-layers
1417 (+ image-width
.5) (+ image-height
.5))))
1418 (new (chain *open-layers
1419 (*size image-div-width
1422 max-resolution
(chain
1425 (/ image-width image-div-width
)
1426 (/ image-height image-div-height
)))))))))
1427 (chain this map
(zoom-to-max-extent))
1428 (if (@ this photo-parameters usable
)
1429 (hide-element-with-id (@ this usable-id
))
1430 (reveal-element-with-id (@ this usable-id
)))
1431 (setf (@ this trigger-time-div inner-h-t-m-l
)
1432 (iso-time-string (@ this photo-parameters trigger-time
)))))
1434 (defun zoom-images-to-max-extent ()
1435 "Zoom out all images."
1436 (loop for i across
*images
* do
(chain i map
(zoom-to-max-extent))))
1438 (defun zoom-anything-to-point ()
1439 "For streetmap and for images that have an Active Point or an
1440 Estimated Position, zoom in and recenter."
1441 (when (checkbox-status-with-id "zoom-to-point-p")
1443 (new (chain *open-layers
1444 (*lon-lat
(@ *global-position
* longitude
)
1445 (@ *global-position
* latitude
))
1446 (transform +geographic
+ +spherical-mercator
+)))))
1449 (set-center point-lonlat
18 nil t
))))
1450 (loop for i across
*images
* do
1453 ((has-layer-p (@ i map
) "Active Point")
1454 (new (chain *open-layers
(*lon-lat
1455 (@ i photo-parameters m
)
1456 (@ i photo-parameters n
)))))
1457 ((has-layer-p (@ i map
) "Estimated Position")
1458 (@ i estimated-position-lonlat
))
1461 (chain i map
(set-center point-lonlat
4 nil t
)))))))
1463 (defun initialize-image (image-index)
1464 "Create an image usable for displaying photos at position
1465 image-index in array *images*."
1466 (setf (aref *images
* image-index
) (new *image
))
1467 (setf (@ (aref *images
* image-index
) usable-id
)
1468 (+ "image-" image-index
"-usable"))
1469 (hide-element-with-id (+ "image-" image-index
"-usable"))
1470 (setf (@ (aref *images
* image-index
) trigger-time-div
)
1473 (get-element-by-id (+ "image-" image-index
"-trigger-time"))))
1474 (setf (@ (aref *images
* image-index
) image-click-action
)
1475 (image-click-action (aref *images
* image-index
)))
1476 (setf (@ (aref *images
* image-index
) click
)
1477 (new (*click-control
*
1478 (create :trigger
(@ (aref *images
* image-index
)
1479 image-click-action
)))))
1480 (chain (aref *images
* image-index
)
1483 (@ (aref *images
* image-index
) click
)))
1484 (chain (aref *images
* image-index
) click
(activate))
1485 ;;(chain (aref *images* image-index)
1488 ;; (new (chain *open-layers
1494 ;; (get-element-by-id
1495 ;; (+ "image-" image-index "-zoom")))))))))
1496 (chain (aref *images
* image-index
)
1499 (new (chain *open-layers
1506 (+ "image-" image-index
"-layer-switcher")))
1507 rounded-corner nil
))))))
1508 (let ((pan-west-control
1509 (new (chain *open-layers
*control
(*pan
"West"))))
1511 (new (chain *open-layers
*control
(*pan
"North"))))
1513 (new (chain *open-layers
*control
(*pan
"South"))))
1515 (new (chain *open-layers
*control
(*pan
"East"))))
1517 (new (chain *open-layers
*control
(*zoom-in
))))
1519 (new (chain *open-layers
*control
(*zoom-out
))))
1520 (zoom-to-max-extent-control
1521 (new (chain *open-layers
*control
(*zoom-to-max-extent
))))
1523 (new (chain *open-layers
1530 (+ "image-" image-index
"-zoom")))))))))
1531 (chain (aref *images
* image-index
)
1533 (add-control pan-zoom-panel
))
1534 (chain pan-zoom-panel
1535 (add-controls (array pan-west-control
1541 zoom-to-max-extent-control
))))
1542 (chain (aref *images
* image-index
)
1544 (render (chain document
1546 (+ "image-" image-index
))))))
1548 (defun user-point-selected (event)
1549 "Things to do once a user point is selected."
1550 (remove-any-layers "Active Point")
1551 (remove-any-layers "Epipolar Line")
1552 (remove-any-layers "Estimated Position")
1553 (unselect-combobox-selection "point-attribute")
1554 (unselect-combobox-selection "point-description")
1555 (user-point-selection-changed))
1557 (defun user-point-unselected (event)
1558 "Things to do once a user point is unselected."
1560 (user-point-selection-changed))
1562 (defun user-point-selection-changed ()
1563 "Things to do once a user point is selected or unselected."
1564 (hide-aux-data-choice)
1565 (setf *current-user-point
*
1566 (@ *streetmap
* user-point-layer selected-features
0))
1567 (let ((selected-features-count
1568 (@ *streetmap
* user-point-layer selected-features length
)))
1569 (setf (@ *streetmap
* user-point-layer style-map
)
1570 (user-point-style-map
1571 (when (> selected-features-count
1)
1572 "${numericDescription}")))
1574 ((> selected-features-count
1)
1575 (hide-element-with-id "real-phoros-controls")
1576 (reveal-element-with-id "multiple-points-phoros-controls"))
1577 ((= selected-features-count
1)
1578 (setf (value-with-id "point-attribute-input")
1579 (@ *current-user-point
* attributes attribute
))
1580 (setf (value-with-id "point-description-input")
1581 (@ *current-user-point
* attributes description
))
1582 (setf (value-with-id "point-numeric-description")
1583 (@ *current-user-point
* attributes numeric-description
))
1584 (setf (inner-html-with-id "point-creation-date")
1585 (@ *current-user-point
* attributes creation-date
))
1586 (setf (inner-html-with-id "aux-numeric-list")
1588 (@ *current-user-point
* attributes aux-numeric
)))
1589 (setf (inner-html-with-id "aux-text-list")
1591 (@ *current-user-point
* attributes aux-text
)))
1592 (if (write-permission-p
1593 (@ *current-user-point
* attributes user-name
))
1595 (setf (chain document
1596 (get-element-by-id "finish-point-button")
1599 (enable-element-with-id "finish-point-button")
1600 (enable-element-with-id "delete-point-button")
1601 (setf (inner-html-with-id "h2-controls") "Edit Point"))
1603 (disable-element-with-id "finish-point-button")
1604 (disable-element-with-id "delete-point-button")
1605 (setf (inner-html-with-id "h2-controls") "View Point")))
1606 (setf (inner-html-with-id "creator")
1608 (@ *current-user-point
* attributes user-name
)
1611 (hide-element-with-id "multiple-points-phoros-controls")
1612 (reveal-element-with-id "real-phoros-controls"))))
1613 (chain *streetmap
* user-point-layer
(redraw))
1614 (remove-any-layers "User Point") ;from images
1616 (chain *json-parser
*
1618 (array (chain *streetmap
*
1621 (map (lambda (x) (@ x fid
))))
1623 for i across
*images
*
1624 collect
(@ i photo-parameters
))))))
1625 (setf *user-point-in-images-response
*
1629 (create :url
"/phoros/lib/user-point-positions"
1631 :headers
(create "Content-type" "text/plain"
1632 "Content-length" (@ content
1634 :success draw-user-points
)))))
1636 (defun aux-point-distance-selected ()
1637 "Things to do on change of aux-point-distance select element."
1639 nearest-aux-points-select-control
1642 nearest-aux-points-select-control
1645 (elt (@ *streetmap
* nearest-aux-points-layer features
)
1646 (@ *aux-point-distance-select
*
1648 selected-index
))))))
1650 (defun enable-aux-point-selection ()
1651 "Check checkbox include-aux-data-p and act accordingly."
1652 (setf (checkbox-status-with-id "include-aux-data-p") t
)
1653 (flip-aux-data-inclusion))
1655 (defun flip-walk-mode ()
1656 "Query status of checkbox walk-p and induce first walking
1657 step if it's just been turned on. Otherwise delete our
1659 (if (checkbox-status-with-id "walk-p")
1660 (request-aux-data-linestring-for-point (@ *streetmap
*
1663 aux-data-linestring-layer
1664 (remove-all-features))))
1666 (defun flip-aux-data-inclusion ()
1667 "Query status of checkbox include-aux-data-p and act
1669 (if (checkbox-status-with-id "include-aux-data-p")
1671 nearest-aux-points-layer
1674 nearest-aux-points-layer
1675 (set-visibility nil
))))
1677 (defun html-ordered-list (aux-data)
1678 "Return a html-formatted list from aux-data."
1681 (:ol
:class
"aux-data-list"
1683 (reduce (lambda (x y
)
1684 (+ x
(who-ps-html (:li y
))))
1688 (defun nearest-aux-point-selected (event)
1689 "Things to do once a nearest auxiliary point is selected in
1691 (setf *current-nearest-aux-point
* (@ event feature
))
1693 (@ event feature attributes aux-numeric
))
1695 (@ event feature attributes aux-text
))
1697 (@ event feature attributes distance
)))
1698 (setf (@ *aux-point-distance-select
* options selected-index
)
1699 (@ event feature fid
))
1700 (setf (inner-html-with-id "aux-numeric-list")
1701 (html-ordered-list aux-numeric
))
1702 (setf (inner-html-with-id "aux-text-list")
1703 (html-ordered-list aux-text
))))
1706 "Store user's current map extent and log out."
1707 (let* ((bbox (chain *streetmap
*
1709 (transform +spherical-mercator
+ +geographic
+)
1711 (href (+ "/phoros/lib/logout?bbox=" bbox
)))
1712 (when (@ *streetmap
* cursor-layer features length
)
1713 (let* ((lonlat-geographic (chain *streetmap
*
1719 (transform +spherical-mercator
+
1722 "&longitude=" (@ lonlat-geographic x
)
1723 "&latitude=" (@ lonlat-geographic y
)))))
1724 (setf (@ location href
) href
)))
1727 "Prepare user's playground."
1728 (unless +presentation-project-bbox-text
+
1729 (setf (inner-html-with-id "presentation-project-emptiness")
1735 (create projection
+geographic
+
1736 display-projection
+geographic
+
1737 controls
(array (new (chain *open-layers
1740 (new (chain *open-layers
1742 (*attribution
)))))))))
1743 (unless +aux-data-p
+
1744 (disable-element-with-id "walk-p")
1745 (hide-element-with-id "decrease-step-size")
1746 (hide-element-with-id "step-size")
1747 (hide-element-with-id "increase-step-size")
1748 (hide-element-with-id "step-button"))
1749 (when (write-permission-p)
1750 (enable-element-with-id "point-attribute-input")
1751 (enable-element-with-id "point-attribute-select")
1752 (enable-element-with-id "point-description-input")
1753 (enable-element-with-id "point-description-select")
1754 (enable-element-with-id "point-numeric-description")
1755 (request-user-point-choice true
))
1756 (setf (inner-html-with-id "h2-controls") "Create Point")
1757 (hide-element-with-id "multiple-points-phoros-controls")
1758 (setf *point-attributes-select
*
1759 (chain document
(get-element-by-id "point-attribute-select")))
1760 (setf *aux-point-distance-select
*
1761 (chain document
(get-element-by-id "aux-point-distance")))
1762 (hide-aux-data-choice)
1763 (let ((cursor-layer-style
1766 external-graphic
"/phoros/lib/public_html/phoros-cursor.png")))
1767 (setf (@ *streetmap
* cursor-layer
)
1773 style cursor-layer-style
)))))
1774 (setf (@ *streetmap
* overview-cursor-layer
)
1780 style cursor-layer-style
))))))
1781 (let ((survey-layer-style
1782 (create stroke-color
(chain *open-layers
*feature
*vector
1783 style
"default" stroke-color
)
1787 graphic-name
"circle")))
1788 (setf (@ *streetmap
* survey-layer
)
1794 strategies
(array (new (*bbox-strategy
*)))
1796 (new (*http-protocol
*
1797 (create :url
"/phoros/lib/points.json")))
1798 style survey-layer-style
))))))
1799 (setf (@ *streetmap
* user-point-layer
)
1805 strategies
(array (new *bbox-strategy
*))
1807 (new (*http-protocol
*
1808 (create :url
"/phoros/lib/user-points.json")))
1809 style-map
(user-point-style-map nil
))))))
1810 (setf (@ *streetmap
* user-points-hover-control
)
1811 (new (chain *open-layers
1813 (*select-feature
(@ *streetmap
* user-point-layer
)
1814 (create render-intent
"temporary"
1816 highlight-only t
)))))
1817 (setf (@ *streetmap
* user-points-select-control
)
1818 (new (chain *open-layers
1820 (*select-feature
(@ *streetmap
* user-point-layer
)
1823 (let ((aux-layer-style
1824 (create stroke-color
"grey"
1828 graphic-name
"circle")))
1829 (setf (@ *streetmap
* aux-point-layer
)
1835 strategies
(array (new (*bbox-strategy
*)))
1837 (new (*http-protocol
*
1838 (create :url
"/phoros/lib/aux-points.json")))
1839 style aux-layer-style
1840 visibility nil
))))))
1841 (let ((nearest-aux-point-layer-style-map
1842 (new (chain *open-layers
1845 (create stroke-color
"grey"
1849 graphic-name
"circle")
1851 (create stroke-color
"black"
1855 graphic-name
"circle")
1857 (create stroke-color
"grey"
1862 graphic-name
"circle")))))))
1863 (setf (@ *streetmap
* nearest-aux-points-layer
)
1864 (new (chain *open-layers
1867 "Nearest Aux Points"
1869 display-in-layer-switcher nil
1870 style-map nearest-aux-point-layer-style-map
1872 (setf (@ *streetmap
* nearest-aux-points-hover-control
)
1873 (new (chain *open-layers
1876 (@ *streetmap
* nearest-aux-points-layer
)
1877 (create render-intent
"temporary"
1879 highlight-only t
)))))
1880 (setf (@ *streetmap
* nearest-aux-points-select-control
)
1881 (new (chain *open-layers
1884 (@ *streetmap
* nearest-aux-points-layer
)))))
1885 (setf (@ *streetmap
* aux-data-linestring-layer
)
1886 (new (chain *open-layers
1889 "Aux Data Linestring"
1891 display-in-layer-switcher nil
1892 style-map nearest-aux-point-layer-style-map
1894 (setf (@ *streetmap
* google-streetmap-layer
)
1895 (new (chain *open-layers
1897 (*google
"Google Streets"
1898 (create num-zoom-levels
23)))))
1899 (setf (@ *streetmap
* osm-layer
)
1900 (new (chain *open-layers
1905 (create num-zoom-levels
23
1907 "Data CC-By-SA by openstreetmap.org")))))
1908 (setf (@ *streetmap
* overview-osm-layer
)
1909 (new (chain *open-layers
1911 (*osm
* "OpenStreetMap"))))
1912 (setf (@ *streetmap
* click-streetmap
)
1913 (new (*click-control
*
1914 (create :trigger request-photos-after-click
))))
1915 (setf (@ *streetmap
* nirvana-layer
)
1920 (create is-base-layer t
1921 projection
(@ *streetmap
* osm-layer projection
)
1922 max-extent
(@ *streetmap
* osm-layer max-extent
)
1923 max-resolution
(@ *streetmap
*
1926 units
(@ *streetmap
* osm-layer units
)
1927 num-zoom-levels
(@ *streetmap
*
1929 num-zoom-levels
))))))
1932 (new (chain *open-layers
1939 "streetmap-layer-switcher"))
1940 rounded-corner nil
))))))
1941 (let ((pan-west-control
1942 (new (chain *open-layers
*control
(*pan
"West"))))
1944 (new (chain *open-layers
*control
(*pan
"North"))))
1946 (new (chain *open-layers
*control
(*pan
"South"))))
1948 (new (chain *open-layers
*control
(*pan
"East"))))
1950 (new (chain *open-layers
*control
(*zoom-in
))))
1952 (new (chain *open-layers
*control
(*zoom-out
))))
1953 (zoom-to-max-extent-control
1959 display-class
"streetmapZoomToMaxExtent"
1963 +presentation-project-bounds
+ ))))))))
1965 (new (chain *open-layers
1972 "streetmap-zoom")))))))
1974 (new (chain *open-layers
1980 (@ *streetmap
* overview-osm-layer
)
1981 (@ *streetmap
* overview-cursor-layer
))
1987 "streetmap-overview")))))))
1988 (mouse-position-control
1989 (new (chain *open-layers
1992 (create div
(chain document
1994 "streetmap-mouse-position"))
1995 empty-string
"longitude, latitude")))))
1997 (new (chain *open-layers
2001 (add-control pan-zoom-panel
))
2002 (chain pan-zoom-panel
2003 (add-controls (array pan-west-control
2009 zoom-to-max-extent-control
)))
2011 (add-control (@ *streetmap
* click-streetmap
)))
2012 (chain *streetmap
* click-streetmap
(activate))
2017 (register "featureselected"
2018 (@ *streetmap
* user-point-layer
)
2019 user-point-selected
))
2023 (register "featureunselected"
2024 (@ *streetmap
* user-point-layer
)
2025 user-point-unselected
))
2027 nearest-aux-points-layer
2029 (register "featureselected"
2030 (@ *streetmap
* nearest-aux-points-layer
)
2031 nearest-aux-point-selected
))
2034 (@ *streetmap
* nearest-aux-points-hover-control
)))
2037 (@ *streetmap
* nearest-aux-points-select-control
)))
2040 (@ *streetmap
* user-points-hover-control
)))
2043 (@ *streetmap
* user-points-select-control
)))
2044 (chain *streetmap
* user-points-hover-control
(activate))
2045 (chain *streetmap
* user-points-select-control
(activate))
2046 (chain *streetmap
* nearest-aux-points-hover-control
(activate))
2047 (chain *streetmap
* nearest-aux-points-select-control
(activate))
2048 (chain *streetmap
* (add-layer (@ *streetmap
* osm-layer
)))
2049 (try (chain *streetmap
*
2050 (add-layer (@ *streetmap
* google-streetmap-layer
)))
2053 (remove-layer (@ *streetmap
*
2054 google-streetmap-layer
)))))
2055 (chain *streetmap
* (add-layer (@ *streetmap
* nirvana-layer
)))
2057 (add-layer (@ *streetmap
* nearest-aux-points-layer
)))
2058 (chain *streetmap
* (add-layer (@ *streetmap
* survey-layer
)))
2060 (add-layer (@ *streetmap
* cursor-layer
)))
2062 (add-layer (@ *streetmap
* aux-point-layer
)))
2064 (add-layer (@ *streetmap
* aux-data-linestring-layer
)))
2066 (add-layer (@ *streetmap
* user-point-layer
)))
2067 (setf (@ overview-map element
)
2068 (chain document
(get-element-by-id
2069 "streetmap-overview-element")))
2070 (chain *streetmap
* (add-control overview-map
))
2071 (chain *streetmap
* (add-control mouse-position-control
))
2072 (chain *streetmap
* (add-control scale-line-control
)))
2074 for i from
0 below
(lisp *number-of-images
*)
2075 do
(initialize-image i
))
2079 (if (lisp (stored-bbox))
2080 (new (chain *open-layers
2082 (from-string (lisp (stored-bbox)))
2083 (transform +geographic
+ +spherical-mercator
+)))
2084 +presentation-project-bounds
+)))
2085 (let ((stored-cursor (lisp (stored-cursor))))
2088 (new (chain *open-layers
2090 (from-string stored-cursor
)
2091 (transform +geographic
+
2092 +spherical-mercator
+)))))))))))
2094 (pushnew (hunchentoot:create-regex-dispatcher
2095 (format nil
"/phoros/lib/phoros-~A-\\S*-\\S*\.js"
2098 hunchentoot
:*dispatch-table
*)