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_once(dirname(__FILE__)."/../Widget.php"); /** * TrueNorth * * @desc Display a bitmap indicating true north */ class TrueNorth extends CWCWidget { var $mszTrueNorthImage = ""; var $mszImage = ""; var $mnWidth = ""; var $mnHeight = ""; /** * TrueNorth * * Constructor. Set the default values. */ function TrueNorth() { // invoke constructor of parent parent::CWCWidget(); // User defined true north image to use $this->maAttributes["TRUENORTHIMAGE"] = new StringAttribute("TRUENORTHIMAGE", true); // This should be executed after navtool $this->mnPriority = PRIORITY_LAST; // set the description for this widget $this->szWidgetDescription = <<mnMaturityLevel = MATURITY_BETA; } /** * Initialize some cnfiguration parameter */ function InitDefaults() { parent::InitDefaults(); $oApp = GetChameleonApplication(); if (isset( $this->maParams["TRUENORTHIMAGE"]) && $this->maParams['TRUENORTHIMAGE'] != '') $this->mszTrueNorthImage = $oApp->findFile( $this->maParams["TRUENORTHIMAGE"] ); if (!$this->mszTrueNorthImage) { $_SESSION['gErrorManager']->setError( ERR_CRITICAL, "TrueNorth: ".$this->maParams["TRUENORTHIMAGE"]." cannot be found." ); $this->mszTrueNorthImage = ''; } } /** * Steps: * - Create a rectangle with extent of the map. * - Reproject the rectangle in degrees. * - create 2 points (vertical line) using the same x * (middle of the image) but use 2 different Y distanced * by 20 pixels. * - Reproject those 2 points in original projection. * - Calculate the angle of point1 relatively to point2. * - Load and rotate the True North image. */ function ParseURL() { parent::ParseURL(); if ($this->mszTrueNorthImage == '') { $_SESSION['gErrorManager']->setError( ERR_CRITICAL, "TrueNorth: invalid or no image specified." ); return false; } if ( PHP_OS == "WINNT" || PHP_OS == "WIN32" ) $szGDModule = "php_gd2.dll"; else $szGDModule = "php_gd2.so"; if (!extension_loaded("gd")) dl($szGDModule); $oMap = $this->moMapObject->oMap; // Get current projection $szTmpMapProj = $oMap->getProjection(); // If the map does not have any projection, it's // impossible to draw true north. if ($szTmpMapProj === false) return false; $projInObj = ms_newprojectionobj( $szTmpMapProj ); $projOutObj = ms_newprojectionobj("init=epsg:4326"); // Get map extent and reproject in degrees $oRect = ms_newrectobj(); $oRect->setExtent($oMap->extent->minx, $oMap->extent->miny, $oMap->extent->maxx, $oMap->extent->maxy); if (strcasecmp("init=epsg:4326", $szTmpMapProj) != 0) $oRect->project($projInObj, $projOutObj); // Create 2 points that represent a straight line (vertical) $nMinY = $this->pixel_to_geo($oMap->height/2-10, 0, $oMap->height, $oRect->miny, $oRect->maxy); $nMaxY = $this->pixel_to_geo($oMap->height/2+10, 0, $oMap->height, $oRect->miny, $oRect->maxy); $poPoint1 = ms_newpointobj(); $poPoint2 = ms_newpointobj(); $poPoint1->setXY(($oRect->maxx - $oRect->minx)/2+$oRect->minx, $nMaxY); $poPoint2->setXY($poPoint1->x, $nMinY); if (strcasecmp("init=epsg:4326", $szTmpMapProj) != 0) { // Reproject points back to original projection $poPoint1->project($projOutObj, $projInObj); $poPoint2->project($projOutObj, $projInObj); } // Calculate angle $nTop = ($poPoint1->y-$poPoint2->y); $nDeltaX = ($poPoint1->x-$poPoint2->x); $nDeltaY = ($poPoint1->y-$poPoint2->y); $nBottom = sqrt( $nDeltaX*$nDeltaX + $nDeltaY*$nDeltaY); if ($nBottom == 0) { $nDeg = 90; } else { $nDeg = rad2deg(asin($nTop/$nBottom)); } if ($poPoint1->x-$poPoint2->x<0) $szFileName = $this->drawSymbolRotated(90-$nDeg); else $szFileName = $this->drawSymbolRotated(-1*(90-$nDeg)); $this->mszImage = "mnWidth. "\" height=\"".$this->mnHeight."\">\n"; // return success return true; } function drawSymbolRotated($nDeg) { $szSufix = strtoupper(substr($this->mszTrueNorthImage, -3)); if ($szSufix=="PNG") { $oImg = imagecreatefrompng($this->mszTrueNorthImage); } else { if ($szSufix=="GIF") { $oImg = imagecreatefromgif($this->mszTrueNorthImage); } else { if ($szSufix=="JPG") { $oImg = imagecreatefromjpeg($this->mszTrueNorthImage); } else { $oImg = imagecreatefrompng($this->mszTrueNorthImage); } } } $this->mnWidth = imagesx($oImg); $this->mnHeight = imagesy($oImg); $oMap = ms_newMapObj(""); $oMap->selectOutputFormat("PNG24"); $oMap->set("width", $this->mnWidth); $oMap->set("height", $this->mnHeight); $oMap->setExtent(0, 0, $this->mnWidth, $this->mnHeight); $oLayer = ms_newLayerObj($oMap); $oLayer->set("transform", MS_FALSE); $oLayer->set("type", MS_LAYER_POINT); $oImage = $oMap->prepareimage(); $oClass = ms_newClassObj($oLayer); $nSymbol = ms_newSymbolObj($oMap, $this->mszTrueNorthImage); $oStyle = ms_newStyleObj($oClass); $oStyle->set("symbol", $nSymbol); $oi = $oClass->createLegendIcon($this->mnWidth, $this->mnHeight); $oImage->pasteImage($oi,0, $this->mnWidth/2, $this->mnHeight/2, $nDeg); $szTmpDir = $_SESSION['gszTmpImgPath']; if (substr($szTmpDir, -1) == "/") $szTmpDir = substr($szTmpDir, 0, -1 ); $szFileName = str_replace("\\", "/", tempnam($szTmpDir, "TN").".png"); $oImage->saveImage($szFileName); return $szFileName; } function drawPublish() { return $this->mszImage; } /** * convert a pixel position to geocoded position * * @param nPixPos double pixel 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 nInversePix integer optional flag to inverse , set to 1 for * Y pixel coordinates where UL > LR * @return double geocoded position */ function pixel_to_geo($nPixPos, $dfPixMin, $dfPixMax, $dfGeoMin, $dfGeoMax, $nInversePix = "") { // calculate the geocoded & pixel width $dfWidthGeo = $dfGeoMax - $dfGeoMin; $dfWidthPix = $dfPixMax - $dfPixMin; // get ratio $dfPixToGeo = $dfWidthGeo / $dfWidthPix; // get difference if (!$nInversePix) $dfDeltaPix = $nPixPos - $dfPixMin; else $dfDeltaPix = $dfPixMax - $nPixPos; // calculate $dfDeltaGeo = $dfDeltaPix * $dfPixToGeo; $dfPosGeo = $dfGeoMin + $dfDeltaGeo; // return value return ($dfPosGeo); // end pixel_to_geo function } /** * 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 geo_to_pixel ($nGeoPos, $dfPixMin, $dfPixMax, $dfGeoMin, $dfGeoMax, $nInverseGeo = "") { // calculate the geocoded & pixel width $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; // return value return round ($dfPosPix); // end pixel_to_geo function } } ?>