NCCOOS Trac Projects: Top | Web | Platforms | Processing | Viz | Sprints | Sandbox | (Wind)

root/Chameleon/trunk/Chameleon/ROIManager/ROIRenderer.php

Revision 13 (checked in by jcleary, 17 years ago)

Latest Chameleon code checkout from previous repository

Line 
1 <?php
2 /**
3  * Render one or more ROIs onto a single image for display over the map.
4  *
5  * @project     CWC2
6  * @revision    $Id: ROIRenderer.php,v 1.8 2005/05/27 20:19:16 bartvde Exp $
7  * @purpose     render ROIs
8  * @author      DM Solutions Group (spencer@dmsolutions.ca)
9  * @copyright
10  * <b>Copyright (c) 2002, DM Solutions Group Inc.</b>
11  * Permission is hereby granted, free of charge, to any person obtaining a
12  * copy of this software and associated documentation files (the "Software"),
13  * to deal in the Software without restriction, including without limitation
14  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15  * and/or sell copies of the Software, and to permit persons to whom the
16  * Software is furnished to do so, subject to the following conditions:
17  *
18  * The above copyright notice and this permission notice shall be included
19  * in all copies or substantial portions of the Software.
20  *
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
24  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27  * DEALINGS IN THE SOFTWARE.
28  */
29
30 // include the session handling file
31 define("LOAD_MAPSESSION", 1);
32 $bInvalidSessionDontFail = true;
33 include("../session.inc.php");
34 define( 'ROIRENDERER_QUERY', getSessionSavePath()."/roirenderer.qry");
35 if (!extension_loaded( "gd" ))
36 {
37     $szGDMod2 = "php_gd2".( (PHP_OS=="WINNT" || PHP_OS=="WIN32") ? ".dll" : ".so" );
38     dl( $szGDMod2 );
39 }
40
41 $width = $_GET['width'];
42 $height = $_GET['height'];
43
44 $oImage = imagecreate( $width, $height );
45 $nTransparent = imagecolorallocate( $oImage, 255, 255, 255 );
46 //$nTransparent = imagecolorresolvealpha( $oImage, 255, 255, 255, 0 );
47 $nBlack = imagecolorallocate( $oImage, 0, 0, 0 );
48
49 //imagealphablending( $oImage, false );
50 imagecolortransparent( $oImage, $nTransparent );
51 imagefill( $oImage, 0, 0, $nTransparent );
52 //imagealphablending( $oImage, true );
53
54 if (!isset($GLOBALS['bSessionOK']) || !($GLOBALS['bSessionOK']))
55 {
56     renderText("session expired!");
57 }
58 else
59 {
60     $geoMinX = $oMapSession->oMap->extent->minx;
61     $geoMinY = $oMapSession->oMap->extent->miny;
62     $geoMaxX = $oMapSession->oMap->extent->maxx;
63     $geoMaxY = $oMapSession->oMap->extent->maxy;
64     //renderText( $geoMinX." ".$geoMinY." ".$geoMaxX." ".$geoMaxY );
65     //mode settings:
66     //mode = -2 : remove all ROIs
67     //mode = -1 : remove the last ROI
68     //mode = 0 : replace any existing ROIs with the one passed
69     //mode = 1 : replace any existing ROIs with the one passed
70     //mode = 2 : add the ROI
71     //mode = 3 : subtract the ROI
72     //
73     if (!isset($_SESSION["ROIRENDERER_COUNT"]))
74     {
75         $_SESSION["ROIRENDERER_COUNT"] = 1;
76     }
77     else
78     {
79         $_SESSION["ROIRENDERER_COUNT"] = $_SESSION["ROIRENDERER_COUNT"] + 1;
80     }
81     $mode = isset($_GET['mode']) ? $_GET['mode'] : 0;
82     //renderText( "count is " .$_SESSION["ROIRENDERER_COUNT"]. ", mode is " . $mode );
83     if (!isset($_SESSION['ROIRENDERER']) || $mode == 1)
84     {
85         //clean up after feature ROIs ...
86         if (isset($_SESSION['ROIRENDERER']))
87         {
88             $nROI = count($_SESSION['ROIRENDERER']);
89
90             for($i=0; $i<$nROI; $i++)
91             {
92                 cleanUpROI( $_SESSION['ROIRENDERER'][$i] );
93             }
94         }
95         $_SESSION['ROIRENDERER'] = array();
96     }
97     if ( $mode > 0 )
98     {
99         $roi = array();
100         $roi['mode'] = $mode;
101         $roi['type'] = isset($_GET['type']) ? $_GET['type'] : 'rectangle';
102         $roi['aGeoCoords'] = isset($_GET['coords']) ? explode( ",", $_GET['coords']) : array();
103         $roi['edgecolor'] = isset($_GET['edgecolor']) ? $_GET['edgecolor'] : '#000000';
104         $roi['edgewidth'] = isset($_GET['edgewidth']) ? $_GET['edgewidth'] : 1;
105         $roi['fillcolor'] = isset($_GET['fillcolor']) ? $_GET['fillcolor'] : '#000000';
106         $roi['fillopacity'] = isset($_GET['fillopacity']) ? $_GET['fillopacity'] : 0;
107         if (isset($_GET['selectedLayer']))
108         {
109             $roi['selectedLayer'] = $_GET['selectedLayer'];
110         }
111         array_push( $_SESSION['ROIRENDERER'], $roi );
112     }
113     elseif ($mode == -1)
114     {
115         $aROI = array_pop($_SESSION['ROIRENDERER']);
116         //clean up after feature ROIs ...
117         cleanUpROI( $aROI );
118     }
119     elseif($mode == -2)
120     {
121         $nROI = count($_SESSION['ROIRENDERER']);
122
123         //clean up after feature ROIs ...
124         for($i=0; $i<$nROI; $i++)
125         {
126            cleanUpROI($_SESSION['ROIRENDERER'][$i]);
127         }
128         //delete all ROIs ...
129         $_SESSION['ROIRENDERER'] = array();
130     }
131
132     if (isset($_SESSION['ROIRENDERER']))
133     {
134         $nROI = count($_SESSION['ROIRENDERER']);
135         for($i=0; $i<$nROI; $i++)
136         {
137             drawROI( $_SESSION['ROIRENDERER'][$i] );
138         }
139     }
140 }
141 header( 'Content-type: image/png' );
142 //imagetruecolortopalette($oImage, false, 256);
143 imagepng($oImage);
144 exit;
145
146 /*
147  * draw a single ROI on the output image.  The intent is for this function to handle
148  * any type of ROI.
149  */
150 function drawROI( &$aROI )
151 {
152     // debug
153     //renderText(count($_SESSION['ROIRENDERER']));
154
155     if ($aROI['mode'] == 3)
156     {
157         //subtract, draw a transparent ROI
158         $nFillColor = $GLOBALS['nTransparent'];
159     }
160     else
161     {
162         //normal or add
163         $nFillColor = allocateImageFromHexValue( $GLOBALS['oImage'], $aROI['fillcolor'], $aROI['fillopacity']);
164     }
165     $aPoints = array();
166     if ($aROI['type'] == 'rectangle')
167     {
168         //for rectangles, we assume that there are two coordinates, top left and bottom right.
169         array_push( $aPoints, Geo2Pix($aROI['aGeoCoords'][0], 0, $GLOBALS['width'],
170                     $GLOBALS['geoMinX'], $GLOBALS['geoMaxX'] ) );
171         array_push( $aPoints, Geo2Pix($aROI['aGeoCoords'][1], 0, $GLOBALS['height'],
172                     $GLOBALS['geoMinY'], $GLOBALS['geoMaxY'], 1 ) );
173
174         array_push( $aPoints, Geo2Pix($aROI['aGeoCoords'][2], 0, $GLOBALS['width'],
175                     $GLOBALS['geoMinX'], $GLOBALS['geoMaxX'] ) );
176         array_push( $aPoints, Geo2Pix($aROI['aGeoCoords'][1], 0, $GLOBALS['height'],
177                     $GLOBALS['geoMinY'], $GLOBALS['geoMaxY'], 1 ) );
178
179         array_push( $aPoints, Geo2Pix($aROI['aGeoCoords'][2], 0, $GLOBALS['width'],
180                     $GLOBALS['geoMinX'], $GLOBALS['geoMaxX'] ) );
181         array_push( $aPoints, Geo2Pix($aROI['aGeoCoords'][3], 0, $GLOBALS['height'],
182                     $GLOBALS['geoMinY'], $GLOBALS['geoMaxY'], 1 ) );
183
184         array_push( $aPoints, Geo2Pix($aROI['aGeoCoords'][0], 0, $GLOBALS['width'],
185                     $GLOBALS['geoMinX'], $GLOBALS['geoMaxX'] ) );
186         array_push( $aPoints, Geo2Pix($aROI['aGeoCoords'][3], 0, $GLOBALS['height'],
187                     $GLOBALS['geoMinY'], $GLOBALS['geoMaxY'], 1 ) );
188
189         array_push( $aPoints, Geo2Pix($aROI['aGeoCoords'][0], 0, $GLOBALS['width'],
190                     $GLOBALS['geoMinX'], $GLOBALS['geoMaxX'] ) );
191         array_push( $aPoints, Geo2Pix($aROI['aGeoCoords'][1], 0, $GLOBALS['height'],
192                     $GLOBALS['geoMinY'], $GLOBALS['geoMaxY'], 1 ) );
193         $nPoints = 5;
194
195         // flag for poly
196         $bPoly = true;
197     }
198     elseif ( $aROI['type'] == 'circle' )
199     {
200         // convert center and radius to pixel
201         $dCenterX = Geo2Pix($aROI['aGeoCoords'][0], 0, $GLOBALS['width'],
202                     $GLOBALS['geoMinX'], $GLOBALS['geoMaxX'] );
203         $dCenterY = Geo2Pix($aROI['aGeoCoords'][1], 0, $GLOBALS['height'],
204                     $GLOBALS['geoMinY'], $GLOBALS['geoMaxY'], 1 );
205         $dRadiusX = Geo2Pix($aROI['aGeoCoords'][2], 0, $GLOBALS['width'],
206                     $GLOBALS['geoMinX'], $GLOBALS['geoMaxX']);
207
208         $dRadius = abs( $dRadiusX - $dCenterX );
209
210         // flag for non-poly
211         $bPoly = false;
212     }
213     elseif ( $aROI['type'] == 'polygon' )
214     {
215         // loop and set coordinates
216         $nCount = count( $aROI['aGeoCoords'] );
217         for( $i=0;$i<$nCount; $i++ )
218         {
219             // even is x, odd is y
220             if ( fmod( $i, 2 ) == 0 )
221             {
222                 array_push( $aPoints, Geo2Pix($aROI['aGeoCoords'][$i], 0, $GLOBALS['width'],
223                     $GLOBALS['geoMinX'], $GLOBALS['geoMaxX'] ) );
224             }
225             else
226             {
227                 array_push( $aPoints, Geo2Pix($aROI['aGeoCoords'][$i], 0, $GLOBALS['height'],
228                     $GLOBALS['geoMinY'], $GLOBALS['geoMaxY'], 1 ) );
229             }
230         }
231
232         $nPoints = round( $nCount/2 );
233
234         // flag for poly
235         $bPoly = true;
236     }
237     elseif ($aROI['type'] == 'feature')
238     {
239         $nPoints = 0;
240         $nLayers = $GLOBALS['oMapSession']->oMap->numlayers;
241         for ($i=0; $i<$nLayers; $i++ )
242         {
243             $oLayer  = $GLOBALS['oMapSession']->oMap->getLayer( $i );
244             $oLayer->set( 'status', MS_OFF );
245         }
246         $oLayer = @$GLOBALS['oMapSession']->oMap->getLayerByName( $aROI['selectedLayer'] );
247
248         if ($oLayer && $oLayer->type == MS_LAYER_POLYGON)
249         {
250             $nResults = 0;
251             //create the query template that turns polygons into something useful.
252             $szTemplatePath = getSessionSavePath()."roirenderer_template.html";
253             if (!file_exists( $szTemplatePath ) )
254             {
255                 $szTemplate = '[shpxy xf="," yf="," sf="|" proj="image"]';
256                 $hTemplate = fopen( $szTemplatePath, "w+" );
257                 fwrite( $hTemplate, $szTemplate );
258                 fclose( $hTemplate );
259             }
260             //put the template on each class ... is this necessary?
261             for ($i=0; $i<$oLayer->numclasses; $i++)
262             {
263                 $oClass = $oLayer->getClass( $i );
264                 $oClass->set( "template", $szTemplatePath );
265             }
266             //make sure the layer is on (doh)
267             $oLayer->set( "status", MS_ON );
268             $oLayer->set( 'tolerance', 0 );
269             $oLayer->set( 'toleranceunits', MS_PIXELS );
270             //its a new query ...
271             if (count($aROI['aGeoCoords']) == 2)
272             {
273                 $aROI['aOrigCoords'] = $aROI['aGeoCoords'];
274                 $oPoint = ms_newPointObj( );
275                 $oPoint->setXY( $aROI['aGeoCoords'][0], $aROI['aGeoCoords'][1] );
276                 @$oLayer->queryByPoint( $oPoint, MS_SINGLE, 0 );
277                 $nResults = $oLayer->getNumResults();
278                 unset( $aROI['aGeoCoords'] );
279
280                 if ($nResults > 0)
281                 {
282                     //save the query results for future passes ...
283                     $aROI['query_file'] = getSessionSavePath()."/".uniqid("").".qry";
284                     $GLOBALS['oMapSession']->oMap->saveQuery( $aROI['query_file'] );
285                 }
286             }
287             else if (isset($aROI['query_file']) && file_exists( $aROI['query_file'] ))
288             {
289                 //load the query and find a layer with query results ...
290                 $GLOBALS['oMapSession']->oMap->loadQuery( $aROI['query_file'] );
291                 $nResults = $oLayer->getNumResults();
292             }
293
294             if ($nResults > 0)
295             {
296                 $szCode = $GLOBALS['oMapSession']->oMap->processQueryTemplate( array(), false );
297                 //there seems to be a bug ... query results are not getting reset ... so we
298                 //introduce a | after each shape and then only take the first shape ...
299                 $aszCode = explode( "|", $szCode );
300                 $szCode = substr($aszCode[0], 0, -1 );
301                 $szCode = '$'.'aPoints = array('.$szCode.');';
302
303                 eval( $szCode );
304                 $nPoints = count($aPoints)/2;
305                 $bPoly = true;
306             }
307         }
308     }
309
310     // draw poly or ellipse or feature
311     if ( $bPoly && $nPoints > 0)
312     {
313         imagefilledpolygon( $GLOBALS['oImage'], $aPoints, $nPoints, $nFillColor);
314     }
315     else if ($aROI['type'] == 'circle')
316     {
317         //renderText( $dCenterX.','.$dCenterY.' radius='.$dRadius );
318         $nEdgeColor = allocateImageFromHexValue( $GLOBALS['oImage'], $aROI['edgecolor']);
319
320         imagefilledellipse ( $GLOBALS['oImage'], $dCenterX,
321             $dCenterY,  $dRadius * 2+$aROI['edgewidth'], $dRadius * 2+$aROI['edgewidth'],
322             $nEdgeColor );
323
324         imagefilledellipse ( $GLOBALS['oImage'], $dCenterX,
325             $dCenterY,  $dRadius * 2, $dRadius * 2,
326             $nFillColor );
327     }
328     else
329     {
330         //something went wrong, can't do anything here.
331     }
332 }
333
334 // clean up after an ROI, specifically Feature ROIs ...
335 function cleanUpROI( $aROI )
336 {
337     if ($aROI['type'] == 'feature' && file_exists($aROI['query_file']))
338     {
339         unlink( $aROI['query_file'] );
340         if (file_exists($aROI['query_file'].".txt"))
341             unlink($aROI['query_file'].".txt");
342     }
343 }
344
345 //use this to put text into the output image (for debugging :))
346 function renderText( $szText )
347 {
348     $x = 10;
349     if (!isset($GLOBALS['y']))
350         $GLOBALS['y'] = 10;
351     else
352         $GLOBALS['y'] += 20;
353     imagestring( $GLOBALS['oImage'], 2, $x, $GLOBALS['y'], $szText, $GLOBALS['nBlack'] );
354
355 }
356 /*
357  * return a color index from the given image for a given hex color.  If opacity
358  * is not false, then assume that it is either a percent or a number from 0-100 and
359  * massage accordingly into a value between 0 (transparent) and 127 (opaque).
360  */
361 function allocateImageFromHexValue( $im, $szHexColor, $opacity = false )
362 {
363     if (substr($szHexColor, 0, 1) == "#")
364         $szHexColor = substr($szHexColor, 1 );
365     $nRed = intval(substr($szHexColor,0,2),16);
366     $nGreen = intval(substr($szHexColor,2,2),16);
367     $nBlue = intval(substr($szHexColor,4,2),16);
368
369     if ($opacity && $opacity >= 0)
370     {
371         if ($opacity < 1)
372             $opacity = $opacity * 100;
373         $opacity = round(127 - ($opacity / 100 * 127));
374         //IE doesn't support transparency like this in PNG files
375         //$nColor = imagecolorallocatealpha( $im, $nRed, $nGreen, $nBlue, $opacity );
376         $nColor = imagecolorresolvealpha( $im, $nRed, $nGreen, $nBlue, $opacity );
377      }
378     else
379         $nColor = imagecolorallocate( $im, $nRed, $nGreen, $nBlue );
380     return $nColor;
381 }
382
383 /**
384  * convert a geocoded position to pixel coord
385  *
386  * @param nGeoPos double Geocoded position
387  * @param dfPixMin double minimum map pixel value
388  * @param dfPixMax double maximum map pixel value
389  * @param dfGeoMin double minimum map geocoded value
390  * @param dfGeoMax double maximum map geocoded value
391  * @param nInverseGeo integer optional flag to inverse , set to 1 for
392  *                            Y pixel coordinates where UL > LR
393  * @return double geocoded position
394  */
395 function Geo2Pix ($nGeoPos, $dfPixMin, $dfPixMax, $dfGeoMin,
396                        $dfGeoMax, $nInverseGeo = "")
397     {
398         //echo "$nGeoPos, $dfPixMin, $dfPixMax, $dfGeoMin, $dfGeoMax";
399         //renderText( "$nGeoPos, $dfPixMin, $dfPixMax, $dfGeoMin, $dfGeoMax" );
400         // calculate the geocoded & pixel width
401         if ($nGeoPos < $dfGeoMin)
402             $nGeoPos = $dfGeoMin;
403         if ($nGeoPos > $dfGeoMax)
404             $nGeoPos = $dfGeoMax;
405
406         $dfWidthGeo = abs($dfGeoMax - $dfGeoMin);
407         $dfWidthPix = abs($dfPixMax - $dfPixMin);
408
409         // get ratio
410         $dfGeoToPix = $dfWidthPix / $dfWidthGeo;
411
412         // get difference
413         if (!$nInverseGeo)
414             $dfDeltaGeo = $nGeoPos - $dfGeoMin;
415         else
416             $dfDeltaGeo = $dfGeoMax - $nGeoPos;
417
418         // calculate
419         $dfDeltaPix = $dfDeltaGeo * $dfGeoToPix;
420         $dfPosPix = $dfPixMin + $dfDeltaPix;
421
422         //echo ": ".round($dfPosPix)."<BR>";
423         //renderText( "$nGeoPos, $dfPixMin, $dfPixMax, $dfGeoMin, $dfGeoMax, ".round($dfPosPix) );
424         // return value
425         return round ($dfPosPix);
426
427         // end pixel_to_geo function
428     }
429
430 ?>
Note: See TracBrowser for help on using the browser.