phpDocumentor SMap
Views
[ class tree: SMap ] [ index: SMap ] [ all elements ]

Source for file View.php

Documentation is available at View.php

  1. <?php
  2. /**
  3.  * The window through which the map is viewed
  4.  * 
  5.  * SMap requires at least PHP version 5, but there are important bug fixes in
  6.  * more recent versions of PHP. Try to stay current.
  7.  *
  8.  * <b>License</b>:
  9.  * 
  10.  * Copyright (c) 2006-2007, Seth Price <{@link mailto:seth@pricepages.org}
  11.  * seth@pricepages.org}> All rights reserved.
  12.  *
  13.  * Redistribution and use in source and binary forms, with or without
  14.  * modification, are permitted provided that the following conditions
  15.  * are met:
  16.  *
  17.  * - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  18.  * - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  19.  * - The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
  22.  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  23.  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  24.  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  25.  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  26.  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  27.  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  28.  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  29.  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  30.  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  31.  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  32.  *
  33.  * @copyright    Copyright (c) 2006-2007, Seth Price
  34.  * @author        Seth Price <seth@pricepages.org>
  35.  * @license        http://opensource.org/licenses/bsd-license.php New BSD License
  36.  * @access        public
  37.  * @package        SMap
  38.  * @version        0.1
  39.  */
  40.  
  41. /**
  42.  * A view of the map
  43.  * 
  44.  * Multiple views can be controlled at the same time. A view is like a porthole
  45.  * through which you can see the map, but only part of it at a time. The view
  46.  * has controls associated with it to pan, zoom, etc.
  47.  * 
  48.  * @package        SMap
  49.  * @subpackage    Views
  50.  */
  51. abstract class SMap_View {
  52.     /**
  53.      * Id of this view
  54.      * 
  55.      * A view with id 0 is the main view. All others are negotiable.
  56.      * 
  57.      * @var        integer 
  58.      */
  59.     protected $id = 0;
  60.     
  61.     /**
  62.      * All of the layers in this view
  63.      * 
  64.      * @var        array 
  65.      */
  66.     protected $layers = array();
  67.     
  68.     /**
  69.      * The map that contains this view
  70.      * 
  71.      * @var        object 
  72.      */
  73.     protected $map;
  74.     
  75.     /**
  76.      * A cached copy of all of the tiles
  77.      * 
  78.      * @var        array 
  79.      */
  80.     protected $tiles;
  81.     
  82.     /**
  83.      * The bounds of this view
  84.      * 
  85.      * @var        array 
  86.      */
  87.     protected $bounds;
  88.     
  89.     /**
  90.      * The zoom of this view
  91.      * 
  92.      * @var        integer 
  93.      */
  94.     protected $zoom;
  95.  
  96.     /**
  97.      * What is the scale in each direction?
  98.      * 
  99.      * This is SMap Units per one pixel.
  100.      * 
  101.      * @var        array 
  102.      */
  103.     protected $scale;
  104.     
  105.     /**
  106.      * Background color for this view
  107.      * 
  108.      * @var        array 
  109.      */
  110.     protected $bkCol;
  111.     
  112.     /**
  113.      * Registered layers
  114.      * 
  115.      * @var        array 
  116.      */
  117.     static protected $regLayers = array(
  118.         'group' => array(false'SMap_Layer_Group'),
  119.         'points' => array(false'SMap_Layer_Points'),
  120.         'polygon' => array(false'SMap_Layer_Polygon'),
  121.         'ogr' => array(false'SMap_Layer_OGR'),
  122.         'images' => array(false'SMap_Layer_Images'),
  123.         'grid' => array(false'SMap_Layer_Grid'),
  124.         'zoom' => array(false'SMap_Layer_Zoom'),
  125.         'pan' => array(false'SMap_Layer_Pan'));
  126.     
  127.     /**
  128.      * Give this view an identity
  129.      * 
  130.      * @param    object    The controlling map
  131.      * @param    integer    This view's ID
  132.      * @param    array    View's background color
  133.      */
  134.     public function __construct(SMap $map$viewId$bkCol null){
  135.         $this->id = (int) $viewId;
  136.         $this->map = $map;
  137.         
  138.         if(empty($bkCol)){
  139.             $this->bkCol = SMap::getOption('backgroundColor');
  140.         else {
  141.             $this->bkCol = $bkCol;
  142.         }
  143.         
  144.         //Calculate/save the view's bounds
  145.         $tv $map->form->getTileVars();
  146.         if($tv['isTile']){
  147.             $this->bounds = $this->getAdjViewBounds($map$tv['tileGrid']);
  148.         else {
  149.             $this->bounds = $map->bounds;
  150.         }
  151.         
  152.         //Save the zoom
  153.         $this->zoom = $map->zoom;
  154.         $this->scale = $map->scale;
  155.     }
  156.  
  157.     /**
  158.      * Access useful vars read-only
  159.      * 
  160.      * @param    string    Name of member
  161.      * @return    mixed    Value of member
  162.      */
  163.     public function __get($nm){
  164.         if(isset($this->$nm)){
  165.             return $this->$nm;
  166.         else {
  167.             throw new SMap_Ex('Attempted to read non-existant member '.$nm);
  168.         }
  169.     }
  170.  
  171.     /**
  172.      * Adjust the view coords if we are in an image
  173.      * 
  174.      * Uses the current bounds and the tile grid to calculate the view bounds of
  175.      * the original image. Sometimes it's missing data, so it does the best it
  176.      * can.
  177.      * 
  178.      * @param    object    The map we are in
  179.      * @param    array    The tile grid
  180.      * @return    array    The overall view bounds
  181.      */
  182.     protected function getAdjViewBounds(SMap $map$tG){
  183.         $B $map->bounds;
  184.         
  185.         if(    !isset($tG[SMap_Tile::POSX]||
  186.             !isset($tG[SMap_Tile::POSY]||
  187.             !isset($tG[SMap_Tile::VIEWX]||
  188.             !isset($tG[SMap_Tile::VIEWY]) ){
  189.             
  190.             return false;
  191.         }
  192.         
  193.         $diffX $B[SMap::MAXX$B[SMap::MINX];
  194.         $diffY $B[SMap::MAXY$B[SMap::MINY];
  195.         
  196.         $B[SMap::MAXX$B[SMap::MAXX$diffX *
  197.             ($tG[SMap_Tile::VIEWX$tG[SMap_Tile::POSX1);
  198.             
  199.         $B[SMap::MINX$B[SMap::MINX$diffX $tG[SMap_Tile::POSX];
  200.         
  201.         $B[SMap::MAXY$B[SMap::MAXY$diffY $tG[SMap_Tile::POSY];
  202.         
  203.         $B[SMap::MINY$B[SMap::MINY$diffY *
  204.             ($tG[SMap_Tile::VIEWY$tG[SMap_Tile::POSY1);
  205.         
  206.         return $B;
  207.     }
  208.     
  209.     /**
  210.      * Adds a layer.
  211.      * 
  212.      * If there are no layers, then this layer becomes the bottom most layer.
  213.      * If there is a layer, then this layer is composited on top of it.
  214.      * 
  215.      * @param    mixed    SMap_Layer subclass or layer to create
  216.      * @param    integer    Normally a Layer ID
  217.      * @param    mixed    Additional arguments passed to layer constructor
  218.      * @return    object    The added layer
  219.      * @see        SMap_Layer
  220.      */
  221.     public function addLayer(    $layer,       $arg1 null$arg2 null,
  222.                                 $arg3 null$arg4 null$arg5 null,
  223.                                 $arg6 null$arg7 null$arg8 null){
  224.         
  225.         //Check if we've already been rendered
  226.         if($this->tiles){
  227.             throw new SMap_Ex('You can\'t add a layer after the tiles have been ' .
  228.                     'created.');
  229.         }
  230.         //Do we need to create the layer?
  231.         elseif(is_string($layer)){
  232.             $layer $this->createLayer($layer$this->map$arg1$arg2$arg3$arg4$arg5$arg6$arg7$arg8);
  233.         }
  234.         //Was the layer passed to us?
  235.         elseif(!($layer instanceof SMap_Layer)){
  236.             throw new SMap_Ex('Passed $layer not an instance of SMap_Layer.');
  237.         }
  238.         
  239.         $lid $layer->getID();
  240.         
  241.         //Make sure it dosen't exist
  242.         if(!empty($this->layers[$lid])){
  243.             throw new SMap_Ex(    'SMap_Layer of ID '.$lid.' already exists',
  244.                                 SMap_Ex::DUP_LAYER);
  245.         }
  246.         
  247.         //Only add enabled layers
  248.         if(!in_array($lid$this->map->visibleLayers)){
  249.             return $layer;
  250.         }
  251.         
  252.         //Store layer
  253.         $this->layers[$lid$layer;
  254.         
  255.         return $layer;
  256.     }
  257.     
  258.     /**
  259.      * Creates a view
  260.      * 
  261.      * Serves as a view factory. The first argument is the name of a view that
  262.      * is registered with, and the rest of the arguments are passed to the view.
  263.      * 
  264.      * @param    string    View name
  265.      * @param    integer    Normally the Layer ID
  266.      * @param    mixed    Additional arguments...
  267.      * @return    object    The created view
  268.      */
  269.     public static function createLayer(    $layer$arg1$arg2 null$arg3 null,
  270.                                         $arg4 null$arg5 null$arg6 null,
  271.                                         $arg7 null$arg8 null$arg9 null){
  272.         $layer strtolower($layer);
  273.         
  274.         if(empty(self::$regLayers[$layer])){
  275.             throw new Exception('The given layer type "'.$layer.'" is not built in. ' .
  276.                     'If you have created a custom layer, please simply ' .
  277.                     'pass the object to addLayer().');
  278.         }
  279.         
  280.         $meta self::$regLayers[$layer];
  281.         
  282.         if($meta[0&& !class_exists($meta[1])){
  283.             include_once($meta[0]);
  284.         }
  285.         
  286.         $lr new $meta[1]($arg1$arg2$arg3$arg4$arg5$arg6$arg7$arg8$arg9);
  287.         
  288.         if(!($lr instanceof SMap_Layer)){
  289.             throw new SMap_Ex('Layer not a subclass of SMap_Layer.');
  290.         }
  291.         
  292.         return $lr;
  293.     }
  294.     
  295.     /**
  296.      * Send an object to another tile
  297.      * 
  298.      * Used to create an object in another tile dynamically. This is intended to
  299.      * only be used by methods in {@link SMap_Object} during rendering. The
  300.      * normal method of adding an object to a tile is to include it in the
  301.      * return value of {@link SMap_Layer::getMapObjs()} or {@link }
  302.      * SMap_Layer::getImgObjs()}.
  303.      * 
  304.      * @param    object    New object
  305.      * @param    integer    X location of tile in tile grid
  306.      * @param    integer    Y location of tile in tile grid
  307.      */
  308.     public function sendObj(SMap_Object $newObj$newX$newY){
  309.         if(!isset($this->tiles[$newY][$newX])){
  310.             return;
  311.         }
  312.         
  313.         $this->tiles[$newY][$newX]->addObject($newObj);
  314.     }
  315.     
  316.     /**
  317.      * Return the name of this view
  318.      * 
  319.      * The name is defined by {@link SMap_Lang}, so this method simply uses that
  320.      * value.
  321.      * 
  322.      * @return    string    View name
  323.      */
  324.     public function getName(){
  325.         $defs $this->map->lang->genViewDefs();
  326.         if(isset($defs[$this->id])){
  327.             return $defs[$this->id];
  328.         else {
  329.             return 'Untitled';
  330.         }
  331.     }
  332.     
  333.     /**
  334.      * Creates and returns the set of tiles that represent this view
  335.      * 
  336.      * This constructs a set of tiles that fully represent this view.
  337.      * {@link SMap_Object Objects} have been added to each tile, and they have
  338.      * been {@link SMap_Tile::flatten() flattened} and {@link }
  339.      * SMap_Tile::constrain() constrained}.
  340.      * 
  341.      * @return    array    The tiles in this view
  342.      * @see        getXHTML()
  343.      */
  344.     public function getTiles(){
  345.         
  346.         //Cache a copy of the cached tiles
  347.         if($this->tiles){
  348.             return $this->tiles;
  349.         }
  350.         
  351.         //Are we constructed correctly?
  352.         if(empty($this->map)){
  353.             throw new SMap_Ex('View not added to a map. ID: '.$this->id);
  354.         }
  355.         
  356.         //Save some local vars
  357.         $viewT $this->bounds[SMap::MAXY];
  358.         $viewL $this->bounds[SMap::MINX];
  359.         
  360.         //PreCalc the offset of each cell
  361.         $widthPx  SMap::getOption('tileWidthPx');
  362.         $heightPx SMap::getOption('tileHeightPx');
  363.         
  364.         $lrDiff $widthPx  $this->scale[0];
  365.         $tbDiff $heightPx $this->scale[1];
  366.         
  367.         //Save these vars locally for speed
  368.         $tilesX $this->map->tilesX;
  369.         $tilesY $this->map->tilesY;
  370.         
  371.         //Count starting at the bottom
  372.         $top $viewT;
  373.         
  374.         //Create the tiles
  375.         $tiles array();
  376.         for($y 0$y $tilesY$y++){
  377.             
  378.             $bottom $top $tbDiff;
  379.             
  380.             //Count starting on the left
  381.             $left $viewL;
  382.             
  383.             for($x 0$x $tilesX$x++){
  384.                 
  385.                 $right $left $lrDiff;
  386.                 
  387.                 //Create new tile with correct bounds and grid position
  388.                 $bounds array(    SMap::MAXY => $top,
  389.                                 SMap::MAXX => $right,
  390.                                 SMap::MINY => $bottom,
  391.                                 SMap::MINX => $left);
  392.  
  393.                 $grid array(    SMap_Tile::POSX => $x,
  394.                                 SMap_Tile::VIEWX => $tilesX,
  395.                                 SMap_Tile::POSY => $y,
  396.                                 SMap_Tile::VIEWY => $tilesY );
  397.                 
  398.                 $tile new SMap_Tile($this->map$this$bounds$grid$this->bkCol);
  399.                 
  400.                 //Build the layers
  401.                 foreach($this->layers as $layer){
  402.                     $tile->addLayer($layer);
  403.                 }
  404.                 
  405.                 //Flatten into objects
  406.                 $tile->flatten(false);
  407.                 
  408.                 $tiles[$y][$x$tile;
  409.                 
  410.                 $left $right;
  411.             }
  412.             
  413.             $top $bottom;
  414.         }
  415.         
  416.         //Set the member so sendObj() can work
  417.         $this->tiles = $tiles;
  418.         
  419.         //Constrain the object bounds
  420.         foreach($this->layers as $lid => $layer){
  421.             for($y 0$y $tilesY$y++){
  422.                 for($x 0$x $tilesX$x++){
  423.                     $tiles[$y][$x]->constrain($lid);
  424.                 }
  425.             }
  426.         }
  427.         
  428.         return $tiles;
  429.     }
  430.     
  431.     /**
  432.      * Handle getting the XHTML
  433.      * 
  434.      * @param    array    The array of tiles
  435.      * @return    string    XHTML of the map
  436.      * @see        getTiles()
  437.      */
  438.     abstract public function getXHTML($tiles);
  439. }
  440.  
  441. /**
  442.  * A view composed of images
  443.  * 
  444.  * @package        SMap
  445.  * @subpackage    Views
  446.  */
  447. class SMap_View_Raster extends SMap_View {
  448.     /**
  449.      * Display a tiled image
  450.      * 
  451.      * This is intended to be called from an image script.
  452.      * 
  453.      * @param    object    SMap_Tile 
  454.      */
  455.     public function dispTileImg(SMap_Tile $tile){
  456.         //Add layers as needed
  457.         foreach($this->layers as $layer){
  458.             $tile->addLayer($layer);
  459.         }
  460.         
  461.         $tile->flatten(true);
  462.  
  463.         foreach($this->layers as $lid => $layer){
  464.             $tile->constrain($lid);
  465.         }
  466.  
  467.         //Display the tile
  468.         $tile->display();
  469.     }
  470.     
  471.     /**
  472.      * Renders and returns the view XHTML
  473.      * 
  474.      * @param    array    Tiles to render
  475.      * @return    string    Rendered XHTML
  476.      * @uses        SMap_Form::getMapXHTML()
  477.      */
  478.     public function getXHTML($tiles){
  479.         return $this->map->form->getMapXHTML($this$tiles);
  480.     }
  481. }
  482.  
  483. /**
  484.  * A view intended to be inset in a layer
  485.  * 
  486.  * The purpose of this view is to appear as an object inside of a layer (which
  487.  * is inside another view).
  488.  * 
  489.  * @package        SMap
  490.  * @subpackage    Views
  491.  */
  492. class SMap_View_Inset extends SMap_View {
  493.     
  494.     /**
  495.      * Tile to draw the view onto
  496.      * 
  497.      * If the tile is null, then no drawing is done, and no inset is created.
  498.      * This is probably because we can't zoom out far enough to create a useful
  499.      * inset.
  500.      * 
  501.      * @var        object 
  502.      */
  503.     protected $tile = null;
  504.     
  505.     /**
  506.      * Construct & adjust the view bounds
  507.      * 
  508.      * @param    object 
  509.      * @param    integer 
  510.      * @param    object    Tile to draw the inset onto
  511.      */
  512.     public function __construct(SMap $map$viewIdSMap_Tile $tile){
  513.         parent::__construct($map$viewId);
  514.         
  515.         $vB $this->bounds;
  516.         $xSpan ($vB[SMap::MAXX$vB[SMap::MINX])*3;
  517.         $ySpan ($vB[SMap::MAXY$vB[SMap::MINY])*3;
  518.         
  519.         //Adjust the zoom & scale
  520.         for($zoom $this->zoom - 2$zoom >= 0--$zoom){
  521.             $scale $map->geo->zoomFctr($this->zoom);
  522.             $wMu $tile->