~ubuntu-branches/ubuntu/saucy/mapserver/saucy-security

« back to all changes in this revision

Viewing changes to mapproject.c

  • Committer: Package Import Robot
  • Author(s): Francesco Paolo Lovergine
  • Date: 2011-12-23 14:02:06 UTC
  • mfrom: (26.1.2 sid)
  • Revision ID: package-import@ubuntu.com-20111223140206-n3h9t2hsa8hyslmu
Tags: 6.0.1-2
Added missed stuff for libmapscript-perl.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/******************************************************************************
2
 
 * $Id: mapproject.c 8022 2008-11-19 01:27:37Z warmerdam $
 
2
 * $Id: mapproject.c 11376 2011-03-30 01:11:13Z dmorissette $
3
3
 *
4
4
 * Project:  MapServer
5
5
 * Purpose:  projectionObj / PROJ.4 interface.
31
31
#include "mapproject.h"
32
32
#include "mapthread.h"
33
33
#include <assert.h>
 
34
#include <sys/types.h>
 
35
#include <sys/stat.h>
34
36
 
35
 
MS_CVSID("$Id: mapproject.c 8022 2008-11-19 01:27:37Z warmerdam $")
 
37
MS_CVSID("$Id: mapproject.c 11376 2011-03-30 01:11:13Z dmorissette $")
36
38
 
37
39
#ifdef USE_PROJ
38
40
static int msTestNeedWrap( pointObj pt1, pointObj pt2, pointObj pt2_geo,
195
197
#endif /* def USE_PROJ */
196
198
 
197
199
/************************************************************************/
198
 
/*                           msProjectRect()                            */
199
 
/************************************************************************/
200
 
 
201
 
#define NUMBER_OF_SAMPLE_POINTS 100
202
 
 
203
 
int msProjectRect(projectionObj *in, projectionObj *out, rectObj *rect) 
204
 
