Пример #1
0
/*
** 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);
}
Пример #2
0
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);
}
Пример #3
0
/* 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);

}
Пример #4
0
/*
 * 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;
}
Пример #5
0
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;
}
Пример #6
0
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;
}