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