{
205
 
#ifdef USE_PROJ
206
 
  pointObj prj_point;
207
 
  rectObj prj_rect;
208
 
  int     rect_initialized = MS_FALSE, failure=0;
209
 
  int     ix, iy;
210
 
 
211
 
  double dx, dy;
212
 
  double x, y;
213
 
 
214
 
  dx = (rect->maxx - rect->minx)/NUMBER_OF_SAMPLE_POINTS;
215
 
  dy = (rect->maxy - rect->miny)/NUMBER_OF_SAMPLE_POINTS;
216
 
 
217
 
  /* first ensure the top left corner is processed, even if the rect
218
 
     turns out to be degenerate. */
219
 
 
220
 
  prj_point.x = rect->minx;
221
 
  prj_point.y = rect->miny;
222
 
#ifdef USE_POINT_Z_M
223
 
  prj_point.z = 0.0;
224
 
  prj_point.m = 0.0;
225
 
#endif /* USE_POINT_Z_M */
226
 
 
227
 
  msProjectGrowRect(in,out,&prj_rect,&rect_initialized,&prj_point,
228
 
                    &failure);
229
 
 
230
 
  /* sample along top and bottom */
231
 
  if(dx > 0) {
232
 
    for(ix = 0; ix <= NUMBER_OF_SAMPLE_POINTS; ix++ )
233
 
    {
234
 
      x = rect->minx + ix * dx;
235
 
 
236
 
      prj_point.x = x;
237
 
      prj_point.y = rect->miny;
238
 
      msProjectGrowRect(in,out,&prj_rect,&rect_initialized,&prj_point,
239
 
                        &failure);
240
 
      
241
 
      prj_point.x = x;
242
 
      prj_point.y = rect->maxy;
243
 
      msProjectGrowRect(in,out,&prj_rect,&rect_initialized,&prj_point,
244
 
                        &failure);
245
 
    }
246
 
  }
247
 
 
248
 
  /* sample along left and right */
249
 
  if(dy > 0) {
250
 
    for(iy = 0; iy <= NUMBER_OF_SAMPLE_POINTS; iy++ )
251
 
    {
252
 
      y = rect->miny + iy * dy;
253
 
 
254
 
      prj_point.y = y;
255
 
      prj_point.x = rect->minx;    
256
 
      msProjectGrowRect(in,out,&prj_rect,&rect_initialized,&prj_point,
257
 
                        &failure);
258
 
      
259
 
      prj_point.x = rect->maxx;
260
 
      prj_point.y = y;
261
 
      msProjectGrowRect(in,out,&prj_rect,&rect_initialized,&prj_point,
262
 
                        &failure);
263
 
    }
264
 
  }
265
 
 
266
 
  /*
267
 
  ** If there have been any failures around the edges, then we had better
268
 
  ** try and fill in the interior to get a close bounds. 
269
 
  */
270
 
  if( failure > 0 )
271
 
  {
272
 
      failure = 0;
273
 
      for(ix = 0; ix <= NUMBER_OF_SAMPLE_POINTS; ix++ )
274
 
      {
275
 
          x = rect->minx + ix * dx;
276
 
 
277
 
          for(iy = 0; iy <= NUMBER_OF_SAMPLE_POINTS; iy++ )
278
 
          {
279
 
              y = rect->miny + iy * dy;
280
 
 
281
 
              prj_point.x = x;
282
 
              prj_point.y = y;
283
 
              msProjectGrowRect(in,out,&prj_rect,&rect_initialized,&prj_point,
284
 
                                &failure);
285
 
          }
286
 
      }
287
 
 
288
 
      if( !rect_initialized )
289
 
      {
290
 
          if( out == NULL || out->proj == NULL 
291
 
              || pj_is_latlong(in->proj) )
292
 
          {
293
 
              prj_rect.minx = -180;
294
 
              prj_rect.maxx = 180;
295
 
              prj_rect.miny = -90;
296
 
              prj_rect.maxy = 90;
297
 
          }
298
 
          else
299
 
          {
300
 
              prj_rect.minx = -22000000;
301
 
              prj_rect.maxx = 22000000;
302
 
              prj_rect.miny = -11000000;
303
 
              prj_rect.maxy = 11000000;
304
 
          }
305
 
 
306
 
          msDebug( "msProjectRect(): all points failed to reproject, trying to fall back to using world bounds ... hope this helps.\n" );
307
 
      }
308
 
      else
309
 
      {
310
 
          msDebug( "msProjectRect(): some points failed to reproject, doing internal sampling.\n" );
311
 
      }
312
 
  }
313
 
 
314
 
  rect->minx = prj_rect.minx;
315
 
  rect->miny = prj_rect.miny;
316
 
  rect->maxx = prj_rect.maxx;
317
 
  rect->maxy = prj_rect.maxy;
318
 
 
319
 
  if( !rect_initialized )
320
 
      return MS_FAILURE;
321
 
  else
322
 
      return(MS_SUCCESS);
323
 
#else
324
 
  msSetError(MS_PROJERR, "Projection support is not available.", "msProjectRect()");
325
 
  return(MS_FAILURE);
326
 
#endif
327
 
}
328
 
 
329
 
/************************************************************************/
330
200
/*                          msProjectSegment()                          */
331
201
/*                                                                      */
332
202
/*      Interpolate along a line segment for which one end              */
418
288
    int line_alloc = numpoints_in;
419
289
    int wrap_test;
420
290
 
421
 
    wrap_test = out->proj != NULL && pj_is_latlong(out->proj)
 
291
    wrap_test = out != NULL && out->proj != NULL && pj_is_latlong(out->proj)
422
292
        && !pj_is_latlong(in->proj);
423
293
 
424
294
    line->numpoints = 0;
583
453
        && (line_out->point[0].x != line_out->point[line_out->numpoints-1].x
584
454
            || line_out->point[0].y != line_out->point[line_out->numpoints-1].y) )
585
455
    {
586
 
        msAddPointToLine( line_out, line_out->point + 0 );
 
456
        /* make a copy because msAddPointToLine can realloc the array */
 
457
        pointObj sFirstPoint = line_out->point[0];
 
458
        msAddPointToLine( line_out, &sFirstPoint );
587
459
    }
