Changeset 3261

Show
Ignore:
Timestamp:
06/04/08 19:14:21 (7 months ago)
Author:
ksprotte
Message:

merge from branches/bos-trunk-sat

The kml-root-handler now contains a link to each existing (persistent)
instance of sat-layer. Thus allowing to switch between different
satellite images.

The old image-tree still exists, but shall be removed later.

A new layer can be created by MAKE-SAT-LAYER with the following lambda-list:
(image geo-box name local-draw-order &optional (start-depth 0))

New is local-draw-order, which can be an integer between 0 and (-
+max-num-of-local-draw-order-levels+ 2). The contract layer is
automatically assigned (- +max-num-of-local-draw-order-levels+ 1),
placing it always on top.

Contracts (transparent png's) and satellite images (jpg's) now play
nicely together.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/projects/bos/web/bos.web.asd

    r3204 r3261  
    3535               (:file "quad-tree" :depends-on ("packages")) 
    3636               (: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")) 
    3838               (:file "countries" :depends-on ("packages")) 
    3939               (:file "kml-handlers" :depends-on ("packages" "web-macros" "countries")) 
  • trunk/projects/bos/web/contract-tree.lisp

    r3163 r3261  
    9898 
    9999;;; kml handler 
    100 (defmethod network-link-lod-min ((node contract-node)) 
    101   (if (zerop (depth node)) 
    102       16 
    103       512)) 
    104  
    105 (defmethod network-link-lod-max ((node contract-node)) 
    106   -1) 
    107  
    108100(defclass contract-tree-kml-handler (page-handler) 
    109101  () 
     
    138130        (setf (hunchentoot:header-out :last-modified) 
    139131              (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)) 
    141133               (box (geo-box node)) 
    142134               (rect (geo-box-rectangle box)) 
     
    155147            (kml-overlay (format nil "http://~a/contract-tree-image?path=~{~d~}" (website-host) path) 
    156148                         rect 
    157                          :draw-order (+ 1000 (depth node)) 
     149                         :draw-order (compute-draw-order node (1- +max-num-of-local-draw-order-levels+)) 
    158150                         ;; :absolute 0 
    159151                         ;; 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) 
    164153            ;; placemark-contracts 
    165154            (let ((placemark-contracts 
     
    202191                       (format nil "http://~A/contract-tree-kml?path=~{~D~}~D" (website-host) path i)) 
    203192                   :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))))))))))) 
    205194 
    206195 
  • trunk/projects/bos/web/image-tree.lisp

    r3138 r3261  
    256256  (format nil "~2,'0X~{~2,'0X~}" opacity (reverse color))) 
    257257 
    258 (defmethod kml-link ((href string)
     258(defmethod kml-link ((href string) &key (http-query "lang=[language]")
    259259  (with-element "Link" 
    260260    (with-element "href" (text href)) 
    261261    (with-element "viewRefreshMode" (text "onRegion")) 
    262     (with-element "httpQuery" (text "lang=[language]")))) 
     262    (when http-query 
     263      (with-element "httpQuery" (text http-query))))) 
    263264 
    264265;; (defmethod kml-link ((href puri:uri)) 
     
    267268;;     (kml-link string))) 
    268269 
    269 (defun kml-network-link (href &key rect lod name
     270(defun kml-network-link (href &key rect lod name (http-query "lang=[language]")
    270271  (with-element "NetworkLink" 
    271272    (when name (with-element "name" (text name))) 
    272273    (when rect (kml-region rect lod)) 
    273     (kml-link href))) 
     274    (kml-link href :http-query http-query))) 
    274275 
    275276(defun kml-lat-lon-box (rect &optional (element "LatLonBox")) 
     
    630631                            :rect (make-rectangle2 (list (geo-x child) (geo-y child) 
    631632                                                         (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)))))) 
    633635 
    634636(defclass image-tree-kml-latest-handler (page-handler) 
  • trunk/projects/bos/web/kml-handlers.lisp

    r3171 r3261  
    6464 
    6565(defclass kml-root-handler (object-handler) 
    66   ()) 
     66  ((timestamp :accessor timestamp :initform (get-universal-time)))) 
    6767 
    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)) 
    7072    ;; only the first contract of SPONSOR will be shown 
    7173    (with-xml-response (:content-type #+nil "text/xml" "application/vnd.google-earth.kml+xml; charset=utf-8" 
    7274                                      :root-element "kml") 
     75      (setf (hunchentoot:header-out :last-modified) 
     76            (hunchentoot:rfc-1123-date (timestamp handler))) 
    7377      (with-query-params ((lang "en")) 
    7478        (with-element "Document" 
     
    96100                              :rect (make-rectangle2 (geo-location image-tree)) 
    97101                              :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)) 
    99110          (let ((href (if (not contract) 
    100111                          (format nil "http://~a/contract-tree-kml" (website-host)) 
     
    106117            (kml-network-link href 
    107118                              :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*) 
    110120                              :name "contracts")) 
    111121          (kml-network-link (format nil "http://~a/poi-kml-all" (website-host)) 
     
    147157 
    148158(defmethod handle-object ((handler kml-root-handler) (object sponsor)) 
    149   (write-root-kml object)) 
     159  (write-root-kml handler object)) 
    150160 
    151161(defmethod handle-object ((handler kml-root-handler) (object contract)) 
     
    153163 
    154164(defmethod handle-object ((handler kml-root-handler) (object null)) 
    155   (write-root-kml)) 
     165  (write-root-kml handler nil)) 
    156166 
  • trunk/projects/bos/web/quad-tree.lisp

    r3199 r3261  
    119119                                   117.02245623511905d0 -1.0920067364569994d0)) 
    120120 
     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 
    121138;;; quad-node 
    122139(defclass quad-node () 
     
    179196(defmethod print-object ((node node-extension) stream) 
    180197  (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))))) 
    182203 
    183204(defun equal-extension-type (a b) 
     
    278299      (ensure-intersecting-children (ensure-child node index) geo-box function leaf-test)))) 
    279300 
    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 
     303traversal. 
     304 
     305NODES is an opaque collection, that is accessed via the given 
     306functions REMOVE-NODE and ADD-NODE. 
     307 
     308REMOVE-NODE will be called with NODES and has to return two 
     309values: The removed node and the updated NODES. 
     310 
     311ADD-NODE will be called with a node to be added and NODES. It has 
     312to return the updated NODES. 
     313 
     314FUNCTION will be called on each visited node. 
     315 
     316If 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)) 
    288360  (block nil 
    289361    (map-nodes (lambda (node) 
     
    291363                   (return node))) 
    292364               node 
    293                :prune-test prune-test) 
     365               :prune-test prune-test 
     366               :order order) 
    294367    nil)) 
    295368 
    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)
    297370  (let (nodes) 
    298371    (map-nodes (lambda (node) 
     
    300373                   (push node nodes))) 
    301374               node 
    302                :prune-test prune-test) 
     375               :prune-test prune-test 
     376               :order order) 
    303377    (nreverse nodes))) 
    304378 
    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)) 
    314380  (let (prev-n path) 
    315381    (map-nodes (lambda (n) 
     
    321387               *quad-tree* 
    322388               :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  
    22 
    33(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))) 
    58 
    69(defpersistent-class sat-layer () 
    710  ((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))) 
    1123 
    1224(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)) 
    2847    (nreverse nodes))) 
    2948 
    3049(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)       
    3351   (path :reader path :initarg :path) 
    3452   (image-geo-box :accessor image-geo-box 
     
    3856 
    3957(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) 
    4173 
    4274(defmethod name ((obj sat-image)) 
     
    5486         (n (geo-box-north geo-box)) 
    5587         (e (geo-box-east geo-box)) 
    56          (s (geo-box-south geo-box))         
     88         (s (geo-box-south geo-box)) 
    5789         (bw (geo-box-west tile-geo-box)) 
    5890         (bn (geo-box-north tile-geo-box)) 
     
    77109         (th (round (/ ph scaling)))) 
    78110    (values scaling 
    79             pw ph px py px2 py2  
     111            pw ph px py px2 py2 
    80112            tw th rounded-geo-box))) 
    81113 
    82114(defun make-sat-image-tile (image geo-box quad-node tile-geo-box name max-scaling) 
     115  (assert (find-sat-layer name)) 
    83116  (multiple-value-bind (scaling 
    84                         pw ph px py px2 py2  
     117                        pw ph px py px2 py2 
    85118                        tw th rounded-geo-box) 
    86119      (sat-image-tile-properties image geo-box tile-geo-box max-scaling) 
     
    93126                          :resize t :resample t 
    94127                          :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) 
    110137  (labels ((layer-quad-nodes () 
    111138             (let (nodes) 
     
    113140                                             (lambda (n) (when (= start-depth (depth n)) 
    114141                                                           (push n nodes))) 
    115                                              (lambda (n) (= start-depth (depth n))))                
     142                                             (lambda (n) (= start-depth (depth n)))) 
    116143               (mapcar 
    117144                (lambda (quad-node) 
     
    128155             (reduce #'max nodes 
    129156                     :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))) 
    132160           (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) 
    134163        (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))) 
    137181 
    138182;; (with-store-image (image (first (class-instances 'store-image))) 
     
    142186;;                   3)) 
    143187 
     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  
    440440        do (vector-push-extend c result) 
    441441        finally (return result))) 
     442 
  • trunk/projects/bos/web/webserver.lisp

    r3074 r3261  
    205205                                        ("/image-tree" image-tree-handler) 
    206206                                        ("/contract-tree-kml" contract-tree-kml-handler) 
    207                                         ("/contract-tree-image" contract-tree-image-handler)                                     
     207                                        ("/contract-tree-image" contract-tree-image-handler)                                                                             
    208208                                        ("/contract-image" contract-image-handler) 
    209209                                        ("/contract" contract-handler) 
     210                                        ("/sat-tree-kml" sat-tree-kml-handler) 
     211                                        ("/sat-root-kml" sat-root-kml-handler)                                         
    210212                                        ("/reports-xml" reports-xml-handler) 
    211213                                        ("/complete-transfer" complete-transfer-handler)