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)++; }
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 }
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); }
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 }
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); }
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; }