Copyright (c) 2002, DM Solutions Group Inc. * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ // include the session handling file define("LOAD_MAPSESSION", 1); $bInvalidSessionDontFail = true; include("../session.inc.php"); define( 'ROIRENDERER_QUERY', getSessionSavePath()."/roirenderer.qry"); if (!extension_loaded( "gd" )) { $szGDMod2 = "php_gd2".( (PHP_OS=="WINNT" || PHP_OS=="WIN32") ? ".dll" : ".so" ); dl( $szGDMod2 ); } $width = $_GET['width']; $height = $_GET['height']; $oImage = imagecreate( $width, $height ); $nTransparent = imagecolorallocate( $oImage, 255, 255, 255 ); //$nTransparent = imagecolorresolvealpha( $oImage, 255, 255, 255, 0 ); $nBlack = imagecolorallocate( $oImage, 0, 0, 0 ); //imagealphablending( $oImage, false ); imagecolortransparent( $oImage, $nTransparent ); imagefill( $oImage, 0, 0, $nTransparent ); //imagealphablending( $oImage, true ); if (!isset($GLOBALS['bSessionOK']) || !($GLOBALS['bSessionOK'])) { renderText("session expired!"); } else { $geoMinX = $oMapSession->oMap->extent->minx; $geoMinY = $oMapSession->oMap->extent->miny; $geoMaxX = $oMapSession->oMap->extent->maxx; $geoMaxY = $oMapSession->oMap->extent->maxy; //renderText( $geoMinX." ".$geoMinY." ".$geoMaxX." ".$geoMaxY ); //mode settings: //mode = -2 : remove all ROIs //mode = -1 : remove the last ROI //mode = 0 : replace any existing ROIs with the one passed //mode = 1 : replace any existing ROIs with the one passed //mode = 2 : add the ROI //mode = 3 : subtract the ROI // if (!isset($_SESSION["ROIRENDERER_COUNT"])) { $_SESSION["ROIRENDERER_COUNT"] = 1; } else { $_SESSION["ROIRENDERER_COUNT"] = $_SESSION["ROIRENDERER_COUNT"] + 1; } $mode = isset($_GET['mode']) ? $_GET['mode'] : 0; //renderText( "count is " .$_SESSION["ROIRENDERER_COUNT"]. ", mode is " . $mode ); if (!isset($_SESSION['ROIRENDERER']) || $mode == 1) { //clean up after feature ROIs ... if (isset($_SESSION['ROIRENDERER'])) { $nROI = count($_SESSION['ROIRENDERER']); for($i=0; $i<$nROI; $i++) { cleanUpROI( $_SESSION['ROIRENDERER'][$i] ); } } $_SESSION['ROIRENDERER'] = array(); } if ( $mode > 0 ) { $roi = array(); $roi['mode'] = $mode; $roi['type'] = isset($_GET['type']) ? $_GET['type'] : 'rectangle'; $roi['aGeoCoords'] = isset($_GET['coords']) ? explode( ",", $_GET['coords']) : array(); $roi['edgecolor'] = isset($_GET['edgecolor']) ? $_GET['edgecolor'] : '#000000'; $roi['edgewidth'] = isset($_GET['edgewidth']) ? $_GET['edgewidth'] : 1; $roi['fillcolor'] = isset($_GET['fillcolor']) ? $_GET['fillcolor'] : '#000000'; $roi['fillopacity'] = isset($_GET['fillopacity']) ? $_GET['fillopacity'] : 0; if (isset($_GET['selectedLayer'])) { $roi['selectedLayer'] = $_GET['selectedLayer']; } array_push( $_SESSION['ROIRENDERER'], $roi ); } elseif ($mode == -1) { $aROI = array_pop($_SESSION['ROIRENDERER']); //clean up after feature ROIs ... cleanUpROI( $aROI ); } elseif($mode == -2) { $nROI = count($_SESSION['ROIRENDERER']); //clean up after feature ROIs ... for($i=0; $i<$nROI; $i++) { cleanUpROI($_SESSION['ROIRENDERER'][$i]); } //delete all ROIs ... $_SESSION['ROIRENDERER'] = array(); } if (isset($_SESSION['ROIRENDERER'])) { $nROI = count($_SESSION['ROIRENDERER']); for($i=0; $i<$nROI; $i++) { drawROI( $_SESSION['ROIRENDERER'][$i] ); } } } header( 'Content-type: image/png' ); //imagetruecolortopalette($oImage, false, 256); imagepng($oImage); exit; /* * draw a single ROI on the output image. The intent is for this function to handle * any type of ROI. */ function drawROI( &$aROI ) { // debug //renderText(count($_SESSION['ROIRENDERER'])); if ($aROI['mode'] == 3) { //subtract, draw a transparent ROI $nFillColor = $GLOBALS['nTransparent']; } else { //normal or add $nFillColor = allocateImageFromHexValue( $GLOBALS['oImage'], $aROI['fillcolor'], $aROI['fillopacity']); } $aPoints = array(); if ($aROI['type'] == 'rectangle') { //for rectangles, we assume that there are two coordinates, top left and bottom right. array_push( $aPoints, Geo2Pix($aROI['aGeoCoords'][0], 0, $GLOBALS['width'], $GLOBALS['geoMinX'], $GLOBALS['geoMaxX'] ) ); array_push( $aPoints, Geo2Pix($aROI['aGeoCoords'][1], 0, $GLOBALS['height'], $GLOBALS['geoMinY'], $GLOBALS['geoMaxY'], 1 ) ); array_push( $aPoints, Geo2Pix($aROI['aGeoCoords'][2], 0, $GLOBALS['width'], $GLOBALS['geoMinX'], $GLOBALS['geoMaxX'] ) ); array_push( $aPoints, Geo2Pix($aROI['aGeoCoords'][1], 0, $GLOBALS['height'], $GLOBALS['geoMinY'], $GLOBALS['geoMaxY'], 1 ) ); array_push( $aPoints, Geo2Pix($aROI['aGeoCoords'][2], 0, $GLOBALS['width'], $GLOBALS['geoMinX'], $GLOBALS['geoMaxX'] ) ); array_push( $aPoints, Geo2Pix($aROI['aGeoCoords'][3], 0, $GLOBALS['height'], $GLOBALS['geoMinY'], $GLOBALS['geoMaxY'], 1 ) ); array_push( $aPoints, Geo2Pix($aROI['aGeoCoords'][0], 0, $GLOBALS['width'], $GLOBALS['geoMinX'], $GLOBALS['geoMaxX'] ) ); array_push( $aPoints, Geo2Pix($aROI['aGeoCoords'][3], 0, $GLOBALS['height'], $GLOBALS['geoMinY'], $GLOBALS['geoMaxY'], 1 ) ); array_push( $aPoints, Geo2Pix($aROI['aGeoCoords'][0], 0, $GLOBALS['width'], $GLOBALS['geoMinX'], $GLOBALS['geoMaxX'] ) ); array_push( $aPoints, Geo2Pix($aROI['aGeoCoords'][1], 0, $GLOBALS['height'], $GLOBALS['geoMinY'], $GLOBALS['geoMaxY'], 1 ) ); $nPoints = 5; // flag for poly $bPoly = true; } elseif ( $aROI['type'] == 'circle' ) { // convert center and radius to pixel $dCenterX = Geo2Pix($aROI['aGeoCoords'][0], 0, $GLOBALS['width'], $GLOBALS['geoMinX'], $GLOBALS['geoMaxX'] ); $dCenterY = Geo2Pix($aROI['aGeoCoords'][1], 0, $GLOBALS['height'], $GLOBALS['geoMinY'], $GLOBALS['geoMaxY'], 1 ); $dRadiusX = Geo2Pix($aROI['aGeoCoords'][2], 0, $GLOBALS['width'], $GLOBALS['geoMinX'], $GLOBALS['geoMaxX']); $dRadius = abs( $dRadiusX - $dCenterX ); // flag for non-poly $bPoly = false; } elseif ( $aROI['type'] == 'polygon' ) { // loop and set coordinates $nCount = count( $aROI['aGeoCoords'] ); for( $i=0;$i<$nCount; $i++ ) { // even is x, odd is y if ( fmod( $i, 2 ) == 0 ) { array_push( $aPoints, Geo2Pix($aROI['aGeoCoords'][$i], 0, $GLOBALS['width'], $GLOBALS['geoMinX'], $GLOBALS['geoMaxX'] ) ); } else { array_push( $aPoints, Geo2Pix($aROI['aGeoCoords'][$i], 0, $GLOBALS['height'], $GLOBALS['geoMinY'], $GLOBALS['geoMaxY'], 1 ) ); } } $nPoints = round( $nCount/2 ); // flag for poly $bPoly = true; } elseif ($aROI['type'] == 'feature') { $nPoints = 0; $nLayers = $GLOBALS['oMapSession']->oMap->numlayers; for ($i=0; $i<$nLayers; $i++ ) { $oLayer = $GLOBALS['oMapSession']->oMap->getLayer( $i ); $oLayer->set( 'status', MS_OFF ); } $oLayer = @$GLOBALS['oMapSession']->oMap->getLayerByName( $aROI['selectedLayer'] ); if ($oLayer && $oLayer->type == MS_LAYER_POLYGON) { $nResults = 0; //create the query template that turns polygons into something useful. $szTemplatePath = getSessionSavePath()."roirenderer_template.html"; if (!file_exists( $szTemplatePath ) ) { $szTemplate = '[shpxy xf="," yf="," sf="|" proj="image"]'; $hTemplate = fopen( $szTemplatePath, "w+" ); fwrite( $hTemplate, $szTemplate ); fclose( $hTemplate ); } //put the template on each class ... is this necessary? for ($i=0; $i<$oLayer->numclasses; $i++) { $oClass = $oLayer->getClass( $i ); $oClass->set( "template", $szTemplatePath ); } //make sure the layer is on (doh) $oLayer->set( "status", MS_ON ); $oLayer->set( 'tolerance', 0 ); $oLayer->set( 'toleranceunits', MS_PIXELS ); //its a new query ... if (count($aROI['aGeoCoords']) == 2) { $aROI['aOrigCoords'] = $aROI['aGeoCoords']; $oPoint = ms_newPointObj( ); $oPoint->setXY( $aROI['aGeoCoords'][0], $aROI['aGeoCoords'][1] ); @$oLayer->queryByPoint( $oPoint, MS_SINGLE, 0 ); $nResults = $oLayer->getNumResults(); unset( $aROI['aGeoCoords'] ); if ($nResults > 0) { //save the query results for future passes ... $aROI['query_file'] = getSessionSavePath()."/".uniqid("").".qry"; $GLOBALS['oMapSession']->oMap->saveQuery( $aROI['query_file'] ); } } else if (isset($aROI['query_file']) && file_exists( $aROI['query_file'] )) { //load the query and find a layer with query results ... $GLOBALS['oMapSession']->oMap->loadQuery( $aROI['query_file'] ); $nResults = $oLayer->getNumResults(); } if ($nResults > 0) { $szCode = $GLOBALS['oMapSession']->oMap->processQueryTemplate( array(), false ); //there seems to be a bug ... query results are not getting reset ... so we //introduce a | after each shape and then only take the first shape ... $aszCode = explode( "|", $szCode ); $szCode = substr($aszCode[0], 0, -1 ); $szCode = '$'.'aPoints = array('.$szCode.');'; eval( $szCode ); $nPoints = count($aPoints)/2; $bPoly = true; } } } // draw poly or ellipse or feature if ( $bPoly && $nPoints > 0) { imagefilledpolygon( $GLOBALS['oImage'], $aPoints, $nPoints, $nFillColor); } else if ($aROI['type'] == 'circle') { //renderText( $dCenterX.','.$dCenterY.' radius='.$dRadius ); $nEdgeColor = allocateImageFromHexValue( $GLOBALS['oImage'], $aROI['edgecolor']); imagefilledellipse ( $GLOBALS['oImage'], $dCenterX, $dCenterY, $dRadius * 2+$aROI['edgewidth'], $dRadius * 2+$aROI['edgewidth'], $nEdgeColor ); imagefilledellipse ( $GLOBALS['oImage'], $dCenterX, $dCenterY, $dRadius * 2, $dRadius * 2, $nFillColor ); } else { //something went wrong, can't do anything here. } } // clean up after an ROI, specifically Feature ROIs ... function cleanUpROI( $aROI ) { if ($aROI['type'] == 'feature' && file_exists($aROI['query_file'])) { unlink( $aROI['query_file'] ); if (file_exists($aROI['query_file'].".txt")) unlink($aROI['query_file'].".txt"); } } //use this to put text into the output image (for debugging :)) function renderText( $szText ) { $x = 10; if (!isset($GLOBALS['y'])) $GLOBALS['y'] = 10; else $GLOBALS['y'] += 20; imagestring( $GLOBALS['oImage'], 2, $x, $GLOBALS['y'], $szText, $GLOBALS['nBlack'] ); } /* * return a color index from the given image for a given hex color. If opacity * is not false, then assume that it is either a percent or a number from 0-100 and * massage accordingly into a value between 0 (transparent) and 127 (opaque). */ function allocateImageFromHexValue( $im, $szHexColor, $opacity = false ) { if (substr($szHexColor, 0, 1) == "#") $szHexColor = substr($szHexColor, 1 ); $nRed = intval(substr($szHexColor,0,2),16); $nGreen = intval(substr($szHexColor,2,2),16); $nBlue = intval(substr($szHexColor,4,2),16); if ($opacity && $opacity >= 0) { if ($opacity < 1) $opacity = $opacity * 100; $opacity = round(127 - ($opacity / 100 * 127)); //IE doesn't support transparency like this in PNG files //$nColor = imagecolorallocatealpha( $im, $nRed, $nGreen, $nBlue, $opacity ); $nColor = imagecolorresolvealpha( $im, $nRed, $nGreen, $nBlue, $opacity ); } else $nColor = imagecolorallocate( $im, $nRed, $nGreen, $nBlue ); return $nColor; } /** * convert a geocoded position to pixel coord * * @param nGeoPos double Geocoded position * @param dfPixMin double minimum map pixel value * @param dfPixMax double maximum map pixel value * @param dfGeoMin double minimum map geocoded value * @param dfGeoMax double maximum map geocoded value * @param nInverseGeo integer optional flag to inverse , set to 1 for * Y pixel coordinates where UL > LR * @return double geocoded position */ function Geo2Pix ($nGeoPos, $dfPixMin, $dfPixMax, $dfGeoMin, $dfGeoMax, $nInverseGeo = "") { //echo "$nGeoPos, $dfPixMin, $dfPixMax, $dfGeoMin, $dfGeoMax"; //renderText( "$nGeoPos, $dfPixMin, $dfPixMax, $dfGeoMin, $dfGeoMax" ); // calculate the geocoded & pixel width if ($nGeoPos < $dfGeoMin) $nGeoPos = $dfGeoMin; if ($nGeoPos > $dfGeoMax) $nGeoPos = $dfGeoMax; $dfWidthGeo = abs($dfGeoMax - $dfGeoMin); $dfWidthPix = abs($dfPixMax - $dfPixMin); // get ratio $dfGeoToPix = $dfWidthPix / $dfWidthGeo; // get difference if (!$nInverseGeo) $dfDeltaGeo = $nGeoPos - $dfGeoMin; else $dfDeltaGeo = $dfGeoMax - $nGeoPos; // calculate $dfDeltaPix = $dfDeltaGeo * $dfGeoToPix; $dfPosPix = $dfPixMin + $dfDeltaPix; //echo ": ".round($dfPosPix)."
"; //renderText( "$nGeoPos, $dfPixMin, $dfPixMax, $dfGeoMin, $dfGeoMax, ".round($dfPosPix) ); // return value return round ($dfPosPix); // end pixel_to_geo function } ?>