Esempio n. 1
0
static void msProjectGrowRect(projectionObj *in, projectionObj *out,
                              rectObj *prj_rect, int *rect_initialized,
                              pointObj *prj_point, int *failure )

{
  if( msProjectPoint(in, out, prj_point) == MS_SUCCESS ) {
    if( *rect_initialized ) {
      prj_rect->miny = MS_MIN(prj_rect->miny, prj_point->y);
      prj_rect->maxy = MS_MAX(prj_rect->maxy, prj_point->y);
      prj_rect->minx = MS_MIN(prj_rect->minx, prj_point->x);
      prj_rect->maxx = MS_MAX(prj_rect->maxx, prj_point->x);
    } else {
      prj_rect->minx = prj_rect->maxx = prj_point->x;
      prj_rect->miny = prj_rect->maxy = prj_point->y;
      *rect_initialized = MS_TRUE;
    }
  } else
    (*failure)++;
}
Esempio n. 2
0
int msProjectLine(projectionObj *in, projectionObj *out, lineObj *line)
{
#ifdef USE_PROJ
  int i, be_careful = 1;

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

  if( be_careful )
  {
      pointObj	startPoint, thisPoint; /* locations in projected space */

      startPoint = line->point[0];

      for(i=0; i<line->numpoints; i++)
      {
          double	dist;

          thisPoint = line->point[i];

          /* 
          ** Read comments before msTestNeedWrap() to better understand
          ** this dateline wrapping logic. 
          */
          msProjectPoint(in, out, &(line->point[i]));
          if( i > 0 )
          {
              dist = line->point[i].x - line->point[0].x;
              if( fabs(dist) > 180.0 )
              {
                  if( msTestNeedWrap( thisPoint, startPoint, 
                                      line->point[0], in, out ) )
                  {
                      if( dist > 0.0 )
                      {
                          line->point[i].x -= 360.0;
                      }
                      else if( dist < 0.0 )
                      {
                          line->point[i].x += 360.0;
                      }
                  }
              }

          }
      }
  }
  else
  {
      for(i=0; i<line->numpoints; i++)
      {
          if( msProjectPoint(in, out, &(line->point[i])) == MS_FAILURE )
              return MS_FAILURE;
      }
  }

  return(MS_SUCCESS);
#else
  msSetError(MS_PROJERR, "Projection support is not available.", "msProjectLine()");
  return(MS_FAILURE);
#endif
}
Esempio n. 3
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);
}
Esempio n. 4
0
static int
msProjectRectAsPolygon(projectionObj *in, projectionObj *out,
                       rectObj *rect)
{
#ifdef USE_PROJ
  shapeObj polygonObj;
  lineObj  ring;
  /*  pointObj ringPoints[NUMBER_OF_SAMPLE_POINTS*4+4]; */
  pointObj *ringPoints;
  int     ix, iy;

  double dx, dy;

  /* If projecting from longlat to projected */
  if( out && !pj_is_latlong(out->proj) && in && pj_is_latlong(in->proj) &&
      fabs(rect->minx - -180.0) < 1e-5 && fabs(rect->miny - -90.0) < 1e-5 &&
      fabs(rect->maxx - 180.0) < 1e-5 && fabs(rect->maxy - 90.0) < 1e-5) {
    rect->minx = -1e15;
    rect->miny = -1e15;
    rect->maxx = 1e15;
    rect->maxy = 1e15;
    return MS_SUCCESS;
  }

  /* -------------------------------------------------------------------- */
  /*      Build polygon as steps around the source rectangle.             */
  /* -------------------------------------------------------------------- */
  dx = (rect->maxx - rect->minx)/NUMBER_OF_SAMPLE_POINTS;
  dy = (rect->maxy - rect->miny)/NUMBER_OF_SAMPLE_POINTS;

  if(dx==0 && dy==0) {
    pointObj foo;
    msDebug( "msProjectRect(): Warning: degenerate rect {%f,%f,%f,%f}\n",rect->minx,rect->miny,rect->minx,rect->miny );
    foo.x = rect->minx;
    foo.y = rect->miny;
    msProjectPoint(in,out,&foo);
    rect->minx=rect->maxx=foo.x;
    rect->miny=rect->maxy=foo.y;
    return MS_SUCCESS;
  }
  
  ringPoints = (pointObj*) calloc(sizeof(pointObj),NUMBER_OF_SAMPLE_POINTS*4+4);
  ring.point = ringPoints;
  ring.numpoints = 0;

  msInitShape( &polygonObj );
  polygonObj.type = MS_SHAPE_POLYGON;

  /* sample along top */
  if(dx != 0) {
    for(ix = 0; ix <= NUMBER_OF_SAMPLE_POINTS; ix++ ) {
      ringPoints[ring.numpoints].x = rect->minx + ix * dx;
      ringPoints[ring.numpoints++].y = rect->miny;
    }
  }

  /* sample on along right side */
  if(dy != 0) {
    for(iy = 1; iy <= NUMBER_OF_SAMPLE_POINTS; iy++ ) {
      ringPoints[ring.numpoints].x = rect->maxx;
      ringPoints[ring.numpoints++].y = rect->miny + iy * dy;
    }
  }

  /* sample along bottom */
  if(dx != 0) {
    for(ix = NUMBER_OF_SAMPLE_POINTS-1; ix >= 0; ix-- ) {
      ringPoints[ring.numpoints].x = rect->minx + ix * dx;
      ringPoints[ring.numpoints++].y = rect->maxy;
    }
  }

  /* sample on along left side */
  if(dy != 0) {
    for(iy = NUMBER_OF_SAMPLE_POINTS-1; iy >= 0; iy-- ) {
      ringPoints[ring.numpoints].x = rect->minx;
      ringPoints[ring.numpoints++].y = rect->miny + iy * dy;
    }
  }

  msAddLineDirectly( &polygonObj, &ring );

#ifdef notdef
  FILE *wkt = fopen("/tmp/www-before.wkt","w");
  char *tmp = msShapeToWKT(&polygonObj);
  fprintf(wkt,"%s\n", tmp);
  free(tmp);
  fclose(wkt);
#endif

  /* -------------------------------------------------------------------- */
  /*      Attempt to reproject.                                           */
  /* -------------------------------------------------------------------- */
  msProjectShapeLine( in, out, &polygonObj, 0 );

  /* If no points reprojected, try a grid sampling */
  if( polygonObj.numlines == 0 || polygonObj.line[0].numpoints == 0 ) {
    msFreeShape( &polygonObj );
    return msProjectRectGrid( in, out, rect );
  }

#ifdef notdef
  wkt = fopen("/tmp/www-after.wkt","w");
  tmp = msShapeToWKT(&polygonObj);
  fprintf(wkt,"%s\n", tmp);
  free(tmp);
  fclose(wkt);
#endif

  /* -------------------------------------------------------------------- */
  /*      Collect bounds.                                                 */
  /* -------------------------------------------------------------------- */
  rect->minx = rect->maxx = polygonObj.line[0].point[0].x;
  rect->miny = rect->maxy = polygonObj.line[0].point[0].y;

  for( ix = 1; ix < polygonObj.line[0].numpoints; ix++ ) {
    pointObj  *pnt = polygonObj.line[0].point + ix;

    rect->minx = MS_MIN(rect->minx,pnt->x);
    rect->maxx = MS_MAX(rect->maxx,pnt->x);
    rect->miny = MS_MIN(rect->miny,pnt->y);
    rect->maxy = MS_MAX(rect->maxy,pnt->y);
  }

  msFreeShape( &polygonObj );

  /* -------------------------------------------------------------------- */
  /*      Special case to handle reprojection from "more than the         */
  /*      whole world" projected coordinates that sometimes produce a     */
  /*      region greater than 360 degrees wide due to various wrapping    */
  /*      logic.                                                          */
  /* -------------------------------------------------------------------- */
  if( out && pj_is_latlong(out->proj) && in && !pj_is_latlong(in->proj)
      && rect->maxx - rect->minx > 360.0 ) {
    rect->maxx = 180;
    rect->minx = -180;
  }

  return MS_SUCCESS;
#else
  msSetError(MS_PROJERR, "Projection support is not available.", "msProjectRect()");
  return(MS_FAILURE);
#endif
}
Esempio n. 5
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);
}
Esempio n. 6
0
static int msProjectSegment( projectionObj *in, projectionObj *out,
                             pointObj *start, pointObj *end )

