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

« back to all changes in this revision

Viewing changes to mapprimitive.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: mapprimitive.c 10379 2010-07-22 08:23:12Z tbonfort $
 
2
 * $Id: mapprimitive.c 11636 2011-05-03 16:10:44Z assefa $
3
3
 *
4
4
 * Project:  MapServer
5
5
 * Purpose:  Implementations for rectObj, pointObj, lineObj, shapeObj, etc.
32
32
#include <assert.h>
33
33
#include <locale.h>
34
34
 
35
 
MS_CVSID("$Id: mapprimitive.c 10379 2010-07-22 08:23:12Z tbonfort $")
 
35
MS_CVSID("$Id: mapprimitive.c 11636 2011-05-03 16:10:44Z assefa $")
36
36
 
37
37
typedef enum {CLIP_LEFT, CLIP_MIDDLE, CLIP_RIGHT} CLIP_STATE;
38
38
 
74
74
char *msShapeToWKT(shapeObj *shape)
75
75
{
76
76
#ifdef USE_GEOS
77
 
  return msGEOSShapeToWKT(shape);
 
77
  char* pszGEOSStr;
 
78
  char* pszStr;
 
79
  pszGEOSStr = msGEOSShapeToWKT(shape);
 
80
  pszStr = (pszGEOSStr) ? msStrdup(pszGEOSStr) : NULL;
 
81
  msGEOSFreeWKT(pszGEOSStr);
 
82
  return pszStr;
78
83
#elif defined(USE_OGR)
79
84
  return msOGRShapeToWKT(shape);
80
85
#else
104
109
 
105
110
  /* bookkeeping component */
106
111
  shape->classindex = 0; /* default class */
107
 
  shape->tileindex = shape->index = -1;
 
112
  shape->tileindex = shape->index = shape->resultindex = -1;
 
113
 
 
114
  shape->scratch = MS_FALSE; /* not a temporary/scratch shape */
108
115
}
109
116
 
110
117
int msCopyShape(shapeObj *from, shapeObj *to) {
122
129
  to->bounds.maxx = from->bounds.maxx;
123
130
  to->bounds.maxy = from->bounds.maxy;
124
131
 
125
 
  if(from->text) to->text = strdup(from->text);
 
132
  if(from->text) to->text = msStrdup(from->text);
126
133
 
127
134
  to->classindex = from->classindex;
128
135
  to->index = from->index;
129
136
  to->tileindex = from->tileindex;
 
137
  to->resultindex = from->resultindex;
130
138
 
131
139
  if(from->values) {    
132
 
    to->values = (char **)malloc(sizeof(char *)*from->numvalues);
 
140
    to->values = (char **)msSmallMalloc(sizeof(char *)*from->numvalues);
133
141
    for(i=0; i<from->numvalues; i++)
134
 
      to->values[i] = strdup(from->values[i]);
 
142
      to->values[i] = msStrdup(from->values[i]);
135
143
    to->numvalues = from->numvalues;
136
144
  }
137
145
 
138
146
  to->geometry = NULL; /* GEOS code will build automatically if necessary */
 
147
  to->scratch = from->scratch;
139
148
 
140
149
  return(0);
141
150
}
148
157
 
149
158
  for (c= 0; c < shape->numlines; c++)
150
159
    free(shape->line[c].point);
151
 
  free(shape->line);
152
160
 
 
161
  if (shape->line) free(shape->line);
153
162
  if(shape->values) msFreeCharArray(shape->values, shape->numvalues);
154
163
  if(shape->text) free(shape->text);
155
164
  
209
218
}
210
219
 
211
220
/* checks to see if ring r is an outer ring of shape */
212
 
static int isOuterRing(shapeObj *shape, int r) 
 
221
int msIsOuterRing(shapeObj *shape, int r) 
213
222
{
214
223
  int i, status=MS_TRUE; 
215
224
  int result1, result2;
248
257
  int *list;
249
258
 
250
259
  list = (int *)malloc(sizeof(int)*shape->numlines);
251
 
  if(!list) return(NULL);
 
260
  MS_CHECK_ALLOC(list, sizeof(int)*shape->numlines, NULL);
252
261
 
253
262
  for(i=0; i<shape->numlines; i++)
254
 
    list[i] = isOuterRing(shape, i);
 
263
    list[i] = msIsOuterRing(shape, i);
255
264
 
256
265
  return(list);
257
266
}
265
274
  int *list;
266
275
 
267
276
  list = (int *)malloc(sizeof(int)*shape->numlines);
268
 
  if(!list) return(NULL);
 
277
  MS_CHECK_ALLOC(list, sizeof(int)*shape->numlines, NULL);
269
278
 