588
460
 
589
461
    return(MS_SUCCESS);
697
569
}
698
570
 
699
571
/************************************************************************/
 
572
/*                           msProjectRectGrid()                        */
 
573
/************************************************************************/
 
574
 
 
575
#define NUMBER_OF_SAMPLE_POINTS 100
 
576
 
 
577
int msProjectRectGrid(projectionObj *in, projectionObj *out, rectObj *rect) 
 
578
{
 
579
#ifdef USE_PROJ
 
580
  pointObj prj_point;
 
581
  rectObj prj_rect;
 
582
  int     rect_initialized = MS_FALSE, failure=0;
 
583
  int     ix, iy;
 
584
 
 
585
  double dx, dy;
 
586
  double x, y;
 
587
 
 
588
  dx = (rect->maxx - rect->minx)/NUMBER_OF_SAMPLE_POINTS;
 
589
  dy = (rect->maxy - rect->miny)/NUMBER_OF_SAMPLE_POINTS;
 
590
 
 
591
  /* first ensure the top left corner is processed, even if the rect
 
592
     turns out to be degenerate. */
 
593
 
 
594
  prj_point.x = rect->minx;
 
595
  prj_point.y = rect->miny;
 
596
#ifdef USE_POINT_Z_M
 
597
  prj_point.z = 0.0;
 
598
  prj_point.m = 0.0;
 
599
#endif /* USE_POINT_Z_M */
 
600
 
 
601
  msProjectGrowRect(in,out,&prj_rect,&rect_initialized,&prj_point,
 
602
                    &failure);
 
603
 
 
604
  failure = 0;
 
605
  for(ix = 0; ix <= NUMBER_OF_SAMPLE_POINTS; ix++ )
 
606
  {
 
607
      x = rect->minx + ix * dx;
 
608
      
 
609
      for(iy = 0; iy <= NUMBER_OF_SAMPLE_POINTS; iy++ )
 
610
      {
 
611
          y = rect->miny + iy * dy;
 
612
          
 
613
          prj_point.x = x;
 
614
          prj_point.y = y;
 
615
          msProjectGrowRect(in,out,&prj_rect,&rect_initialized,&prj_point,
 
616
                            &failure);
 
617
      }
 
618
  }
 
619
  
 
620
  if( !rect_initialized )
 
621
  {
 
622
      if( out == NULL || out->proj == NULL 
 
623
          || pj_is_latlong(in->proj) )
 
624
      {
 
625
          prj_rect.minx = -180;
 
626
          prj_rect.maxx = 180;
 
627
          prj_rect.miny = -90;
 
628
          prj_rect.maxy = 90;
 
629
      }
 
630
      else
 
631
      {
 
632
          prj_rect.minx = -22000000;
 
633
          prj_rect.maxx = 22000000;
 
634
          prj_rect.miny = -11000000;
 
635
          prj_rect.maxy = 11000000;
 
636
      }
 
637
      
 
638
      msDebug( "msProjectRect(): all points failed to reproject, trying to fall back to using world bounds ... hope this helps.\n" );
 
639
  }
 
640
  else
 
641
  {
 
642
      msDebug( "msProjectRect(): some points failed to reproject, doing internal sampling.\n" );
 
643
  }
 
644
 
 
645
  rect->minx = prj_rect.minx;
 
646
  rect->miny = prj_rect.miny;
 
647
  rect->maxx = prj_rect.maxx;
 
648
  rect->maxy = prj_rect.maxy;
 
649
 
 
650
  if( !rect_initialized )
 
651
      return MS_FAILURE;
 
652
  else
 
653
      return(MS_SUCCESS);
 
654
#else
 
655
  msSetError(MS_PROJERR, "Projection support is not available.", "msProjectRect()");
 
656
  return(MS_FAILURE);
 
657
#endif
 
658
}
 
659
 
 
660
/************************************************************************/
 
661
/*                    msProjectRectTraditionalEdge()                    */
 
662
/************************************************************************/
 
663
#ifdef notdef
 
