/********************************************************************** * msWFSLayerGetNextShape() * **********************************************************************/ int msWFSLayerNextShape(layerObj *layer, shapeObj *shape) { #ifdef USE_WFS_LYR msWFSLayerInfo* psInfo = NULL; if(layer != NULL && layer->wfslayerinfo != NULL) psInfo = (msWFSLayerInfo*)layer->wfslayerinfo; else { msSetError(MS_WFSERR, "Layer is not opened.", "msWFSLayerNextShape()"); return MS_FAILURE; } if(psInfo->bLayerHasValidGML) return msOGRLayerNextShape(layer, shape); else { /* Layer is successful, but there is no data to process */ msFreeShape(shape); shape->type = MS_SHAPE_NULL; return MS_FAILURE; } #else /* ------------------------------------------------------------------ * WFS CONNECTION Support not included... * ------------------------------------------------------------------ */ msSetError(MS_WFSCONNERR, "WFS CLIENT CONNECTION support is not available.", "msWFSLayerNextShape()"); return(MS_FAILURE); #endif /* USE_WFS_LYR */ }
int msProjectShape(projectionObj *in, projectionObj *out, shapeObj *shape) { #ifdef USE_PROJ int i; for( i = shape->numlines-1; i >= 0; i-- ) { if( shape->type == MS_SHAPE_LINE || shape->type == MS_SHAPE_POLYGON ) { if( msProjectShapeLine( in, out, shape, i ) == MS_FAILURE ) msShapeDeleteLine( shape, i ); } else if( msProjectLine(in, out, shape->line+i ) == MS_FAILURE ) { msShapeDeleteLine( shape, i ); } } if( shape->numlines == 0 ) { msFreeShape( shape ); return MS_FAILURE; } else { msComputeBounds( shape ); /* fixes bug 1586 */ return(MS_SUCCESS); } #else msSetError(MS_PROJERR, "Projection support is not available.", "msProjectShape()"); return(MS_FAILURE); #endif }
int msCircleDrawShadeSymbol(mapObj *map, imageObj *image, pointObj *p, double r, styleObj *style, double scalefactor) { shapeObj *circle; int status; if (!image) return MS_FAILURE; circle = msRasterizeArc(p->x, p->y, r, 0, 360, 0); if (!circle) return MS_FAILURE; status = msDrawShadeSymbol(map, image, circle, style, scalefactor); msFreeShape(circle); msFree(circle); return status; }
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; }
int msProjectShape(projectionObj *in, projectionObj *out, shapeObj *shape) { #ifdef USE_PROJ int i; #ifdef USE_PROJ_FASTPATHS int j; if(in->wellknownprojection == wkp_lonlat && out->wellknownprojection == wkp_gmerc) { for( i = shape->numlines-1; i >= 0; i-- ) { for( j = shape->line[i].numpoints-1; j >= 0; j-- ) { #define p_x shape->line[i].point[j].x #define p_y shape->line[i].point[j].y 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; #undef p_x #undef p_y } } msComputeBounds( shape ); /* fixes bug 1586 */ return MS_SUCCESS; } #endif for( i = shape->numlines-1; i >= 0; i-- ) { if( shape->type == MS_SHAPE_LINE || shape->type == MS_SHAPE_POLYGON ) { if( msProjectShapeLine( in, out, shape, i ) == MS_FAILURE ) msShapeDeleteLine( shape, i ); } else if( msProjectLine(in, out, shape->line+i ) == MS_FAILURE ) { msShapeDeleteLine( shape, i ); } } if( shape->numlines == 0 ) { msFreeShape( shape ); return MS_FAILURE; } else { msComputeBounds( shape ); /* fixes bug 1586 */ return(MS_SUCCESS); } #else msSetError(MS_PROJERR, "Projection support is not available.", "msProjectShape()"); return(MS_FAILURE); #endif }
shapeObj *layerObj_nextShape(layerObj *self) { int status; shapeObj *shape; shape = (shapeObj *)malloc(sizeof(shapeObj)); if (!shape) return NULL; msInitShape(shape); status = msLayerNextShape(self, shape); if(status != MS_SUCCESS) { msFreeShape(shape); free(shape); return NULL; } else return shape; }
/* destroy memory of the cluster list */ static void clusterInfoDestroyList(msClusterLayerInfo* layerinfo, clusterInfo* feature) { clusterInfo* s = feature; clusterInfo* next; /* destroy the shapes added to this node */ while (s) { next = s->next; if (s->siblings) { clusterInfoDestroyList(layerinfo, s->siblings); } msFreeShape(&s->shape); msFree(s->group); msFree(s); --layerinfo->numFeatures; s = next; } }
int msDrawPieSlice(mapObj *map, imageObj *image, pointObj *p, styleObj *style, double radius, double start, double end) { int status; shapeObj *circle; double center_x = p->x; double center_y = p->y; if (!image) return MS_FAILURE; if(style->offsetx>0) { center_x+=style->offsetx*cos(((-start-end)*MS_PI/360.)); center_y-=style->offsetx*sin(((-start-end)*MS_PI/360.)); } circle = msRasterizeArc(center_x, center_y, radius, start, end, 1); if (!circle) return MS_FAILURE; status = msDrawShadeSymbol(map, image, circle, style, 1.0); msFreeShape(circle); msFree(circle); return status; }
int msUVRASTERLayerNextShape(layerObj *layer, shapeObj *shape) { uvRasterLayerInfo *uvlinfo = (uvRasterLayerInfo *) layer->layerinfo; if( uvlinfo->next_shape < 0 || uvlinfo->next_shape >= uvlinfo->query_results ) { msFreeShape(shape); shape->type = MS_SHAPE_NULL; return MS_DONE; } else { resultObj record; record.shapeindex = uvlinfo->next_shape++; record.tileindex = 0; record.classindex = record.resultindex = -1; return msUVRASTERLayerGetShape( layer, shape, &record); } }
/* * RFC48 implementation: * - transform the original shapeobj * - use the styleObj to render the transformed shapeobj */ int msDrawTransformedShape(mapObj *map, imageObj *image, shapeObj *shape, styleObj *style, double scalefactor) { int type = style->_geomtransform.type; int i,j,status = MS_SUCCESS; switch(type) { case MS_GEOMTRANSFORM_END: /*render point on last vertex only*/ for(j=0; j<shape->numlines; j++) { lineObj *line = &(shape->line[j]); pointObj *p = &(line->point[line->numpoints-1]); if(p->x<0||p->x>image->width||p->y<0||p->y>image->height) continue; if(style->autoangle==MS_TRUE && line->numpoints>1) { style->angle = calcOrientation(&(line->point[line->numpoints-2]),p); } status = msDrawMarkerSymbol(map,image,p,style,scalefactor); } break; case MS_GEOMTRANSFORM_START: /*render point on first vertex only*/ for(j=0; j<shape->numlines; j++) { lineObj *line = &(shape->line[j]); pointObj *p = &(line->point[0]); /*skip if outside image*/ if(p->x<0||p->x>image->width||p->y<0||p->y>image->height) continue; if(style->autoangle==MS_TRUE && line->numpoints>1) { style->angle = calcOrientation(p,&(line->point[1])); } status = msDrawMarkerSymbol(map,image,p,style,scalefactor); } break; case MS_GEOMTRANSFORM_VERTICES: for(j=0; j<shape->numlines; j++) { lineObj *line = &(shape->line[j]); for(i=1; i<line->numpoints-1; i++) { pointObj *p = &(line->point[i]); /*skip points outside image*/ if(p->x<0||p->x>image->width||p->y<0||p->y>image->height) continue; if(style->autoangle==MS_TRUE) { style->angle = calcMidAngle(&(line->point[i-1]),&(line->point[i]),&(line->point[i+1])); } status = msDrawMarkerSymbol(map,image,p,style,scalefactor); } } break; case MS_GEOMTRANSFORM_BBOX: { shapeObj bbox; lineObj bbox_line; pointObj bbox_points[5]; int padding = MS_MAX(style->width,style->size)+3; /* so clipped shape does not extent into image */ /*create a shapeObj representing the bounding box (clipped by the image size)*/ bbox.numlines = 1; bbox.line = &bbox_line; bbox.line->numpoints = 5; bbox.line->point = bbox_points; msComputeBounds(shape); bbox_points[0].x=bbox_points[4].x=bbox_points[1].x = (shape->bounds.minx < -padding) ? -padding : shape->bounds.minx; bbox_points[2].x=bbox_points[3].x = (shape->bounds.maxx > image->width+padding) ? image->width+padding : shape->bounds.maxx; bbox_points[0].y=bbox_points[4].y=bbox_points[3].y = (shape->bounds.miny < -padding) ? -padding : shape->bounds.miny; bbox_points[1].y=bbox_points[2].y = (shape->bounds.maxy > image->height+padding) ? image->height+padding : shape->bounds.maxy; status = msDrawShadeSymbol(map, image, &bbox, style, scalefactor); } break; case MS_GEOMTRANSFORM_CENTROID: { double unused; /*used by centroid function*/ pointObj centroid; if(MS_SUCCESS == msGetPolygonCentroid(shape,¢roid,&unused,&unused)) { status = msDrawMarkerSymbol(map,image,¢roid,style,scalefactor); } } break; case MS_GEOMTRANSFORM_EXPRESSION: { int status; shapeObj *tmpshp; parseObj p; p.shape = shape; /* set a few parser globals (hence the lock) */ p.expr = &(style->_geomtransform); if(p.expr->tokens == NULL) { /* this could happen if drawing originates from legend code (#5193) */ status = msTokenizeExpression(p.expr, NULL, NULL); if(status != MS_SUCCESS) { msSetError(MS_MISCERR, "Unable to tokenize expression.", "msDrawTransformedShape()"); return MS_FAILURE; } } p.expr->curtoken = p.expr->tokens; /* reset */ p.type = MS_PARSE_TYPE_SHAPE; status = yyparse(&p); if (status != 0) { msSetError(MS_PARSEERR, "Failed to process shape expression: %s", "msDrawTransformedShape", style->_geomtransform.string); return MS_FAILURE; } tmpshp = p.result.shpval; switch (tmpshp->type) { case MS_SHAPE_POINT: case MS_SHAPE_POLYGON: status = msDrawShadeSymbol(map, image, tmpshp, style, scalefactor); break; case MS_SHAPE_LINE: status = msDrawLineSymbol(map, image, tmpshp, style, scalefactor); break; } msFreeShape(tmpshp); msFree(tmpshp); } break; case MS_GEOMTRANSFORM_LABELPOINT: case MS_GEOMTRANSFORM_LABELPOLY: break; default: msSetError(MS_MISCERR, "unknown geomtransform", "msDrawTransformedShape()"); return MS_FAILURE; } return status; }
/* * 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; }
void XShape::clear() { msFreeShape(&shape); }
int msDrawShadeSymbol(mapObj *map, imageObj *image, shapeObj *p, styleObj *style, double scalefactor) { int ret = MS_SUCCESS; symbolObj *symbol; if (!p) return MS_SUCCESS; if (p->numlines <= 0) return MS_SUCCESS; if (style->symbol >= map->symbolset.numsymbols || style->symbol < 0) return MS_SUCCESS; /* no such symbol, 0 is OK */ symbol = map->symbolset.symbol[style->symbol]; /* * if only an outlinecolor was defined, and not a color, * switch to the line drawing function * * this behavior is kind of a mapfile hack, and must be * kept for backwards compatibility */ if (symbol->type != MS_SYMBOL_PIXMAP && symbol->type != MS_SYMBOL_SVG ) { if (!MS_VALID_COLOR(style->color)) { if(MS_VALID_COLOR(style->outlinecolor)) return msDrawLineSymbol(map, image, p, style, scalefactor); else { /* just do nothing if no color has been set */ return MS_SUCCESS; } } } if (image) { if (MS_RENDERER_PLUGIN(image->format)) { rendererVTableObj *renderer = image->format->vtable; shapeObj *offsetPolygon = NULL; /* store a reference to the renderer to be used for freeing */ if(style->symbol) symbol->renderer = renderer; if (style->offsetx != 0 || style->offsety != 0) { if(style->offsety==MS_STYLE_SINGLE_SIDED_OFFSET) { offsetPolygon = msOffsetPolyline(p, style->offsetx*scalefactor, MS_STYLE_SINGLE_SIDED_OFFSET); } else if(style->offsety==MS_STYLE_DOUBLE_SIDED_OFFSET) { offsetPolygon = msOffsetPolyline(p,style->offsetx * scalefactor ,MS_STYLE_DOUBLE_SIDED_OFFSET); } else { offsetPolygon = msOffsetPolyline(p, style->offsetx*scalefactor,style->offsety*scalefactor); } } else { offsetPolygon=p; } /* simple polygon drawing, without any specific symbol. * also draws an optional outline */ if(style->symbol == 0 || symbol->type == MS_SYMBOL_SIMPLE) { ret = renderer->renderPolygon(image,offsetPolygon,&style->color); if(ret != MS_SUCCESS) goto cleanup; if(MS_VALID_COLOR(style->outlinecolor)) { strokeStyleObj s; INIT_STROKE_STYLE(s); s.color = &style->outlinecolor; s.color->alpha = style->color.alpha; s.width = (style->width == 0)?scalefactor:style->width*scalefactor; s.width = MS_MIN(s.width, style->maxwidth); s.width = MS_MAX(s.width, style->minwidth); ret = renderer->renderLine(image,offsetPolygon,&s); } goto cleanup; /*finished plain polygon*/ } else if(symbol->type == MS_SYMBOL_HATCH) { double width, spacing; double pattern[MS_MAXPATTERNLENGTH]; int i; if(MS_VALID_COLOR(style->backgroundcolor)) { ret = renderer->renderPolygon(image,offsetPolygon, &style->backgroundcolor); if(ret != MS_SUCCESS) goto cleanup; } width = (style->width <= 0)?scalefactor:style->width*scalefactor; width = MS_MIN(width, style->maxwidth*image->resolutionfactor); width = MS_MAX(width, style->minwidth*image->resolutionfactor); spacing = (style->size <= 0)?scalefactor:style->size*scalefactor; spacing = MS_MIN(spacing, style->maxsize*image->resolutionfactor); spacing = MS_MAX(spacing, style->minsize*image->resolutionfactor); /* scale the pattern by the factor applied to the width */ for(i=0; i<style->patternlength; i++) { pattern[i] = style->pattern[i]*width/style->width; } ret = msHatchPolygon(image,offsetPolygon,spacing,width,pattern,style->patternlength,style->angle, &style->color); goto cleanup; } else { symbolStyleObj s; int pw,ph; imageObj *tile; int seamless = 0; if(preloadSymbol(&map->symbolset,symbol,renderer) != MS_SUCCESS) { return MS_FAILURE; } INIT_SYMBOL_STYLE(s); computeSymbolStyle(&s,style,symbol,scalefactor,image->resolutionfactor); s.style = style; if (!s.color && !s.outlinecolor && symbol->type != MS_SYMBOL_PIXMAP && symbol->type != MS_SYMBOL_SVG) { ret = MS_SUCCESS; /* nothing to do (colors are required except for PIXMAP symbols */ goto cleanup; } if(s.backgroundcolor) { ret = renderer->renderPolygon(image,offsetPolygon, s.backgroundcolor); if(ret != MS_SUCCESS) goto cleanup; } if(s.scale != 1) { if (s.gap > 0) { pw = MS_MAX(MS_NINT(s.gap),symbol->sizex * s.scale); ph = MS_MAX(MS_NINT(s.gap),symbol->sizey * s.scale); } else { pw = MS_NINT(symbol->sizex * s.scale); ph = MS_NINT(symbol->sizey * s.scale); } } else { if (s.gap > 0) { pw = MS_MAX(s.gap,symbol->sizex); ph = MS_MAX(s.gap,symbol->sizey); } else { pw = symbol->sizex; ph = symbol->sizey; } } if(pw<1) pw=1; if(ph<1) ph=1; /* if we're doing vector symbols with an antialiased pixel rendererer, we want to enable * seamless mode, i.e. comute a tile that accounts for the blending of neighbouring * tiles at the tile border */ if(symbol->type == MS_SYMBOL_VECTOR && style->gap == 0 && (image->format->renderer == MS_RENDER_WITH_AGG || image->format->renderer == MS_RENDER_WITH_CAIRO_RASTER)) { seamless = 1; } tile = getTile(image,symbol,&s,pw,ph,seamless); ret = renderer->renderPolygonTiled(image,offsetPolygon, tile); } cleanup: if (offsetPolygon != p) { msFreeShape(offsetPolygon); msFree(offsetPolygon); } return ret; } else if( MS_RENDERER_IMAGEMAP(image->format) ) msDrawShadeSymbolIM(map, image, p, style, scalefactor); } return ret; }
int msDrawLineSymbol(mapObj *map, imageObj *image, shapeObj *p, styleObj *style, double scalefactor) { int status = MS_SUCCESS; if (image) { if (MS_RENDERER_PLUGIN(image->format)) { rendererVTableObj *renderer = image->format->vtable; symbolObj *symbol; shapeObj *offsetLine = p; int i; double width; double finalscalefactor; if (p->numlines == 0) return MS_SUCCESS; if (style->symbol >= map->symbolset.numsymbols || style->symbol < 0) return MS_SUCCESS; /* no such symbol, 0 is OK */ symbol = map->symbolset.symbol[style->symbol]; /* store a reference to the renderer to be used for freeing */ symbol->renderer = renderer; width = style->width * scalefactor; width = MS_MIN(width,style->maxwidth*image->resolutionfactor); width = MS_MAX(width,style->minwidth*image->resolutionfactor); if(style->width != 0) { finalscalefactor = width / style->width; } else { finalscalefactor = 1.0; } if(style->offsety==MS_STYLE_SINGLE_SIDED_OFFSET) { offsetLine = msOffsetPolyline(p,style->offsetx * finalscalefactor ,MS_STYLE_SINGLE_SIDED_OFFSET); } else if(style->offsety==MS_STYLE_DOUBLE_SIDED_OFFSET) { offsetLine = msOffsetPolyline(p,style->offsetx * finalscalefactor ,MS_STYLE_DOUBLE_SIDED_OFFSET); } else if(style->offsetx!=0 || style->offsety!=0) { offsetLine = msOffsetPolyline(p, style->offsetx * finalscalefactor, style->offsety * finalscalefactor); } if(style->symbol == 0 || (symbol->type==MS_SYMBOL_SIMPLE)) { strokeStyleObj s; s.linecap = style->linecap; s.linejoin = style->linejoin; s.linejoinmaxsize = style->linejoinmaxsize; s.width = width; s.patternlength = style->patternlength; for(i=0; i<s.patternlength; i++) s.pattern[i] = style->pattern[i] * finalscalefactor; s.patternoffset = (style->initialgap<=0) ? 0 : (style->initialgap * finalscalefactor); if(MS_VALID_COLOR(style->color)) s.color = &style->color; else if(MS_VALID_COLOR(style->outlinecolor)) s.color = &style->outlinecolor; else { /* msSetError(MS_MISCERR,"no color defined for line styling","msDrawLineSymbol()"); * not really an error */ status = MS_SUCCESS; goto draw_line_cleanup; } status = renderer->renderLine(image,offsetLine,&s); } else { symbolStyleObj s; if(preloadSymbol(&map->symbolset, symbol, renderer) != MS_SUCCESS) { return MS_FAILURE; } INIT_SYMBOL_STYLE(s); computeSymbolStyle(&s,style,symbol,scalefactor,image->resolutionfactor); s.style = style; /* compute a markerStyle and use it on the line */ if(style->gap<0) { /* special function that treats any other symbol used as a marker, not a brush */ status = msImagePolylineMarkers(image,offsetLine,symbol,&s,-s.gap, style->initialgap * finalscalefactor, 1); } else if(style->gap>0) { status = msImagePolylineMarkers(image,offsetLine,symbol,&s,s.gap, style->initialgap * finalscalefactor,0); } else { if(renderer->renderLineTiled != NULL) { int pw,ph; imageObj* tile=NULL; if(s.scale != 1) { pw = MS_NINT(symbol->sizex * s.scale); ph = MS_NINT(symbol->sizey * s.scale); } else { pw = symbol->sizex; ph = symbol->sizey; } if(pw<1) pw=1; if(ph<1) ph=1; tile = getTile(image, symbol,&s,pw,ph,0); status = renderer->renderLineTiled(image, offsetLine, tile); } else { msSetError(MS_RENDERERERR, "renderer does not support brushed lines", "msDrawLineSymbol()"); status = MS_FAILURE; } } } draw_line_cleanup: if(offsetLine!=p) { msFreeShape(offsetLine); msFree(offsetLine); } } else if( MS_RENDERER_IMAGEMAP(image->format) ) msDrawLineSymbolIM(map, image, p, style, scalefactor); else { msSetError(MS_RENDERERERR, "unsupported renderer", "msDrawShadeSymbol()"); status = MS_FAILURE; } } else { status = MS_FAILURE; } return status; }
XShape::~XShape() { free(label); msFreeShape(&shape); }
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; ringPoints = (pointObj*) calloc(sizeof(pointObj),NUMBER_OF_SAMPLE_POINTS*4+4); ring.point = ringPoints; ring.numpoints = 0; msInitShape( &polygonObj ); polygonObj.type = MS_SHAPE_POLYGON; /* -------------------------------------------------------------------- */ /* 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; } } msAddLineDirectly( &polygonObj, &ring ); /* -------------------------------------------------------------------- */ /* 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 ); } /* -------------------------------------------------------------------- */ /* 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 }
XShape::XShape(shapefileObj *shpfile, const GeoPoint &file_center, int i, int label_field) :label(nullptr) { #ifdef ENABLE_OPENGL std::fill_n(index_count, THINNING_LEVELS, nullptr); std::fill_n(indices, THINNING_LEVELS, nullptr); #endif shapeObj shape; msInitShape(&shape); msSHPReadShape(shpfile->hSHP, i, &shape); bounds = ImportRect(shape.bounds); type = shape.type; num_lines = 0; const int min_points = min_points_for_type(shape.type); if (min_points < 0) { /* not supported, leave an empty XShape object */ points = nullptr; msFreeShape(&shape); return; } const unsigned input_lines = std::min((unsigned)shape.numlines, (unsigned)MAX_LINES); unsigned num_points = 0; for (unsigned l = 0; l < input_lines; ++l) { if (shape.line[l].numpoints < min_points) /* malformed shape */ continue; lines[num_lines] = std::min(shape.line[l].numpoints, 16384); num_points += lines[num_lines]; ++num_lines; } #ifdef ENABLE_OPENGL /* OpenGL: convert GeoPoints to ShapePoints, make them relative to the map's boundary center */ points = new ShapePoint[num_points]; ShapePoint *p = points; #else // !ENABLE_OPENGL /* convert all points of all lines to GeoPoints */ points = new GeoPoint[num_points]; GeoPoint *p = points; #endif for (unsigned l = 0; l < num_lines; ++l) { const pointObj *src = shape.line[l].point; num_points = lines[l]; for (unsigned j = 0; j < num_points; ++j, ++src) { #ifdef ENABLE_OPENGL const GeoPoint vertex(Angle::Degrees(src->x), Angle::Degrees(src->y)); const GeoPoint relative = vertex - file_center; *p++ = ShapePoint(ShapeScalar(relative.longitude.Native()), ShapeScalar(relative.latitude.Native())); #else *p++ = GeoPoint(Angle::Degrees(fixed(src->x)), Angle::Degrees(fixed(src->y))); #endif } } if (label_field >= 0) { const char *src = msDBFReadStringAttribute(shpfile->hDBF, i, label_field); label = import_label(src); } msFreeShape(&shape); }
int msDrawBarChartLayer(mapObj *map, layerObj *layer, imageObj *image) { shapeObj shape; int status=MS_SUCCESS; const char *chartSizeProcessingKey=msLayerGetProcessingKey( layer,"CHART_SIZE" ); const char *barMax=msLayerGetProcessingKey( layer,"CHART_BAR_MAXVAL" ); const char *barMin=msLayerGetProcessingKey( layer,"CHART_BAR_MINVAL" ); float width,height; float barWidth; float *values; styleObj **styles; pointObj center; float barMaxVal,barMinVal; int numvalues = layer->numclasses; if(chartSizeProcessingKey==NULL) { width=height=20; } else { switch(sscanf(chartSizeProcessingKey ,"%f %f",&width,&height)) { case 2: break; case 1: height = width; break; default: msSetError(MS_MISCERR, "msDrawChart format error for processing key \"CHART_SIZE\"", "msDrawBarChartLayer()"); return MS_FAILURE; } } if(barMax) { if(sscanf(barMax,"%f",&barMaxVal)!=1) { msSetError(MS_MISCERR, "Error reading value for processing key \"CHART_BAR_MAXVAL\"", "msDrawBarChartLayer()"); return MS_FAILURE; } } if(barMin) { if(sscanf(barMin,"%f",&barMinVal)!=1) { msSetError(MS_MISCERR, "Error reading value for processing key \"CHART_BAR_MINVAL\"", "msDrawBarChartLayer()"); return MS_FAILURE; } } if(barMin && barMax && barMinVal>=barMaxVal) { msSetError(MS_MISCERR, "\"CHART_BAR_MINVAL\" must be less than \"CHART_BAR_MAXVAL\"", "msDrawBarChartLayer()"); return MS_FAILURE; } barWidth=(float)width/(float)layer->numclasses; if(!barWidth) { msSetError(MS_MISCERR, "Specified width of chart too small to fit given number of classes", "msDrawBarChartLayer()"); return MS_FAILURE; } msInitShape(&shape); values=(float*)calloc(numvalues,sizeof(float)); MS_CHECK_ALLOC(values, numvalues*sizeof(float), MS_FAILURE); styles = (styleObj**)malloc(numvalues*sizeof(styleObj*)); if (styles == NULL) { msSetError(MS_MEMERR, "%s: %d: Out of memory allocating %u bytes.\n", "msDrawBarChartLayer()", __FILE__, __LINE__, numvalues*sizeof(styleObj*)); free(values); return MS_FAILURE; } while(MS_SUCCESS == getNextShape(map,layer,values,styles,&shape)) { msDrawStartShape(map, layer, image, &shape); if(findChartPoint(map, &shape, width,height, ¢er)==MS_SUCCESS) { status = msDrawBarChart(map,image, ¢er, values, styles, numvalues, width,height, (barMax!=NULL)?&barMaxVal:NULL, (barMin!=NULL)?&barMinVal:NULL, barWidth); } msDrawEndShape(map,layer,image,&shape); msFreeShape(&shape); } free(values); free(styles); return status; }
char *FLTGetSpatialComparisonCommonExpression(FilterEncodingNode *psNode, layerObj *lp) { char *pszExpression = NULL; shapeObj *psQueryShape = NULL; double dfDistance = -1; int nUnit = -1, nLayerUnit = -1; char *pszWktText = NULL; char szBuffer[256]; char *pszTmp=NULL; projectionObj sProjTmp; rectObj sQueryRect; shapeObj *psTmpShape=NULL; int bBBoxQuery = 0; int bAlreadyReprojected = 0; if (psNode == NULL || lp == NULL) return NULL; if (psNode->eType != FILTER_NODE_TYPE_SPATIAL) return NULL; /* get the shape */ if (FLTIsBBoxFilter(psNode)) { char szPolygon[512]; FLTGetBBOX(psNode, &sQueryRect); snprintf(szPolygon, sizeof(szPolygon), "POLYGON((%.18f %.18f,%.18f %.18f,%.18f %.18f,%.18f %.18f,%.18f %.18f))", sQueryRect.minx, sQueryRect.miny, sQueryRect.minx, sQueryRect.maxy, sQueryRect.maxx, sQueryRect.maxy, sQueryRect.maxx, sQueryRect.miny, sQueryRect.minx, sQueryRect.miny); psTmpShape = msShapeFromWKT(szPolygon); /* ** This is a horrible hack to deal with world-extent requests and ** reprojection. msProjectRect() detects if reprojection from longlat to ** projected SRS, and in that case it transforms the bbox to -1e-15,-1e-15,1e15,1e15 ** to ensure that all features are returned. ** ** Make wfs_200_cite_filter_bbox_world.xml and wfs_200_cite_postgis_bbox_world.xml pass */ if (fabs(sQueryRect.minx - -180.0) < 1e-5 && fabs(sQueryRect.miny - -90.0) < 1e-5 && fabs(sQueryRect.maxx - 180.0) < 1e-5 && fabs(sQueryRect.maxy - 90.0) < 1e-5) { if (lp->projection.numargs > 0) { if (psNode->pszSRS) msInitProjection(&sProjTmp); if (psNode->pszSRS) { /* Use the non EPSG variant since axis swapping is done in FLTDoAxisSwappingIfNecessary */ if (msLoadProjectionString(&sProjTmp, psNode->pszSRS) == 0) { msProjectRect(&sProjTmp, &lp->projection, &sQueryRect); } } else if (lp->map->projection.numargs > 0) msProjectRect(&lp->map->projection, &lp->projection, &sQueryRect); if (psNode->pszSRS) msFreeProjection(&sProjTmp); } if (sQueryRect.minx <= -1e14) { msFreeShape(psTmpShape); msFree(psTmpShape); psTmpShape = (shapeObj*) msSmallMalloc(sizeof(shapeObj)); msInitShape(psTmpShape); msRectToPolygon(sQueryRect, psTmpShape); bAlreadyReprojected = 1; } } bBBoxQuery = 1; } else { /* other geos type operations */ /* project shape to layer projection. If the proj is not part of the filter query, assume that the cooredinates are in the map projection */ psQueryShape = FLTGetShape(psNode, &dfDistance, &nUnit); if ((strcasecmp(psNode->pszValue, "DWithin") == 0 || strcasecmp(psNode->pszValue, "Beyond") == 0 ) && dfDistance > 0) { nLayerUnit = lp->units; if(nLayerUnit == -1) nLayerUnit = GetMapserverUnitUsingProj(&lp->projection); if(nLayerUnit == -1) nLayerUnit = lp->map->units; if(nLayerUnit == -1) nLayerUnit = GetMapserverUnitUsingProj(&lp->map->projection); if (nUnit >= 0 && nUnit != nLayerUnit) dfDistance *= msInchesPerUnit(nUnit,0)/msInchesPerUnit(nLayerUnit,0); /* target is layer units */ } psTmpShape = psQueryShape; } if (psTmpShape) { /* ** target is layer projection */ if (!bAlreadyReprojected && lp->projection.numargs > 0) { if (psNode->pszSRS) msInitProjection(&sProjTmp); if (psNode->pszSRS) { /* Use the non EPSG variant since axis swapping is done in FLTDoAxisSwappingIfNecessary */ if (msLoadProjectionString(&sProjTmp, psNode->pszSRS) == 0) { msProjectShape(&sProjTmp, &lp->projection, psTmpShape); } } else if (lp->map->projection.numargs > 0) msProjectShape(&lp->map->projection, &lp->projection, psTmpShape); if (psNode->pszSRS) msFreeProjection(&sProjTmp); } /* function name */ if (bBBoxQuery) { sprintf(szBuffer, "%s", "intersects"); } else { if (strncasecmp(psNode->pszValue, "intersect", 9) == 0) sprintf(szBuffer, "%s", "intersects"); else { pszTmp = msStrdup(psNode->pszValue); msStringToLower(pszTmp); sprintf(szBuffer, "%s", pszTmp); msFree(pszTmp); } } pszExpression = msStringConcatenate(pszExpression, szBuffer); pszExpression = msStringConcatenate(pszExpression, "("); /* geometry binding */ sprintf(szBuffer, "%s", "[shape]"); pszExpression = msStringConcatenate(pszExpression, szBuffer); pszExpression = msStringConcatenate(pszExpression, ","); /* filter geometry */ pszWktText = msGEOSShapeToWKT(psTmpShape); sprintf(szBuffer, "%s", "fromText('"); pszExpression = msStringConcatenate(pszExpression, szBuffer); pszExpression = msStringConcatenate(pszExpression, pszWktText); sprintf(szBuffer, "%s", "')"); pszExpression = msStringConcatenate(pszExpression, szBuffer); msGEOSFreeWKT(pszWktText); /* (optional) beyond/dwithin distance, always 0.0 since we apply the distance as a buffer earlier */ if ((strcasecmp(psNode->pszValue, "DWithin") == 0 || strcasecmp(psNode->pszValue, "Beyond") == 0)) { // pszExpression = msStringConcatenate(pszExpression, ",0.0"); sprintf(szBuffer, ",%g", dfDistance); pszExpression = msStringConcatenate(pszExpression, szBuffer); } /* terminate the function */ pszExpression = msStringConcatenate(pszExpression, ") = TRUE"); } /* ** Cleanup */ if (bBBoxQuery) { msFreeShape(psTmpShape); msFree(psTmpShape); } return pszExpression; }
/* 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; }
XShape::XShape(shapefileObj *shpfile, int i, int label_field) :label(NULL) { #ifdef ENABLE_OPENGL for (unsigned l=0; l < THINNING_LEVELS; l++) index_count[l] = indices[l] = NULL; #endif shapeObj shape; msInitShape(&shape); msSHPReadShape(shpfile->hSHP, i, &shape); bounds.west = Angle::Degrees(fixed(shape.bounds.minx)); bounds.south = Angle::Degrees(fixed(shape.bounds.miny)); bounds.east = Angle::Degrees(fixed(shape.bounds.maxx)); bounds.north = Angle::Degrees(fixed(shape.bounds.maxy)); #ifdef ENABLE_OPENGL center = bounds.GetCenter(); #endif type = shape.type; num_lines = 0; const int min_points = min_points_for_type(shape.type); if (min_points < 0) { /* not supported, leave an empty XShape object */ points = NULL; msFreeShape(&shape); return; } const unsigned input_lines = std::min((unsigned)shape.numlines, (unsigned)MAX_LINES); unsigned num_points = 0; for (unsigned l = 0; l < input_lines; ++l) { if (shape.line[l].numpoints < min_points) /* malformed shape */ continue; lines[num_lines] = std::min(shape.line[l].numpoints, 16384); num_points += lines[num_lines]; ++num_lines; } #ifdef ENABLE_OPENGL /* OpenGL: * Convert all points of all lines to ShapePoints, using a projection * that assumes the center of the screen is also the center of the shape. * Resolution is set to 1m per pixel. This enables us to use a simple matrix * multiplication to draw the shape. * This approximation should work well with shapes of limited size * (<< 400km). Perceivable distortion will only happen, when the latitude of * the actual center of the screen is far away from the latitude of the * center of the shape and the shape has a big vertical size. */ points = new ShapePoint[num_points]; ShapePoint *p = points; #else // !ENABLE_OPENGL /* convert all points of all lines to GeoPoints */ points = new GeoPoint[num_points]; GeoPoint *p = points; #endif for (unsigned l = 0; l < num_lines; ++l) { const pointObj *src = shape.line[l].point; num_points = lines[l]; for (unsigned j = 0; j < num_points; ++j, ++src) #ifdef ENABLE_OPENGL *p++ = geo_to_shape(GeoPoint(Angle::Degrees(fixed(src->x)), Angle::Degrees(fixed(src->y)))); #else *p++ = GeoPoint(Angle::Degrees(fixed(src->x)), Angle::Degrees(fixed(src->y))); #endif } if (label_field >= 0) { const char *src = msDBFReadStringAttribute(shpfile->hDBF, i, label_field); label = import_label(src); } msFreeShape(&shape); }
int msDrawPieChartLayer(mapObj *map, layerObj *layer, imageObj *image) { shapeObj shape; int status=MS_SUCCESS; const char *chartRangeProcessingKey=NULL; const char *chartSizeProcessingKey=msLayerGetProcessingKey( layer,"CHART_SIZE" ); float diameter, mindiameter=-1, maxdiameter, minvalue, maxvalue; float *values; styleObj **styles; pointObj center; int numvalues = layer->numclasses; /* the number of classes to represent in the graph */ if(chartSizeProcessingKey==NULL) { chartRangeProcessingKey=msLayerGetProcessingKey( layer,"CHART_SIZE_RANGE" ); if(chartRangeProcessingKey==NULL) diameter=20; else { sscanf(chartRangeProcessingKey,"%*s %f %f %f %f", &mindiameter,&maxdiameter,&minvalue,&maxvalue); } } else { if(sscanf(chartSizeProcessingKey ,"%f",&diameter)!=1) { msSetError(MS_MISCERR, "msDrawChart format error for processing key \"CHART_SIZE\"", "msDrawPieChartLayer()"); return MS_FAILURE; } } /* step through the target shapes */ msInitShape(&shape); values=(float*)calloc(numvalues,sizeof(float)); MS_CHECK_ALLOC(values, numvalues*sizeof(float), MS_FAILURE); styles = (styleObj**)malloc((numvalues)*sizeof(styleObj*)); if (styles == NULL) { msSetError(MS_MEMERR, "%s: %d: Out of memory allocating %u bytes.\n", "msDrawPieChartLayer()", __FILE__, __LINE__, numvalues*sizeof(styleObj*)); free(values); return MS_FAILURE; } if(chartRangeProcessingKey!=NULL) numvalues--; while(MS_SUCCESS == getNextShape(map,layer,values,styles,&shape)) { msDrawStartShape(map, layer, image, &shape); if(chartRangeProcessingKey!=NULL) { diameter = values[numvalues]; if(mindiameter>=0) { if(diameter<=minvalue) diameter=mindiameter; else if(diameter>=maxvalue) diameter=maxdiameter; else { diameter=MS_NINT( mindiameter+ ((diameter-minvalue)/(maxvalue-minvalue))* (maxdiameter-mindiameter) ); } } } if(findChartPoint(map, &shape, diameter, diameter, ¢er) == MS_SUCCESS) { status = msDrawPieChart(map,image, ¢er, diameter, values,styles,numvalues); } msDrawEndShape(map,layer,image,&shape); msFreeShape(&shape); } free(values); free(styles); return status; }
int msDrawVBarChartLayer(mapObj *map, layerObj *layer, imageObj *image) { shapeObj shape; int status=MS_SUCCESS; const char *chartSizeProcessingKey=msLayerGetProcessingKey( layer,"CHART_SIZE" ); const char *chartScaleProcessingKey=msLayerGetProcessingKey( layer,"CHART_SCALE" ); float barWidth,scale=1.0; float *values; styleObj **styles; pointObj center; int numvalues = layer->numclasses; if(chartSizeProcessingKey==NULL) { barWidth=20; } else { if(sscanf(chartSizeProcessingKey ,"%f",&barWidth) != 1) { msSetError(MS_MISCERR, "msDrawChart format error for processing key \"CHART_SIZE\"", "msDrawVBarChartLayer()"); return MS_FAILURE; } } if(chartScaleProcessingKey) { if(sscanf(chartScaleProcessingKey,"%f",&scale)!=1) { msSetError(MS_MISCERR, "Error reading value for processing key \"CHART_SCALE\"", "msDrawVBarChartLayer()"); return MS_FAILURE; } } msInitShape(&shape); values=(float*)calloc(numvalues,sizeof(float)); MS_CHECK_ALLOC(values, numvalues*sizeof(float), MS_FAILURE); styles = (styleObj**)malloc(numvalues*sizeof(styleObj*)); if (styles == NULL) { msSetError(MS_MEMERR, "%s: %d: Out of memory allocating %u bytes.\n", "msDrawVBarChartLayer()", __FILE__, __LINE__, numvalues*sizeof(styleObj*)); free(values); return MS_FAILURE; } while(MS_SUCCESS == getNextShape(map,layer,values,styles,&shape)) { int i; double h=0; for(i=0; i<numvalues; i++) { values[i]*=scale; h += values[i]; } msDrawStartShape(map, layer, image, &shape); if(findChartPoint(map, &shape, barWidth,h, ¢er)==MS_SUCCESS) { status = msDrawVBarChart(map,image, ¢er, values, styles, numvalues, barWidth); } msDrawEndShape(map,layer,image,&shape); msFreeShape(&shape); } free(values); free(styles); return status; }
/* rebuild the clusters according to the current extent */ int RebuildClusters(layerObj *layer, int isQuery) { mapObj* map; layerObj* srcLayer; double distance, maxDistanceX, maxDistanceY, cellSizeX, cellSizeY; rectObj searchrect; int status; clusterInfo* current; int depth; #ifdef USE_CLUSTER_EXTERNAL int layerIndex; #endif msClusterLayerInfo* layerinfo = layer->layerinfo; if (!layerinfo) { msSetError(MS_MISCERR, "Layer is not open: %s", "RebuildClusters()", layer->name); return MS_FAILURE; } if (!layer->map) { msSetError(MS_MISCERR, "No map associated with this layer: %s", "RebuildClusters()", layer->name); return MS_FAILURE; } if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug("Clustering started.\n"); map = layer->map; layerinfo->current = layerinfo->finalized; /* restart */ /* check whether all shapes should be returned from a query */ if(msLayerGetProcessingKey(layer, "CLUSTER_GET_ALL_SHAPES") != NULL) layerinfo->get_all_shapes = MS_TRUE; else layerinfo->get_all_shapes = MS_FALSE; /* identify the current extent */ if(layer->transform == MS_TRUE) searchrect = map->extent; else { searchrect.minx = searchrect.miny = 0; searchrect.maxx = map->width-1; searchrect.maxy = map->height-1; } if (searchrect.minx == layerinfo->searchRect.minx && searchrect.miny == layerinfo->searchRect.miny && searchrect.maxx == layerinfo->searchRect.maxx && searchrect.maxy == layerinfo->searchRect.maxy) { /* already built */ return MS_SUCCESS; } /* destroy previous data*/ clusterDestroyData(layerinfo); layerinfo->searchRect = searchrect; /* reproject the rectangle to layer coordinates */ #ifdef USE_PROJ if((map->projection.numargs > 0) && (layer->projection.numargs > 0)) msProjectRect(&map->projection, &layer->projection, &searchrect); /* project the searchrect to source coords */ #endif /* determine the compare method */ layerinfo->fnCompare = CompareRectangleRegion; if (layer->cluster.region) { if (EQUAL(layer->cluster.region, "ellipse")) layerinfo->fnCompare = CompareEllipseRegion; } /* trying to find a reasonable quadtree depth */ depth = 0; distance = layer->cluster.maxdistance; while ((distance < map->width || distance < map->height) && depth <= TREE_MAX_DEPTH) { distance *= 2; ++depth; } layerinfo->depth = depth; cellSizeX = MS_CELLSIZE(searchrect.minx, searchrect.maxx, map->width); cellSizeY = MS_CELLSIZE(searchrect.miny, searchrect.maxy, map->height); maxDistanceX = layer->cluster.maxdistance * cellSizeX; maxDistanceY = layer->cluster.maxdistance * cellSizeY; /* increase the search rectangle so that the neighbouring shapes are also retrieved */ searchrect.minx -= layer->cluster.buffer * cellSizeX; searchrect.maxx += layer->cluster.buffer * cellSizeX; searchrect.miny -= layer->cluster.buffer * cellSizeY; searchrect.maxy += layer->cluster.buffer * cellSizeY; /* create the root node */ if (layerinfo->root) clusterTreeNodeDestroy(layerinfo, layerinfo->root); layerinfo->root = clusterTreeNodeCreate(layerinfo, searchrect); srcLayer = &layerinfo->srcLayer; /* start retrieving the shapes */ status = msLayerWhichShapes(srcLayer, searchrect, isQuery); if(status == MS_DONE) { /* no overlap */ return MS_SUCCESS; } else if(status != MS_SUCCESS) { return MS_FAILURE; } /* step through the source shapes and populate the quadtree with the tentative clusters */ if ((current = clusterInfoCreate(layerinfo)) == NULL) return MS_FAILURE; while((status = msLayerNextShape(srcLayer, ¤t->shape)) == MS_SUCCESS) { #if defined(USE_PROJ) && defined(USE_CLUSTER_EXTERNAL) /* transform the shape to the projection of this layer */ if(srcLayer->transform == MS_TRUE && srcLayer->project && layer->transform == MS_TRUE && layer->project &&msProjectionsDiffer(&(srcLayer->projection), &(layer->projection))) msProjectShape(&srcLayer->projection, &layer->projection, ¤t->shape); #endif /* set up positions and variance */ current->avgx = current->x = current->shape.bounds.minx; current->avgy = current->y = current->shape.bounds.miny; current->varx = current->vary = 0; /* set up the area of interest when searching for the neighboring shapes */ current->bounds.minx = current->x - maxDistanceX; current->bounds.miny = current->y - maxDistanceY; current->bounds.maxx = current->x + maxDistanceX; current->bounds.maxy = current->y + maxDistanceY; /* if the shape doesn't overlap we must skip it to avoid further issues */ if(!msRectOverlap(&searchrect, ¤t->bounds)) { msFreeShape(¤t->shape); msInitShape(¤t->shape); msDebug("Skipping an invalid shape falling outside of the given extent\n"); continue; } /* construct the item array */ if (layer->iteminfo) BuildFeatureAttributes(layer, layerinfo, ¤t->shape); /* evaluate the group expression */ if (layer->cluster.group.string) current->group = msClusterGetGroupText(&layer->cluster.group, ¤t->shape); /*start a query for the related shapes */ findRelatedShapes(layerinfo, layerinfo->root, current); /* add this shape to the tree */ if (treeNodeAddShape(layerinfo, layerinfo->root, current, depth) != MS_SUCCESS) { clusterInfoDestroyList(layerinfo, current); return MS_FAILURE; } if ((current = clusterInfoCreate(layerinfo)) == NULL) { clusterInfoDestroyList(layerinfo, current); return MS_FAILURE; } } clusterInfoDestroyList(layerinfo, current); while (layerinfo->root) { #ifdef TESTCOUNT int n; double avgx, avgy; #endif /* pick up the best cluster from the tree and do the finalization */ /* the initial rank must be big enough */ layerinfo->rank = (searchrect.maxx - searchrect.minx) * (searchrect.maxx - searchrect.minx) + (searchrect.maxy - searchrect.miny) * (searchrect.maxy - searchrect.miny) + 1; layerinfo->current = NULL; findBestCluster(layer, layerinfo, layerinfo->root); if (layerinfo->current == NULL) { if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug("Clustering terminated.\n"); break; /* completed */ } /* Update the feature count of the shape */ InitShapeAttributes(layer, layerinfo->current); /* collecting the shapes of the cluster */ collectClusterShapes(layerinfo, layerinfo->root, layerinfo->current); if (layer->debug >= MS_DEBUGLEVEL_VVV) { msDebug("processing cluster %p: rank=%lf fcount=%d ncoll=%d nfin=%d nfins=%d nflt=%d bounds={%lf %lf %lf %lf}\n", layerinfo->current, layerinfo->rank, layerinfo->current->numsiblings + 1, layerinfo->current->numcollected, layerinfo->numFinalized, layerinfo->numFinalizedSiblings, layerinfo->numFiltered, layerinfo->current->bounds.minx, layerinfo->current->bounds.miny, layerinfo->current->bounds.maxx, layerinfo->current->bounds.maxy); if (layerinfo->current->node) { char pszBuffer[TREE_MAX_DEPTH + 1]; clusterTreeNode* node = layerinfo->current->node; int position = node->position; int i = 1; while (position > 0 && i <= TREE_MAX_DEPTH) { pszBuffer[TREE_MAX_DEPTH - i] = '0' + (position % 4); position = position >> 2; ++i; } pszBuffer[TREE_MAX_DEPTH] = 0; msDebug(" ->node %p: count=%d index=%d pos=%s subn={%p %p %p %p} rect={%lf %lf %lf %lf}\n", node, node->numshapes, node->index, pszBuffer + TREE_MAX_DEPTH - i + 1, node->subnode[0], node->subnode[1], node->subnode[2], node->subnode[3], node->rect.minx, node->rect.miny, node->rect.maxx, node->rect.maxy); } }
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; }
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 }
char *FLTGetSpatialComparisonCommonExpression(FilterEncodingNode *psNode, layerObj *lp) { char *pszExpression = NULL; shapeObj *psQueryShape = NULL; double dfDistance = -1; int nUnit = -1; char *pszWktText = NULL; char szBuffer[256]; char *pszTmp=NULL; projectionObj sProjTmp; char *pszEPSG= NULL; rectObj sQueryRect; shapeObj *psTmpShape=NULL, *psBufferShape=NULL; int bBBoxQuery = 0; if (psNode == NULL || lp == NULL) return NULL; if (psNode->eType != FILTER_NODE_TYPE_SPATIAL) return NULL; /* get the shape*/ /*BBOX case: replace it with NOT DISJOINT.*/ if(FLTIsBBoxFilter(psNode)) { pszEPSG = FLTGetBBOX(psNode, &sQueryRect); /*this should be removed and bbox should parse and strore the srs properly, using now legacy code*/ if (pszEPSG) psNode->pszSRS = msStrdup(pszEPSG); psTmpShape = (shapeObj *)msSmallMalloc(sizeof(shapeObj)); msInitShape(psTmpShape); msRectToPolygon(sQueryRect, psTmpShape); bBBoxQuery = 1; } else { /*other geos type operations*/ /*project shape to layer projection. If the proj is not part of the filter query, assume that the cooredinates are in the map projection*/ psQueryShape = FLTGetShape(psNode, &dfDistance, &nUnit); if ((strcasecmp(psNode->pszValue, "DWithin") == 0 || strcasecmp(psNode->pszValue, "Beyond") == 0 ) && dfDistance > 0) { if (nUnit >=0 && nUnit != lp->map->units) dfDistance *= msInchesPerUnit(nUnit,0)/msInchesPerUnit(lp->map->units,0); psBufferShape = msGEOSBuffer(psQueryShape, dfDistance); } if (psBufferShape) psTmpShape = psBufferShape; else psTmpShape = psQueryShape; } if (psTmpShape) { if( lp->projection.numargs > 0) { if (psNode->pszSRS && FTLParseEpsgString(psNode->pszSRS, &sProjTmp)) { msProjectShape(&sProjTmp, &lp->projection, psTmpShape); msFreeProjection(&sProjTmp); } else if (lp->map->projection.numargs > 0) msProjectShape(&lp->map->projection, &lp->projection, psTmpShape); } /* ==================================================================== */ /* use within for bbox. Not Disjoint does not work. */ /* ==================================================================== */ if (bBBoxQuery) sprintf(szBuffer, "%s", " ([shape] "); /* sprintf(szBuffer, "%s", " (NOT ([shape] "); */ else sprintf(szBuffer, "%s", " ([shape] "); pszExpression = msStringConcatenate(pszExpression, szBuffer); if (strncasecmp(psNode->pszValue, "intersect", 9) == 0) pszTmp = msStrdup("intersects"); else pszTmp = msStrdup(psNode->pszValue); msStringToLower(pszTmp); if (bBBoxQuery) sprintf(szBuffer, " %s ", "intersects"); /* sprintf(szBuffer, " %s ", "disjoint"); */ else sprintf(szBuffer, " %s ", pszTmp); pszExpression = msStringConcatenate(pszExpression, szBuffer); msFree(pszTmp); pszWktText = msGEOSShapeToWKT(psTmpShape); sprintf(szBuffer, "%s", " fromText('"); pszExpression = msStringConcatenate(pszExpression, szBuffer); pszExpression = msStringConcatenate(pszExpression, pszWktText); sprintf(szBuffer, "%s", "')"); pszExpression = msStringConcatenate(pszExpression, szBuffer); msGEOSFreeWKT(pszWktText); } if (psBufferShape) msFreeShape(psBufferShape); sprintf(szBuffer, "%s", ")"); pszExpression = msStringConcatenate(pszExpression, szBuffer); if (0) /* bBBoxQuery */ { sprintf(szBuffer, "%s", ")"); pszExpression = msStringConcatenate(pszExpression, szBuffer); } return pszExpression; }