/* ** Routine for clipping a polyline, stored in a shapeObj struct, to a ** rectangle. Uses clipLine() function to create a new shapeObj. */ void msClipPolylineRect(shapeObj *shape, rectObj rect) { int i,j; lineObj line={0,NULL}; double x1, x2, y1, y2; shapeObj tmp={0,NULL}; if(shape->numlines == 0) /* nothing to clip */ return; for(i=0; i<shape->numlines; i++) { line.point = (pointObj *)malloc(sizeof(pointObj)*shape->line[i].numpoints); line.numpoints = 0; x1 = shape->line[i].point[0].x; y1 = shape->line[i].point[0].y; for(j=1; j<shape->line[i].numpoints; j++) { x2 = shape->line[i].point[j].x; y2 = shape->line[i].point[j].y; if(clipLine(&x1,&y1,&x2,&y2,rect) == MS_TRUE) { if(line.numpoints == 0) { /* first segment, add both points */ line.point[0].x = x1; line.point[0].y = y1; line.point[1].x = x2; line.point[1].y = y2; line.numpoints = 2; } else { /* add just the last point */ line.point[line.numpoints].x = x2; line.point[line.numpoints].y = y2; line.numpoints++; } if((x2 != shape->line[i].point[j].x) || (y2 != shape->line[i].point[j].y)) { msAddLine(&tmp, &line); line.numpoints = 0; /* new line */ } } x1 = shape->line[i].point[j].x; y1 = shape->line[i].point[j].y; } if(line.numpoints > 0) msAddLine(&tmp, &line); free(line.point); line.numpoints = 0; /* new line */ } for (i=0; i<shape->numlines; i++) free(shape->line[i].point); free(shape->line); shape->line = tmp.line; shape->numlines = tmp.numlines; }
int msCopyShape(shapeObj *from, shapeObj *to) { int i; if(!from || !to) return(-1); for(i=0; i<from->numlines; i++) msAddLine(to, &(from->line[i])); // copy each line to->type = from->type; to->bounds.minx = from->bounds.minx; to->bounds.miny = from->bounds.miny; to->bounds.maxx = from->bounds.maxx; to->bounds.maxy = from->bounds.maxy; if(from->text) to->text = _strdup(from->text); to->classindex = from->classindex; to->index = from->index; to->tileindex = from->tileindex; if(from->values) { to->values = (char **)malloc(sizeof(char *)*from->numvalues); for(i=0; i<from->numvalues; i++) to->values[i] = _strdup(from->values[i]); to->numvalues = from->numvalues; } return(0); }
int msUVRASTERLayerGetShape(layerObj *layer, shapeObj *shape, resultObj *record) { uvRasterLayerInfo *uvlinfo = (uvRasterLayerInfo *) layer->layerinfo; lineObj line ; pointObj point; int i, j, k, x=0, y=0; long shapeindex = record->shapeindex; msFreeShape(shape); shape->type = MS_SHAPE_NULL; if( shapeindex < 0 || shapeindex >= uvlinfo->query_results ) { msSetError(MS_MISCERR, "Out of range shape index requested. Requested %ld\n" "but only %d shapes available.", "msUVRASTERLayerGetShape()", shapeindex, uvlinfo->query_results ); return MS_FAILURE; } /* loop to the next non null vector */ k = 0; for (i=0, x=-1; i<uvlinfo->width && k<=shapeindex; ++i, ++x) { for (j=0, y=-1; j<uvlinfo->height && k<=shapeindex; ++j, ++k, ++y) { if (uvlinfo->u[i][j] == 0 && uvlinfo->v[i][j] == 0) --k; } } point.x = Pix2Georef(x, 0, uvlinfo->width-1, uvlinfo->extent.minx, uvlinfo->extent.maxx, MS_FALSE); point.y = Pix2Georef(y, 0, uvlinfo->height-1, uvlinfo->extent.miny, uvlinfo->extent.maxy, MS_TRUE); if (layer->debug == 5) msDebug("msUVRASTERLayerWhichShapes(): shapeindex: %ld, x: %g, y: %g\n", shapeindex, point.x, point.y); #ifdef USE_POINT_Z_M point.m = 0.0; #endif shape->type = MS_SHAPE_POINT; line.numpoints = 1; line.point = &point; msAddLine( shape, &line ); msComputeBounds( shape ); shape->numvalues = layer->numitems; shape->values = msUVRASTERGetValues(layer, &uvlinfo->u[x][y], &uvlinfo->v[x][y]); return MS_SUCCESS; }
/* static pointObj get_metrics(pointObj *p, int position, rectObj rect, int ox, int oy, double angle, int buffer, shapeObj *poly) */ pointObj get_metrics(pointObj *p, int position, rectObj rect, int ox, int oy, double angle, int buffer, shapeObj *poly) { lineObj newline; pointObj newpoints[5]; pointObj rp; newline.numpoints=5; newline.point=newpoints; rp = get_metrics_line(p, position, rect, ox,oy, angle, buffer, &newline); if(poly) { msAddLine(poly,&newline); msComputeBounds(poly); } return rp; }
/* ** Converts a rect array to a shapeObj structure. Note order is CW assuming y origin ** is in the lower left corner (normal cartesian coordinate system). Also polygon is ** is closed (i.e. first=last). This conforms to the shapefile specification. For image ** coordinate systems (i.e. GD) this is back-ass-ward, which is fine cause the function ** that calculates direction assumes min y = lower left, this way it'll still work. Drawing ** functions are independent of direction. Orientation problems can cause some nasty bugs. */ void msRectToPolygon(rectObj rect, shapeObj *poly) { lineObj line={0,NULL}; line.point = (pointObj *)malloc(sizeof(pointObj)*5); line.point[0].x = rect.minx; line.point[0].y = rect.miny; line.point[1].x = rect.minx; line.point[1].y = rect.maxy; line.point[2].x = rect.maxx; line.point[2].y = rect.maxy; line.point[3].x = rect.maxx; line.point[3].y = rect.miny; line.point[4].x = line.point[0].x; line.point[4].y = line.point[0].y; line.numpoints = 5; msAddLine(poly, &line); poly->type = MS_SHAPE_POLYGON; poly->bounds = rect; free(line.point); }
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); }
/* * RFC89 implementation: * - transform directly the shapeobj */ int msGeomTransformShape(mapObj *map, layerObj *layer, shapeObj *shape) { int i; expressionObj *e = &layer->_geomtransform; #ifdef USE_V8_MAPSCRIPT if (!map->v8context) { msV8CreateContext(map); if (!map->v8context) { msSetError(MS_V8ERR, "Unable to create v8 context.", "msGeomTransformShape()"); return MS_FAILURE; } } msV8ContextSetLayer(map, layer); #endif switch(e->type) { case MS_GEOMTRANSFORM_EXPRESSION: { int status; shapeObj *tmpshp; parseObj p; p.shape = shape; /* set a few parser globals (hence the lock) */ p.expr = e; p.expr->curtoken = p.expr->tokens; /* reset */ p.type = MS_PARSE_TYPE_SHAPE; p.dblval = map->cellsize * (msInchesPerUnit(map->units,0)/msInchesPerUnit(layer->units,0)); p.dblval2 = 0; /* data_cellsize is only set with contour layer */ if (layer->connectiontype == MS_CONTOUR) { char *value = msLookupHashTable(&layer->metadata, "__data_cellsize__"); if (value) p.dblval2 = atof(value); } status = yyparse(&p); if (status != 0) { msSetError(MS_PARSEERR, "Failed to process shape expression: %s", "msGeomTransformShape()", e->string); return MS_FAILURE; } tmpshp = p.result.shpval; for (i= 0; i < shape->numlines; i++) free(shape->line[i].point); shape->numlines = 0; if (shape->line) free(shape->line); for(i=0; i<tmpshp->numlines; i++) msAddLine(shape, &(tmpshp->line[i])); /* copy each line */ msFreeShape(tmpshp); msFree(tmpshp); } break; default: msSetError(MS_MISCERR, "unknown geomtransform", "msGeomTransformShape()"); return MS_FAILURE; } 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); }
/* ** Slightly modified version of the Liang-Barsky polygon clipping algorithm */ void msClipPolygonRect(shapeObj *shape, rectObj rect) { int i, j; double deltax, deltay, xin,xout, yin,yout; double tinx,tiny, toutx,touty, tin1, tin2, tout; double x1,y1, x2,y2; shapeObj tmp; lineObj line={0,NULL}; msInitShape(&tmp); if(shape->numlines == 0) /* nothing to clip */ return; for(j=0; j<shape->numlines; j++) { line.point = (pointObj *)malloc(sizeof(pointObj)*2*shape->line[j].numpoints+1); /* worst case scenario, +1 allows us to duplicate the 1st and last point */ line.numpoints = 0; for (i = 0; i < shape->line[j].numpoints-1; i++) { x1 = shape->line[j].point[i].x; y1 = shape->line[j].point[i].y; x2 = shape->line[j].point[i+1].x; y2 = shape->line[j].point[i+1].y; deltax = x2-x1; if (deltax == 0) { /* bump off of the vertical */ deltax = (x1 > rect.minx) ? -NEARZERO : NEARZERO ; } deltay = y2-y1; if (deltay == 0) { /* bump off of the horizontal */ deltay = (y1 > rect.miny) ? -NEARZERO : NEARZERO ; } if (deltax > 0) { /* points to right */ xin = rect.minx; xout = rect.maxx; } else { xin = rect.maxx; xout = rect.minx; } if (deltay > 0) { /* points up */ yin = rect.miny; yout = rect.maxy; } else { yin = rect.maxy; yout = rect.miny; } tinx = (xin - x1)/deltax; tiny = (yin - y1)/deltay; if (tinx < tiny) { /* hits x first */ tin1 = tinx; tin2 = tiny; } else { /* hits y first */ tin1 = tiny; tin2 = tinx; } if (1 >= tin1) { if (0 < tin1) { line.point[line.numpoints].x = xin; line.point[line.numpoints].y = yin; line.numpoints++; } if (1 >= tin2) { toutx = (xout - x1)/deltax; touty = (yout - y1)/deltay; tout = (toutx < touty) ? toutx : touty ; if (0 < tin2 || 0 < tout) { if (tin2 <= tout) { if (0 < tin2) { if (tinx > tiny) { line.point[line.numpoints].x = xin; line.point[line.numpoints].y = y1 + tinx*deltay; line.numpoints++; } else { line.point[line.numpoints].x = x1 + tiny*deltax; line.point[line.numpoints].y = yin; line.numpoints++; } } if (1 > tout) { if (toutx < touty) { line.point[line.numpoints].x = xout; line.point[line.numpoints].y = y1 + toutx*deltay; line.numpoints++; } else { line.point[line.numpoints].x = x1 + touty*deltax; line.point[line.numpoints].y = yout; line.numpoints++; } } else { line.point[line.numpoints].x = x2; line.point[line.numpoints].y = y2; line.numpoints++; } } else { if (tinx > tiny) { line.point[line.numpoints].x = xin; line.point[line.numpoints].y = yout; line.numpoints++; } else { line.point[line.numpoints].x = xout; line.point[line.numpoints].y = yin; line.numpoints++; } } } } } } if(line.numpoints > 0) { line.point[line.numpoints].x = line.point[0].x; // force closure line.point[line.numpoints].y = line.point[0].y; line.numpoints++; msAddLine(&tmp, &line); } free(line.point); } /* next line */ for (i=0; i<shape->numlines; i++) free(shape->line[i].point); free(shape->line); shape->line = tmp.line; shape->numlines = tmp.numlines; return; }
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; }
/* 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; }