Ejemplo n.º 1
0
int msProjectShape(projectionObj *in, projectionObj *out, shapeObj *shape)
{
#ifdef USE_PROJ
  int i;
#ifdef USE_PROJ_FASTPATHS
  int j;

  if(in->wellknownprojection == wkp_lonlat && out->wellknownprojection == wkp_gmerc) {
    for( i = shape->numlines-1; i >= 0; i-- ) {
      for( j = shape->line[i].numpoints-1; j >= 0; j-- ) {
#define p_x shape->line[i].point[j].x
#define p_y shape->line[i].point[j].y
        p_x *= MAXEXTENTby180;
        p_y = log(tan((90 + p_y) * M_PIby360)) * MS_RAD_TO_DEG;
        p_y *= MAXEXTENTby180;
        if (p_x > MAXEXTENT) p_x = MAXEXTENT;
        if (p_x < -MAXEXTENT) p_x = -MAXEXTENT;
        if (p_y > MAXEXTENT) p_y = MAXEXTENT;
        if (p_y < -MAXEXTENT) p_y = -MAXEXTENT;
#undef p_x
#undef p_y
      }
    }
    msComputeBounds( shape ); /* fixes bug 1586 */
    return MS_SUCCESS;
  }
#endif



  for( i = shape->numlines-1; i >= 0; i-- ) {
    if( shape->type == MS_SHAPE_LINE || shape->type == MS_SHAPE_POLYGON ) {
      if( msProjectShapeLine( in, out, shape, i ) == MS_FAILURE )
        msShapeDeleteLine( shape, i );
    } else if( msProjectLine(in, out, shape->line+i ) == MS_FAILURE ) {
      msShapeDeleteLine( shape, i );
    }
  }

  if( shape->numlines == 0 ) {
    msFreeShape( shape );
    return MS_FAILURE;
  } else {
    msComputeBounds( shape ); /* fixes bug 1586 */
    return(MS_SUCCESS);
  }
#else
  msSetError(MS_PROJERR, "Projection support is not available.", "msProjectShape()");
  return(MS_FAILURE);
#endif
}
Ejemplo n.º 2
0
int msProjectShape(projectionObj *in, projectionObj *out, shapeObj *shape)
{
#ifdef USE_PROJ
  int i;

  for( i = shape->numlines-1; i >= 0; i-- )
  {
      if( shape->type == MS_SHAPE_LINE || shape->type == MS_SHAPE_POLYGON )
      {
          if( msProjectShapeLine( in, out, shape, i ) == MS_FAILURE )
              msShapeDeleteLine( shape, i );
      }
      else if( msProjectLine(in, out, shape->line+i ) == MS_FAILURE )
      {
          msShapeDeleteLine( shape, i );
      }
  }

  if( shape->numlines == 0 ) {
      msFreeShape( shape );
      return MS_FAILURE;
  } else {
      msComputeBounds( shape ); /* fixes bug 1586 */
      return(MS_SUCCESS);
  }
#else
  msSetError(MS_PROJERR, "Projection support is not available.", "msProjectShape()");
  return(MS_FAILURE);
#endif
}
Ejemplo n.º 3
0
static shapeObj *msGEOSGeometry2Shape_line(GEOSGeom g)
{
  shapeObj *shape=NULL;

  int i;
  int numPoints;
  GEOSCoordSeq coords;

  if(!g) return NULL;
  numPoints = GEOSGetNumCoordinates(g);
  coords = (GEOSCoordSeq) GEOSGeom_getCoordSeq(g);

  shape = (shapeObj *) malloc(sizeof(shapeObj));
  msInitShape(shape);

  shape->type = MS_SHAPE_LINE; 
  shape->line = (lineObj *) malloc(sizeof(lineObj));
  shape->numlines = 1;
  shape->line[0].point = (pointObj *) malloc(sizeof(pointObj)*numPoints);
  shape->line[0].numpoints = numPoints;
  shape->geometry = (GEOSGeom) g;

  for(i=0; i<numPoints; i++) {
    GEOSCoordSeq_getX(coords, i, &(shape->line[0].point[i].x));
    GEOSCoordSeq_getY(coords, i, &(shape->line[0].point[i].y));
    /* GEOSCoordSeq_getZ(coords, i, &(shape->line[0].point[i].z)); */
  }

  msComputeBounds(shape); 

  return shape;
}
Ejemplo n.º 4
0
static shapeObj *msGEOSGeometry2Shape_multipoint(GEOSGeom g)
{
  int i;
  int numPoints;
  GEOSCoordSeq coords;
  GEOSGeom point;
  
  shapeObj *shape=NULL;

  if(!g) return NULL;
  numPoints = GEOSGetNumGeometries(g); /* each geometry has 1 point */

  shape = (shapeObj *) malloc(sizeof(shapeObj));
  msInitShape(shape);

  shape->type = MS_SHAPE_POINT;
  shape->line = (lineObj *) malloc(sizeof(lineObj));
  shape->numlines = 1;
  shape->line[0].point = (pointObj *) malloc(sizeof(pointObj)*numPoints);
  shape->line[0].numpoints = numPoints;
  shape->geometry = (GEOSGeom) g;

  for(i=0; i<numPoints; i++) {
    point = (GEOSGeom) GEOSGetGeometryN(g, i);
    coords = (GEOSCoordSeq) GEOSGeom_getCoordSeq(point);

    GEOSCoordSeq_getX(coords, 0, &(shape->line[0].point[i].x));
    GEOSCoordSeq_getY(coords, 0, &(shape->line[0].point[i].y));
    /* GEOSCoordSeq_getZ(coords, 0, &(shape->line[0].point[i].z)); */
  }
 
  msComputeBounds(shape); 

  return shape;
}
Ejemplo n.º 5
0
int msHatchPolygon(imageObj *img, shapeObj *poly, double spacing, double width, double *pattern, int patternlength, double angle, colorObj *color)
{
  assert(MS_RENDERER_PLUGIN(img->format));
  msComputeBounds(poly);

  /* amount we should expand the bounding box by */
  double exp = width * 0.7072;

  /* width and height of the bounding box we will be creating the hatch in */
  int pw=(int)(poly->bounds.maxx-poly->bounds.minx+exp*2)+1;
  int ph=(int)(poly->bounds.maxy-poly->bounds.miny+exp*2)+1;

  /* position of the top-left corner of the bounding box */
  double ox = poly->bounds.minx - exp;
  double oy = poly->bounds.miny - exp;

  //create a rectangular hatch of size pw,ph starting at 0,0
  //the created hatch is of the size of the shape's bounding box
  mapserver::path_storage hatch = createHatch(ox,oy,
                                  img->refpt.x,img->refpt.y,pw,ph,angle,spacing);
  if(hatch.total_vertices()<=0) return MS_SUCCESS;

  //translate the hatch so it overlaps the current shape
  hatch.transform(mapserver::trans_affine_translation(ox,oy));

  polygon_adaptor polygons(poly);



  if(patternlength>1) {
    //dash the hatch and render it clipped by the shape
    mapserver::conv_dash<mapserver::path_storage > dash(hatch);
    mapserver::conv_stroke<mapserver::conv_dash<mapserver::path_storage> > stroke(dash);
    for (int i=0; i<patternlength; i+=2) {
      if (i < patternlength-1) {
        dash.add_dash(pattern[i], pattern[i+1]);
      }
    }
    stroke.width(width);
    stroke.line_cap(mapserver::butt_cap);
    mapserver::conv_clipper<polygon_adaptor,mapserver::conv_stroke<mapserver::conv_dash<mapserver::path_storage> > > clipper(polygons,stroke, mapserver::clipper_and);
    renderPolygonHatches(img,clipper,color);
  } else {
    //render the hatch clipped by the shape
    mapserver::conv_stroke <mapserver::path_storage > stroke(hatch);
    stroke.width(width);
    stroke.line_cap(mapserver::butt_cap);
    mapserver::conv_clipper<polygon_adaptor,mapserver::conv_stroke<mapserver::path_storage> > clipper(polygons,stroke, mapserver::clipper_and);
    renderPolygonHatches(img,clipper,color);
  }


  //assert(prevCmd == mapserver::path_cmd_line_to);
  //delete lines;
  return MS_SUCCESS;
}
Ejemplo n.º 6
0
static shapeObj *msGEOSGeometry2Shape_polygon(GEOSGeom g)
{
  shapeObj *shape=NULL;
  lineObj line;
  int numPoints, numRings;
  int i, j;

  GEOSCoordSeq coords;
  GEOSGeom ring;

  if(!g) return NULL;

  shape = (shapeObj *) malloc(sizeof(shapeObj));
  msInitShape(shape);
  shape->type = MS_SHAPE_POLYGON;
  shape->geometry = (GEOSGeom) g;

  /* exterior ring */
  ring = (GEOSGeom) GEOSGetExteriorRing(g);
  numPoints = GEOSGetNumCoordinates(ring);
  coords = (GEOSCoordSeq) GEOSGeom_getCoordSeq(ring);
  
  line.point = (pointObj *) malloc(sizeof(pointObj)*numPoints);
  line.numpoints = numPoints;

  for(i=0; i<numPoints; i++) {
    GEOSCoordSeq_getX(coords, i, &(line.point[i].x));
    GEOSCoordSeq_getY(coords, i, &(line.point[i].y));
    /* GEOSCoordSeq_getZ(coords, i, &(line.point[i].z)); */    
  }
  msAddLineDirectly(shape, &line);

  /* interior rings */
  numRings = GEOSGetNumInteriorRings(g);
  for(j=0; j<numRings; j++) {
    ring = (GEOSGeom) GEOSGetInteriorRingN(g, j);
    if(GEOSisRing(ring) != 1) continue; /* skip it */

    numPoints = GEOSGetNumCoordinates(ring);
    coords = (GEOSCoordSeq) GEOSGeom_getCoordSeq(ring);

    line.point = (pointObj *) malloc(sizeof(pointObj)*numPoints);
    line.numpoints = numPoints;

    for(i=0; i<numPoints; i++) {
      GEOSCoordSeq_getX(coords, i, &(line.point[i].x));
      GEOSCoordSeq_getY(coords, i, &(line.point[i].y));
      /* GEOSCoordSeq_getZ(coords, i, &(line.point[i].z)); */
    }
    msAddLineDirectly(shape, &line);
  }

  msComputeBounds(shape); 

  return shape;
}
Ejemplo n.º 7
0
int msUVRASTERLayerGetShape(layerObj *layer, shapeObj *shape, resultObj *record)
{
  uvRasterLayerInfo *uvlinfo = (uvRasterLayerInfo *) layer->layerinfo;
  lineObj line ;
  pointObj point;
  int i, j, k, x=0, y=0;
  long shapeindex = record->shapeindex;

  msFreeShape(shape);
  shape->type = MS_SHAPE_NULL;

  if( shapeindex < 0 || shapeindex >= uvlinfo->query_results ) {
    msSetError(MS_MISCERR,
               "Out of range shape index requested.  Requested %ld\n"
               "but only %d shapes available.",
               "msUVRASTERLayerGetShape()",
               shapeindex, uvlinfo->query_results );
    return MS_FAILURE;
  }

  /* loop to the next non null vector */
  k = 0;
  for (i=0, x=-1; i<uvlinfo->width && k<=shapeindex; ++i, ++x) {
    for (j=0, y=-1; j<uvlinfo->height && k<=shapeindex; ++j, ++k, ++y) {
      if (uvlinfo->u[i][j] == 0 && uvlinfo->v[i][j] == 0)
        --k;
    }
  }

  point.x = Pix2Georef(x, 0, uvlinfo->width-1,
                       uvlinfo->extent.minx, uvlinfo->extent.maxx, MS_FALSE);
  point.y = Pix2Georef(y, 0, uvlinfo->height-1,
                       uvlinfo->extent.miny, uvlinfo->extent.maxy, MS_TRUE);
  if (layer->debug == 5)
    msDebug("msUVRASTERLayerWhichShapes(): shapeindex: %ld, x: %g, y: %g\n",
            shapeindex, point.x, point.y);

#ifdef USE_POINT_Z_M
  point.m = 0.0;
#endif

  shape->type = MS_SHAPE_POINT;
  line.numpoints = 1;
  line.point = &point;
  msAddLine( shape, &line );
  msComputeBounds( shape );

  shape->numvalues = layer->numitems;
  shape->values = msUVRASTERGetValues(layer, &uvlinfo->u[x][y], &uvlinfo->v[x][y]);

  return MS_SUCCESS;

}
Ejemplo n.º 8
0
/* static pointObj get_metrics(pointObj *p, int position, rectObj rect, int ox, int oy, double angle, int buffer, shapeObj *poly) */
pointObj get_metrics(pointObj *p, int position, rectObj rect, int ox, int oy, double angle, int buffer, shapeObj *poly)
{
  lineObj newline;
  pointObj newpoints[5];
  pointObj rp;
  newline.numpoints=5;
  newline.point=newpoints;
  rp = get_metrics_line(p, position, rect, ox,oy, angle, buffer, &newline);
  if(poly) {
    msAddLine(poly,&newline);
    msComputeBounds(poly);
  }
  return rp;
}
Ejemplo n.º 9
0
static shapeObj *msGEOSGeometry2Shape_multiline(GEOSGeom g)
{
  int i, j;
  int numPoints, numLines;
  GEOSCoordSeq coords;
  GEOSGeom lineString;

  shapeObj *shape=NULL;
  lineObj line;

  if(!g) return NULL;
  numLines = GEOSGetNumGeometries(g);

  shape = (shapeObj *) malloc(sizeof(shapeObj));
  msInitShape(shape);

  shape->type = MS_SHAPE_LINE;
  shape->geometry = (GEOSGeom) g;

  for(j=0; j<numLines; j++) {
    lineString = (GEOSGeom) GEOSGetGeometryN(g, j);
    numPoints = GEOSGetNumCoordinates(lineString);
    coords = (GEOSCoordSeq) GEOSGeom_getCoordSeq(lineString);

    line.point = (pointObj *) malloc(sizeof(pointObj)*numPoints);
    line.numpoints = numPoints;

    for(i=0; i<numPoints; i++) {
      GEOSCoordSeq_getX(coords, i, &(line.point[i].x));
      GEOSCoordSeq_getY(coords, i, &(line.point[i].y));
      /* GEOSCoordSeq_getZ(coords, i, &(line.point[i].z)); */  	
    }

    msAddLineDirectly(shape, &line);
  }

  msComputeBounds(shape); 

  return shape;
}
Ejemplo n.º 10
0
/*
 * RFC48 implementation:
 *  - transform the original shapeobj
 *  - use the styleObj to render the transformed shapeobj
 */