{
  pointObj testPoint, subStart, subEnd;

  /* -------------------------------------------------------------------- */
  /*      Without loss of generality we assume the first point            */
  /*      reprojects, and the second doesn't.  If that is not the case    */
  /*      then re-call with the points reversed.                          */
  /* -------------------------------------------------------------------- */
  testPoint = *start;
  if( msProjectPoint( in, out, &testPoint ) == MS_FAILURE ) {
    testPoint = *end;
    if( msProjectPoint( in, out, &testPoint ) == MS_FAILURE )
      return MS_FAILURE;
    else
      return msProjectSegment( in, out, end, start );
  }

  /* -------------------------------------------------------------------- */
  /*      We will apply a binary search till we are within out            */
  /*      tolerance.                                                      */
  /* -------------------------------------------------------------------- */
  subStart = *start;
  subEnd = *end;

#define TOLERANCE 0.01

  while( fabs(subStart.x - subEnd.x)
         + fabs(subStart.y - subEnd.y) > TOLERANCE ) {
    pointObj midPoint;

    midPoint.x = (subStart.x + subEnd.x) * 0.5;
    midPoint.y = (subStart.y + subEnd.y) * 0.5;

    testPoint = midPoint;

    if( msProjectPoint( in, out, &testPoint ) == MS_FAILURE ) {
      if (midPoint.x == subEnd.x && midPoint.y == subEnd.y)
        return MS_FAILURE; /* break infinite loop */

      subEnd = midPoint;
    }
    else {
      if (midPoint.x == subStart.x && midPoint.y == subStart.y)
        return MS_FAILURE; /* break infinite loop */

      subStart = midPoint;
    }
  }

  /* -------------------------------------------------------------------- */
  /*      Now reproject the end points and return.                        */
  /* -------------------------------------------------------------------- */
  *end = subStart;

  if( msProjectPoint( in, out, end ) == MS_FAILURE
      || msProjectPoint( in, out, start ) == MS_FAILURE )
    return MS_FAILURE;
  else
    return MS_SUCCESS;
}