664
static int 
 
665
msProjectRectTraditionalEdge(projectionObj *in, projectionObj *out, 
 
666
                             rectObj *rect) 
 
667
{
 
668
#ifdef USE_PROJ
 
669
  pointObj prj_point;
 
670
  rectObj prj_rect;
 
671
  int     rect_initialized = MS_FALSE, failure=0;
 
672
  int     ix, iy;
 
673
 
 
674
  double dx, dy;
 
675
  double x, y;
 
676
 
 
677
  dx = (rect->maxx - rect->minx)/NUMBER_OF_SAMPLE_POINTS;
 
678
  dy = (rect->maxy - rect->miny)/NUMBER_OF_SAMPLE_POINTS;
 
679
 
 
680
  /* first ensure the top left corner is processed, even if the rect
 
681
     turns out to be degenerate. */
 
682
 
 
683
  prj_point.x = rect->minx;
 
684
  prj_point.y = rect->miny;
 
685
#ifdef USE_POINT_Z_M
 
686
  prj_point.z = 0.0;
 
687
  prj_point.m = 0.0;
 
688
#endif /* USE_POINT_Z_M */
 
689
 
 
690
  msProjectGrowRect(in,out,&prj_rect,&rect_initialized,&prj_point,
 
691
                    &failure);
 
692
 
 
693
  /* sample along top and bottom */
 
694
  if(dx > 0) {
 
695
    for(ix = 0; ix <= NUMBER_OF_SAMPLE_POINTS; ix++ )
 
696
    {
 
697
      x = rect->minx + ix * dx;
 
698
 
 
699
      prj_point.x = x;
 
700
      prj_point.y = rect->miny;
 
701
      msProjectGrowRect(in,out,&prj_rect,&rect_initialized,&prj_point,
 
702
                        &failure);
 
703
      
 
704
      prj_point.x = x;
 
705
      prj_point.y = rect->maxy;
 
706
      msProjectGrowRect(in,out,&prj_rect,&rect_initialized,&prj_point,
 
707
                        &failure);
 
708
    }
 
709
  }
 
710
 
 
711
  /* sample along left and right */
 
712
  if(dy > 0) {
 
713
    for(iy = 0; iy <= NUMBER_OF_SAMPLE_POINTS; iy++ )
 
714
    {
 
715
      y = rect->miny + iy * dy;
 
716
 
 
717
      prj_point.y = y;
 
718
      prj_point.x = rect->minx;    
 
719
      msProjectGrowRect(in,out,&prj_rect,&rect_initialized,&prj_point,
 
720
                        &failure);
 
721
      
 
722
      prj_point.x = rect->maxx;
 
723
      prj_point.y = y;
 
724
      msProjectGrowRect(in,out,&prj_rect,&rect_initialized,&prj_point,
 
725
                        &failure);
 
726
    }
 
727
  }
 
728
 
 
729
  /*
 
730
  ** If there have been any failures around the edges, then we had better
 
731
  ** try and fill in the interior to get a close bounds. 
 
732
  */
 
733
  if( failure > 0 )
 
734
      return msProjectRectGrid( in, out, rect );
 
735
 
 
736
  rect->minx = prj_rect.minx;
 
737
  rect->miny = prj_rect.miny;
 
738
  rect->maxx = prj_rect.maxx;
 
739
  rect->maxy = prj_rect.maxy;
 
740
 
 
741
  if( !rect_initialized )
 
742
      return MS_FAILURE;
 
743
  else
 
744
      return(MS_SUCCESS);
 
745
#else
 
746
  msSetError(MS_PROJERR, "Projection support is not available.", "msProjectRect()");
 
747
  return(MS_FAILURE);
 
748
#endif
 
749
}
 
750
#endif /* def notdef */
 
751
 
 
752
/************************************************************************/
 
753
/*                       msProjectRectAsPolygon()                       */
 
754
/************************************************************************/
 
755
 
 
756
static int 
 
757
msProjectRectAsPolygon(projectionObj *in, projectionObj *out, 
 
758
                       rectObj *rect) 
 