int msDrawTransformedShape(mapObj *map, imageObj *image, shapeObj *shape, styleObj *style, double scalefactor)
{
  int type = style->_geomtransform.type;
  int i,j,status = MS_SUCCESS;
  switch(type) {
    case MS_GEOMTRANSFORM_END: /*render point on last vertex only*/
      for(j=0; j<shape->numlines; j++) {
        lineObj *line = &(shape->line[j]);
        pointObj *p = &(line->point[line->numpoints-1]);
        if(p->x<0||p->x>image->width||p->y<0||p->y>image->height)
          continue;
        if(style->autoangle==MS_TRUE && line->numpoints>1) {
          style->angle = calcOrientation(&(line->point[line->numpoints-2]),p);
        }
        status = msDrawMarkerSymbol(map,image,p,style,scalefactor);
      }
      break;
    case MS_GEOMTRANSFORM_START: /*render point on first vertex only*/
      for(j=0; j<shape->numlines; j++) {
        lineObj *line = &(shape->line[j]);
        pointObj *p = &(line->point[0]);
        /*skip if outside image*/
        if(p->x<0||p->x>image->width||p->y<0||p->y>image->height)
          continue;
        if(style->autoangle==MS_TRUE && line->numpoints>1) {
          style->angle = calcOrientation(p,&(line->point[1]));
        }
        status = msDrawMarkerSymbol(map,image,p,style,scalefactor);
      }
      break;
    case MS_GEOMTRANSFORM_VERTICES:
      for(j=0; j<shape->numlines; j++) {
        lineObj *line = &(shape->line[j]);
        for(i=1; i<line->numpoints-1; i++) {
          pointObj *p = &(line->point[i]);
          /*skip points outside image*/
          if(p->x<0||p->x>image->width||p->y<0||p->y>image->height)
            continue;
          if(style->autoangle==MS_TRUE) {
            style->angle = calcMidAngle(&(line->point[i-1]),&(line->point[i]),&(line->point[i+1]));
          }
          status = msDrawMarkerSymbol(map,image,p,style,scalefactor);
        }
      }
      break;
    case MS_GEOMTRANSFORM_BBOX: {
      shapeObj bbox;
      lineObj bbox_line;
      pointObj bbox_points[5];
      int padding = MS_MAX(style->width,style->size)+3; /* so clipped shape does not extent into image */

      /*create a shapeObj representing the bounding box (clipped by the image size)*/
      bbox.numlines = 1;
      bbox.line = &bbox_line;
      bbox.line->numpoints = 5;
      bbox.line->point = bbox_points;

      msComputeBounds(shape);
      bbox_points[0].x=bbox_points[4].x=bbox_points[1].x =
                                          (shape->bounds.minx < -padding) ? -padding : shape->bounds.minx;
      bbox_points[2].x=bbox_points[3].x =
                         (shape->bounds.maxx > image->width+padding) ? image->width+padding : shape->bounds.maxx;
      bbox_points[0].y=bbox_points[4].y=bbox_points[3].y =
                                          (shape->bounds.miny < -padding) ? -padding : shape->bounds.miny;
      bbox_points[1].y=bbox_points[2].y =
                         (shape->bounds.maxy > image->height+padding) ? image->height+padding : shape->bounds.maxy;
      status = msDrawShadeSymbol(map, image, &bbox, style, scalefactor);
    }
    break;
    case MS_GEOMTRANSFORM_CENTROID: {
      double unused; /*used by centroid function*/
      pointObj centroid;
      if(MS_SUCCESS == msGetPolygonCentroid(shape,&centroid,&unused,&unused)) {
        status = msDrawMarkerSymbol(map,image,&centroid,style,scalefactor);
      }
    }
    break;
    case MS_GEOMTRANSFORM_EXPRESSION: {
      int status;
      shapeObj *tmpshp;
      parseObj p;

      p.shape = shape; /* set a few parser globals (hence the lock) */
      p.expr = &(style->_geomtransform);

      if(p.expr->tokens == NULL) { /* this could happen if drawing originates from legend code (#5193) */
        status = msTokenizeExpression(p.expr, NULL, NULL);
        if(status != MS_SUCCESS) {
          msSetError(MS_MISCERR, "Unable to tokenize expression.", "msDrawTransformedShape()");
          return MS_FAILURE;
        }
      }

      p.expr->curtoken = p.expr->tokens; /* reset */
      p.type = MS_PARSE_TYPE_SHAPE;

      status = yyparse(&p);
      if (status != 0) {
        msSetError(MS_PARSEERR, "Failed to process shape expression: %s", "msDrawTransformedShape", style->_geomtransform.string);
        return MS_FAILURE;
      }
      tmpshp = p.result.shpval;

      switch (tmpshp->type) {
        case MS_SHAPE_POINT:
        case MS_SHAPE_POLYGON:        
          status = msDrawShadeSymbol(map, image, tmpshp, style, scalefactor);
          break;
        case MS_SHAPE_LINE:
          status = msDrawLineSymbol(map, image, tmpshp, style, scalefactor);
          break;
      }

      msFreeShape(tmpshp);
      msFree(tmpshp);
    }
    break;
    case MS_GEOMTRANSFORM_LABELPOINT:
    case MS_GEOMTRANSFORM_LABELPOLY:
      break;
    default:
      msSetError(MS_MISCERR, "unknown geomtransform", "msDrawTransformedShape()");
      return MS_FAILURE;
  }
  return status;
}
Ejemplo n.º 11
0
static int
msProjectShapeLine(projectionObj *in, projectionObj *out,
                   shapeObj *shape, int line_index)

