/* ** Calculate the approximate scale based on a few parameters. Note that this assumes the scale is ** the same in the x direction as in the y direction, so run msAdjustExtent(...) first. */ int msCalculateScale(rectObj extent, int units, int width, int height, double resolution, double *scale) { double md, gd, center_y; /* if((extent.maxx == extent.minx) || (extent.maxy == extent.miny)) */ if(!MS_VALID_EXTENT(extent)) { msSetError(MS_MISCERR, "Invalid image extent, minx=%lf, miny=%lf, maxx=%lf, maxy=%lf.", "msCalculateScale()", extent.minx, extent.miny, extent.maxx, extent.maxy); return(MS_FAILURE); } if((width <= 0) || (height <= 0)) { msSetError(MS_MISCERR, "Invalid image width or height.", "msCalculateScale()"); return(MS_FAILURE); } switch (units) { case(MS_DD): case(MS_METERS): case(MS_KILOMETERS): case(MS_MILES): case(MS_NAUTICALMILES): case(MS_INCHES): case(MS_FEET): center_y = (extent.miny+extent.maxy)/2.0; md = (width-1)/(resolution*msInchesPerUnit(units, center_y)); /* remember, we use a pixel-center to pixel-center extent, hence the width-1 */ gd = extent.maxx - extent.minx; *scale = gd/md; break; default: *scale = -1; /* this is not an error */ break; } return(MS_SUCCESS); }
int msMapScaleExtent( mapObj *map, double zoomfactor, double minscaledenom, double maxscaledenom) { double geo_width, geo_height, center_x, center_y, md; if (zoomfactor <= 0.0) { msSetError(MS_MISCERR, "The given zoomfactor is invalid", "msMapScaleExtent()"); } geo_width = map->extent.maxx - map->extent.minx; geo_height = map->extent.maxy - map->extent.miny; center_x = map->extent.minx + geo_width * 0.5; center_y = map->extent.miny + geo_height * 0.5; geo_width *= zoomfactor; if (minscaledenom > 0 || maxscaledenom > 0) { /* ensure we are within the valid scale domain */ md = (map->width-1)/(map->resolution * msInchesPerUnit(map->units, center_y)); if (minscaledenom > 0 && geo_width < minscaledenom * md) geo_width = minscaledenom * md; if (maxscaledenom > 0 && geo_width > maxscaledenom * md) geo_width = maxscaledenom * md; } geo_width *= 0.5; geo_height = geo_width * map->height / map->width; return msMapSetExtent( map, center_x - geo_width, center_y - geo_height, center_x + geo_width, center_y + geo_height); }
/* TODO : the will be msDrawScalebarGD */ imageObj *msDrawScalebar(mapObj *map) { int status; char label[32]; double i, msx; int j; int isx, sx, sy, ox, oy, state, dsx; pointObj p; rectObj r; imageObj *image = NULL; double fontWidth, fontHeight; outputFormatObj *format = NULL; strokeStyleObj strokeStyle; shapeObj shape; lineObj line; pointObj points[5]; rendererVTableObj *renderer; strokeStyle.patternlength=0; if(map->units == -1) { msSetError(MS_MISCERR, "Map units not set.", "msDrawScalebar()"); return(NULL); } renderer = MS_MAP_RENDERER(map); if(!renderer || !MS_MAP_RENDERER(map)->supports_pixel_buffer) { msSetError(MS_MISCERR, "Outputformat not supported for scalebar", "msDrawScalebar()"); return(NULL); } /* * A string containing the ten decimal digits is rendered to compute an average cell size * for each number, which is used later to place labels on the scalebar. */ if(msGetLabelSize(map,&map->scalebar.label,"0123456789",map->scalebar.label.size,&r,NULL) != MS_SUCCESS) { return NULL; } fontWidth = (r.maxx-r.minx)/10.0; fontHeight = r.maxy -r.miny; map->cellsize = msAdjustExtent(&(map->extent), map->width, map->height); status = msCalculateScale(map->extent, map->units, map->width, map->height, map->resolution, &map->scaledenom); if(status != MS_SUCCESS) { return(NULL); } dsx = map->scalebar.width - 2*HMARGIN; do { msx = (map->cellsize * dsx)/(msInchesPerUnit(map->scalebar.units,0)/msInchesPerUnit(map->units,0)); i = roundInterval(msx/map->scalebar.intervals); snprintf(label, sizeof(label), "%g", map->scalebar.intervals*i); /* last label */ isx = MS_NINT((i/(msInchesPerUnit(map->units,0)/msInchesPerUnit(map->scalebar.units,0)))/map->cellsize); sx = (map->scalebar.intervals*isx) + MS_NINT((1.5 + strlen(label)/2.0 + strlen(unitText[map->scalebar.units]))*fontWidth); if(sx <= (map->scalebar.width - 2*HMARGIN)) break; /* it will fit */ dsx -= X_STEP_SIZE; /* change the desired size in hopes that it will fit in user supplied width */ } while(1); sy = (2*VMARGIN) + MS_NINT(VSPACING*fontHeight) + fontHeight + map->scalebar.height - VSLOP; /*Ensure we have an image format representing the options for the scalebar.*/ msApplyOutputFormat( &format, map->outputformat, map->scalebar.transparent, map->scalebar.interlace, MS_NOOVERRIDE ); if(map->scalebar.transparent == MS_OFF) { if(!MS_VALID_COLOR(map->scalebar.imagecolor)) MS_INIT_COLOR(map->scalebar.imagecolor,255,255,255,255); } image = msImageCreate(map->scalebar.width, sy, format, map->web.imagepath, map->web.imageurl, map->resolution, map->defresolution, &map->scalebar.imagecolor); /* drop this reference to output format */ msApplyOutputFormat( &format, NULL, MS_NOOVERRIDE, MS_NOOVERRIDE, MS_NOOVERRIDE ); /* did we succeed in creating the image? */ if(!image) { msSetError(MS_MISCERR, "Unable to initialize image.", "msDrawScalebar()"); return NULL; } switch(map->scalebar.align) { case(MS_ALIGN_LEFT): ox = HMARGIN; break; case(MS_ALIGN_RIGHT): ox = MS_NINT((map->scalebar.width - sx) + fontWidth); break; default: ox = MS_NINT((map->scalebar.width - sx)/2.0 + fontWidth/2.0); /* center the computed scalebar */ } oy = VMARGIN; switch(map->scalebar.style) { case(0): { line.numpoints = 5; line.point = points; shape.line = &line; shape.numlines = 1; if(MS_VALID_COLOR(map->scalebar.color)) { INIT_STROKE_STYLE(strokeStyle); strokeStyle.color = &map->scalebar.outlinecolor; strokeStyle.color->alpha = 255; strokeStyle.width = 1; } map->scalebar.backgroundcolor.alpha = 255; map->scalebar.color.alpha = 255; state = 1; /* 1 means filled */ for(j=0; j<map->scalebar.intervals; j++) { points[0].x = points[4].x = points[3].x = ox + j*isx + 0.5; points[0].y = points[4].y = points[1].y = oy + 0.5; points[1].x = points[2].x = ox + (j+1)*isx + 0.5; points[2].y = points[3].y = oy + map->scalebar.height + 0.5; if(state == 1 && MS_VALID_COLOR(map->scalebar.color)) renderer->renderPolygon(image,&shape,&map->scalebar.color); else if(MS_VALID_COLOR(map->scalebar.backgroundcolor)) renderer->renderPolygon(image,&shape,&map->scalebar.backgroundcolor); if(strokeStyle.color) renderer->renderLine(image,&shape,&strokeStyle); sprintf(label, "%g", j*i); map->scalebar.label.position = MS_CC; p.x = ox + j*isx; /* + MS_NINT(fontPtr->w/2); */ p.y = oy + map->scalebar.height + MS_NINT(VSPACING*fontHeight); msDrawLabel(map,image,p,label,&map->scalebar.label,1.0); state = -state; } sprintf(label, "%g", j*i); ox = ox + j*isx - MS_NINT((strlen(label)*fontWidth)/2.0); sprintf(label, "%g %s", j*i, unitText[map->scalebar.units]); map->scalebar.label.position = MS_CR; p.x = ox; /* + MS_NINT(fontPtr->w/2); */ p.y = oy + map->scalebar.height + MS_NINT(VSPACING*fontHeight); msDrawLabel(map,image,p,label,&map->scalebar.label,1.0); break; } case(1): { line.numpoints = 2; line.point = points; shape.line = &line; shape.numlines = 1; if(MS_VALID_COLOR(map->scalebar.color)) { strokeStyle.width = 1; strokeStyle.color = &map->scalebar.color; } points[0].y = points[1].y = oy; points[0].x = ox; points[1].x = ox + isx*map->scalebar.intervals; renderer->renderLine(image,&shape,&strokeStyle); points[0].y = oy; points[1].y = oy + map->scalebar.height; p.y = oy + map->scalebar.height + MS_NINT(VSPACING*fontHeight); for(j=0; j<=map->scalebar.intervals; j++) { points[0].x = points[1].x = ox + j*isx; renderer->renderLine(image,&shape,&strokeStyle); sprintf(label, "%g", j*i); if(j!=map->scalebar.intervals) { map->scalebar.label.position = MS_CC; p.x = ox + j*isx; /* + MS_NINT(fontPtr->w/2); */ } else { sprintf(label, "%g %s", j*i, unitText[map->scalebar.units]); map->scalebar.label.position = MS_CR; p.x = ox + j*isx - MS_NINT((strlen(label)*fontWidth)/2.0); } msDrawLabel(map,image,p,label,&map->scalebar.label,1.0); } break; } default: msSetError(MS_MISCERR, "Unsupported scalebar style.", "msDrawScalebar()"); return(NULL); } return(image); }
/* * 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; }
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; }
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; }