[mapserver-commits] r9786 - trunk/mapserver
svn at osgeo.org
svn at osgeo.org
Tue Feb 9 13:31:03 EST 2010
Author: warmerdam
Date: 2010-02-09 13:31:01 -0500 (Tue, 09 Feb 2010)
New Revision: 9786
Modified:
trunk/mapserver/HISTORY.TXT
trunk/mapserver/mapproject.c
Log:
reproject rectangles as polygons to get datelin wrapping benefits (#3179)
Modified: trunk/mapserver/HISTORY.TXT
===================================================================
--- trunk/mapserver/HISTORY.TXT 2010-02-09 03:25:47 UTC (rev 9785)
+++ trunk/mapserver/HISTORY.TXT 2010-02-09 18:31:01 UTC (rev 9786)
@@ -14,6 +14,8 @@
Current Version (SVN trunk):
----------------------------
+- Reproject rectangles as polygons to get datelin wrapping (#3179)
+
- Add support for the WMS capabilities items AuthorityURL, Identifier (#3251)
- Added support to write a null shape in a shape file. (#3277)
Modified: trunk/mapserver/mapproject.c
===================================================================
--- trunk/mapserver/mapproject.c 2010-02-09 03:25:47 UTC (rev 9785)
+++ trunk/mapserver/mapproject.c 2010-02-09 18:31:01 UTC (rev 9786)
@@ -195,138 +195,6 @@
#endif /* def USE_PROJ */
/************************************************************************/
-/* msProjectRect() */
-/************************************************************************/
-
-#define NUMBER_OF_SAMPLE_POINTS 100
-
-int msProjectRect(projectionObj *in, projectionObj *out, rectObj *rect)
-{
-#ifdef USE_PROJ
- pointObj prj_point;
- rectObj prj_rect;
- int rect_initialized = MS_FALSE, failure=0;
- int ix, iy;
-
- double dx, dy;
- double x, y;
-
- dx = (rect->maxx - rect->minx)/NUMBER_OF_SAMPLE_POINTS;
- dy = (rect->maxy - rect->miny)/NUMBER_OF_SAMPLE_POINTS;
-
- /* first ensure the top left corner is processed, even if the rect
- turns out to be degenerate. */
-
- prj_point.x = rect->minx;
- prj_point.y = rect->miny;
-#ifdef USE_POINT_Z_M
- prj_point.z = 0.0;
- prj_point.m = 0.0;
-#endif /* USE_POINT_Z_M */
-
- msProjectGrowRect(in,out,&prj_rect,&rect_initialized,&prj_point,
- &failure);
-
- /* sample along top and bottom */
- if(dx > 0) {
- for(ix = 0; ix <= NUMBER_OF_SAMPLE_POINTS; ix++ )
- {
- x = rect->minx + ix * dx;
-
- prj_point.x = x;
- prj_point.y = rect->miny;
- msProjectGrowRect(in,out,&prj_rect,&rect_initialized,&prj_point,
- &failure);
-
- prj_point.x = x;
- prj_point.y = rect->maxy;
- msProjectGrowRect(in,out,&prj_rect,&rect_initialized,&prj_point,
- &failure);
- }
- }
-
- /* sample along left and right */
- if(dy > 0) {
- for(iy = 0; iy <= NUMBER_OF_SAMPLE_POINTS; iy++ )
- {
- y = rect->miny + iy * dy;
-
- prj_point.y = y;
- prj_point.x = rect->minx;
- msProjectGrowRect(in,out,&prj_rect,&rect_initialized,&prj_point,
- &failure);
-
- prj_point.x = rect->maxx;
- prj_point.y = y;
- msProjectGrowRect(in,out,&prj_rect,&rect_initialized,&prj_point,
- &failure);
- }
- }
-
- /*
- ** If there have been any failures around the edges, then we had better
- ** try and fill in the interior to get a close bounds.
- */
- if( failure > 0 )
- {
- failure = 0;
- for(ix = 0; ix <= NUMBER_OF_SAMPLE_POINTS; ix++ )
- {
- x = rect->minx + ix * dx;
-
- for(iy = 0; iy <= NUMBER_OF_SAMPLE_POINTS; iy++ )
- {
- y = rect->miny + iy * dy;
-
- prj_point.x = x;
- prj_point.y = y;
- msProjectGrowRect(in,out,&prj_rect,&rect_initialized,&prj_point,
- &failure);
- }
- }
-
- if( !rect_initialized )
- {
- if( out == NULL || out->proj == NULL
- || pj_is_latlong(in->proj) )
- {
- prj_rect.minx = -180;
- prj_rect.maxx = 180;
- prj_rect.miny = -90;
- prj_rect.maxy = 90;
- }
- else
- {
- prj_rect.minx = -22000000;
- prj_rect.maxx = 22000000;
- prj_rect.miny = -11000000;
- prj_rect.maxy = 11000000;
- }
-
- msDebug( "msProjectRect(): all points failed to reproject, trying to fall back to using world bounds ... hope this helps.\n" );
- }
- else
- {
- msDebug( "msProjectRect(): some points failed to reproject, doing internal sampling.\n" );
- }
- }
-
- rect->minx = prj_rect.minx;
- rect->miny = prj_rect.miny;
- rect->maxx = prj_rect.maxx;
- rect->maxy = prj_rect.maxy;
-
- if( !rect_initialized )
- return MS_FAILURE;
- else
- return(MS_SUCCESS);
-#else
- msSetError(MS_PROJERR, "Projection support is not available.", "msProjectRect()");
- return(MS_FAILURE);
-#endif
-}
-
-/************************************************************************/
/* msProjectSegment() */
/* */
/* Interpolate along a line segment for which one end */
@@ -418,7 +286,7 @@
int line_alloc = numpoints_in;
int wrap_test;
- wrap_test = out->proj != NULL && pj_is_latlong(out->proj)
+ wrap_test = out != NULL && out->proj != NULL && pj_is_latlong(out->proj)
&& !pj_is_latlong(in->proj);
line->numpoints = 0;
@@ -697,6 +565,311 @@
}
/************************************************************************/
+/* msProjectRectGrid() */
+/************************************************************************/
+
+//#define NUMBER_OF_SAMPLE_POINTS 100
+#define NUMBER_OF_SAMPLE_POINTS 5
+
+int msProjectRectGrid(projectionObj *in, projectionObj *out, rectObj *rect)
+{
+#ifdef USE_PROJ
+ pointObj prj_point;
+ rectObj prj_rect;
+ int rect_initialized = MS_FALSE, failure=0;
+ int ix, iy;
+
+ double dx, dy;
+ double x, y;
+
+ dx = (rect->maxx - rect->minx)/NUMBER_OF_SAMPLE_POINTS;
+ dy = (rect->maxy - rect->miny)/NUMBER_OF_SAMPLE_POINTS;
+
+ /* first ensure the top left corner is processed, even if the rect
+ turns out to be degenerate. */
+
+ prj_point.x = rect->minx;
+ prj_point.y = rect->miny;
+#ifdef USE_POINT_Z_M
+ prj_point.z = 0.0;
+ prj_point.m = 0.0;
+#endif /* USE_POINT_Z_M */
+
+ msProjectGrowRect(in,out,&prj_rect,&rect_initialized,&prj_point,
+ &failure);
+
+ failure = 0;
+ for(ix = 0; ix <= NUMBER_OF_SAMPLE_POINTS; ix++ )
+ {
+ x = rect->minx + ix * dx;
+
+ for(iy = 0; iy <= NUMBER_OF_SAMPLE_POINTS; iy++ )
+ {
+ y = rect->miny + iy * dy;
+
+ prj_point.x = x;
+ prj_point.y = y;
+ msProjectGrowRect(in,out,&prj_rect,&rect_initialized,&prj_point,
+ &failure);
+ }
+ }
+
+ if( !rect_initialized )
+ {
+ if( out == NULL || out->proj == NULL
+ || pj_is_latlong(in->proj) )
+ {
+ prj_rect.minx = -180;
+ prj_rect.maxx = 180;
+ prj_rect.miny = -90;
+ prj_rect.maxy = 90;
+ }
+ else
+ {
+ prj_rect.minx = -22000000;
+ prj_rect.maxx = 22000000;
+ prj_rect.miny = -11000000;
+ prj_rect.maxy = 11000000;
+ }
+
+ msDebug( "msProjectRect(): all points failed to reproject, trying to fall back to using world bounds ... hope this helps.\n" );
+ }
+ else
+ {
+ msDebug( "msProjectRect(): some points failed to reproject, doing internal sampling.\n" );
+ }
+
+ rect->minx = prj_rect.minx;
+ rect->miny = prj_rect.miny;
+ rect->maxx = prj_rect.maxx;
+ rect->maxy = prj_rect.maxy;
+
+ if( !rect_initialized )
+ return MS_FAILURE;
+ else
+ return(MS_SUCCESS);
+#else
+ msSetError(MS_PROJERR, "Projection support is not available.", "msProjectRect()");
+ return(MS_FAILURE);
+#endif
+}
+
+/************************************************************************/
+/* msProjectRectTraditionalEdge() */
+/************************************************************************/
+
+static int
+msProjectRectTraditionalEdge(projectionObj *in, projectionObj *out,
+ rectObj *rect)
+{
+#ifdef USE_PROJ
+ pointObj prj_point;
+ rectObj prj_rect;
+ int rect_initialized = MS_FALSE, failure=0;
+ int ix, iy;
+
+ double dx, dy;
+ double x, y;
+
+ dx = (rect->maxx - rect->minx)/NUMBER_OF_SAMPLE_POINTS;
+ dy = (rect->maxy - rect->miny)/NUMBER_OF_SAMPLE_POINTS;
+
+ /* first ensure the top left corner is processed, even if the rect
+ turns out to be degenerate. */
+
+ prj_point.x = rect->minx;
+ prj_point.y = rect->miny;
+#ifdef USE_POINT_Z_M
+ prj_point.z = 0.0;
+ prj_point.m = 0.0;
+#endif /* USE_POINT_Z_M */
+
+ msProjectGrowRect(in,out,&prj_rect,&rect_initialized,&prj_point,
+ &failure);
+
+ /* sample along top and bottom */
+ if(dx > 0) {
+ for(ix = 0; ix <= NUMBER_OF_SAMPLE_POINTS; ix++ )
+ {
+ x = rect->minx + ix * dx;
+
+ prj_point.x = x;
+ prj_point.y = rect->miny;
+ msProjectGrowRect(in,out,&prj_rect,&rect_initialized,&prj_point,
+ &failure);
+
+ prj_point.x = x;
+ prj_point.y = rect->maxy;
+ msProjectGrowRect(in,out,&prj_rect,&rect_initialized,&prj_point,
+ &failure);
+ }
+ }
+
+ /* sample along left and right */
+ if(dy > 0) {
+ for(iy = 0; iy <= NUMBER_OF_SAMPLE_POINTS; iy++ )
+ {
+ y = rect->miny + iy * dy;
+
+ prj_point.y = y;
+ prj_point.x = rect->minx;
+ msProjectGrowRect(in,out,&prj_rect,&rect_initialized,&prj_point,
+ &failure);
+
+ prj_point.x = rect->maxx;
+ prj_point.y = y;
+ msProjectGrowRect(in,out,&prj_rect,&rect_initialized,&prj_point,
+ &failure);
+ }
+ }
+
+ /*
+ ** If there have been any failures around the edges, then we had better
+ ** try and fill in the interior to get a close bounds.
+ */
+ if( failure > 0 )
+ return msProjectRectGrid( in, out, rect );
+
+ rect->minx = prj_rect.minx;
+ rect->miny = prj_rect.miny;
+ rect->maxx = prj_rect.maxx;
+ rect->maxy = prj_rect.maxy;
+
+ if( !rect_initialized )
+ return MS_FAILURE;
+ else
+ return(MS_SUCCESS);
+#else
+ msSetError(MS_PROJERR, "Projection support is not available.", "msProjectRect()");
+ return(MS_FAILURE);
+#endif
+}
+
+/************************************************************************/
+/* msProjectRectAsPolygon() */
+/************************************************************************/
+
+static int
+msProjectRectAsPolygon(projectionObj *in, projectionObj *out,
+ rectObj *rect)
+{
+#ifdef USE_PROJ
+ shapeObj polygonObj;
+ lineObj ring;
+ pointObj ringPoints[NUMBER_OF_SAMPLE_POINTS*4+4];
+ int ix, iy;
+
+ double dx, dy;
+
+ ring.point = &(ringPoints[0]);
+ ring.numpoints = 0;
+
+ polygonObj.type = MS_SHAPE_POLYGON;
+ polygonObj.line = ˚
+ polygonObj.numlines = 1;
+ polygonObj.numvalues = 0;
+
+/* -------------------------------------------------------------------- */
+/* 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;
+
+ /* 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;
+ }
+ }
+
+/* -------------------------------------------------------------------- */
+/* Attempt to reproject. */
+/* -------------------------------------------------------------------- */
+ msProjectShapeLine( in, out, &polygonObj, 0 );
+
+ /* If no points reprojected, try a grid sampling */
+ if( ring.numpoints == 0 )
+ {
+ return msProjectRectGrid( in, out, rect );
+ }
+
+/* -------------------------------------------------------------------- */
+/* Collect bounds. */
+/* -------------------------------------------------------------------- */
+ rect->minx = rect->maxx = ringPoints[0].x;
+ rect->miny = rect->maxy = ringPoints[0].y;
+
+ for( ix = 1; ix < ring.numpoints; ix++ )
+ {
+ rect->minx = MIN(rect->minx,ringPoints[ix].x);
+ rect->maxx = MAX(rect->maxx,ringPoints[ix].x);
+ rect->miny = MIN(rect->miny,ringPoints[ix].y);
+ rect->maxy = MAX(rect->maxy,ringPoints[ix].y);
+ }
+
+/* -------------------------------------------------------------------- */
+/* 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
+}
+
+/************************************************************************/
+/* msProjectRect() */
+/************************************************************************/
+
+int msProjectRect(projectionObj *in, projectionObj *out, rectObj *rect)
+{
+#ifdef notdef
+ return msProjectRectTraditionalEdge( in, out, rect );
+#else
+ return msProjectRectAsPolygon( in, out, rect );
+#endif
+}
+
+/************************************************************************/
/* msProjectionsDiffer() */
/************************************************************************/
More information about the mapserver-commits
mailing list