Changeset 3261
- Timestamp:
- 06/04/08 19:14:21 (7 months ago)
- Files:
-
- trunk/projects/bos/web/bos.web.asd (modified) (1 diff)
- trunk/projects/bos/web/contract-tree.lisp (modified) (4 diffs)
- trunk/projects/bos/web/image-tree.lisp (modified) (3 diffs)
- trunk/projects/bos/web/kml-handlers.lisp (modified) (5 diffs)
- trunk/projects/bos/web/quad-tree.lisp (modified) (6 diffs)
- trunk/projects/bos/web/sat-tree.lisp (modified) (8 diffs)
- trunk/projects/bos/web/utils.lisp (modified) (1 diff)
- trunk/projects/bos/web/webserver.lisp (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/projects/bos/web/bos.web.asd
r3204 r3261 35 35 (:file "quad-tree" :depends-on ("packages")) 36 36 (:file "contract-tree" :depends-on ("quad-tree")) 37 (:file "sat-tree" :depends-on ("quad-tree" ))37 (:file "sat-tree" :depends-on ("quad-tree" "contract-tree")) 38 38 (:file "countries" :depends-on ("packages")) 39 39 (:file "kml-handlers" :depends-on ("packages" "web-macros" "countries")) trunk/projects/bos/web/contract-tree.lisp
r3163 r3261 98 98 99 99 ;;; kml handler 100 (defmethod network-link-lod-min ((node contract-node))101 (if (zerop (depth node))102 16103 512))104 105 (defmethod network-link-lod-max ((node contract-node))106 -1)107 108 100 (defclass contract-tree-kml-handler (page-handler) 109 101 () … … 138 130 (setf (hunchentoot:header-out :last-modified) 139 131 (hunchentoot:rfc-1123-date (timestamp node))) 140 (let* ((lod `(:min ,(network-link-lod-min node) :max ,(network-link-lod-max node)))132 (let* ((lod (node-lod node)) 141 133 (box (geo-box node)) 142 134 (rect (geo-box-rectangle box)) … … 155 147 (kml-overlay (format nil "http://~a/contract-tree-image?path=~{~d~}" (website-host) path) 156 148 rect 157 :draw-order ( + 1000 (depth node))149 :draw-order (compute-draw-order node (1- +max-num-of-local-draw-order-levels+)) 158 150 ;; :absolute 0 159 151 ;; GroundOverlay specific LOD 160 :lod `(:min ,(network-link-lod-min node) 161 :max ,(if (node-has-children-p node) 162 (* 6 (network-link-lod-min (any-child node))) 163 -1))) 152 :lod lod) 164 153 ;; placemark-contracts 165 154 (let ((placemark-contracts … … 202 191 (format nil "http://~A/contract-tree-kml?path=~{~D~}~D" (website-host) path i)) 203 192 :rect (geo-box-rectangle (geo-box child)) 204 :lod `(:min ,(network-link-lod-min child) :max ,(network-link-lod-max child))))))))))))193 :lod (node-lod child))))))))))) 205 194 206 195 trunk/projects/bos/web/image-tree.lisp
r3138 r3261 256 256 (format nil "~2,'0X~{~2,'0X~}" opacity (reverse color))) 257 257 258 (defmethod kml-link ((href string) )258 (defmethod kml-link ((href string) &key (http-query "lang=[language]")) 259 259 (with-element "Link" 260 260 (with-element "href" (text href)) 261 261 (with-element "viewRefreshMode" (text "onRegion")) 262 (with-element "httpQuery" (text "lang=[language]")))) 262 (when http-query 263 (with-element "httpQuery" (text http-query))))) 263 264 264 265 ;; (defmethod kml-link ((href puri:uri)) … … 267 268 ;; (kml-link string))) 268 269 269 (defun kml-network-link (href &key rect lod name )270 (defun kml-network-link (href &key rect lod name (http-query "lang=[language]")) 270 271 (with-element "NetworkLink" 271 272 (when name (with-element "name" (text name))) 272 273 (when rect (kml-region rect lod)) 273 (kml-link href )))274 (kml-link href :http-query http-query))) 274 275 275 276 (defun kml-lat-lon-box (rect &optional (element "LatLonBox")) … … 630 631 :rect (make-rectangle2 (list (geo-x child) (geo-y child) 631 632 (geo-width child) (geo-height child))) 632 :lod `(:min ,(lod-min child) :max ,(lod-max child)))))))) 633 :lod `(:min ,(lod-min child) :max ,(lod-max child)) 634 :http-query nil)))))) 633 635 634 636 (defclass image-tree-kml-latest-handler (page-handler) trunk/projects/bos/web/kml-handlers.lisp
r3171 r3261 64 64 65 65 (defclass kml-root-handler (object-handler) 66 ( ))66 ((timestamp :accessor timestamp :initform (get-universal-time)))) 67 67 68 (defun write-root-kml (&optional sponsor) 69 (let ((contract (when sponsor (first (sponsor-contracts sponsor))))) 68 (defun write-root-kml (handler sponsor) 69 (let ((*print-case* :downcase) 70 (contract (when sponsor (first (sponsor-contracts sponsor))))) 71 (hunchentoot:handle-if-modified-since (timestamp handler)) 70 72 ;; only the first contract of SPONSOR will be shown 71 73 (with-xml-response (:content-type #+nil "text/xml" "application/vnd.google-earth.kml+xml; charset=utf-8" 72 74 :root-element "kml") 75 (setf (hunchentoot:header-out :last-modified) 76 (hunchentoot:rfc-1123-date (timestamp handler))) 73 77 (with-query-params ((lang "en")) 74 78 (with-element "Document" … … 96 100 :rect (make-rectangle2 (geo-location image-tree)) 97 101 :lod `(:min ,(lod-min image-tree) :max ,(lod-max image-tree)) 98 :name "sat-image")) 102 :name "old-image-tree" 103 :http-query nil)) 104 (dolist (sat-layer (class-instances 'sat-layer)) 105 (kml-network-link (format nil "http://~a/sat-root-kml?name=~A" (website-host) (name sat-layer)) 106 :rect (geo-box-rectangle *m2-geo-box*) 107 :lod '(:min 0 :max -1) 108 :name (princ-to-string (name sat-layer)) 109 :http-query nil)) 99 110 (let ((href (if (not contract) 100 111 (format nil "http://~a/contract-tree-kml" (website-host)) … … 106 117 (kml-network-link href 107 118 :rect (geo-box-rectangle (geo-box *contract-tree*)) 108 :lod `(:min ,(network-link-lod-min *contract-tree*) 109 :max ,(network-link-lod-max *contract-tree*)) 119 :lod (node-lod *contract-tree*) 110 120 :name "contracts")) 111 121 (kml-network-link (format nil "http://~a/poi-kml-all" (website-host)) … … 147 157 148 158 (defmethod handle-object ((handler kml-root-handler) (object sponsor)) 149 (write-root-kml object))159 (write-root-kml handler object)) 150 160 151 161 (defmethod handle-object ((handler kml-root-handler) (object contract)) … … 153 163 154 164 (defmethod handle-object ((handler kml-root-handler) (object null)) 155 (write-root-kml ))165 (write-root-kml handler nil)) 156 166 trunk/projects/bos/web/quad-tree.lisp
r3199 r3261 119 119 117.02245623511905d0 -1.0920067364569994d0)) 120 120 121 ;;; simple queue 122 (defun make-queue () 123 (cons nil nil)) 124 125 (defun queue-empty-p (queue) 126 (null (car queue))) 127 128 (defun enqueue (x queue) 129 (if (null (car queue)) 130 (setf (cdr queue) (setf (car queue) (list x))) 131 (setf (cdr (cdr queue)) (list x) 132 (cdr queue) (cdr (cdr queue)))) 133 (car queue)) 134 135 (defun dequeue (queue) 136 (pop (car queue))) 137 121 138 ;;; quad-node 122 139 (defclass quad-node () … … 179 196 (defmethod print-object ((node node-extension) stream) 180 197 (print-unreadable-object (node stream :type t :identity t) 181 (format stream "name: ~s" (name node)))) 198 (format stream "name: ~s path: ~s" (name node) (node-path node)))) 199 200 (defmethod delete-node-extension ((node node-extension)) 201 (setf (%extensions (base-node node)) 202 (delete node (%extensions (base-node node))))) 182 203 183 204 (defun equal-extension-type (a b) … … 278 299 (ensure-intersecting-children (ensure-child node index) geo-box function leaf-test)))) 279 300 280 (defun map-nodes (function node &key (prune-test (constantly nil))) 281 (funcall function node) 282 (dotimes (i 4) 283 (let ((child (child node i))) 284 (when (and child (not (funcall prune-test child))) 285 (map-nodes function child :prune-test prune-test))))) 286 287 (defun find-node-if (test node &key (prune-test (constantly nil))) 301 (defun map-nodes-internal (nodes function prune-test remove-node add-node) 302 "Used by MAP-NODES for depth-first and breadth-first 303 traversal. 304 305 NODES is an opaque collection, that is accessed via the given 306 functions REMOVE-NODE and ADD-NODE. 307 308 REMOVE-NODE will be called with NODES and has to return two 309 values: The removed node and the updated NODES. 310 311 ADD-NODE will be called with a node to be added and NODES. It has 312 to return the updated NODES. 313 314 FUNCTION will be called on each visited node. 315 316 If PRUNE-TEST returns true, the given node will not be visited." 317 (labels ((pop* () 318 (multiple-value-bind (node new-nodes) 319 (funcall remove-node nodes) 320 (setq nodes new-nodes) 321 node)) 322 (push* (node) 323 (setq nodes (funcall add-node node nodes)))) 324 (let ((node (pop*))) 325 (when node 326 (funcall function node) 327 (dotimes (i 4) 328 (let ((child (child node i))) 329 (when (and child (not (funcall prune-test child))) 330 (push* child)))) 331 (map-nodes-internal nodes function prune-test remove-node add-node))))) 332 333 (defun map-nodes-depth-first (function node prune-test) 334 ;; nodes is here a stack 335 (map-nodes-internal (list node) function prune-test 336 (lambda (nodes) 337 (values (car nodes) (cdr nodes))) 338 (lambda (node nodes) 339 (cons node nodes)))) 340 341 (defun map-nodes-breadth-first (function node prune-test) 342 ;; nodes is here a queue 343 (let ((nodes (make-queue))) 344 (enqueue node nodes) 345 (map-nodes-internal nodes function prune-test 346 (lambda (nodes) 347 (values (dequeue nodes) nodes)) 348 (lambda (node nodes) 349 (enqueue node nodes) 350 nodes)))) 351 352 (defun map-nodes (function node &key (prune-test (constantly nil)) (order :depth-first)) 353 (check-type order (member :depth-first :breadth-first)) 354 (let ((mapper (case order 355 (:depth-first #'map-nodes-depth-first) 356 (:breadth-first #'map-nodes-breadth-first)))) 357 (funcall mapper function node prune-test))) 358 359 (defun find-node-if (test node &key (prune-test (constantly nil)) (order :depth-first)) 288 360 (block nil 289 361 (map-nodes (lambda (node) … … 291 363 (return node))) 292 364 node 293 :prune-test prune-test) 365 :prune-test prune-test 366 :order order) 294 367 nil)) 295 368 296 (defun collect-nodes (test node &key (prune-test (constantly nil)) )369 (defun collect-nodes (test node &key (prune-test (constantly nil)) (order :depth-first)) 297 370 (let (nodes) 298 371 (map-nodes (lambda (node) … … 300 373 (push node nodes))) 301 374 node 302 :prune-test prune-test) 375 :prune-test prune-test 376 :order order) 303 377 (nreverse nodes))) 304 378 305 ;;; *quad-tree* 306 (defvar *quad-tree*) 307 308 (defun make-quad-tree () 309 (setq *quad-tree* (make-instance 'quad-node :geo-box *m2-geo-box*))) 310 311 (register-store-transient-init-function 'make-quad-tree) 312 313 (defun node-path (node) 379 (defmethod node-path ((node quad-node)) 314 380 (let (prev-n path) 315 381 (map-nodes (lambda (n) … … 321 387 *quad-tree* 322 388 :prune-test (lambda (n) (not (geo-box-intersect-p (geo-box n) 323 (geo-box node))))))) 324 389 (geo-box node)))) 390 :order :depth-first))) 391 392 (defmethod node-path ((node node-extension)) 393 (node-path (base-node node))) 394 395 ;;; *quad-tree* 396 (defvar *quad-tree*) 397 398 (defun make-quad-tree () 399 (setq *quad-tree* (make-instance 'quad-node :geo-box *m2-geo-box*))) 400 401 (defun node-lod (node) 402 (if (zerop (depth node)) 403 '(:min 16 :max -1) 404 '(:min 512 :max -1))) 405 406 (defconstant +max-num-of-local-draw-order-levels+ 10) 407 408 (defun compute-draw-order (node local-draw-order) 409 (+ local-draw-order 410 (* (depth node) +max-num-of-local-draw-order-levels+))) 411 412 (register-store-transient-init-function 'make-quad-tree) 413 trunk/projects/bos/web/sat-tree.lisp
r3205 r3261 2 2 3 3 (defclass sat-node (node-extension) 4 ((image :accessor image :initarg :image :type store-image))) 4 ((image :accessor image :initarg :image))) 5 6 (defmethod delete-node-extension :before ((obj sat-node)) 7 (delete-object (image obj))) 5 8 6 9 (defpersistent-class sat-layer () 7 10 ((name :reader name :initarg :name 8 :index-type unique-index 9 :index-reader find-sat-layer) 10 (geo-box :reader geo-box :initarg :geo-box))) 11 :index-type unique-index 12 :index-reader find-sat-layer) 13 (geo-box :reader geo-box :initarg :geo-box) 14 (local-draw-order :reader local-draw-order :initarg :local-draw-order))) 15 16 (defmethod print-object ((obj sat-layer) stream) 17 (print-unreadable-object (obj stream :type t :identity t) 18 (format stream "name: ~s" (name obj)))) 19 20 (defmethod destroy-object :before ((obj sat-layer)) 21 (dolist (top-level-node (sat-layer-top-level-nodes obj)) 22 (delete-node-extension top-level-node))) 11 23 12 24 (defun sat-layer-top-level-nodes (sat-layer) 13 (warn "this function is till buggy") 14 (let (nodes 15 top-level-depth) 16 (map-nodes (lambda (n) 17 (let ((sat-node (find-if (lambda (e) (and (eql (name e) (name sat-layer)) 18 (typep e 'sat-node))) 19 (extensions n)))) 20 (when sat-node 21 (unless top-level-depth 22 (setq top-level-depth (depth n))) 23 (if (= top-level-depth (depth n)) 24 (push sat-node nodes) 25 nil)))) 26 *quad-tree* 27 :prune-test (lambda (n) (not (geo-box-intersect-p (geo-box n) (geo-box sat-layer))))) 25 (check-type sat-layer sat-layer) 26 (let ((nodes ()) 27 top-level-depth 28 (state 'no-layer-node)) 29 (block collect 30 (map-nodes (lambda (n) 31 (let ((layer-node (find-if (lambda (e) (and (eql (name e) (name sat-layer)) 32 (typep e 'sat-node))) 33 (extensions n)))) 34 (ecase state 35 (no-layer-node 36 (when layer-node 37 (push layer-node nodes) 38 (setq state 'got-top-level-layer-node) 39 (setq top-level-depth (depth n)))) 40 (got-top-level-layer-node 41 (if (and layer-node (= (depth n) top-level-depth)) 42 (push layer-node nodes) 43 (return-from collect)))))) 44 *quad-tree* 45 :prune-test (lambda (n) (not (geo-box-intersect-p (geo-box n) (geo-box sat-layer)))) 46 :order :breadth-first)) 28 47 (nreverse nodes))) 29 48 30 49 (defpersistent-class sat-image (store-image) 31 ((layer :reader layer :initarg :layer) 32 (node :reader node :initarg :node :transient t) 50 ((layer :reader layer :initarg :layer) 33 51 (path :reader path :initarg :path) 34 52 (image-geo-box :accessor image-geo-box … … 38 56 39 57 (defmethod print-object ((obj sat-image) stream) 40 (print-unreadable-object (obj stream :type t :identity t))) 58 (print-unreadable-object (obj stream :type t :identity t) 59 (format stream "~s of layer ~s" (path obj) (name (layer obj))))) 60 61 (defun quad-tree-insert-sat-image (sat-image) 62 (let ((node (ensure-node-with-path *quad-tree* (path sat-image)))) 63 (make-instance 'sat-node 64 :name (name (layer sat-image)) 65 :base-node node 66 :image sat-image))) 67 68 (defun quad-tree-insert-sat-images () 69 (mapc #'quad-tree-insert-sat-image (class-instances 'sat-image))) 70 71 (register-store-transient-init-function 'quad-tree-insert-sat-images 72 'make-quad-tree) 41 73 42 74 (defmethod name ((obj sat-image)) … … 54 86 (n (geo-box-north geo-box)) 55 87 (e (geo-box-east geo-box)) 56 (s (geo-box-south geo-box)) 88 (s (geo-box-south geo-box)) 57 89 (bw (geo-box-west tile-geo-box)) 58 90 (bn (geo-box-north tile-geo-box)) … … 77 109 (th (round (/ ph scaling)))) 78 110 (values scaling 79 pw ph px py px2 py2 111 pw ph px py px2 py2 80 112 tw th rounded-geo-box))) 81 113 82 114 (defun make-sat-image-tile (image geo-box quad-node tile-geo-box name max-scaling) 115 (assert (find-sat-layer name)) 83 116 (multiple-value-bind (scaling 84 pw ph px py px2 py2 117 pw ph px py px2 py2 85 118 tw th rounded-geo-box) 86 119 (sat-image-tile-properties image geo-box tile-geo-box max-scaling) … … 93 126 :resize t :resample t 94 127 :dest-width tw :dest-height th) 95 (make-instance 'sat-node 96 :name name 97 :base-node quad-node 98 :image (make-store-image :class-name 'sat-image 99 :name (format nil "~A-~{~D~}" name path) 100 :initargs `(:path ,path 101 :image-geo-box ,rounded-geo-box))))))) 102 103 (defun make-sat-layer (image geo-box name &optional (start-depth 0)) 104 (check-type name symbol) 105 (assert (not (find-sat-layer name)) (name) 106 "A sat-layer of name ~S already exists." name) 107 (check-type image cl-gd::image) 108 (assert (geo-box-encloses-p *m2-geo-box* geo-box)) 109 (check-type start-depth (integer 0)) 128 (quad-tree-insert-sat-image 129 (make-store-image :class-name 'sat-image 130 :name (format nil "~A-~{~D~}" name path) 131 :type :jpg 132 :initargs `(:path ,path 133 :layer ,(find-sat-layer name) 134 :image-geo-box ,rounded-geo-box))))))) 135 136 (defun make-sat-image-tiles-for-depth (image geo-box layer start-depth) 110 137 (labels ((layer-quad-nodes () 111 138 (let (nodes) … … 113 140 (lambda (n) (when (= start-depth (depth n)) 114 141 (push n nodes))) 115 (lambda (n) (= start-depth (depth n)))) 142 (lambda (n) (= start-depth (depth n)))) 116 143 (mapcar 117 144 (lambda (quad-node) … … 128 155 (reduce #'max nodes 129 156 :key (lambda (node) 130 (sat-image-tile-properties image geo-box (tile-geo-box node)))))) 131 (let* ((nodes (remove-if-not #'pw-ph-large-enough (layer-quad-nodes))) 157 (sat-image-tile-properties image geo-box (tile-geo-box node)))))) 158 (let* ((name (name layer)) 159 (nodes (remove-if-not #'pw-ph-large-enough (layer-quad-nodes))) 132 160 (max-scaling (max-scaling nodes))) 133 (dolist (node nodes) 161 (format t "; creating ~a at depth ~a~%" name start-depth) 162 (dolist (node nodes layer) 134 163 (make-sat-image-tile image geo-box (quad-node node) 135 (tile-geo-box node) name max-scaling))) 136 (make-object 'sat-layer :name name :geo-box geo-box))) 164 (tile-geo-box node) name max-scaling)) 165 (unless (= 1 max-scaling) 166 (make-sat-image-tiles-for-depth image geo-box layer (1+ start-depth)))))) 167 168 (defun make-sat-layer (image geo-box name local-draw-order &optional (start-depth 0)) 169 (check-type name symbol) 170 (assert (not (find-sat-layer name)) (name) 171 "A sat-layer of name ~S already exists." name) 172 (check-type image cl-gd::image) 173 (assert (geo-box-encloses-p *m2-geo-box* geo-box)) 174 (check-type start-depth (integer 0)) 175 (check-type local-draw-order (integer 0)) 176 (assert (< local-draw-order +max-num-of-local-draw-order-levels+)) 177 (when (find local-draw-order (class-instances 'sat-layer) :key #'local-draw-order) 178 (cerror "create the new layer anyway" "There is already a sat-layer with the same local-draw-order '~A'." local-draw-order)) 179 (let ((layer (make-object 'sat-layer :name name :geo-box geo-box :local-draw-order local-draw-order))) 180 (make-sat-image-tiles-for-depth image geo-box layer start-depth))) 137 181 138 182 ;; (with-store-image (image (first (class-instances 'store-image))) … … 142 186 ;; 3)) 143 187 188 189 ;;; handlers 190 191 (defclass sat-tree-kml-handler (page-handler) 192 ()) 193 194 (defmethod handle ((handler sat-tree-kml-handler)) 195 (with-query-params ((path) (name)) 196 (let ((path (parse-path path)) 197 (layer (find-sat-layer (intern (string-upcase name) #.(find-package "KEYWORD"))))) 198 (assert layer nil "Cannnot find layer of name ~s." name) 199 (let* ((quad-node (find-node-with-path *quad-tree* path)) 200 (sat-node (find-if (lambda (e) (and (eql (name e) (name layer)) 201 (typep e 'sat-node))) 202 (extensions quad-node)))) 203 (assert sat-node nil "There is no sat-node of name ~s at path ~s." name path) 204 (let ((sat-image (image sat-node))) 205 (hunchentoot:handle-if-modified-since (blob-timestamp sat-image)) 206 (with-xml-response (:content-type "text/xml" #+nil"application/vnd.google-earth.kml+xml" 207 :root-element "kml") 208 (setf (hunchentoot:header-out :last-modified) 209 (hunchentoot:rfc-1123-date (blob-timestamp sat-image))) 210 (let ((lod (node-lod sat-node)) 211 (rect (geo-box-rectangle (geo-box sat-node)))) 212 (with-element "Document" 213 (kml-region rect lod) 214 (kml-overlay (format nil "http://~a/image/~d" (website-host) (store-object-id sat-image)) 215 (geo-box-rectangle (image-geo-box sat-image)) 216 :draw-order (compute-draw-order sat-node (local-draw-order layer)) 217 ;; :absolute 0 218 ) 219 (let ((*print-case* :downcase)) 220 (dotimes (i 4) 221 (let ((child (child sat-node i))) 222 (when child 223 (kml-network-link (format nil "http://~A/sat-tree-kml?name=~A&path=~{~D~}" 224 (website-host) (name layer) (append path (list i))) 225 :rect (geo-box-rectangle (geo-box child)) 226 :lod (node-lod child) 227 :http-query nil))))))))))))) 228 229 (defclass sat-root-kml-handler (page-handler) 230 ()) 231 232 (defmethod handle ((handler sat-root-kml-handler)) 233 (with-query-params ((name)) 234 (let ((*print-case* :downcase) 235 (layer (find-sat-layer (intern (string-upcase name) #.(find-package "KEYWORD"))))) 236 (assert layer nil "Cannnot find layer of name ~s." name) 237 (let ((top-level-nodes (sat-layer-top-level-nodes layer))) 238 (assert top-level-nodes) 239 (hunchentoot:handle-if-modified-since (blob-timestamp (image (first top-level-nodes)))) 240 (with-xml-response (:content-type "text/xml" #+nil"application/vnd.google-earth.kml+xml" 241 :root-element "kml") 242 (setf (hunchentoot:header-out :last-modified) 243 (hunchentoot:rfc-1123-date (blob-timestamp (image (first top-level-nodes))))) 244 (with-element "Document" 245 (dolist (node top-level-nodes) 246 (kml-network-link (format nil "http://~A/sat-tree-kml?name=~A&path=~{~D~}" 247 (website-host) (name layer) (node-path node)) 248 :rect (geo-box-rectangle (geo-box node)) 249 :lod (node-lod node) 250 :http-query nil)))))))) 251 trunk/projects/bos/web/utils.lisp
r2343 r3261 440 440 do (vector-push-extend c result) 441 441 finally (return result))) 442 trunk/projects/bos/web/webserver.lisp
r3074 r3261 205 205 ("/image-tree" image-tree-handler) 206 206 ("/contract-tree-kml" contract-tree-kml-handler) 207 ("/contract-tree-image" contract-tree-image-handler) 207 ("/contract-tree-image" contract-tree-image-handler) 208 208 ("/contract-image" contract-image-handler) 209 209 ("/contract" contract-handler) 210 ("/sat-tree-kml" sat-tree-kml-handler) 211 ("/sat-root-kml" sat-root-kml-handler) 210 212 ("/reports-xml" reports-xml-handler) 211 213 ("/complete-transfer" complete-transfer-handler)