759
{
 
760
#ifdef USE_PROJ
 
761
  shapeObj polygonObj;
 
762
  lineObj  ring;
 
763
//  pointObj ringPoints[NUMBER_OF_SAMPLE_POINTS*4+4];
 
764
  pointObj *ringPoints;
 
765
  int     ix, iy;
 
766
 
 
767
  double dx, dy;
 
768
 
 
769
  ringPoints = (pointObj*) calloc(sizeof(pointObj),NUMBER_OF_SAMPLE_POINTS*4+4);
 
770
  ring.point = ringPoints;
 
771
  ring.numpoints = 0;
 
772
 
 
773
  msInitShape( &polygonObj );
 
774
  polygonObj.type = MS_SHAPE_POLYGON;
 
775
 
 
776
/* -------------------------------------------------------------------- */
 
777
/*      Build polygon as steps around the source rectangle.             */
 
778
/* -------------------------------------------------------------------- */
 
779
  dx = (rect->maxx - rect->minx)/NUMBER_OF_SAMPLE_POINTS;
 
780
  dy = (rect->maxy - rect->miny)/NUMBER_OF_SAMPLE_POINTS;
 
781
 
 
782
  /* sample along top */
 
783
  if(dx != 0) {
 
784
    for(ix = 0; ix <= NUMBER_OF_SAMPLE_POINTS; ix++ )
 
785
    {
 
786
      ringPoints[ring.numpoints].x = rect->minx + ix * dx;
 
787
      ringPoints[ring.numpoints++].y = rect->miny;
 
788
    }
 
789
  }
 
790
 
 
791
  /* sample on along right side */
 
792
  if(dy != 0) {
 
793
    for(iy = 1; iy <= NUMBER_OF_SAMPLE_POINTS; iy++ )
 
794
    {
 
795
      ringPoints[ring.numpoints].x = rect->maxx;
 
796
      ringPoints[ring.numpoints++].y = rect->miny + iy * dy;
 
797
    }
 
798
  }
 
799
 
 
800
  /* sample along bottom */
 
801
  if(dx != 0) {
 
802
    for(ix = NUMBER_OF_SAMPLE_POINTS-1; ix >= 0; ix-- )
 
803
    {
 
804
      ringPoints[ring.numpoints].x = rect->minx + ix * dx;
 
805
      ringPoints[ring.numpoints++].y = rect->maxy;
 
806
    }
 
807
  }
 
808
 
 
809
  /* sample on along left side */
 
810
  if(dy != 0) {
 
811
    for(iy = NUMBER_OF_SAMPLE_POINTS-1; iy >= 0; iy-- )
 
812
    {
 
813
      ringPoints[ring.numpoints].x = rect->minx;
 
814
      ringPoints[ring.numpoints++].y = rect->miny + iy * dy;
 
815
    }
 
816
  }
 
817
 
 
818
  msAddLineDirectly( &polygonObj, &ring );
 
819
 
 
820
/* -------------------------------------------------------------------- */
 
821
/*      Attempt to reproject.                                           */
 
822
/* -------------------------------------------------------------------- */
 
823
  msProjectShapeLine( in, out, &polygonObj, 0 );
 
824
 
 
825
  /* If no points reprojected, try a grid sampling */
 
826
  if( polygonObj.numlines == 0 || polygonObj.line[0].numpoints == 0 )
 
827
  {
 
828
      msFreeShape( &polygonObj );
 
829
      return msProjectRectGrid( in, out, rect );
 
830
  }
 
831
 
 
832
/* -------------------------------------------------------------------- */
 
833
/*      Collect bounds.                                                 */
 
834
/* -------------------------------------------------------------------- */
 
835
  rect->minx = rect->maxx = polygonObj.line[0].point[0].x;
 
836
  rect->miny = rect->maxy = polygonObj.line[0].point[0].y;
 
837
  
 
838
  for( ix = 1; ix < polygonObj.line[0].numpoints; ix++ )
 
839
  {
 
840
      pointObj  *pnt = polygonObj.line[0].point + ix;
 
841
 
 
842
      rect->minx = MS_MIN(rect->minx,pnt->x);
 
843
      rect->maxx = MS_MAX(rect->maxx,pnt->x);
 
844
      rect->miny = MS_MIN(rect->miny,pnt->y);
 
845
      rect->maxy = MS_MAX(rect->maxy,pnt->y);
 
846
  }
 
847
 
 
848
  msFreeShape( &polygonObj );
 
849
 
 
850
/* -------------------------------------------------------------------- */
 
851
/*      Special case to handle reprojection from "more than the         */
 
852
/*      whole world" projected coordinates that sometimes produce a     */
 
853
/*      region greater than 360 degrees wide due to various wrapping    */
 
854
/*      logic.                                                          */
 
855
/* -------------------------------------------------------------------- */
 
856
  if( out && pj_is_latlong(out->proj) && in && !pj_is_latlong(in->proj) 
 
857
      && rect->maxx - rect->minx > 360.0 )
 
858
  {
 
859
      rect->maxx = 180;
 
860
      rect->minx = -180;
 
861
  }
 
862
 
 
863
  return MS_SUCCESS;
 
864
#else
 
865
  msSetError(MS_PROJERR, "Projection support is not available.", "msProjectRect()");
 
866
  return(MS_FAILURE);
 
867
#endif
 
868
}
 
