Exemple #1
0
static int 
msProjectShapeLine(projectionObj *in, projectionObj *out, 
                   shapeObj *shape, int line_index)

{
    int i;
    pointObj	lastPoint, thisPoint, wrkPoint, firstPoint;
    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;

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

    line->numpoints = 0;

    if( numpoints_in > 0 )
        firstPoint = line->point[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[0];
            else
                pt1Geo = wrkPoint; /* this is a cop out */

            dist = wrkPoint.x - pt1Geo.x;
            if( fabs(dist) > 180.0 
                && msTestNeedWrap( thisPoint, firstPoint, 
                                   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);
}
shapeObj* msSmoothShapeSIA(shapeObj *shape, int ss, int si, char *preprocessing)
{
  int i, j;
  pointObj *p;
  double *coeff;
  shapeObj *newShape;

  newShape = (shapeObj *) msSmallMalloc(sizeof (shapeObj));
  msInitShape(newShape);

  if (ss < 3)
    ss = 3;
  
  if (si < 1)
    si = 1;

  /* Apply preprocessing */
  if (preprocessing)
  {
    if (strcasecmp(preprocessing, "all") == 0)
      processShapePathDistance(shape, MS_TRUE);
    else if (strcasecmp(preprocessing, "angle") == 0)
      processShapePathDistance(shape, MS_FALSE);
  }
  
  p = (pointObj *) msSmallMalloc(ss*sizeof(pointObj));
  coeff = (double *) msSmallMalloc(ss*sizeof (double));        
  
  for (i=0;i<si;++i) {
    shapeObj initialShape;
    
    if (si > 1 && i>0) {
      msInitShape(&initialShape);    
      msCopyShape(shape, &initialShape);
      
      /* Clean our shape object */
      for (j=0; j < newShape->numlines; ++j)
        free(newShape->line[j].point);
      newShape->numlines = 0;
      if (newShape->line) {
        free(newShape->line);
        newShape->line = NULL;
      }

      shape = &initialShape;
    }
    
    for (j=0;j<shape->numlines;++j) {
      int k, ws, res;      
      lineObj newLine = {0,NULL};
      lineWindow lw;

      /* determine if we can use the ss for this line */
      ws = ss;      
      if (ws >= shape->line[j].numpoints) {
        ws = shape->line[j].numpoints-1;
      }

      if (ws%2==0)
        ws-=1;  

      initLineWindow(&lw, &shape->line[j], ws);
      msAddLine(newShape, &newLine);

      coeff[lw.index] = 1;
      for (k=0;k<lw.index;++k) {
        coeff[lw.index+(k+1)] = coeff[lw.index-k]/2;
        coeff[lw.index-(k+1)] = coeff[lw.index+k]/2;    
      }
      
      
      while ((res = nextLineWindow(&lw)) != MS_DONE) {
        double sum_x=0, sum_y=0, sum = 0;
        pointObj point;
        int k = 0;        

        if (res == MS_FALSE) { /* invalid window */
          msAddPointToLine(&newShape->line[j],
                           lw.points[lw.index]);
          continue;
        }

        /* Apply Coefficient */
        p[lw.index] = *lw.points[lw.index];
        for (k=0; k<lw.index; ++k) {
          p[lw.index-(k+1)] = *lw.points[lw.index-(k+1)];
          p[lw.index-(k+1)].x *= coeff[lw.index-(k+1)];
          p[lw.index-(k+1)].y *= coeff[lw.index-(k+1)];
          p[lw.index+(k+1)] = *lw.points[lw.index+(k+1)];
          p[lw.index+(k+1)].x *= coeff[lw.index+(k+1)];
          p[lw.index+(k+1)].y *= coeff[lw.index+(k+1)];
        }
        
        for (k=0; k<lw.size; ++k) {
          sum += coeff[k];
          sum_x += p[k].x;
          sum_y += p[k].y;          
        }
      
        point.x = sum_x/sum;
        point.y = sum_y/sum;
        msAddPointToLine(&newShape->line[j],
                         &point);
      }

      freeLineWindow(&lw);      
    }
    
    if (i>0) {
      msFreeShape(shape);
      shape = newShape;
    }
    
  }
  
  free(p);
  free(coeff);
  
  return newShape;
}
Exemple #3
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);
}
/* Pre-Processing of a shape. It modifies the shape by adding intermediate
   points where a loop is detected to improve the smoothing result. */
static int processShapePathDistance(shapeObj *shape, int force)
{
  shapeObj initialShape, *newShape;
  int i;
  
  /* initial shape to process */
  msInitShape(&initialShape);    
  msCopyShape(shape, &initialShape);

  newShape = shape; /* we modify the shape object directly */
  shape = &initialShape;
  
  /* Clean our shape object */
  for (i= 0; i < newShape->numlines; i++)
    free(newShape->line[i].point);
  newShape->numlines = 0;
  if (newShape->line) free(newShape->line);
  
  for (i=0;i<shape->numlines;++i) {
    const int windowSize = 5;
    int res;
    lineWindow lw;
    lineObj line = {0, NULL};

    initLineWindow(&lw, &shape->line[i], windowSize);
    msAddLine(newShape, &line);

    while ((res = nextLineWindow(&lw)) != MS_DONE) {
      double ratio = 0;
      pointObj point;

      if (lw.lineIsRing && lw.pos==lw.line->numpoints-1) {
        point = newShape->line[i].point[0];
        msAddPointToLine(&newShape->line[i],
                         &point);
        continue;
      }

      if (res == MS_FALSE) { /* invalid window */
        msAddPointToLine(&newShape->line[i],
                         lw.points[lw.index]);
        continue;
      }

      if (!force)
        ratio = computePathDistanceRatio(lw.points, windowSize);
                      
      if (force || (ratio > 1.3)) {
        point.x = (lw.line->point[lw.pos].x + lw.points[lw.index-1]->x)/2;
        point.y = (lw.line->point[lw.pos].y + lw.points[lw.index-1]->y)/2;
        msAddPointToLine(&newShape->line[i],
                         &point);
      }
      
      point = lw.line->point[lw.pos];
      msAddPointToLine(&newShape->line[i],
                       &point);
      
      if (force || (ratio > 1.3)) {
        point.x = (lw.line->point[lw.pos].x + lw.points[lw.index+1]->x)/2;
        point.y = (lw.line->point[lw.pos].y + lw.points[lw.index+1]->y)/2;
        msAddPointToLine(&newShape->line[i],
                         &point);
      }
      
    }
       
    freeLineWindow(&lw);
  }
    
  msFreeShape(shape);
  
  return MS_SUCCESS;
}