Files
pmgr/site/controllers/maps_controller.php
abijah 4e33c58246 Further progress on the site map. The scale is off at the moment, but it's working well enough that it's worth a snapshot.
git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@33 97e9348a-65ac-dc4b-aefc-98561f571b83
2009-05-29 02:45:23 +00:00

261 lines
9.8 KiB
PHP

<?php
class MapsController extends AppController {
var $helpers = array('Html');
/**************************************************************************
**************************************************************************
**************************************************************************
* action: index
* - Generates a list of all site maps
*
* REVISIT <AP> 20090528:
* We'll need to present only those site area maps that correspond
* to the users particular site.
*/
function index() {
$this->Map->recursive = 0;
$this->set('maps', $this->paginate());
}
/**************************************************************************
**************************************************************************
**************************************************************************
* action: view
* - Generates a site map page
*/
function view($id = null) {
if (!$id) {
$this->Session->setFlash(__('Invalid Item.', true));
$this->redirect(array('action'=>'index'));
}
$this->set('info', $this->mapInfo($id));
}
/**************************************************************************
**************************************************************************
**************************************************************************
* action: map
* - Produces a PNG site map image
*/
function map($id = null, $requested_width = 600) {
if (!$id) {
$this->Session->setFlash(__('Invalid Item.', true));
$this->redirect(array('action'=>'index'));
}
$this->image($this->mapInfo($id), $requested_width);
}
/**************************************************************************
**************************************************************************
**************************************************************************
* mapInfo
*/
function mapInfo($id) {
// Set up array to hold the map information
$info = array('extents' => array(), 'units' => array(),
'map_id' => $id, 'border' => true);
/* // Find all of the map/unit information from this SiteArea */
/* $this->Map->SiteArea->recursive = 3; */
/* $this->Map->SiteArea->Site->unbindModel(array('hasMany' => array('SiteArea'))); */
/* $this->Map->unbindModel(array('belongsTo' => array('SiteArea'))); */
/* $map = $this->Map->SiteArea->read(null, $site_area_id); */
// 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);
// Get the overall site limits, and then compute the
// actual boundary extents, adjusting for a border
$top_adjustment = 5;
$left_adjustment = 5;
$info['extents']['top'] = 0;
$info['extents']['left'] = 0;
$info['extents']['bottom'] = $top_adjustment + $map['Map']['depth'] + 5;
$info['extents']['right'] = $left_adjustment + $map['Map']['width'] + 5;
// Go through each unit in the map, calculating the map location
foreach ($map['Unit'] AS $unit) {
$lft = $unit['MapsUnit']['pt_left'] + $left_adjustment;
$top = $unit['MapsUnit']['pt_top'] + $top_adjustment;
$width =
$unit['MapsUnit']['transpose']
? $unit['UnitSize']['depth']
: $unit['UnitSize']['width'];
$depth =
$unit['MapsUnit']['transpose']
? $unit['UnitSize']['width']
: $unit['UnitSize']['depth'];
$info['units'][$unit['id']] =
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;
}
// Temporary function
function unitStatusList() {
return
array('DELETED' => array(),
'DAMAGED' => array(),
'COMPANY' => array(),
'UNAVAILABLE' => array(),
'RESERVED' => array(),
'DIRTY' => array(),
'VACANT' => array(),
'OCCUPIED' => array(),
'LATE' => array(),
'LOCKED' => array(),
'LIENED' => array(),
);
}
/**************************************************************************
**************************************************************************
**************************************************************************
* action: legend
* - Produces a PNG color legend image
*/
function legend($id = null, $requested_width = 400) {
$status = $this->unitStatusList();
$cols = 6;
$rows = (int)((count($status) + $cols - 1) / $cols);
$info = array('extents' => array(), 'units' => array(), 'legend' => array());
$info['legend']['width'] = 360;
$info['legend']['depth'] = 120;
$info['extents']['right'] = $info['legend']['width'] * $cols;
$info['extents']['bottom'] = $info['legend']['depth'] * $rows;
$top = $lft = 0;
foreach ($status AS $code => $color) {
$info['units'][] = array('name' => $code,
'status' => $code,
'width' => $info['legend']['width'],
'depth' => $info['legend']['depth'],
'left' => $lft,
'right' => $lft + $info['legend']['width'],
'top' => $top,
'bottom' => $top + $info['legend']['depth']);
$top += $info['legend']['depth'];
if ($top >= $info['legend']['depth'] * $rows) {
$top = 0; $lft += $info['legend']['width'];
}
}
$this->image($info, $requested_width, true);
}
/**************************************************************************
**************************************************************************
**************************************************************************
* helper: image
* - used by actions map & legend to set up unit information and
* color palates before rendering the PNG image.
*/
function image($info, $requested_width, $legend = false) {
//var $helpers = array('Html', 'Form', 'Javascript', 'Graph');
$this->layout = null;
$this->autoLayout = false;
Configure::write('debug', '0');
// Define our color palate
// REVISIT <AP>: 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;
}
//pr($info);
/*****
* 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.
*****/
// Scale things according to desired display width
$screen_adjustment_factor = $requested_width / $info['extents']['right'];;
// Define image size
$info['width'] = $info['extents']['right'] * $screen_adjustment_factor;
$info['depth'] = $info['extents']['bottom'] * $screen_adjustment_factor;
// Go through each unit, adjusting map locations
foreach ($info['units'] AS $unit) {
$unit['left'] *= $screen_adjustment_factor;
$unit['right'] *= $screen_adjustment_factor;
$unit['top'] *= $screen_adjustment_factor;
$unit['bottom'] *= $screen_adjustment_factor;
}
$this->set(compact('info'));
$this->render('image');
}
}
?>