270
279
  for(i=0; i<shape->numlines; i++) { /* test all rings against the ring */
271
280
 
293
302
{
294
303
  line->numpoints += 1;
295
304
    
296
 
  line->point = (pointObj *) realloc(line->point, sizeof(pointObj) * line->numpoints);
 
305
  line->point = (pointObj *) msSmallRealloc(line->point, sizeof(pointObj) * line->numpoints);
297
306
  line->point[line->numpoints-1] = *point;
298
307
 
299
308
  return MS_SUCCESS;
305
314
 
306
315
  lineCopy.numpoints = new_line->numpoints;
307
316
  lineCopy.point = (pointObj *) malloc(new_line->numpoints*sizeof(pointObj));
308
 
  if( lineCopy.point == NULL ) {
309
 
    msSetError(MS_MEMERR, NULL, "msAddLine()");
310
 
    return(MS_FAILURE);
311
 
  }
 
317
  MS_CHECK_ALLOC(lineCopy.point, new_line->numpoints*sizeof(pointObj), MS_FAILURE);
312
318
    
313
319
  memcpy( lineCopy.point, new_line->point, sizeof(pointObj) * new_line->numpoints );
314
320
 
323
329
{
324
330
  int c;
325
331
 
326
 
  if( p->numlines == 0 )
327
 
    p->line = (lineObj *) malloc(sizeof(lineObj));
328
 
  else
329
 
    p->line = (lineObj *) realloc(p->line, (p->numlines+1)*sizeof(lineObj));
330
 
 
331
 
  if(!p->line) {
332
 
    msSetError(MS_MEMERR, NULL, "msAddLineDirectly()");
333
 
    return(MS_FAILURE);
 
332
  if( p->numlines == 0 ) {
 
333
      p->line = (lineObj *) malloc(sizeof(lineObj));
 
334
      MS_CHECK_ALLOC(p->line, sizeof(lineObj), MS_FAILURE);
 
335
  }
 
336
  else {
 
337
      p->line = (lineObj *) realloc(p->line, (p->numlines+1)*sizeof(lineObj));
 
338
      MS_CHECK_ALLOC(p->line, (p->numlines+1)*sizeof(lineObj), MS_FAILURE);
334
339
  }
335
340
 
336
341
  /* Copy the new line onto the end of the extended line array */
360
365
{
361
366
  lineObj line={0,NULL};
362
367
 
363
 
  line.point = (pointObj *)malloc(sizeof(pointObj)*5);
 
368
  line.point = (pointObj *)msSmallMalloc(sizeof(pointObj)*5);
364
369
  
365
370
  line.point[0].x = rect.minx;
366
371
  line.point[0].y = rect.miny;
491
496
 
492
497
  for(i=0; i<shape->numlines; i++) {
493
498
 
494
 
    line.point = (pointObj *)malloc(sizeof(pointObj)*shape->line[i].numpoints);
 
499
    line.point = (pointObj *)msSmallMalloc(sizeof(pointObj)*shape->line[i].numpoints);
495
500
    line.numpoints = 0;
496
501
 
497
502
    x1 = shape->line[i].point[0].x;
571
576
 
572
577
  for(j=0; j<shape->numlines; j++) {
573
578
 
574
 
    line.point = (pointObj *)malloc(sizeof(pointObj)*2*shape->line[j].numpoints+1); /* worst case scenario, +1 allows us to duplicate the 1st and last point */
 
579
    line.point = (pointObj *)msSmallMalloc(sizeof(pointObj)*2*shape->line[j].numpoints+1); /* worst case scenario, +1 allows us to duplicate the 1st and last point */
575
580
    line.numpoints = 0;
576
581
 
577
582
    for (i = 0; i < shape->line[j].numpoints-1; i++) {
820
825
  return;
821
826
}
822
827
 
823
 
/*
824
 
** converts from map coordinates to image coordinates
825
 
*/
826
 
void msTransformShapeToPixel(shapeObj *shape, rectObj extent, double cellsize)
827
 
{
828
 
  int i,j,k; /* loop counters */
829
 
  double inv_cs = 1.0 / cellsize; /* invert and multiply much faster */
830
 
 
831
 
  if(shape->numlines == 0) return; /* nothing to transform */
832
 
 
833
 
  if(shape->type == MS_SHAPE_LINE || shape->type == MS_SHAPE_POLYGON) { /* remove duplicate vertices */
834
 
    for(i=0; i<shape->numlines; i++) { /* for each part */
835
 
      shape->line[i].point[0].x = MS_MAP2IMAGE_X_IC(shape->line[i].point[0].x, extent.minx, inv_cs);
836
 
      shape->line[i].point[0].y = MS_MAP2IMAGE_Y_IC(shape->line[i].point[0].y, extent.maxy, inv_cs);
837
 
      for(j=1, k=1; j < shape->line[i].numpoints; j++ ) {
838
 
        shape->line[i].point[k].x = MS_MAP2IMAGE_X_IC(shape->line[i].point[j].x, extent.minx, inv_cs);
839
 
        shape->line[i].point[k].y = MS_MAP2IMAGE_Y_IC(shape->line[i].point[j].y, extent.maxy, inv_cs);
840
 
        if(shape->line[i].point[k].x!=shape->line[i].point[k-1].x || shape->line[i].point[k].y!=shape->line[i].point[k-1].y)
841
 
          k++;
842
 
      }
843
 
      shape->line[i].numpoints = k; /* save actual number kept */
844
 
    }
845
 
  } else { /* points or untyped shapes */
846
 
    for(i=0; i<shape->numlines; i++) { /* for each part */
847
 
      for(j=1; j < shape->line[i].numpoints; j++ ) {
848
 
        shape->line[i].point[j].x = MS_MAP2IMAGE_X_IC(shape->line[i].point[j].x, extent.minx, inv_cs);
849
 
        shape->line[i].point[j].y = MS_MAP2IMAGE_Y_IC(shape->line[i].point[j].y, extent.maxy, inv_cs);
850
 
      }
851
 
    }
852
 
  }
853
 
}
 
828
void msTransformShapeSimplify(shapeObj *shape, rectObj extent, double cellsize)
 
829
{
 
830
    int i,j,k,beforelast; /* loop counters */
 
831
    double dx,dy;
 
832
    pointObj *point;
 
833
    double inv_cs = 1.0 / cellsize; /* invert and multiply much faster */
 
834
    if(shape->numlines == 0) return; /* nothing to transform */
 
835
 
 
836
    if(shape->type == MS_SHAPE_LINE) {
 
837
        /*
 
838
         * loop through the shape's lines, and do naive simplification
 
839
         * to discard the points that are too close to one another.
 
840
         * currently the threshold is to discard points if they fall
 
841
         * less than a pixel away from their predecessor.
 
842
         * the simplified line is guaranteed to contain at 
 
843
         * least its first and last point
 
844
         */
 
845
        for(i=0; i<shape->numlines; i++) { /* for each part */
 
846
            if(shape->line[i].numpoints<2) {
 
847
                shape->line[i].numpoints=0;
 
848
                continue; /*skip degenerate lines*/
 
849
            }
 
850
            point=shape->line[i].point;
 
851
            /*always keep first point*/
 
852
            point[0].x = MS_MAP2IMAGE_X_IC_DBL(point[0].x, extent.minx, inv_cs);
 
853
            point[0].y = MS_MAP2IMAGE_Y_IC_DBL(point[0].y, extent.maxy, inv_cs);
 
854
            beforelast=shape->line[i].numpoints-1;
 
855
            for(j=1,k=1; j < beforelast; j++ ) { /*loop from second point to first-before-last point*/
 
856
                point[k].x = MS_MAP2IMAGE_X_IC_DBL(point[j].x, extent.minx, inv_cs);
 
857
                point[k].y = MS_MAP2IMAGE_Y_IC_DBL(point[j].y, extent.maxy, inv_cs);
 
858
                dx=(point[k].x-point[k-1].x);
 
859
                dy=(point[k].y-point[k-1].y);
 
860
                if(dx*dx+dy*dy>1)
 
861
                    k++;
 
862
            }
 
863
            /*try to keep last point*/
 
864
            point[k].x = MS_MAP2IMAGE_X_IC_DBL(point[j].x, extent.minx, inv_cs);
 
865
            point[k].y = MS_MAP2IMAGE_Y_IC_DBL(point[j].y, extent.maxy, inv_cs);
 
866
            /*discard last point if equal to the one before it*/
 
867
            if(point[k].x!=point[k-1].x || point[k].y!=point[k-1].y) {
 
868
                shape->line[i].numpoints=k+1;
 
869
            } else {
 
870
                shape->line[i].numpoints=k;
 
871
            }
 
872
            //skip degenerate line once more
 
873
            if(shape->line[i].numpoints<2)
 
874
               shape->line[i].numpoints=0;
 
875
        }
 
876
    }
 
877
    else if(shape->type == MS_SHAPE_POLYGON) {
 
878
        /*
 
879
         * loop through the shape's lines, and do naive simplification
 
880
         * to discard the points that are too close to one another.
 
881
         * currently the threshold is to discard points if they fall
 
882
         * less than a pixel away from their predecessor.
 
883
         * the simplified polygon is guaranteed to contain at 
 
884
         * least its first, second and last point
 
885
         */
 
886
        for(i=0; i<shape->numlines; i++) { /* for each part */
 
887
            if(shape->line[i].numpoints<3) {
 
888
                shape->line[i].numpoints=0;
 
889
                continue; /*skip degenerate lines*/
 
890
            }
 
891
            point=shape->line[i].point;
 
892
            /*always keep first and second point*/
 
893
            point[0].x = MS_MAP2IMAGE_X_IC_DBL(point[0].x, extent.minx, inv_cs);
 
894
            point[0].y = MS_MAP2IMAGE_Y_IC_DBL(point[0].y, extent.maxy, inv_cs);
 
895
            point[1].x = MS_MAP2IMAGE_X_IC_DBL(point[1].x, extent.minx, inv_cs);
 
896
            point[1].y = MS_MAP2IMAGE_Y_IC_DBL(point[1].y, extent.maxy, inv_cs);         
 
897
            beforelast=shape->line[i].numpoints-1;
 
898
            for(j=2,k=2; j < beforelast; j++ ) { /*loop from second point to first-before-last point*/
 
899
                point[k].x = MS_MAP2IMAGE_X_IC_DBL(point[j].x, extent.minx, inv_cs);
 
900
                point[k].y = MS_MAP2IMAGE_Y_IC_DBL(point[j].y, extent.maxy, inv_cs);
 
901
                dx=(point[k].x-point[k-1].x);
 
902
                dy=(point[k].y-point[k-1].y);
 
903
                if(dx*dx+dy*dy>1)
 
904
                    k++;
 
905
            }
 
906
            /*always keep last point*/
 
907
            point[k].x = MS_MAP2IMAGE_X_IC_DBL(point[j].x, extent.minx, inv_cs);
 
908
            point[k].y = MS_MAP2IMAGE_Y_IC_DBL(point[j].y, extent.maxy, inv_cs);
 
909
            shape->line[i].numpoints=k+1;
 
910
        }
 
911
    }
 
912
    else { /* only for untyped shapes, as point layers don't go through this function */
 
913
        for(i=0; i<shape->numlines; i++) {
 
914
            point=shape->line[i].point;
 
915
            for(j=0;j<shape->line[i].numpoints;j++) {
 
916
                point[j].x = MS_MAP2IMAGE_X_IC_DBL(point[j].x, extent.minx, inv_cs);
 
917
                point[j].y = MS_MAP2IMAGE_Y_IC_DBL(point[j].y, extent.maxy, inv_cs);
 
918
            }
 
919
        }
 
920
    }
 
921
}
 
922
 
 
923
/**
 
924
 * Generic function to transorm the shape coordinates to output coordinates
 
925
 */
 
926
void  msTransformShape(shapeObj *shape, rectObj extent, double cellsize, imageObj *image)
 
927
{
 
928
        if (image != NULL && MS_RENDERER_PLUGIN(image->format)) {
 
929
           rendererVTableObj *renderer = MS_IMAGE_RENDERER(image);
 
930
           if(renderer->transform_mode == MS_TRANSFORM_SNAPTOGRID) {
 
931
              msTransformShapeToPixelSnapToGrid(shape, extent, cellsize, renderer->approximation_scale);
 
932
           } else if(renderer->transform_mode == MS_TRANSFORM_SIMPLIFY) {
 
933
         msTransformShapeSimplify(shape, extent, cellsize);
 
934
      } else if(renderer->transform_mode == MS_TRANSFORM_ROUND) {
 
935
              msTransformShapeToPixelRound(shape, extent, cellsize);
 
936
      } else if(renderer->transform_mode == MS_TRANSFORM_FULLRESOLUTION) {
 
937
              msTransformShapeToPixelDoublePrecision(shape,extent,cellsize);
 
938
           } else if(renderer->transform_mode == MS_TRANSFORM_NONE) {
 
939
         /* nothing to do */
 
940
         return;
 
941
      } 
 
942
           /* unknown, do nothing */
 
943
                return;
 
944
        }
 
945
   msTransformShapeToPixelRound(shape, extent, cellsize);
 
946
}
 
947
 
 
948
void msTransformShapeToPixelSnapToGrid(shapeObj *shape, rectObj extent, double cellsize, double grid_resolution)
 
949
{
 
950
   int i,j,k; /* loop counters */
 
951
   double inv_cs;
 
952
   if(shape->numlines == 0) return;
 
953
   inv_cs = 1.0 / cellsize; /* invert and multiply much faster */
 
954
   
 
955
   
 
956
   if(shape->type == MS_SHAPE_LINE || shape->type == MS_SHAPE_POLYGON) { /* remove duplicate vertices */
 
957
      for(i=0; i<shape->numlines; i++) { /* for each part */
 
958
         int snap = 1;
 
959
         double x0,y0,x1,y1,x2,y2;
 
960
         /*do a quick heuristic: will we risk having a degenerate shape*/
 
961
         if(shape->type == MS_SHAPE_LINE) {
 
962
            /*a line is degenerate if it has a single pixel. we check that the first and last pixel are different*/
 
963
            x0 = MS_MAP2IMAGE_X_IC_SNAP(shape->line[i].point[0].x, extent.minx, inv_cs, grid_resolution);
 
964
            y0 = MS_MAP2IMAGE_Y_IC_SNAP(shape->line[i].point[0].y, extent.maxy, inv_cs, grid_resolution);
 
965
            x1 = MS_MAP2IMAGE_X_IC_SNAP(shape->line[i].point[shape->line[i].numpoints-1].x, extent.minx, inv_cs, grid_resolution);
 
966
            y1 = MS_MAP2IMAGE_Y_IC_SNAP(shape->line[i].point[shape->line[i].numpoints-1].y, extent.maxy, inv_cs, grid_resolution);
 
967
            if(x0 == x1 && y0 == y1) {
 
968
               snap = 0;
 
969
            }
 
970
         } else if(shape->type == MS_SHAPE_POLYGON) {
 
971
            x0 = MS_MAP2IMAGE_X_IC_SNAP(shape->line[i].point[0].x, extent.minx, inv_cs, grid_resolution);
 
972
            y0 = MS_MAP2IMAGE_Y_IC_SNAP(shape->line[i].point[0].y, extent.maxy, inv_cs, grid_resolution);
 
973
            x1 = MS_MAP2IMAGE_X_IC_SNAP(shape->line[i].point[shape->line[i].numpoints/3].x, extent.minx, inv_cs, grid_resolution);
 
974
            y1 = MS_MAP2IMAGE_Y_IC_SNAP(shape->line[i].point[shape->line[i].numpoints/3].y, extent.maxy, inv_cs, grid_resolution);
 
975
            x2 = MS_MAP2IMAGE_X_IC_SNAP(shape->line[i].point[shape->line[i].numpoints/3*2].x, extent.minx, inv_cs, grid_resolution);
 
976
            y2 = MS_MAP2IMAGE_Y_IC_SNAP(shape->line[i].point[shape->line[i].numpoints/3*2].y, extent.maxy, inv_cs, grid_resolution);
 
977
            if((x0 == x1 && y0 == y1) ||
 
978
                  (x0 == x2 && y0 == y2) ||
 
979
                  (x1 == x2 && y1 == y2)) {
 
980
               snap = 0;
 
981
            }
 
982
         }
 
983
         if(snap) {
 
984
               shape->line[i].point[0].x = x0;
 
985
               shape->line[i].point[0].y = y0;
 
986
               for(j=1, k=1; j < shape->line[i].numpoints; j++ ) {
 
987
                  shape->line[i].point[k].x = MS_MAP2IMAGE_X_IC_SNAP(shape->line[i].point[j].x, extent.minx, inv_cs, grid_resolution);
 
988
                  shape->line[i].point[k].y = MS_MAP2IMAGE_Y_IC_SNAP(shape->line[i].point[j].y, extent.maxy, inv_cs, grid_resolution);
 
989
                  if(shape->line[i].point[k].x!=shape->line[i].point[k-1].x || shape->line[i].point[k].y!=shape->line[i].point[k-1].y)
 
990
                     k++;
 
991
               }
 
992
               shape->line[i].numpoints=k;
 
993
         } else {
 
994
            if(shape->type == MS_SHAPE_LINE) {
 
995
               shape->line[i].point[0].x = MS_MAP2IMAGE_X_IC_DBL(shape->line[i].point[0].x, extent.minx, inv_cs);
 
996
               shape->line[i].point[0].y = MS_MAP2IMAGE_Y_IC_DBL(shape->line[i].point[0].y, extent.maxy, inv_cs);
 
997
               shape->line[i].point[1].x = MS_MAP2IMAGE_X_IC_DBL(shape->line[i].point[shape->line[i].numpoints-1].x, extent.minx, inv_cs);
 
998
               shape->line[i].point[1].y = MS_MAP2IMAGE_Y_IC_DBL(shape->line[i].point[shape->line[i].numpoints-1].y, extent.maxy, inv_cs);      
 
999
               shape->line[i].numpoints = 2;
 
1000
            } else {
 
1001
               for(j=0; j < shape->line[i].numpoints; j++ ) {
 
1002
                  shape->line[i].point[j].x = MS_MAP2IMAGE_X_IC_DBL(shape->line[i].point[j].x, extent.minx, inv_cs);
 
1003
                  shape->line[i].point[j].y = MS_MAP2IMAGE_Y_IC_DBL(shape->line[i].point[j].y, extent.maxy, inv_cs);
 
1004
               }
 
1005
            }
 
1006
         }
 
1007
      }
 
1008
   } else { /* points or untyped shapes */
 
1009
      for(i=0; i<shape->numlines; i++) { /* for each part */
 
1010
         for(j=1; j < shape->line[i].numpoints; j++ ) {
 
1011
            shape->line[i].point[j].x = MS_MAP2IMAGE_X_IC_DBL(shape->line[i].point[j].x, extent.minx, inv_cs);
 
1012
            shape->line[i].point[j].y = MS_MAP2IMAGE_Y_IC_DBL(shape->line[i].point[j].y, extent.maxy, inv_cs);
 
1013
         }
 
1014
      }
 
1015
   }
 
1016
 
 
1017
}
 
1018
 
 
1019
void msTransformShapeToPixelRound(shapeObj *shape, rectObj extent, double cellsize)
 
1020
{
 
1021
   int i,j,k; /* loop counters */
 
1022
   double inv_cs;
 
1023
   if(shape->numlines == 0) return;
 
1024
   inv_cs = 1.0 / cellsize; /* invert and multiply much faster */
 
1025
   if(shape->type == MS_SHAPE_LINE || shape->type == MS_SHAPE_POLYGON) { /* remove duplicate vertices */
 
1026
      for(i=0; i<shape->numlines; i++) { /* for each part */
 
1027
         shape->line[i].point[0].x = MS_MAP2IMAGE_X_IC(shape->line[i].point[0].x, extent.minx, inv_cs);;
 
1028
         shape->line[i].point[0].y = MS_MAP2IMAGE_Y_IC(shape->line[i].point[0].y, extent.maxy, inv_cs);
 
1029
         for(j=1, k=1; j < shape->line[i].numpoints; j++ ) {
 
1030
            shape->line[i].point[k].x = MS_MAP2IMAGE_X_IC(shape->line[i].point[j].x, extent.minx, inv_cs);
 
1031
            shape->line[i].point[k].y = MS_MAP2IMAGE_Y_IC(shape->line[i].point[j].y, extent.maxy, inv_cs);
 
1032
            if(shape->line[i].point[k].x!=shape->line[i].point[k-1].x || shape->line[i].point[k].y!=shape->line[i].point[k-1].y)
 
1033
               k++;
 
1034
         }
 
1035
         shape->line[i].numpoints=k;
 
1036
      }
 
1037
   } else { /* points or untyped shapes */
 
1038
      for(i=0; i<shape->numlines; i++) { /* for each part */
 
1039
         for(j=1; j < shape->line[i].numpoints; j++ ) {
 
1040
            shape->line[i].point[j].x = MS_MAP2IMAGE_X_IC(shape->line[i].point[j].x, extent.minx, inv_cs);
 
1041
            shape->line[i].point[j].y = MS_MAP2IMAGE_Y_IC(shape->line[i].point[j].y, extent.maxy, inv_cs);
 
1042
         }
 
1043
      }
 
1044
   }
 
1045
 
 
1046
}
 
1047
 
 
1048
void msTransformShapeToPixelDoublePrecision(shapeObj *shape, rectObj extent, double cellsize)
 
1049
{
 
1050
   int i,j; /* loop counters */
 
1051
   double inv_cs = 1.0 / cellsize; /* invert and multiply much faster */
 
1052
   for(i=0; i<shape->numlines; i++) {
 
1053
      for(j=0;j<shape->line[i].numpoints;j++) {
 
1054
         shape->line[i].point[j].x = MS_MAP2IMAGE_X_IC_DBL(shape->line[i].point[j].x, extent.minx, inv_cs);
 
1055
         shape->line[i].point[j].y = MS_MAP2IMAGE_Y_IC_DBL(shape->line[i].point[j].y, extent.maxy, inv_cs);
 
1056
      }
 
1057
   }
 
1058
}
 
1059
 
 
1060
 
854
1061
 
855
1062
/*
856
1063
** Converts from map coordinates to image coordinates
915
1122
 
916
1123
  for (i = 0; i < p->numlines; i++) {
917
1124
 
918
 
    inside.point = (pointObj *)malloc(sizeof(pointObj)*p->line[i].numpoints);
919
 
    outside.point = (pointObj *)malloc(sizeof(pointObj)*p->line[i].numpoints);
 
1125
    inside.point = (pointObj *)msSmallMalloc(sizeof(pointObj)*p->line[i].numpoints);
 
1126
    outside.point = (pointObj *)msSmallMalloc(sizeof(pointObj)*p->line[i].numpoints);
920
1127
    inside.numpoints = outside.numpoints = p->line[i].numpoints;    
921
1128
 
922
 
    angle = asin(MS_ABS(p->line[i].point[1].x - p->line[i].point[0].x)/sqrt((pow((p->line[i].point[1].x - p->line[i].point[0].x),2.0) + pow((p->line[i].point[1].y - p->line[i].point[0].y),2.0))));
 
1129
    angle = asin(MS_ABS(p->line[i].point[1].x - p->line[i].point[0].x)/sqrt((((p->line[i].point[1].x - p->line[i].point[0].x)*(p->line[i].point[1].x - p->line[i].point[0].x)) + ((p->line[i].point[1].y - p->line[i].point[0].y)*(p->line[i].point[1].y - p->line[i].point[0].y)))));
923
1130
    if(p->line[i].point[0].x < p->line[i].point[1].x)
924
1131
      dy = sin(angle) * (w/2);
925
1132
    else
941
1148
 
942
1149
    for(j=2; j<p->line[i].numpoints; j++) {
943
1150
 
944
 
      angle = asin(MS_ABS(p->line[i].point[j].x - p->line[i].point[j-1].x)/sqrt((pow((p->line[i].point[j].x - p->line[i].point[j-1].x),2.0) + pow((p->line[i].point[j].y - p->line[i].point[j-1].y),2.0))));
 
1151
      angle = asin(MS_ABS(p->line[i].point[j].x - p->line[i].point[j-1].x)/sqrt((((p->line[i].point[j].x - p->line[i].point[j-1].x)*(p->line[i].point[j].x - p->line[i].point[j-1].x)) + ((p->line[i].point[j].y - p->line[i].point[j-1].y)*(p->line[i].point[j].y - p->line[i].point[j-1].y)))));
945
1152
      if(p->line[i].point[j-1].x < p->line[i].point[j].x)
946
1153
        dy = sin(angle) * (w/2);
947
1154
      else
993
1200
  double area=0;
994
1201
 
995
1202
  for(i=0; i<p->numlines; i++) {
996
 
    if(isOuterRing(p, i))
 
1203
    if(msIsOuterRing(p, i))
997
1204
      area += getRingArea(&(p->line[i]));
998
1205
    else
999
1206
      area -= getRingArea(&(p->line[i])); /* hole */
1064
1271
  return(MS_SUCCESS);
1065
1272
}
1066
1273
 
1067
 
#define NUM_SCANLINES 5
1068
 
 
1069
1274
/*
1070
1275
** Find a label point in a polygon.
1071
1276
*/
1134
1339
  n=0;
1135
1340
  for(j=0; j<p->numlines; j++) /* count total number of points */
1136
1341
    n += p->line[j].numpoints;
1137
 
  if(!(intersect = (double *) calloc(n, sizeof(double)))) {
1138
 
    msSetError(MS_MEMERR, "Allocation of intersection array failed.", "msPolygonLabelPoint()");
1139
 
    return MS_FAILURE;
1140
 
  }
 
1342
  intersect = (double *) calloc(n, sizeof(double));
 
1343
  MS_CHECK_ALLOC(intersect, n*sizeof(double), MS_FAILURE);
 
1344
  
1141
1345
 
1142
1346
  if(MS_ABS((int)lp->x - (int)cp.x) > MS_ABS((int)lp->y - (int)cp.y)) { /* center horizontally, fix y */
1143
1347
 
1315
1519
  int i, j, temp_segment_index;
1316
1520
  double segment_length, max_segment_length;
1317
1521
 
1318
 
  (*segment_lengths) = (double **) malloc(sizeof(double *) * shape->numlines);
1319
 
  (*line_lengths) = (double *) malloc(sizeof(double) * shape->numlines);
 
1522
  (*segment_lengths) = (double **) msSmallMalloc(sizeof(double *) * shape->numlines);
 
1523
  (*line_lengths) = (double *) msSmallMalloc(sizeof(double) * shape->numlines);
1320
1524
 
1321
1525
  temp_segment_index = *segment_index = *max_line_index = 0;
1322
1526
 
1324
1528
  *max_line_length = 0;
1325
1529
  for(i=0; i<shape->numlines; i++) {
1326
1530
    
1327
 
    (*segment_lengths)[i] = (double*) malloc(sizeof(double) * shape->line[i].numpoints);    
 
1531
    (*segment_lengths)[i] = (double*) msSmallMalloc(sizeof(double) * shape->line[i].numpoints);    
1328
1532
    
1329
1533
    (*line_lengths)[i] = 0;
1330
1534
    max_segment_length = 0;
1331
1535
    for(j=1;j<shape->line[i].numpoints;j++) {
1332
 
      segment_length = sqrt((pow((shape->line[i].point[j].x-shape->line[i].point[j-1].x),2.0) + pow((shape->line[i].point[j].y-shape->line[i].point[j-1].y),2.0)));
 
1536
      segment_length = sqrt((((shape->line[i].point[j].x-shape->line[i].point[j-1].x)*(shape->line[i].point[j].x-shape->line[i].point[j-1].x)) + ((shape->line[i].point[j].y-shape->line[i].point[j-1].y)*(shape->line[i].point[j].y-shape->line[i].point[j-1].y))));
1333
1537
      (*line_lengths)[i] += segment_length;
1334
1538
      (*segment_lengths)[i][j-1] = segment_length;
1335
1539
      if(segment_length > max_segment_length) {
1352
1556
** If no repeatdistance, find center of longest segment in polyline p. The polyline must have been converted
1353
1557
** to image coordinates before calling this function.
1354
1558
*/
1355
 
pointObj** msPolylineLabelPoint(shapeObj *p, int min_length, int repeat_distance, double ***angles, double ***lengths, int *numpoints, int center_on_longest_segment)
 
1559
pointObj** msPolylineLabelPoint(shapeObj *p, int min_length, int repeat_distance, double ***angles, double ***lengths, int *numpoints, int anglemode)
1356
1560
{
1357
 
  return msPolylineLabelPointExtended(p, min_length, repeat_distance, angles, lengths, numpoints, NULL, 0, center_on_longest_segment);
 
1561
  return msPolylineLabelPointExtended(p, min_length, repeat_distance, angles, lengths, numpoints, NULL, 0, anglemode);
1358
1562
}
1359
1563
 
1360
 
pointObj** msPolylineLabelPointExtended(shapeObj *p, int min_length, int repeat_distance, double ***angles, double ***lengths, int *numpoints, int *regularLines, int numlines, int center_on_longest_segment)
 
1564
pointObj** msPolylineLabelPointExtended(shapeObj *p, int min_length, int repeat_distance, double ***angles, double ***lengths, int *numpoints, int *regularLines, int numlines, int anglemode)
1361
1565
{
1362
1566
  double total_length, max_line_length;
1363
1567
  int i,j, max_line_index, segment_index, labelpoints_index, labelpoints_size;
1369
1573
  labelpoints_size = p->numlines; // minimal array size
1370
1574
  *numpoints = 0;
1371
1575
 
1372
 
  labelpoints = (pointObj **) malloc(sizeof(pointObj *) * labelpoints_size);
1373
 
  (*angles) = (double **) malloc(sizeof(double *) * labelpoints_size);
1374
 
  (*lengths) = (double **) malloc(sizeof(double *) * labelpoints_size);
 
1576
  labelpoints = (pointObj **) msSmallMalloc(sizeof(pointObj *) * labelpoints_size);
 
1577
  (*angles) = (double **) msSmallMalloc(sizeof(double *) * labelpoints_size);
 
1578
  (*lengths) = (double **) msSmallMalloc(sizeof(double *) * labelpoints_size);
1375
1579
 
1376
1580
  msPolylineComputeLineSegments(p, &segment_lengths, &line_lengths, &max_line_index, &max_line_length, &segment_index, &total_length);
1377
1581
 
1380
1584
      if (numlines > 0) {
1381
1585
        for (j=0; j<numlines; j++)
1382
1586
          if (regularLines[j] == i) {
1383
 
              msPolylineLabelPointLineString(p, min_length, repeat_distance, angles, lengths, segment_lengths, i, line_lengths[i], total_length, segment_index, &labelpoints_index, &labelpoints_size, &labelpoints, center_on_longest_segment);
 
1587
              msPolylineLabelPointLineString(p, min_length, repeat_distance, angles, lengths, segment_lengths, i, line_lengths[i], total_length, segment_index, &labelpoints_index, &labelpoints_size, &labelpoints, anglemode);
1384
1588
            break;
1385
1589
          }
1386
1590
      } else {
1387
 
          msPolylineLabelPointLineString(p, min_length, repeat_distance, angles, lengths, segment_lengths, i, line_lengths[i], total_length, segment_index, &labelpoints_index, &labelpoints_size, &labelpoints, center_on_longest_segment);
 
1591
          msPolylineLabelPointLineString(p, min_length, repeat_distance, angles, lengths, segment_lengths, i, line_lengths[i], total_length, segment_index, &labelpoints_index, &labelpoints_size, &labelpoints, anglemode);
1388
1592
      }
1389
1593
  }
1390
1594
  else
1391
 
      msPolylineLabelPointLineString(p, min_length, repeat_distance, angles, lengths, segment_lengths, max_line_index, max_line_length, total_length, segment_index, &labelpoints_index, &labelpoints_size, &labelpoints, center_on_longest_segment);
 
1595
      msPolylineLabelPointLineString(p, min_length, repeat_distance, angles, lengths, segment_lengths, max_line_index, max_line_length, total_length, segment_index, &labelpoints_index, &labelpoints_size, &labelpoints, anglemode);
1392
1596
 
1393
1597
  *numpoints = labelpoints_index;
1394
1598
 
1405
1609
}
1406
1610
 
1407
1611
void msPolylineLabelPointLineString(shapeObj *p, int min_length, int repeat_distance, double ***angles, double ***lengths, double** segment_lengths,
1408
 
                                    int line_index, double line_length, double total_length, int segment_index, int* labelpoints_index, int* labelpoints_size, pointObj ***labelpoints, int center_on_longest_segment)
 
1612
                                    int line_index, double line_length, double total_length, int segment_index, int* labelpoints_index, int* labelpoints_size, pointObj ***labelpoints, int anglemode)
1409
1613
{
1410
1614
  int i, j, k, l, n, index, point_repeat;
1411
1615
  double t, tmp_length, theta, fwd_length, point_distance;
1419
1623
    return;
1420
1624
 
1421
1625
  i = line_index;
 
1626
 
 
1627
  if(p->line[i].numpoints < 2)
 
1628
          return;
1422
1629
  point_distance = 0;
1423
1630
  point_repeat = 1;
1424
1631
  left_point_position = right_point_position = center_point_position = line_length / 2.0; 
1455
1662
    do {
1456
1663
      if (*labelpoints_index == *labelpoints_size) {
1457
1664
        *labelpoints_size *= 2;
1458
 
        (*labelpoints) = (pointObj **) realloc(*labelpoints,sizeof(pointObj *) * (*labelpoints_size));
1459
 
        (*angles) = (double **) realloc(*angles,sizeof(double *) * (*labelpoints_size));
1460
 
        (*lengths) = (double **) realloc(*lengths,sizeof(double *) * (*labelpoints_size));
 
1665
        (*labelpoints) = (pointObj **) msSmallRealloc(*labelpoints,sizeof(pointObj *) * (*labelpoints_size));
 
1666
        (*angles) = (double **) msSmallRealloc(*angles,sizeof(double *) * (*labelpoints_size));
 
1667
        (*lengths) = (double **) msSmallRealloc(*lengths,sizeof(double *) * (*labelpoints_size));
1461
1668
      }
1462
1669
      
1463
1670
      index = (*labelpoints_index)++;
1464
 
      (*labelpoints)[index] = (pointObj *) malloc(sizeof(pointObj));
1465
 
      (*angles)[index] = (double *) malloc(sizeof(double));
1466
 
      (*lengths)[index] = (double *) malloc(sizeof(double));
 
1671
      (*labelpoints)[index] = (pointObj *) msSmallMalloc(sizeof(pointObj));
 
1672
      (*angles)[index] = (double *) msSmallMalloc(sizeof(double));
 
1673
      (*lengths)[index] = (double *) msSmallMalloc(sizeof(double));
1467
1674
 
1468
1675
      if (repeat_distance > 0)
1469
1676
        *(*lengths)[index] = line_length;
1471
1678
        *(*lengths)[index] = total_length;
1472
1679
 
1473
1680
      /* if there is only 1 label to place... put it in the middle of the current segment (as old behavior) */
1474
 
      if (center_on_longest_segment && (point_repeat == 1))
 
1681
      if ( ((anglemode == MS_AUTO) || (anglemode == MS_AUTO2)) &&  
 
1682
           (point_repeat == 1) ) 
1475
1683
      {
1476
1684
        j = segment_index;
1477
1685
        (*labelpoints)[index]->x = (p->line[i].point[j].x + p->line[i].point[j-1].x)/2.0;
1490
1698
        (*labelpoints)[index]->y = t * (p->line[i].point[k+1].y - p->line[i].point[k].y) + p->line[i].point[k].y;
1491
1699
      }
1492
1700
 
1493
 
      theta = asin(MS_ABS(p->line[i].point[j].x - p->line[i].point[j-1].x)/sqrt((pow((p->line[i].point[j].x - p->line[i].point[j-1].x),2.0) + pow((p->line[i].point[j].y - p->line[i].point[j-1].y),2.0))));
 
1701
      theta = asin(MS_ABS(p->line[i].point[j].x - p->line[i].point[j-1].x)/sqrt((((p->line[i].point[j].x - p->line[i].point[j-1].x)*(p->line[i].point[j].x - p->line[i].point[j-1].x)) + ((p->line[i].point[j].y - p->line[i].point[j-1].y)*(p->line[i].point[j].y - p->line[i].point[j-1].y)))));
1494
1702
    
1495
 
      if(p->line[i].point[j-1].x < p->line[i].point[j].x) { /* i.e. to the left */
 
1703
      if(p->line[i].point[j-1].x < p->line[i].point[j].x || anglemode == MS_AUTO2) { /* i.e. to the left */
1496
1704
        if(p->line[i].point[j-1].y < p->line[i].point[j].y) /* i.e. below */
1497
1705
          *(*angles)[index] = -(90.0 - MS_RAD_TO_DEG*theta);
1498
1706
        else
1516
1724
}
1517
1725
 
1518
1726
/* Calculate the labelpath for each line if repeatdistance is enabled, else the labelpath of the longest line segment */
1519
 
labelPathObj** msPolylineLabelPath(imageObj *img,shapeObj *p, int min_length, fontSetObj *fontset, char *string, labelObj *label, double scalefactor, int *numpaths,
 
1727
labelPathObj** msPolylineLabelPath(mapObj *map, imageObj *img,shapeObj *p, int min_length, fontSetObj *fontset, char *string, labelObj *label, double scalefactor, int *numpaths,
1520
1728
                                   int** regular_lines, int* num_regular_lines)
1521
1729
{
1522
1730
  double max_line_length, total_length;
1532
1740
  segment_index = max_line_index = 0;
1533
1741
  total_length = max_line_length = 0.0;
1534
1742
 
1535
 
  labelpaths = (labelPathObj **) malloc(sizeof(labelPathObj *) * labelpaths_size);
1536
 
  (*regular_lines) = (int *) malloc(sizeof(int) * regular_lines_size);
 
1743
  labelpaths = (labelPathObj **) msSmallMalloc(sizeof(labelPathObj *) * labelpaths_size);
 
1744
  (*regular_lines) = (int *) msSmallMalloc(sizeof(int) * regular_lines_size);
1537
1745
 
1538
1746
  msPolylineComputeLineSegments(p, &segment_lengths, &line_lengths, &max_line_index, &max_line_length, &segment_index, &total_length);
1539
1747
 
1540
1748
  if (label->repeatdistance > 0)
1541
1749
    for(i=0; i<p->numlines; i++) {
1542
 
      msPolylineLabelPathLineString(img, p,min_length, fontset, string, label, scalefactor, i, segment_lengths, line_lengths[i], total_length, 
 
1750
      msPolylineLabelPathLineString(map,img, p,min_length, fontset, string, label, scalefactor, i, segment_lengths, line_lengths[i], total_length, 
1543
1751
                                    &labelpaths_index, &labelpaths_size, &labelpaths, regular_lines, &regular_lines_index, &regular_lines_size);
1544
1752
    }
1545
1753
  else
1546
 
    msPolylineLabelPathLineString(img, p,min_length, fontset, string, label, scalefactor, max_line_index, segment_lengths, line_lengths[max_line_index], total_length, 
 
1754
    msPolylineLabelPathLineString(map, img, p,min_length, fontset, string, label, scalefactor, max_line_index, segment_lengths, line_lengths[max_line_index], total_length, 
1547
1755
                                  &labelpaths_index, &labelpaths_size, &labelpaths, regular_lines, &regular_lines_index, &regular_lines_size);
1548
1756
 
1549
1757
  /* freeing memory: allocated by msPolylineComputeLineSegments */
1568
1776
 * are allocated in this function.  The polyline must be converted to image 
1569
1777
 * coordinates before calling this function.
1570
1778
 */
1571
 
void msPolylineLabelPathLineString(imageObj *img, shapeObj *p, int min_length, fontSetObj *fontset, char *string, labelObj *label, double scalefactor, int line_index, 
 
1779
void msPolylineLabelPathLineString(mapObj *map, imageObj *img, shapeObj *p, int min_length, fontSetObj *fontset, char *string, labelObj *label, double scalefactor, int line_index, 
1572
1780
                                   double** segment_lengths, double line_length, double total_length, int* labelpaths_index, int* labelpaths_size, labelPathObj*** labelpaths, 
1573
1781
                                   int** regular_lines, int *regular_lines_index, int* regular_lines_size)
1574
1782
{
1596
1804
  int kernel_size = 5;
1597
1805
  
1598
1806
  double letterspacing = 1.25;
 
1807
  /* As per RFC 60, if label->maxoverlapangle == 0 then fall back on pre-6.0 behavior 
 
1808
     which was to use maxoverlapangle = 0.4*MS_PI ( 40% of 180 degrees ) */
 
1809
  double maxoverlapangle = 0.4 * MS_PI;
1599
1810
 
1600
1811
  offsets = NULL;
1601
1812
 
1626
1837
  if(p->line[i].numpoints == 2) /* use the regular angled text algorithm */
1627
1838
    goto ANGLEFOLLOW_FAILURE;
1628
1839
  
1629
 
  /* determine the total length of the text */
1630
 
  if (msGetLabelSize(img,string, label, &bbox, fontset, scalefactor, MS_FALSE, &offsets) == -1) {
1631
 
    goto FAILURE;
1632
 
  }
1633
 
 
1634
1840
  size = label->size*scalefactor;
1635
1841
  size = MS_MAX(size, label->minsize*img->resolutionfactor);
1636
1842
  size = MS_MIN(size, label->maxsize*img->resolutionfactor);
 
1843
  
 
1844
  /* determine the total length of the text */
 
1845
  if (msGetLabelSize(map,label,string,size,&bbox,&offsets) != MS_SUCCESS) {
 
1846
    goto FAILURE;
 
1847
  }
 
1848
 
 
1849
  
1637
1850
  scalefactor = size / label->size;
1638
1851
 
1639
1852
  text_length = letterspacing * (bbox.maxx - bbox.minx);
1669
1882
    label_repeat = 1;
1670
1883
    center_label_position = (line_length - text_length) / 2.0;
1671
1884
  }
 
1885
  
 
1886
  if(label->maxoverlapangle >=0)
 
1887
    maxoverlapangle = label->maxoverlapangle * MS_DEG_TO_RAD; // radian
1672
1888
 
1673
1889
  for (l=0; l < label_repeat; l++)
1674
1890
  {
1683
1899
 
1684
1900
    do {
1685
1901
        /* allocate the labelpath */
1686
 
        labelpath = (labelPathObj *) malloc(sizeof(labelPathObj));
 
1902
        labelpath = (labelPathObj *) msSmallMalloc(sizeof(labelPathObj));
1687
1903
        labelpath->path.numpoints = numchars;
1688
 
        labelpath->path.point = (pointObj *) calloc(labelpath->path.numpoints, sizeof(pointObj));
1689
 
        labelpath->angles = (double *) malloc(sizeof(double) * (labelpath->path.numpoints));
 
1904
        labelpath->path.point = (pointObj *) msSmallCalloc(labelpath->path.numpoints, sizeof(pointObj));
 
1905
        labelpath->angles = (double *) msSmallMalloc(sizeof(double) * (labelpath->path.numpoints));
1690
1906
        msInitShape(&(labelpath->bounds));
1691
1907
    
1692
1908
 
1696
1912
        ** will be tied together.
1697
1913
        */
1698
1914
        bounds.numpoints = 2*numchars + 1;
1699
 
        bounds.point = (pointObj *) malloc(sizeof(pointObj) * bounds.numpoints);
 
1915
        bounds.point = (pointObj *) msSmallMalloc(sizeof(pointObj) * bounds.numpoints);
1700
1916
 
1701
1917
        /* the points start at (line_length - text_length) / 2 in order to be centred */
1702
1918
        //  text_start_length = (line_length - text_length) / 2.0;
1840
2056
 
1841
2057
        labelpath->path.point[0].x /= kernel_normal;
1842
2058
        labelpath->path.point[0].y /= kernel_normal;
1843
 
  
 
2059
 
1844
2060
        /* Average the points and calculate each angle */
1845
2061
        for (k = 1; k <= labelpath->path.numpoints; k++) {
1846
2062
 
1857
2073
 
1858
2074
            theta = -atan2(dy,dx);
1859
2075
 
1860
 
            /* If the difference between subsequent angles is > 80% of 180deg
1861
 
               bail because the line likely overlaps itself. */
1862
 
   
1863
 
            if ( k > 2 && fabs(theta - labelpath->angles[k-2]) > 0.4 * MS_PI ) {
 
2076
            /* If the difference between the last char angle and the current one 
 
2077
              is greater than the MAXOVERLAPANGLE value (set at 80% of 180deg by default)
 
2078
              , bail the label */
 
2079
            if ( maxoverlapangle > 0 && (k > 2 && fabs(theta - labelpath->angles[k-2]) > maxoverlapangle) ) {
1864
2080
                goto LABEL_FAILURE;
1865
2081
            }
1866
2082
      
1867
2083
            /* msDebug("s: %c (x,y): (%0.2f,%0.2f) t: %0.2f\n", string[k-1], labelpath->path.point[k-1].x, labelpath->path.point[k-1].y, theta); */
1868
 
 
 
2084
            
1869
2085
            labelpath->angles[k-1] = theta;
 
2086
 
1870
2087
  
1871
2088
            /* Move the previous point so that when the character is rotated and
1872
2089
               placed it is centred on the line */
1873
2090
            cos_t = cos(theta);
1874
2091
            sin_t = sin(theta);
1875
 
  
 
2092
 
1876
2093
            w = letterspacing*offsets[k-1];
1877
2094
 
1878
2095
            cx = 0; /* Center the character vertically only */
1888
2105
            bbox.maxx = w;
1889
2106
            bbox.maxy = 0;
1890
2107
            bbox.miny = -size;
1891
 
 
 
2108
  
1892
2109
            /* Add the label buffer to the bounds */
1893
2110
            bbox.maxx += label->buffer;
1894
2111
            bbox.maxy += label->buffer;
1895
2112
            bbox.minx -= label->buffer;
1896
2113
            bbox.miny -= label->buffer;
1897
 
  
 
2114
 
1898
2115
            if ( k < labelpath->path.numpoints ) {
1899
2116
                /* Transform the bbox too.  We take the UL and LL corners and rotate
1900
2117
                   then translate them. */
1947
2164
        if (labelpath) {
1948
2165
            if (*labelpaths_index == *labelpaths_size) {
1949
2166
                *labelpaths_size *= 2;
1950
 
                (*labelpaths) = (labelPathObj **) realloc(*labelpaths,sizeof(labelPathObj *) * (*labelpaths_size));
 
2167
                (*labelpaths) = (labelPathObj **) msSmallRealloc(*labelpaths,sizeof(labelPathObj *) * (*labelpaths_size));
1951
2168
            }
1952
2169
            (*labelpaths)[(*labelpaths_index)++] = labelpath;
1953
2170
        }
1967
2184
  ANGLEFOLLOW_FAILURE: // Angle follow failure: add the line index in the arrays
1968
2185
  if (*regular_lines_index == *regular_lines_size) {
1969
2186
      *regular_lines_size *= 2;
1970
 
      (*regular_lines) = (int*) realloc(*regular_lines,sizeof(int) * (*regular_lines_size));
 
2187
      (*regular_lines) = (int*) msSmallRealloc(*regular_lines,sizeof(int) * (*regular_lines_size));
1971
2188
  }
1972
2189
  (*regular_lines)[(*regular_lines_index)++] = line_index;
1973
2190
 
1997
2214
  snprintf(buffer, buffer_length, format, point->x, point->y);
1998
2215
#endif
1999
2216
}
 
2217
 
 
2218
/* Returns true if a shape contains only degenerate parts */
 
2219
int msIsDegenerateShape(shapeObj *shape)
 
2220
{
 
2221
  int i;
 
2222
  int non_degenerate_parts = 0;
 
2223
  for(i=0; i<shape->numlines; i++) { /* e.g. part */
 
2224
        
 
2225
    /* skip degenerate parts, really should only happen with pixel output */ 
 
2226
    if((shape->type == MS_SHAPE_LINE && shape->line[i].numpoints < 2) ||
 
2227
       (shape->type == MS_SHAPE_POLYGON && shape->line[i].numpoints < 3))
 
2228
     continue;
 
2229
        
 
2230
    non_degenerate_parts++;
 
2231
  }
 
2232
  return( non_degenerate_parts == 0 );
 
2233
}
 
2234