Changeset 2733

Show
Ignore:
Timestamp:
03/14/08 13:50:14 (10 months ago)
Author:
ksprotte
Message:

working on image-tree-kml-handler

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/projects/bos/web/image-tree.lisp

    r2730 r2733  
    11(in-package :bos.web) 
     2 
     3;;; kml utils (including point / rect stuff) - for now  
     4 
     5(defmacro values-nsew () 
     6  '(values north south east west)) 
     7 
     8(defmacro bind-nsew (form &body body) 
     9  `(multiple-value-bind (north south east west) 
     10       ,form 
     11     ,@body)) 
     12 
     13(defmacro let-nsew ((north south east west) &body body) 
     14  `(let ((north ,north) 
     15         (south ,south) 
     16         (east ,east) 
     17         (west ,west)) 
     18     ,@body)) 
     19 
     20(defclass point () 
     21  ()) 
     22 
     23(defgeneric point-lon-lat (point)) 
     24(defgeneric point-x-y (point)) 
     25 
     26(defmethod print-object ((point point) stream) 
     27  (print-unreadable-object (point stream) 
     28    (multiple-value-bind (x y) 
     29        (point-x-y point) 
     30      (if (and (integerp x) (integerp y)) 
     31          (format stream "~a,~a" x y) 
     32          (format stream "~,5f,~,5f" x y))))) 
     33 
     34(defclass lon-lat-point (point) 
     35  ((lon :accessor %point-lon :initarg :lon) 
     36   (lat :accessor %point-lat :initarg :lat))) 
     37 
     38(defmethod point-lon-lat ((p lon-lat-point)) 
     39  (values (%point-lon p) (%point-lat p))) 
     40 
     41(defmethod point-x-y ((p lon-lat-point)) 
     42  (destructuring-bind (x y zone southhemi-p) 
     43      (geo-utm:lon-lat-to-utm-x-y (%point-lon p) (%point-lat p)) 
     44    (assert (= +utm-zone+ zone)) 
     45    (assert southhemi-p) 
     46    (values (- x +nw-utm-x+) (- +nw-utm-y+ y)))) 
     47 
     48(defclass x-y-point (point) 
     49  ((x :accessor %point-x :initarg :x) 
     50   (y :accessor %point-y :initarg :y))) 
     51 
     52(defmethod point-x-y ((p x-y-point)) 
     53  (values (%point-x p) (%point-y p))) 
     54 
     55(defmethod point-lon-lat ((p x-y-point)) 
     56  (destructuring-bind (lon lat) 
     57      (geo-utm:utm-x-y-to-lon-lat (+ +nw-utm-x+ (%point-x p)) 
     58                                  (- +nw-utm-y+ (%point-y p)) 
     59                                  +utm-zone+ t) 
     60    (values lon lat))) 
     61 
     62(defun make-point (&key x y lon lat) 
     63  (cond 
     64    ((and x y (not lon) (not lat)) 
     65     (make-instance 'x-y-point :x x :y y)) 
     66    ((and lon lat (not x) (not y)) 
     67     (make-instance 'lon-lat-point :lon lon :lat lat)) 
     68    (t (error "Cannot make point")))) 
     69 
     70(defun point-equal (a b) 
     71  (assert (and (typep a 'x-y-point) (typep b 'x-y-point)) 
     72          nil 
     73          "point-equal only impl for 2 point-x-y") 
     74  (and (= (%point-x a) (%point-x b)) 
     75       (= (%point-y a) (%point-y b)))) 
     76 
     77(defun point1- (point) 
     78  (multiple-value-bind (x y) (point-x-y point) 
     79    (make-point :x (1- x) :y (1- y)))) 
     80 
     81(defclass rectangle () 
     82  ((top-left :accessor top-left :initarg :top-left) 
     83   (bottom-right :accessor bottom-right :initarg :bottom-right))) 
     84 
     85(defmethod width-height ((rect rectangle))   
     86  (multiple-value-bind 
     87        (x y) 
     88      (point-x-y (top-left rect))    
     89    (multiple-value-bind 
     90          (x2 y2) 
     91        (point-x-y (bottom-right rect))      
     92      (let ((width (- x2 x)) 
     93            (height (- y2 y)))         
     94        (values width height))))) 
     95 
     96(defmethod size ((rect rectangle)) 
     97  (multiple-value-bind (width height) 
     98      (width-height rect) 
     99    (max width height))) 
     100 
     101(defmethod print-object ((rect rectangle) stream) 
     102  (print-unreadable-object (rect stream :type t :identity t)     
     103    (multiple-value-bind 
     104          (x y) 
     105        (point-x-y (top-left rect))     
     106      (multiple-value-bind 
     107            (x2 y2) 
     108          (point-x-y (bottom-right rect))         
     109        (let ((width (- x2 x)))          
     110          (let ((height (- y2 y)))             
     111            (format stream "~a,~a ~a x ~a" x y width height))))))) 
     112 
     113(defun make-rectangle (&key x y width height (type 'rectangle)) 
     114  (make-instance type 
     115                 :top-left (make-point :x x :y y) 
     116                 :bottom-right (make-point :x (+ x width) :y (+ y height)))) 
     117 
     118(defun make-rectangle2 (x-y-width-height) 
     119  (destructuring-bind (x y width height) 
     120      x-y-width-height 
     121    (make-rectangle :x x :y y :width width :height height))) 
     122 
     123(defun rect-equal (a b) 
     124  (and (point-equal (top-left a) (top-left b)) 
     125       (point-equal (bottom-right a) (bottom-right b)))) 
     126 
     127(defmethod bounding-box-lon-lat ((rect rectangle)) 
     128  (MULTIPLE-VALUE-BIND 
     129        (WEST NORTH) 
     130      (POINT-LON-LAT (TOP-LEFT RECT)) 
     131    (MULTIPLE-VALUE-BIND 
     132          (EAST SOUTH) 
     133        (POINT-LON-LAT (BOTTOM-RIGHT RECT)) 
     134      (VALUES-NSEW)))) 
     135 
     136(defmethod bounding-box-x-y ((rect rectangle)) 
     137  (multiple-value-bind 
     138        (west north) 
     139      (point-x-y (top-left rect)) 
     140    (multiple-value-bind 
     141          (east south) 
     142        (point-x-y (bottom-right rect)) 
     143      (values-nsew)))) 
     144 
     145 
     146;; (defmethod split ((rect rectangle) side-num) 
     147;;   (let ((array (make-array (list side-num side-num)))) 
     148;;     (multiple-value-bind 
     149;;           (x y) 
     150;;         (point-x-y (top-left rect)) 
     151;;       (multiple-value-bind 
     152;;             (width height) 
     153;;           (width-height rect) 
     154;;         (let ((new-width (/ width side-num))) 
     155;;           (assert (integerp (/ width side-num))) 
     156;;           (assert (= width height)) 
     157;;           (dotimes (xind side-num) 
     158;;             (dotimes (yind side-num) 
     159;;               (setf (aref array xind yind) 
     160;;                     (make-rectangle :x (+ x (* xind new-width)) :y 
     161;;                                     (+ y (* yind new-width)) :width new-width 
     162;;                                     :height new-width))))))) 
     163;;     array)) 
     164 
     165(defmethod quad-split ((rect rectangle) &optional (sub-rect-type 'rectangle)) 
     166  (multiple-value-bind 
     167        (x y) 
     168      (point-x-y (top-left rect)) 
     169    (multiple-value-bind 
     170          (width height) 
     171        (width-height rect) 
     172      (let ((width1 (floor width 2))) 
     173        (let ((width2 (ceiling width 2))) 
     174          (let ((height1 (floor height 2))) 
     175            (let ((height2 (ceiling height 2))) 
     176              (assert (> width 1)) 
     177              (assert (> height 1)) 
     178              (list 
     179               (make-rectangle :x x :y y :width width1 :height height1 :type 
     180                               sub-rect-type) 
     181               (make-rectangle :x x :y (+ y height1) :width width1 :height 
     182                               height2 :type sub-rect-type) 
     183               (make-rectangle :x (+ x width1) :y (+ y height1) :width width2 
     184                               :height height2 :type sub-rect-type) 
     185               (make-rectangle :x (+ x width1) :y y :width width2 :height height1 
     186                               :type sub-rect-type))))))))) 
     187 
     188(defun point-in-rect-p (point rect) 
     189  (multiple-value-bind 
     190        (x y) 
     191      (point-x-y point) 
     192    (multiple-value-bind 
     193          (r-x r-y) 
     194        (point-x-y (top-left rect)) 
     195      (multiple-value-bind 
     196            (r-x2 r-y2) 
     197          (point-x-y (bottom-right rect)) 
     198        (and (<= r-x x (1- r-x2)) (<= r-y y (1- r-y2))))))) 
     199 
     200(defun contains-p (parent-rect rect)   
     201  (and (point-in-rect-p (top-left rect) parent-rect) 
     202       (point-in-rect-p (point1- (bottom-right rect)) parent-rect))) 
     203 
     204(defun intersects-p (parent-rect rect)   
     205  (or (point-in-rect-p (top-left rect) parent-rect) 
     206      (point-in-rect-p (point1- (bottom-right rect)) parent-rect))) 
     207 
     208(defun rectangle-union (rects) 
     209  (let ((left (reduce #'min rects :key #'(lambda (r) (point-x-y (top-left r))))) 
     210        (right (reduce #'max rects :key #'(lambda (r) (point-x-y (bottom-right r))))) 
     211        (top (reduce #'min rects :key #'(lambda (r) (nth-value 1 (point-x-y (top-left r)))))) 
     212        (bottom (reduce #'max rects :key #'(lambda (r) (nth-value 1 (point-x-y (bottom-right r))))))) 
     213    (make-rectangle :x left :y top :width (- right left) :height (- bottom top)))) 
     214 
     215(defun rectangle-points (rect) 
     216  (multiple-value-bind 
     217        (r-x r-y) 
     218      (point-x-y (top-left rect)) 
     219    (multiple-value-bind 
     220          (r-x2 r-y2) 
     221        (point-x-y (bottom-right rect)) 
     222      (loop for x from r-x below r-x2 for y from r-y below r-y2 collect 
     223           (make-point :x x :y y))))) 
     224 
     225(defclass container () 
     226  ((items :accessor items :initarg :items :initform nil))) 
     227 
     228(defclass quad () 
     229  ((quads :accessor quads :initarg :quads :initform nil))) 
     230 
     231(defclass rectangle-container (rectangle container) 
     232  ()) 
     233 
     234(defclass rectangle-quad (rectangle container quad) 
     235  ()) 
     236 
     237(defmacro doarray ((array x y) &body body) 
     238  `(destructuring-bind (xdim ydim) 
     239       (array-dimensions ,array) 
     240     (dotimes (,y ydim) 
     241       (dotimes (,x xdim) 
     242         ,@body)))) 
     243 
     244 
     245(defun float-text (float) 
     246  (text (format nil "~F" float))) 
     247 
     248(defun integer-text (int) 
     249  (text (format nil "~D" int))) 
     250 
     251(defun kml-format-points (points &optional (altitude 0)) 
     252  (format nil "~:{~F,~F,~F ~}" 
     253          (mapcar #'(lambda (p) (append (multiple-value-list (point-lon-lat p)) 
     254                                        (list altitude))) 
     255                  points))) 
     256 
     257(defun kml-format-color (color &optional (opacity 255)) 
     258  (format nil "~2,'0X~{~2,'0X~}" opacity (reverse color))) 
     259 
     260(defmethod kml-link ((href pathname)) 
     261  (with-element "Link" 
     262    (with-element "href" (text (enough-namestring href))) 
     263    (with-element "viewRefreshMode" (text "onRegion")))) 
     264 
     265;; (defmethod kml-link ((href puri:uri)) 
     266;;   (let ((string (with-output-to-string (out) 
     267;;                   (puri:render-uri href out)))) 
     268;;     (kml-link string))) 
     269 
     270(defun kml-network-link (href rect lod) 
     271  (with-element "NetworkLink" 
     272    (kml-region rect lod) 
     273    (kml-link href))) 
     274 
     275(defun kml-lat-lon-box (rect &optional (element "LatLonBox")) 
     276  (bind-nsew (bounding-box-lon-lat rect) 
     277    (with-element element 
     278      (with-element "north" (float-text north)) 
     279      (with-element "south" (float-text south)) 
     280      (with-element "east" (float-text east)) 
     281      (with-element "west" (float-text west))))) 
     282 
     283(defun kml-lat-lon-alt-box (rect) 
     284  (kml-lat-lon-box rect "LatLonAltBox")) 
     285 
     286(defun kml-overlay (img-path rect &optional (drawOrder 0)) 
     287  (with-element "GroundOverlay"                                           
     288    (with-element "name" (text (file-namestring img-path))) 
     289    (with-element "drawOrder" (integer-text drawOrder)) 
     290    (with-element "Icon" 
     291      (with-element "href" (text (enough-namestring img-path))) 
     292      ;; (with-element "refreshMode" (text "...")) 
     293      ) 
     294    (kml-lat-lon-box rect))) 
     295 
     296(defun kml-region (rect lod) 
     297  (with-element "Region" 
     298    (kml-lat-lon-alt-box rect) 
     299    (destructuring-bind (&key min max min-fade max-fade) lod 
     300      (with-element "Lod" 
     301        (when min (with-element "minLodPixels" (integer-text min))) 
     302        (when max (with-element "maxLodPixels" (integer-text max))) 
     303        (when min-fade (with-element "minFadeExtent" (integer-text min-fade))) 
     304        (when max-fade (with-element "maxFadeExtent" (integer-text max-fade))))))) 
     305 
     306;; end kml utils 
    2307 
    3308(defvar *image-tree-node-counter*) 
     
    14319   (geo-y :initarg :geo-y :reader geo-y) 
    15320   (geo-width :initarg :geo-width :reader geo-width) 
    16    (geo-height :initarg :geo-height :reader geo-height) 
    17    (children :initarg :children :reader children))) 
     321   (geo-height :initarg :geo-height :reader geo-height)    
     322   (children :initarg :children :reader children) 
     323   (parent :reader parent))) 
    18324 
    19325(defpersistent-class image-tree (image-tree-node) 
    20   ()) 
     326  ((parent :initform nil))) 
    21327 
    22328(defmethod print-object ((object image-tree-node) stream) 
     
    27333            (store-image-height object)))) 
    28334 
    29 (defun make-image-tree-node (image &key geo-rect children (class-name 'image-tree-node)) 
     335(defmethod initialize-persistent-instance :after ((obj image-tree-node)) 
     336  (dolist (child (children obj)) 
     337    (setf (slot-value child 'parent) obj))) 
     338 
     339(defun make-image-tree-node (image &key geo-rect children 
     340                             (class-name 'image-tree-node)) 
    30341  (destructuring-bind (geo-x geo-y geo-width geo-height) 
    31342      geo-rect 
     
    36347                                         :geo-y ,geo-y 
    37348                                         :geo-width ,geo-width 
    38                                          :geo-height ,geo-height 
     349                                         :geo-height ,geo-height              
    39350                                         :children ,children)))) 
    40351 
     
    45356     (< (geo-y a) (geo-y b))) 
    46357    (t nil))) 
     358 
     359(defmethod lod-min ((obj image-tree-node)) 
     360  (/ (min (store-image-width obj) (store-image-height obj)) 2.0)) 
     361 
     362(defmethod lod-min ((obj image-tree)) 
     363  900) 
     364 
     365(defmethod lod-max ((obj image-tree-node)) 
     366  (if (children obj) 
     367      (* (store-image-width obj) (store-image-height obj)) 
     368      -1)) 
    47369 
    48370(defun children-sizes (width height &key (divisor 3)) 
     
    72394        (incf left w))))) 
    73395 
    74 (defun make-image-tree (source-image geo-location &key (output-images-size 256)) 
     396(defun make-image-tree (source-image geo-location &key 
     397                        (output-images-size 256)) 
    75398  (destructuring-bind (geo-x geo-y geo-width geo-height) geo-location 
    76399    (let* ((source-image-width (cl-gd:image-width source-image)) 
     
    143466(defmethod handle-object ((image-tree-handler image-tree-handler) (object image-tree-node)) 
    144467  (with-bknr-page (:title (prin1-to-string object)) 
     468    #+nil(:pre                             
     469          (:princ                       
     470           (arnesi:escape-as-html       
     471            (with-output-to-string (*standard-output*)   
     472              (describe object)))))     
    145473    (img-image-tree object) 
     474    (when (parent object) 
     475      (html 
     476       (:p 
     477        ((:a :href (website-make-path *website* 
     478                                      (format nil "image-tree/~d" (store-object-id (parent object))))) 
     479         "go to parent")))) 
     480    (:p "lod-min:" (:princ (lod-min object)) "lod-max:" (:princ (lod-max object))) 
    146481    (:table 
    147482     (dolist (row (group-on (children object) :key #'geo-y :include-key nil)) 
     
    150485                (html (:td (img-image-tree child)))))))))) 
    151486 
     487 
     488 
     489(defclass image-tree-kml-handler (object-handler) 
     490  () 
     491  (:default-initargs :object-class 'image-tree-node)) 
     492 
     493(defmethod handle-object ((handler image-tree-kml-handler) (image-tree-node image-tree-node)) 
     494  (with-xml-response (:content-type "text/plain" #+nil"application/vnd.google-earth.kml+xml" 
     495                                    :root-element "kml") 
     496    (with-element "Document" 
     497      ))) 
     498 
  • trunk/projects/bos/web/webserver.lisp

    r2730 r2733  
    201201                                        ("/edit-sponsor" edit-sponsor-handler) 
    202202                                        ("/contract-kml" contract-kml-handler) 
    203                                         ("/image-tree" image-tree-handler) 
     203                                        ("/image-tree-kml" image-tree-kml-handler) 
     204                                        ("/image-tree" image-tree-handler)                               
    204205                                        ("/contract-image" contract-image-handler) 
    205206                                        ("/contract" contract-handler)