1 /******************************************************************************
2 * $Id$
3 *
4 * Project: MapServer
5 * Purpose: Functions for operating on a mapObj that don't belong in a
6 * more specific file such as mapfile.c, or mapdraw.c.
7 * Author: Frank Warmerdam, warmerdam@pobox.com
8 *
9 ******************************************************************************
10 * Copyright (c) 2004, Frank Warmerdam
11 *
12 * Permission is hereby granted, free of charge, to any person obtaining a
13 * copy of this software and associated documentation files (the "Software"),
14 * to deal in the Software without restriction, including without limitation
15 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16 * and/or sell copies of the Software, and to permit persons to whom the
17 * Software is furnished to do so, subject to the following conditions:
18 *
19 * The above copyright notice and this permission notice shall be included in
20 * all copies of this Software or works derived from this Software.
21 *
22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28 * DEALINGS IN THE SOFTWARE.
29 ****************************************************************************/
30
31 #include "mapserver.h"
32 #include "mapows.h"
33
34 #include "gdal.h"
35 #include "cpl_conv.h"
36
37 void freeWeb(webObj *web);
38 void freeScalebar(scalebarObj *scalebar);
39 void freeReferenceMap(referenceMapObj *ref);
40 void freeLegend(legendObj *legend);
41
42 /************************************************************************/
43 /* msNewMapObj() */
44 /* */
45 /* Create a new initialized map object. */
46 /************************************************************************/
47
msNewMapObj()48 mapObj *msNewMapObj()
49 {
50 mapObj *map = NULL;
51
52 /* create an empty map, no layers etc... */
53 map = (mapObj *)calloc(sizeof(mapObj),1);
54
55 if(!map) {
56 msSetError(MS_MEMERR, NULL, "msCreateMap()");
57 return NULL;
58 }
59
60 if( initMap( map ) == -1 ) {
61 msFreeMap(map);
62 return NULL;
63 }
64
65 if( msPostMapParseOutputFormatSetup( map ) == MS_FAILURE ) {
66 msFreeMap(map);
67 return NULL;
68 }
69
70 return map;
71 }
72
73 /************************************************************************/
74 /* msFreeMap() */
75 /************************************************************************/
76
msFreeMap(mapObj * map)77 void msFreeMap(mapObj *map)
78 {
79 int i;
80
81 if(!map) return;
82
83 /* printf("msFreeMap(): maybe freeing map at %p count=%d.\n",map, map->refcount); */
84 if(MS_REFCNT_DECR_IS_NOT_ZERO(map)) {
85 return;
86 }
87 if(map->debug >= MS_DEBUGLEVEL_VV)
88 msDebug("msFreeMap(): freeing map at %p.\n",map);
89
90 msCloseConnections(map);
91
92 msFree(map->name);
93 msFree(map->shapepath);
94 msFree(map->mappath);
95
96 msFreeProjection(&(map->projection));
97 msFreeProjection(&(map->latlon));
98 msProjectionContextReleaseToPool(map->projContext);
99
100 msFreeLabelCache(&(map->labelcache));
101
102 msFree(map->imagetype);
103
104 msFreeFontSet(&(map->fontset));
105
106 msFreeSymbolSet(&map->symbolset); /* free symbols */
107 msFree(map->symbolset.filename);
108
109 freeWeb(&(map->web));
110
111 freeScalebar(&(map->scalebar));
112 freeReferenceMap(&(map->reference));
113 freeLegend(&(map->legend));
114
115 for(i=0; i<map->maxlayers; i++) {
116 if(GET_LAYER(map, i) != NULL) {
117 GET_LAYER(map, i)->map = NULL;
118 if(freeLayer((GET_LAYER(map, i))) == MS_SUCCESS)
119 free(GET_LAYER(map, i));
120 }
121 }
122 msFree(map->layers);
123
124 if(map->layerorder)
125 free(map->layerorder);
126
127 msFree(map->templatepattern);
128 msFree(map->datapattern);
129 msFreeHashItems(&(map->configoptions));
130 if(map->outputformat && map->outputformat->refcount > 0 && --map->outputformat->refcount < 1)
131 msFreeOutputFormat(map->outputformat);
132
133 for(i=0; i<map->numoutputformats; i++ ) {
134 if(map->outputformatlist[i]->refcount > 0 && --map->outputformatlist[i]->refcount < 1)
135 msFreeOutputFormat(map->outputformatlist[i]);
136 }
137 if(map->outputformatlist != NULL)
138 msFree(map->outputformatlist);
139
140 msFreeQuery(&(map->query));
141
142 #ifdef USE_V8_MAPSCRIPT
143 if (map->v8context)
144 msV8FreeContext(map);
145 #endif
146
147 msFree(map);
148 }
149
150 /************************************************************************/
151 /* msGetConfigOption() */
152 /************************************************************************/
153
msGetConfigOption(mapObj * map,const char * key)154 const char *msGetConfigOption( mapObj *map, const char *key)
155
156 {
157 return msLookupHashTable( &(map->configoptions), key );
158 }
159
160 /************************************************************************/
161 /* msSetConfigOption() */
162 /************************************************************************/
163
msSetConfigOption(mapObj * map,const char * key,const char * value)164 int msSetConfigOption( mapObj *map, const char *key, const char *value)
165
166 {
167 /* We have special "early" handling of this so that it will be */
168 /* in effect when the projection blocks are parsed and pj_init is called. */
169 if( strcasecmp(key,"PROJ_LIB") == 0 ) {
170 /* value may be relative to map path */
171 msSetPROJ_LIB( value, map->mappath );
172 }
173
174 /* Same for MS_ERRORFILE, we want it to kick in as early as possible
175 * to catch parsing errors.
176 * Value can be relative to mapfile, unless it's already absolute
177 */
178 if( strcasecmp(key,"MS_ERRORFILE") == 0 ) {
179 if (msSetErrorFile( value, map->mappath ) != MS_SUCCESS)
180 return MS_FAILURE;
181 }
182
183 if( msLookupHashTable( &(map->configoptions), key ) != NULL )
184 msRemoveHashTable( &(map->configoptions), key );
185 msInsertHashTable( &(map->configoptions), key, value );
186
187 return MS_SUCCESS;
188 }
189
190 /************************************************************************/
191 /* msTestConfigOption() */
192 /************************************************************************/
193
msTestConfigOption(mapObj * map,const char * key,int default_result)194 int msTestConfigOption( mapObj *map, const char *key, int default_result )
195
196 {
197 const char *result = msGetConfigOption( map, key );
198
199 if( result == NULL )
200 return default_result;
201
202 if( strcasecmp(result,"YES") == 0
203 || strcasecmp(result,"ON") == 0
204 || strcasecmp(result,"TRUE") == 0 )
205 return MS_TRUE;
206 else
207 return MS_FALSE;
208 }
209
210 /************************************************************************/
211 /* msApplyMapConfigOptions() */
212 /************************************************************************/
213
msApplyMapConfigOptions(mapObj * map)214 void msApplyMapConfigOptions( mapObj *map )
215
216 {
217 const char *key;
218
219 for( key = msFirstKeyFromHashTable( &(map->configoptions) );
220 key != NULL;
221 key = msNextKeyFromHashTable( &(map->configoptions), key ) ) {
222 const char *value = msLookupHashTable( &(map->configoptions), key );
223 if( strcasecmp(key,"PROJ_LIB") == 0 ) {
224 msSetPROJ_LIB( value, map->mappath );
225 } else if( strcasecmp(key,"MS_ERRORFILE") == 0 ) {
226 msSetErrorFile( value, map->mappath );
227 } else {
228 CPLSetConfigOption( key, value );
229 }
230 }
231 }
232
233 /************************************************************************/
234 /* msMapIgnoreMissingData() */
235 /************************************************************************/
236
msMapIgnoreMissingData(mapObj * map)237 int msMapIgnoreMissingData( mapObj *map )
238 {
239 const char *result = msGetConfigOption( map, "ON_MISSING_DATA" );
240 const int default_result =
241 #ifndef IGNORE_MISSING_DATA
242 MS_MISSING_DATA_FAIL;
243 #else
244 MS_MISSING_DATA_LOG;
245 #endif
246
247 if( result == NULL )
248 return default_result;
249
250 if( strcasecmp(result,"FAIL") == 0 )
251 return MS_MISSING_DATA_FAIL;
252 else if( strcasecmp(result,"LOG") == 0 )
253 return MS_MISSING_DATA_LOG;
254 else if( strcasecmp(result,"IGNORE") == 0 )
255 return MS_MISSING_DATA_IGNORE;
256
257 return default_result;
258 }
259
260 /************************************************************************/
261 /* msMapSetExtent() */
262 /************************************************************************/
263
msMapSetExtent(mapObj * map,double minx,double miny,double maxx,double maxy)264 int msMapSetExtent( mapObj *map,
265 double minx, double miny, double maxx, double maxy)
266 {
267
268 map->extent.minx = minx;
269 map->extent.miny = miny;
270 map->extent.maxx = maxx;
271 map->extent.maxy = maxy;
272
273 if (!MS_VALID_EXTENT(map->extent)) {
274 msSetError(MS_MISCERR, "Given map extent is invalid. Check that it " \
275 "is in the form: minx, miny, maxx, maxy", "setExtent()");
276 return MS_FAILURE;
277 }
278
279 map->cellsize = msAdjustExtent(&(map->extent), map->width,
280 map->height);
281
282 /* if the map size is also set, recompute scale, ignore errors? */
283 if( map->width != -1 || map->height != -1 )
284 msCalculateScale(map->extent, map->units, map->width, map->height,
285 map->resolution, &(map->scaledenom));
286
287 return msMapComputeGeotransform( map );
288 }
289
290 /************************************************************************/
291 /* msMapOffsetExtent() */
292 /************************************************************************/
293
msMapOffsetExtent(mapObj * map,double x,double y)294 int msMapOffsetExtent( mapObj *map, double x, double y)
295 {
296 return msMapSetExtent( map,
297 map->extent.minx + x, map->extent.miny + y,
298 map->extent.maxx + x, map->extent.maxy + y);
299 }
300
301 /************************************************************************/
302 /* msMapScaleExtent() */
303 /************************************************************************/
304
msMapScaleExtent(mapObj * map,double zoomfactor,double minscaledenom,double maxscaledenom)305 int msMapScaleExtent( mapObj *map, double zoomfactor,
306 double minscaledenom, double maxscaledenom)
307 {
308 double geo_width, geo_height, center_x, center_y, md;
309
310 if (zoomfactor <= 0.0) {
311 msSetError(MS_MISCERR, "The given zoomfactor is invalid", "msMapScaleExtent()");
312 }
313
314 geo_width = map->extent.maxx - map->extent.minx;
315 geo_height = map->extent.maxy - map->extent.miny;
316
317 center_x = map->extent.minx + geo_width * 0.5;
318 center_y = map->extent.miny + geo_height * 0.5;
319
320 geo_width *= zoomfactor;
321
322 if (minscaledenom > 0 || maxscaledenom > 0) {
323 /* ensure we are within the valid scale domain */
324 md = (map->width-1)/(map->resolution * msInchesPerUnit(map->units, center_y));
325 if (minscaledenom > 0 && geo_width < minscaledenom * md)
326 geo_width = minscaledenom * md;
327 if (maxscaledenom > 0 && geo_width > maxscaledenom * md)
328 geo_width = maxscaledenom * md;
329 }
330
331 geo_width *= 0.5;
332 geo_height = geo_width * map->height / map->width;
333
334 return msMapSetExtent( map,
335 center_x - geo_width, center_y - geo_height,
336 center_x + geo_width, center_y + geo_height);
337 }
338
339 /************************************************************************/
340 /* msMapSetCenter() */
341 /************************************************************************/
342
msMapSetCenter(mapObj * map,pointObj * center)343 int msMapSetCenter( mapObj *map, pointObj *center)
344 {
345 return msMapOffsetExtent(map, center->x - (map->extent.minx + map->extent.maxx) * 0.5,
346 center->y - (map->extent.miny + map->extent.maxy) * 0.5);
347 }
348
349 /************************************************************************/
350 /* msMapSetRotation() */
351 /************************************************************************/
352
msMapSetRotation(mapObj * map,double rotation_angle)353 int msMapSetRotation( mapObj *map, double rotation_angle )
354
355 {
356 map->gt.rotation_angle = rotation_angle;
357 if( map->gt.rotation_angle != 0.0 )
358 map->gt.need_geotransform = MS_TRUE;
359 else
360 map->gt.need_geotransform = MS_FALSE;
361
362 return msMapComputeGeotransform( map );
363 }
364
365 /************************************************************************/
366 /* msMapSetSize() */
367 /************************************************************************/
368
msMapSetSize(mapObj * map,int width,int height)369 int msMapSetSize( mapObj *map, int width, int height )
370
371 {
372 map->width = width;
373 map->height = height;
374
375 return msMapComputeGeotransform( map ); /* like SetRotation -- sean */
376 }
377
378 /************************************************************************/
379 /* msMapComputeGeotransform() */
380 /************************************************************************/
381
382 extern int InvGeoTransform( double *gt_in, double *gt_out );
383
msMapComputeGeotransform(mapObj * map)384 int msMapComputeGeotransform( mapObj * map )
385
386 {
387 double rot_angle;
388 double geo_width, geo_height, center_x, center_y;
389
390 map->saved_extent = map->extent;
391
392 /* Do we have all required parameters? */
393 if( map->extent.minx == map->extent.maxx
394 || map->width == 0 || map->height == 0 )
395 return MS_FAILURE;
396
397 rot_angle = map->gt.rotation_angle * MS_PI / 180.0;
398
399 geo_width = map->extent.maxx - map->extent.minx;
400 geo_height = map->extent.maxy - map->extent.miny;
401
402 center_x = map->extent.minx + geo_width*0.5;
403 center_y = map->extent.miny + geo_height*0.5;
404
405 /*
406 ** Per bug 1916 we have to adjust for the fact that map extents
407 ** are based on the center of the edge pixels, not the outer
408 ** edges as is expected in a geotransform.
409 */
410 map->gt.geotransform[1] =
411 cos(rot_angle) * geo_width / (map->width-1);
412 map->gt.geotransform[2] =
413 sin(rot_angle) * geo_height / (map->height-1);
414 map->gt.geotransform[0] = center_x
415 - (map->width * 0.5) * map->gt.geotransform[1]
416 - (map->height * 0.5) * map->gt.geotransform[2];
417
418 map->gt.geotransform[4] =
419 sin(rot_angle) * geo_width / (map->width-1);
420 map->gt.geotransform[5] =
421 - cos(rot_angle) * geo_height / (map->height-1);
422 map->gt.geotransform[3] = center_y
423 - (map->width * 0.5) * map->gt.geotransform[4]
424 - (map->height * 0.5) * map->gt.geotransform[5];
425
426 if( InvGeoTransform( map->gt.geotransform,
427 map->gt.invgeotransform ) )
428 return MS_SUCCESS;
429 else
430 return MS_FAILURE;
431 }
432
433 /************************************************************************/
434 /* msMapPixelToGeoref() */
435 /************************************************************************/
436
msMapPixelToGeoref(mapObj * map,double * x,double * y)437 void msMapPixelToGeoref( mapObj *map, double *x, double *y )
438
439 {
440 msSetError(MS_MISCERR, NULL, "msMapPixelToGeoref() not yet implemented");
441 }
442
443 /************************************************************************/
444 /* msMapGeorefToPixel() */
445 /************************************************************************/
446
msMapGeorefToPixel(mapObj * map,double * x,double * y)447 void msMapGeorefToPixel( mapObj *map, double *x, double *y )
448
449 {
450 msSetError(MS_MISCERR, NULL, "msMapGeorefToPixel() not yet implemented");
451 }
452
453 /************************************************************************/
454 /* msMapSetFakedExtent() */
455 /************************************************************************/
456
msMapSetFakedExtent(mapObj * map)457 int msMapSetFakedExtent( mapObj *map )
458
459 {
460 int i;
461 /* -------------------------------------------------------------------- */
462 /* Remember the original map extents so we can restore them */
463 /* later. */
464 /* -------------------------------------------------------------------- */
465 map->saved_extent = map->extent;
466
467 /* -------------------------------------------------------------------- */
468 /* Set extents such that the bottom left corner is 0,0 and the */
469 /* top right is width,height. Note this is upside down from */
470 /* the normal sense of pixel/line coordiantes, but we do this */
471 /* so that the normal "extent" concept of coordinates */
472 /* increasing to the right, and up is maintained (like in */
473 /* georeferenced coordinate systems). */
474 /* -------------------------------------------------------------------- */
475 map->extent.minx = 0;
476 map->extent.maxx = map->width;
477 map->extent.miny = 0;
478 map->extent.maxy = map->height;
479 map->cellsize = 1.0;
480
481 /* -------------------------------------------------------------------- */
482 /* When we copy the geotransform into the projection object we */
483 /* have to flip it to account for the preceeding upside-down */
484 /* coordinate system. */
485 /* -------------------------------------------------------------------- */
486 map->projection.gt = map->gt;
487
488 map->projection.gt.geotransform[0]
489 += map->height * map->gt.geotransform[2];
490 map->projection.gt.geotransform[3]
491 += map->height * map->gt.geotransform[5];
492
493 map->projection.gt.geotransform[2] *= -1;
494 map->projection.gt.geotransform[5] *= -1;
495
496 for(i=0; i<map->numlayers; i++)
497 GET_LAYER(map, i)->project = MS_TRUE;
498
499 return InvGeoTransform( map->projection.gt.geotransform,
500 map->projection.gt.invgeotransform );
501 }
502
503 /************************************************************************/
504 /* msMapRestoreRealExtent() */
505 /************************************************************************/
506
msMapRestoreRealExtent(mapObj * map)507 int msMapRestoreRealExtent( mapObj *map )
508
509 {
510 map->projection.gt.need_geotransform = MS_FALSE;
511 map->extent = map->saved_extent;
512 map->cellsize = msAdjustExtent(&(map->extent), map->width, map->height);
513
514 return MS_SUCCESS;
515 }
516
517 /************************************************************************/
518 /* msInsertLayer() */
519 /************************************************************************/
520 /* Returns the index at which the layer was inserted
521 */
522
msInsertLayer(mapObj * map,layerObj * layer,int nIndex)523 int msInsertLayer(mapObj *map, layerObj *layer, int nIndex)
524 {
525 if (!layer) {
526 msSetError(MS_CHILDERR, "Can't insert a NULL Layer", "msInsertLayer()");
527 return -1;
528 }
529
530 /* Ensure there is room for a new layer */
531 if (map->numlayers == map->maxlayers) {
532 if (msGrowMapLayers(map) == NULL)
533 return -1;
534 }
535
536 /* msGrowMapLayers allocates the new layer which we don't need to do since we have 1 that we are inserting
537 not sure if it is possible for this to be non null otherwise, but better to check since this function
538 replaces the value */
539 if (map->layers[map->numlayers]!=NULL)
540 free(map->layers[map->numlayers]);
541
542 /* Catch attempt to insert past end of layers array */
543 if (nIndex >= map->numlayers) {
544 msSetError(MS_CHILDERR, "Cannot insert layer beyond index %d",
545 "msInsertLayer()", map->numlayers-1);
546 return -1;
547 } else if (nIndex < 0) { /* Insert at the end by default */
548 map->layerorder[map->numlayers] = map->numlayers;
549 GET_LAYER(map, map->numlayers) = layer;
550 GET_LAYER(map, map->numlayers)->index = map->numlayers;
551 GET_LAYER(map, map->numlayers)->map = map;
552 MS_REFCNT_INCR(layer);
553 map->numlayers++;
554 return map->numlayers-1;
555 } else if (nIndex >= 0 && nIndex < map->numlayers) {
556 /* Move existing layers at the specified nIndex or greater */
557 /* to an index one higher */
558 int i;
559 for (i=map->numlayers; i>nIndex; i--) {
560 GET_LAYER(map, i)=GET_LAYER(map, i-1);
561 GET_LAYER(map, i)->index = i;
562 }
563
564 /* assign new layer to specified index */
565 GET_LAYER(map, nIndex)=layer;
566 GET_LAYER(map, nIndex)->index = nIndex;
567 GET_LAYER(map, nIndex)->map = map;
568
569 /* adjust layers drawing order */
570 for (i=map->numlayers; i>nIndex; i--) {
571 map->layerorder[i] = map->layerorder[i-1];
572 if (map->layerorder[i] >= nIndex) map->layerorder[i]++;
573 }
574 for (i=0; i<nIndex; i++) {
575 if (map->layerorder[i] >= nIndex) map->layerorder[i]++;
576 }
577 map->layerorder[nIndex] = nIndex;
578
579 /* increment number of layers and return */
580 MS_REFCNT_INCR(layer);
581 map->numlayers++;
582 return nIndex;
583 } else {
584 msSetError(MS_CHILDERR, "Invalid index", "msInsertLayer()");
585 return -1;
586 }
587 }
588
589 /************************************************************************/
590 /* msRemoveLayer() */
591 /************************************************************************/
msRemoveLayer(mapObj * map,int nIndex)592 layerObj *msRemoveLayer(mapObj *map, int nIndex)
593 {
594 int i;
595 int order_index;
596 layerObj *layer;
597
598 if (nIndex < 0 || nIndex >= map->numlayers) {
599 msSetError(MS_CHILDERR, "Cannot remove Layer, invalid index %d",
600 "msRemoveLayer()", nIndex);
601 return NULL;
602 } else {
603 layer=GET_LAYER(map, nIndex);
604 /* msCopyLayer(layer, (GET_LAYER(map, nIndex))); */
605
606 /* Iteratively copy the higher index layers down one index */
607 for (i=nIndex; i<map->numlayers-1; i++) {
608 /* freeLayer((GET_LAYER(map, i))); */
609 /* initLayer((GET_LAYER(map, i)), map); */
610 /* msCopyLayer(GET_LAYER(map, i), GET_LAYER(map, i+1)); */
611 GET_LAYER(map, i)=GET_LAYER(map, i+1);
612 GET_LAYER(map, i)->index = i;
613 }
614 /* Free the extra layer at the end */
615 /* freeLayer((GET_LAYER(map, map->numlayers-1))); */
616 GET_LAYER(map, map->numlayers-1)=NULL;
617
618 /* Adjust drawing order */
619 order_index = 0;
620 for (i=0; i<map->numlayers; i++) {
621 if (map->layerorder[i] > nIndex) map->layerorder[i]--;
622 if (map->layerorder[i] == nIndex) {
623 order_index = i;
624 break;
625 }
626 }
627 for (i=order_index; i<map->numlayers-1; i++) {
628 map->layerorder[i] = map->layerorder[i+1];
629 if (map->layerorder[i] > nIndex) map->layerorder[i]--;
630 }
631
632 /* decrement number of layers and return copy of removed layer */
633 map->numlayers--;
634 layer->map=NULL;
635 MS_REFCNT_DECR(layer);
636 return layer;
637 }
638 }
639
640 /*
641 ** Move the layer's order for drawing purpose. Moving it up here
642 ** will have the effect of drawing the layer earlier.
643 */
msMoveLayerUp(mapObj * map,int nLayerIndex)644 int msMoveLayerUp(mapObj *map, int nLayerIndex)
645 {
646 int iCurrentIndex = -1;
647 int i = 0;
648 if (map && nLayerIndex < map->numlayers && nLayerIndex >=0) {
649 for (i=0; i<map->numlayers; i++) {
650 if ( map->layerorder[i] == nLayerIndex) {
651 iCurrentIndex = i;
652 break;
653 }
654 }
655 if (iCurrentIndex >=0) {
656 /* we do not need to promote if it is the first one. */
657 if (iCurrentIndex == 0)
658 return MS_FAILURE;
659
660 map->layerorder[iCurrentIndex] =
661 map->layerorder[iCurrentIndex-1];
662 map->layerorder[iCurrentIndex-1] = nLayerIndex;
663
664 return MS_SUCCESS;
665 }
666 }
667 msSetError(MS_CHILDERR, "Invalid index: %d", "msMoveLayerUp()",
668 nLayerIndex);
669 return MS_FAILURE;
670 }
671
672 /*
673 ** Move the layer's order for drawing purpose. Moving it down here
674 ** will have the effect of drawing the layer later.
675 */
msMoveLayerDown(mapObj * map,int nLayerIndex)676 int msMoveLayerDown(mapObj *map, int nLayerIndex)
677 {
678 int iCurrentIndex = -1;
679 int i = 0;
680 if (map && nLayerIndex < map->numlayers && nLayerIndex >=0) {
681 for (i=0; i<map->numlayers; i++) {
682 if ( map->layerorder[i] == nLayerIndex) {
683 iCurrentIndex = i;
684 break;
685 }
686 }
687 if (iCurrentIndex >=0) {
688 /* we do not need to demote if it is the last one. */
689 if (iCurrentIndex == map->numlayers-1)
690 return MS_FAILURE;
691
692 map->layerorder[iCurrentIndex] =
693 map->layerorder[iCurrentIndex+1];
694 map->layerorder[iCurrentIndex+1] = nLayerIndex;
695
696 return MS_SUCCESS;
697 }
698 }
699 msSetError(MS_CHILDERR, "Invalid index: %d", "msMoveLayerDown()",
700 nLayerIndex);
701 return MS_FAILURE;
702 }
703
704
705 /*
706 ** Set the array used for the drawing order. The array passed must contain
707 ** all the layer's index ordered by the drawing priority.
708 ** Ex : for 3 layers in the map file, if
709 ** panIndexes[0] = 2
710 ** panIndexes[1] = 0
711 ** panIndexes[2] = 1
712 ** will set the darwing order to layer 2, layer 0,
713 ** and then layer 1.
714 **
715 ** Note : It is assumed that the index panIndexes has the same number of
716 ** of elements as the number of layers in the map.
717 ** Return TRUE on success else FALSE.
718 */
msSetLayersdrawingOrder(mapObj * self,int * panIndexes)719 int msSetLayersdrawingOrder(mapObj *self, int *panIndexes)
720 {
721 int nElements = 0;
722 int i, j = 0;
723 int bFound = 0;
724
725 if (self && panIndexes) {
726 nElements = self->numlayers;
727 for (i=0; i<nElements; i++) {
728 bFound = 0;
729 for (j=0; j<nElements; j++) {
730 if (panIndexes[j] == i) {
731 bFound = 1;
732 break;
733 }
734 }
735 if (!bFound)
736 return 0;
737 }
738 /* -------------------------------------------------------------------- */
739 /* At this point the array is valid so update the layers order array.*/
740 /* -------------------------------------------------------------------- */
741 for (i=0; i<nElements; i++) {
742 self->layerorder[i] = panIndexes[i];
743 }
744 return 1;
745 }
746 return 0;
747 }
748
749
750 /* =========================================================================
751 msMapLoadOWSParameters
752
753 Function to support mapscript mapObj::loadOWSParameters
754 ========================================================================= */
755
msMapLoadOWSParameters(mapObj * map,cgiRequestObj * request,const char * wmtver)756 int msMapLoadOWSParameters(mapObj *map, cgiRequestObj *request,
757 const char *wmtver)
758 {
759 #ifdef USE_WMS_SVR
760 int version;
761 char *wms_exception_format = NULL;
762 const char *wms_request= NULL;
763 int result, i = 0;
764 owsRequestObj ows_request;
765
766 msOWSInitRequestObj(&ows_request);
767
768
769 version = msOWSParseVersionString(wmtver);
770 for(i=0; i<request->NumParams; i++) {
771 if (strcasecmp(request->ParamNames[i], "EXCEPTIONS") == 0)
772 wms_exception_format = request->ParamValues[i];
773 else if (strcasecmp(request->ParamNames[i], "REQUEST") == 0)
774 wms_request = request->ParamValues[i];
775
776 }
777
778 msOWSRequestLayersEnabled(map, "M", wms_request, &ows_request);
779
780 result = msWMSLoadGetMapParams(map, version, request->ParamNames,
781 request->ParamValues, request->NumParams, wms_exception_format,
782 wms_request, &ows_request);
783
784 msOWSClearRequestObj(&ows_request);
785
786 return result;
787
788 #else
789 msSetError(MS_WMSERR, "WMS server support is not available.",
790 "msMapLoadOWSParameters()");
791 return MS_FAILURE;
792 #endif
793 }
794
795