20090528: * We'll need to present only those site area maps that correspond * to the users particular site. */ function index() { $this->all(); } function all() { $this->jqGridView('All Maps', 'all'); } /************************************************************************** ************************************************************************** ************************************************************************** * virtuals: jqGridData * - With the application controller handling the jqGridData action, * these virtual functions ensure that the correct data is passed * to jqGrid. */ function jqGridDataTables(&$params, &$model) { return array ('link' => array('SiteArea' => array('fields' => array('SiteArea.id', 'SiteArea.name')), ), ); } function jqGridRecordLinks(&$params, &$model, &$records, $links) { $links['Map'] = array('id'); return parent::jqGridRecordLinks($params, $model, $records, $links); } /************************************************************************** ************************************************************************** ************************************************************************** * action: view * - Generates a site map page */ function view($id = null, $requested_width = 800) { if (!$id) { $this->Session->setFlash(__('Invalid Item.', true)); $this->redirect(array('action'=>'index')); } $this->set('info', $this->mapInfo($id, $requested_width)); $this->set('title', "Site Map"); } /************************************************************************** ************************************************************************** ************************************************************************** * action: map * - Produces a PNG site map image */ function map($id = null, $requested_width = 800) { if (!$id) { $this->Session->setFlash(__('Invalid Item.', true)); $this->redirect(array('action'=>'index')); } $this->image($this->mapInfo($id, $requested_width)); } /************************************************************************** ************************************************************************** ************************************************************************** * mapInfo */ function mapInfo($id, $requested_width) { // Set up array to hold the map information $info = array('map_id' => $id, 'border' => true, 'units' => array()); // Find all of the map/unit information from this SiteArea $this->Map->recursive = 2; $this->Map->SiteArea->unbindModel(array('hasOne' => array('Map'))); $map = $this->Map->read(null, $id); //pr($map); /***** * The preference would be to leave all things "screen" related * to reside in the view. However, two separate views need this * information. The 'view' needs it to include a clickable map * that corresponds to the map image, and of course, the 'map' * (or 'image') view needs it to render the image. So, in the * controller for now, unless I come up with a better idea. *****/ // Get the overall site limits, and then compute the // actual boundary extents, adjusting for a border $boundary_adjustment = 12; $bottom = 2*$boundary_adjustment + $map['Map']['depth']; $right = 2*$boundary_adjustment + $map['Map']['width']; // Scale things according to desired display width $screen_adjustment_factor = $requested_width / $right; // Define the overall canvas size $info['width'] = $right * $screen_adjustment_factor; $info['depth'] = $bottom * $screen_adjustment_factor; // Go through each unit in the map, calculating the map location foreach ($map['Unit'] AS $unit) { $lft = $unit['MapsUnit']['pt_left'] + $boundary_adjustment; $top = $unit['MapsUnit']['pt_top'] + $boundary_adjustment; $width = $unit['MapsUnit']['transpose'] ? $unit['UnitSize']['depth'] : $unit['UnitSize']['width']; $depth = $unit['MapsUnit']['transpose'] ? $unit['UnitSize']['width'] : $unit['UnitSize']['depth']; $lft *= $screen_adjustment_factor; $top *= $screen_adjustment_factor; $width *= $screen_adjustment_factor; $depth *= $screen_adjustment_factor; //$info['units'][$unit['id']] = $info['units'][] = array( 'id' => $unit['id'], 'name' => $unit['name'], 'left' => $lft, 'right' => $lft + $width, 'top' => $top, 'bottom' => $top + $depth, 'width' => $width, 'depth' => $depth, 'n-s' => $unit['MapsUnit']['transpose'] ? 0 : 1, 'status' => $unit['status'] ); } //pr($info); return $info; } /************************************************************************** ************************************************************************** ************************************************************************** * action: legend * - Produces a PNG color legend image */ function legend($id = null, $requested_width = 400) { $status = $this->Map->Unit->activeStatusEnums(); //pr($status); $rows = 2; $cols = (int)((count($status) + $rows - 1) / $rows); $info = array('units' => array()); // Get the overall site limits, and then compute the // actual boundary extents, adjusting for a border $boundary_adjustment = 1; $item_width = 40; // Absolute values are irrelevant, as they $item_depth = 10; // will be scaled in the end anyway. $bottom = 2*$boundary_adjustment + $rows*$item_depth; $right = 2*$boundary_adjustment + $cols*$item_width; // Scale things according to desired display width $screen_adjustment_factor = $requested_width / $right; // Define the overall canvas size $info['width'] = $right * $screen_adjustment_factor; $info['depth'] = $bottom * $screen_adjustment_factor; // Get a starting point for our top left position. $top = $lft = $boundary_adjustment; // Scale it appropriately. $top *= $screen_adjustment_factor; $lft *= $screen_adjustment_factor; $item_width *= $screen_adjustment_factor; $item_depth *= $screen_adjustment_factor; foreach ($status AS $code => $value) { $info['units'][] = array('name' => $code, 'status' => $code, 'width' => $item_width, 'depth' => $item_depth, 'left' => $lft, 'right' => $lft + $item_width, 'top' => $top, 'bottom' => $top + $item_depth); $top += $item_depth; if ($top >= $item_depth * $rows) { $top = $boundary_adjustment * $screen_adjustment_factor; $lft += $item_width; } } $this->image($info, true); } /************************************************************************** ************************************************************************** ************************************************************************** * helper: image * - used by actions map & legend to set up unit information and * color palates before rendering the PNG image. */ function image($info, $legend = false) { $debug = false; if (!$debug) { $this->layout = null; $this->autoLayout = false; Configure::write('debug', '0'); } // Define our color palate // REVISIT : 20090513 // Get colors from DB option tables $info['palate']['main']['layout']['bg'] = array('red' => 255, 'green' => 255, 'blue' => 255); $info['palate']['main']['layout']['border'] = array('red' => 192, 'green' => 192, 'blue' => 192); $info['palate']['main']['layout']['wall'] = array('red' => 0, 'green' => 0, 'blue' => 0); $info['palate']['unit']['DELETED']['bg'] = array('red' => 0, 'green' => 0, 'blue' => 0); $info['palate']['unit']['DAMAGED']['bg'] = array('red' => 192, 'green' => 128, 'blue' => 128); $info['palate']['unit']['COMPANY']['bg'] = array('red' => 128, 'green' => 192, 'blue' => 128); $info['palate']['unit']['UNAVAILABLE']['bg'] = array('red' => 128, 'green' => 128, 'blue' => 192); $info['palate']['unit']['RESERVED']['bg'] = array('red' => 192, 'green' => 192, 'blue' => 128); $info['palate']['unit']['DIRTY']['bg'] = array('red' => 128, 'green' => 192, 'blue' => 192); $info['palate']['unit']['VACANT']['bg'] = array('red' => 0, 'green' => 255, 'blue' => 128); $info['palate']['unit']['OCCUPIED']['bg'] = array('red' => 0, 'green' => 128, 'blue' => 255); $info['palate']['unit']['LATE']['bg'] = array('red' => 255, 'green' => 64, 'blue' => 64); $info['palate']['unit']['LOCKED']['bg'] = array('red' => 255, 'green' => 128, 'blue' => 128); $info['palate']['unit']['LIENED']['bg'] = array('red' => 255, 'green' => 192, 'blue' => 192); // Determine text color to go with each background foreach ($info['palate']['unit'] AS &$code) { $component = $code['bg']; $method = 3; if ($method == 1) { foreach (array('red', 'green', 'blue') AS $prim) $component[$prim] = 255 - $component[$prim]; } elseif ($method == 2) { foreach (array('red', 'green', 'blue') AS $prim) $component[$prim] = ($component[$prim]) >= 128 ? 0 : 255; } elseif ($method == 3) { $val = (sqrt(pow($component['red'], 2) + pow($component['green'], 2) + pow($component['blue'], 2)) >= sqrt(3) * 128) ? 0 : 255; foreach (array('red', 'green', 'blue') AS $prim) $component[$prim] = $val; } $code['fg'] = $component; } $this->set(compact('info', 'debug')); $this->render('image'); } } ?>