{
  int i;
  pointObj  lastPoint, thisPoint, wrkPoint;
  lineObj *line = shape->line + line_index;
  lineObj *line_out = line;
  int valid_flag = 0; /* 1=true, -1=false, 0=unknown */
  int numpoints_in = line->numpoints;
  int line_alloc = numpoints_in;
  int wrap_test;

#ifdef USE_PROJ_FASTPATHS
#define MAXEXTENT 20037508.34
#define M_PIby360 .0087266462599716479
#define MAXEXTENTby180 111319.4907777777777777777
#define p_x line->point[i].x
#define p_y line->point[i].y
  if(in->wellknownprojection == wkp_lonlat && out->wellknownprojection == wkp_gmerc) {
    for( i = line->numpoints-1; i >= 0; i-- ) {
      p_x *= MAXEXTENTby180;
      p_y = log(tan((90 + p_y) * M_PIby360)) * MS_RAD_TO_DEG;
      p_y *= MAXEXTENTby180;
      if (p_x > MAXEXTENT) p_x = MAXEXTENT;
      if (p_x < -MAXEXTENT) p_x = -MAXEXTENT;
      if (p_y > MAXEXTENT) p_y = MAXEXTENT;
      if (p_y < -MAXEXTENT) p_y = -MAXEXTENT;
    }
    return MS_SUCCESS;
  }
  if(in->wellknownprojection == wkp_gmerc && out->wellknownprojection == wkp_lonlat) {
    for( i = line->numpoints-1; i >= 0; i-- ) {
      if (p_x > MAXEXTENT) p_x = MAXEXTENT;
      else if (p_x < -MAXEXTENT) p_x = -MAXEXTENT;
      if (p_y > MAXEXTENT) p_y = MAXEXTENT;
      else if (p_y < -MAXEXTENT) p_y = -MAXEXTENT;
      p_x = (p_x / MAXEXTENT) * 180;
      p_y = (p_y / MAXEXTENT) * 180;
      p_y = MS_RAD_TO_DEG * (2 * atan(exp(p_y * MS_DEG_TO_RAD)) - MS_PI2);
    }
    msComputeBounds( shape ); /* fixes bug 1586 */
    return MS_SUCCESS;
  }
#undef p_x
#undef p_y
#endif



  wrap_test = out != NULL && out->proj != NULL && pj_is_latlong(out->proj)
              && !pj_is_latlong(in->proj);

  line->numpoints = 0;

  memset( &lastPoint, 0, sizeof(lastPoint) );

  /* -------------------------------------------------------------------- */
  /*      Loop over all input points in linestring.                       */
  /* -------------------------------------------------------------------- */
  for( i=0; i < numpoints_in; i++ ) {
    int ms_err;
    wrkPoint = thisPoint = line->point[i];

    ms_err = msProjectPoint(in, out, &wrkPoint );

    /* -------------------------------------------------------------------- */
    /*      Apply wrap logic.                                               */
    /* -------------------------------------------------------------------- */
    if( wrap_test && i > 0 && ms_err != MS_FAILURE ) {
      double dist;
      pointObj pt1Geo;

      if( line_out->numpoints > 0 )
        pt1Geo = line_out->point[line_out->numpoints-1];
      else
        pt1Geo = wrkPoint; /* this is a cop out */

      dist = wrkPoint.x - pt1Geo.x;
      if( fabs(dist) > 180.0
          && msTestNeedWrap( thisPoint, lastPoint,
                             pt1Geo, in, out ) ) {
        if( dist > 0.0 )
          wrkPoint.x -= 360.0;
        else if( dist < 0.0 )
          wrkPoint.x += 360.0;
      }
    }

    /* -------------------------------------------------------------------- */
    /*      Put result into output line with appropriate logic for          */
    /*      failure breaking lines, etc.                                    */
    /* -------------------------------------------------------------------- */
    if( ms_err == MS_FAILURE ) {
      /* We have started out invalid */
      if( i == 0 ) {
        valid_flag = -1;
      }

      /* valid data has ended, we need to work out the horizon */
      else if( valid_flag == 1 ) {
        pointObj startPoint, endPoint;

        startPoint = lastPoint;
        endPoint = thisPoint;
        if( msProjectSegment( in, out, &startPoint, &endPoint )
            == MS_SUCCESS ) {
          line_out->point[line_out->numpoints++] = endPoint;
        }
        valid_flag = -1;
      }

      /* Still invalid ... */
      else if( valid_flag == -1 ) {
        /* do nothing */
      }
    }

    else {
      /* starting out valid. */
      if( i == 0 ) {
        line_out->point[line_out->numpoints++] = wrkPoint;
        valid_flag = 1;
      }

      /* Still valid, nothing special */
      else if( valid_flag == 1 ) {
        line_out->point[line_out->numpoints++] = wrkPoint;
      }

      /* we have come over the horizon, figure out where, start newline*/
      else {
        pointObj startPoint, endPoint;

        startPoint = lastPoint;
        endPoint = thisPoint;
        if( msProjectSegment( in, out, &endPoint, &startPoint )
            == MS_SUCCESS ) {
          lineObj newLine;

          /* force pre-allocation of lots of points room */
          if( line_out->numpoints > 0
              && shape->type == MS_SHAPE_LINE ) {
            newLine.numpoints = numpoints_in - i + 1;
            newLine.point = line->point;
            msAddLine( shape, &newLine );

            /* new line is now lineout, but start without any points */
            line_out = shape->line + shape->numlines-1;

            line_out->numpoints = 0;

            /* the shape->line array is realloc, refetch "line" */
            line = shape->line + line_index;
          } else if( line_out == line
                     && line->numpoints >= i-2 ) {
            newLine.numpoints = numpoints_in;
            newLine.point = line->point;
            msAddLine( shape, &newLine );

            line = shape->line + line_index;

            line_out = shape->line + shape->numlines-1;
            line_out->numpoints = line->numpoints;
            line->numpoints = 0;

            /*
             * Now realloc this array large enough to hold all
             * the points we could possibly need to add.
             */
            line_alloc = line_alloc * 2;

            line_out->point = (pointObj *)
                              realloc(line_out->point,
                                      sizeof(pointObj) * line_alloc);
          }

          line_out->point[line_out->numpoints++] = startPoint;
        }
        line_out->point[line_out->numpoints++] = wrkPoint;
        valid_flag = 1;
      }
    }

    lastPoint = thisPoint;
  }

  /* -------------------------------------------------------------------- */
  /*      Make sure that polygons are closed, even if the trip over       */
  /*      the horizon left them unclosed.                                 */
  /* -------------------------------------------------------------------- */
  if( shape->type == MS_SHAPE_POLYGON
      && line_out->numpoints > 2
      && (line_out->point[0].x != line_out->point[line_out->numpoints-1].x
          || line_out->point[0].y != line_out->point[line_out->numpoints-1].y) ) {
    /* make a copy because msAddPointToLine can realloc the array */
    pointObj sFirstPoint = line_out->point[0];
    msAddPointToLine( line_out, &sFirstPoint );
  }

  return(MS_SUCCESS);
}