869
 
 
870
/************************************************************************/
 
871
/*                           msProjectRect()                            */
 
872
/************************************************************************/
 
873
 
 
874
int msProjectRect(projectionObj *in, projectionObj *out, rectObj *rect) 
 
875
{
 
876
#ifdef notdef
 
877
    return msProjectRectTraditionalEdge( in, out, rect );
 
878
#else
 
879
    return msProjectRectAsPolygon( in, out, rect );
 
880
#endif    
 
881
}
 
882
 
 
883
/************************************************************************/
700
884
/*                        msProjectionsDiffer()                         */
701
885
/************************************************************************/
702
886
 
871
1055
/************************************************************************/
872
1056
/*                           msSetPROJ_LIB()                            */
873
1057
/************************************************************************/
874
 
void msSetPROJ_LIB( const char *proj_lib )
 
1058
void msSetPROJ_LIB( const char *proj_lib, const char *pszRelToPath )
875
1059
 
876
1060
{
877
1061
#ifdef USE_PROJ
878
1062
    static int finder_installed = 0;
 
1063
    char *extended_path = NULL;
 
1064
 
 
1065
    /* Handle relative path if applicable */
 
1066
    if( proj_lib && pszRelToPath
 
1067
        && proj_lib[0] != '/'
 
1068
        && proj_lib[0] != '\\'
 
1069
        && !(proj_lib[0] != '\0' && proj_lib[1] == ':') )
 
1070
    {
 
1071
        struct stat stat_buf;
 
1072
        extended_path = (char*) msSmallMalloc(strlen(pszRelToPath)
 
1073
                                              + strlen(proj_lib) + 10);
 
1074
        sprintf( extended_path, "%s/%s", pszRelToPath, proj_lib );
 
1075
 
 
1076
#ifndef S_ISDIR
 
1077
#  define S_ISDIR(x) ((x) & S_IFDIR)
 
1078
#endif            
 
1079
            
 
1080
        if( stat( extended_path, &stat_buf ) == 0 
 
1081
            && S_ISDIR(stat_buf.st_mode) )
 
1082
            proj_lib = extended_path;
 
1083
    }
 
1084
 
879
1085
 
880
1086
    msAcquireLock( TLOCK_PROJ );
881
1087
 
900
1106
    }
901
1107
 
902
1108
    if( proj_lib != NULL )
903
 
        ms_proj_lib = strdup( proj_lib );
 
1109
        ms_proj_lib = msStrdup( proj_lib );
904
1110
    
905
1111
    msReleaseLock( TLOCK_PROJ );
 
1112
 
 
1113
    if ( extended_path )
 
1114
        msFree( extended_path );
906
1115
#endif
907
1116
}
908
1117