Ejemplo n.º 1
0
int KmlRenderer::checkProjection(mapObj *map)
{
    projectionObj *projection= &map->projection;
#ifdef USE_PROJ
    if (projection && projection->numargs > 0 && pj_is_latlong(projection->proj))
    {
        return MS_SUCCESS;
    }
    else
    {
        char epsg_string[100];
        rectObj sRect;
        projectionObj out;

        /* for layer the do not have any projection set, set them with the current map
           projection*/
        if (projection && projection->numargs > 0)
        {
            layerObj *lp = NULL;
            int i =0;
            char *pszMapProjectString = msGetProjectionString(projection);
            if (pszMapProjectString)
            {
                for(i=0; i<map->numlayers; i++)
                {
                    lp = GET_LAYER(map, i);
                    if (lp->projection.numargs == 0 && lp->transform == MS_TRUE)
                    {
                        msFreeProjection(&lp->projection);
                        msLoadProjectionString(&lp->projection, pszMapProjectString);
                    }
                }
                msFree(pszMapProjectString);
            }
        }
        strcpy(epsg_string, "epsg:4326" );
        msInitProjection(&out);
        msLoadProjectionString(&out, epsg_string);

        sRect = map->extent;
        msProjectRect(projection, &out, &sRect);
        msFreeProjection(projection);
        msLoadProjectionString(projection, epsg_string);

        /*change also units and extents*/
        map->extent = sRect;
        map->units = MS_DD;


        if (map->debug)
          msDebug("KmlRenderer::checkProjection: Mapfile projection set to epsg:4326\n");

        return MS_SUCCESS;
    }

#else
    msSetError(MS_MISCERR, "Projection support not enabled", "KmlRenderer::checkProjection" );
    return MS_FAILURE;
#endif
}
Ejemplo n.º 2
0
int msContourLayerWhichShapes(layerObj *layer, rectObj rect, int isQuery)
{
  rectObj newRect;
  contourLayerInfo *clinfo = (contourLayerInfo *) layer->layerinfo;

  if (layer->debug)
    msDebug("Entering msContourLayerWhichShapes().\n");

  if (clinfo == NULL) {
    msSetError(MS_MISCERR, "Assertion failed: Contour layer not opened!!!",
               "msContourLayerWhichShapes()");
    return MS_FAILURE;
  }

  newRect = rect;
  
#ifdef USE_PROJ
    /* if necessary, project the searchrect to source coords */
    if (msProjectionsDiffer( &(layer->map->projection), &(layer->projection)))  {
      if (msProjectRect(&layer->projection, &layer->map->projection, &newRect)
          != MS_SUCCESS ) {
        msDebug("msContourLayerWhichShapes(%s): unable to reproject map request rectangle into layer projection, canceling.\n", layer->name);
        return MS_FAILURE;
      }
    }
#endif

  /* regenerate the raster io */
  msConnPoolRelease(&clinfo->ogrLayer, clinfo->hOGRDS);
  msLayerClose(&clinfo->ogrLayer);
  
  /* Open the raster source */
  if (msContourLayerReadRaster(layer, newRect) != MS_SUCCESS)
    return MS_FAILURE;

  /* Generate Contour Dataset */
  if (msContourLayerGenerateContour(layer) != MS_SUCCESS)
    return MS_FAILURE;

  GDALClose(clinfo->hDS);
  clinfo->hDS = NULL;
  free(clinfo->buffer);  
  
  /* Open our virtual ogr layer */
  if (msLayerOpen(&clinfo->ogrLayer) != MS_SUCCESS)
    return MS_FAILURE;

  clinfo->ogrLayer.numitems = layer->numitems;
  clinfo->ogrLayer.items = CSLDuplicate(layer->items); 

  return msLayerWhichShapes(&clinfo->ogrLayer, rect, isQuery);
}
Ejemplo n.º 3
0
Handle<Value> MSRect::Project(const Arguments &args) {
  MSRect *rect = ObjectWrap::Unwrap<MSRect>(args.This());
  Local<Object> obj;
  MSProjection *projIn;
  MSProjection *projOut;

  if (args.Length() != 2) {
    THROW_ERROR(Error, "projecting a point requires two projection arguments");
  }

  if (!args[0]->IsObject()) {
    THROW_ERROR(TypeError, "first argument to project must be Projection object");
  }

  obj = args[0]->ToObject();

  if (obj->IsNull() || obj->IsUndefined() || !MSProjection::constructor->HasInstance(obj)) {
    THROW_ERROR(TypeError, "first argument to project must be Projection object");
  }

  projIn = ObjectWrap::Unwrap<MSProjection>(obj);

  if (!args[1]->IsObject()) {
    THROW_ERROR(TypeError, "second argument to project must be Projection object");
  }

  obj = args[1]->ToObject();

  if (obj->IsNull() || obj->IsUndefined() || !MSProjection::constructor->HasInstance(obj)) {
    THROW_ERROR(TypeError, "first argument to project must be Projection object");
  }

  projOut = ObjectWrap::Unwrap<MSProjection>(obj);

  msProjectRect(projIn->this_, projOut->this_, rect->this_);

  return Undefined();
}
Ejemplo n.º 4
0
static xmlNodePtr msWFSDumpLayer11(mapObj *map, layerObj *lp, xmlNsPtr psNsOws)
{
    rectObj ext;
   
    xmlNodePtr psRootNode, psNode;
    const char *value    = NULL;
    const char *encoding = NULL;
    char *encoded=NULL;
    char *valueToFree;
    char **tokens;
    int n=0,i=0;      

    encoding = msOWSLookupMetadata(&(map->web.metadata), "FO", "encoding");
    if (!encoding)
      encoding = "ISO-8859-1";

    psRootNode = xmlNewNode(NULL, BAD_CAST "FeatureType");

    /*if there is an encoding using it on some of the items*/
    psNode = msOWSCommonxmlNewChildEncoded(psRootNode, NULL, "Name", lp->name, encoding);


    if (lp->name && strlen(lp->name) > 0 &&
        (msIsXMLTagValid(lp->name) == MS_FALSE || isdigit(lp->name[0])))
      xmlAddSibling(psNode,
                    xmlNewComment(BAD_CAST "WARNING: The layer name '%s' might contain spaces or "
                                  "invalid characters or may start with a number. This could lead to potential problems"));
   
    value = msOWSLookupMetadata(&(lp->metadata), "FO", "title");
    if (!value)
      value =(const char*)lp->name;

    psNode = msOWSCommonxmlNewChildEncoded(psRootNode, NULL, "Title", value, encoding);

 
    value = msOWSLookupMetadata(&(lp->metadata), "FO", "abstract");
    if (value)
      psNode = msOWSCommonxmlNewChildEncoded(psRootNode, NULL, "Abstract", value, encoding);



    value = msOWSLookupMetadata(&(lp->metadata), "FO", "keywordlist");

    if (value)
    {
	if (encoding)
	  encoded = msGetEncodedString(value, encoding);
        else
          encoded = msGetEncodedString(value, "ISO-8859-1");

        msLibXml2GenerateList(
            xmlNewChild(psRootNode, psNsOws, BAD_CAST "Keywords", NULL),
            NULL, "Keyword", encoded, ',' );
	msFree(encoded);
    }
      /*support DefaultSRS and OtherSRS*/
    valueToFree = msOWSGetProjURN(&(map->projection),&(map->web.metadata),"FO",MS_FALSE);
    if (!valueToFree)
      valueToFree = msOWSGetProjURN(&(lp->projection), &(lp->metadata), "FO", MS_FALSE);

    if (valueToFree)
    {
        tokens = msStringSplit(valueToFree, ' ', &n);
        if (tokens && n > 0)
        {
            psNode = xmlNewChild(psRootNode, NULL, BAD_CAST "DefaultSRS", BAD_CAST tokens[0]);
            for (i=1; i<n; i++)
              psNode = xmlNewChild(psRootNode, NULL, BAD_CAST "OtherSRS", BAD_CAST tokens[i]);

            msFreeCharArray(tokens, n);
        }
    }
    else
      xmlAddSibling(psNode,
                    xmlNewComment(BAD_CAST "WARNING: Mandatory mapfile parameter: (at least one of) MAP.PROJECTION, LAYER.PROJECTION or wfs/ows_srs metadata was missing in this context."));

    free(valueToFree);
    valueToFree = NULL;

    /*TODO: adevertize only gml3?*/
    psNode = xmlNewNode(NULL, BAD_CAST "OutputFormats");
    xmlAddChild(psRootNode, psNode);

    {
        char *formats_list = msWFSGetOutputFormatList( map, lp, "1.1.0" );
        int iformat, n;
        char **tokens;

        n = 0;
        tokens = msStringSplit(formats_list, ',', &n);

        for( iformat = 0; iformat < n; iformat++ )
            xmlNewChild(psNode, NULL, BAD_CAST "Format", 
                        BAD_CAST tokens[iformat] );
        msFree( formats_list );
        msFreeCharArray( tokens, n );
    }
  
    /*bbox*/
    if (msOWSGetLayerExtent(map, lp, "FO", &ext) == MS_SUCCESS)
    {   
        /*convert to latlong*/
        if (lp->projection.numargs > 0)
        {
            if (!pj_is_latlong(&lp->projection.proj))
              msProjectRect(&lp->projection, NULL, &ext);
        }
        else if (map->projection.numargs > 0 && !pj_is_latlong(&map->projection.proj))
          msProjectRect(&map->projection, NULL, &ext);

        xmlAddChild(psRootNode,
                    msOWSCommonWGS84BoundingBox( psNsOws, 2,
                                                 ext.minx, ext.miny,
                                                 ext.maxx, ext.maxy));
    }
    else
    {
        xmlNewChild(psRootNode, psNsOws, BAD_CAST "WGS84BoundingBox", NULL);
        xmlAddSibling(psNode,
                      xmlNewComment(BAD_CAST "WARNING: Optional WGS84BoundingBox could not be established for this layer.  Consider setting the EXTENT in the LAYER object, or wfs_extent metadata. Also check that your data exists in the DATA statement"));
    }

    value = msOWSLookupMetadata(&(lp->metadata), "FO", "metadataurl_href");

    if (value)
    {
        psNode = xmlNewChild(psRootNode, NULL, BAD_CAST "MetadataURL", BAD_CAST value);

        value = msOWSLookupMetadata(&(lp->metadata), "FO", "metadataurl_format");

        if (!value)
          value = msStrdup("text/html"); /* default */

        xmlNewProp(psNode, BAD_CAST "format", BAD_CAST value);

        value = msOWSLookupMetadata(&(lp->metadata), "FO", "metadataurl_type");

        if (!value)
          value = msStrdup("FGDC"); /* default */

        xmlNewProp(psNode, BAD_CAST "type", BAD_CAST value);
    }

    return psRootNode;
}
Ejemplo n.º 5
0
/* 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, &current->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, &current->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, &current->bounds)) {
      msFreeShape(&current->shape);
      msInitShape(&current->shape);

      msDebug("Skipping an invalid shape falling outside of the given extent\n");
      continue;
    }

    /* construct the item array */
    if (layer->iteminfo)
      BuildFeatureAttributes(layer, layerinfo, &current->shape);

    /* evaluate the group expression */
    if (layer->cluster.group.string)
      current->group = msClusterGetGroupText(&layer->cluster.group, &current->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);
      }
    }
Ejemplo n.º 6
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;
}
Ejemplo n.º 7
0
int msWFSLayerOpen(layerObj *lp,
                   const char *pszGMLFilename, rectObj *defaultBBOX)
{
#ifdef USE_WFS_LYR
  int status = MS_SUCCESS;
  msWFSLayerInfo *psInfo = NULL;

  if ( msCheckParentPointer(lp->map,"map")==MS_FAILURE )
    return MS_FAILURE;

  if (lp->wfslayerinfo != NULL) {
    psInfo =(msWFSLayerInfo*)lp->wfslayerinfo;

    /* Layer already opened.  If explicit filename requested then check */
    /* that file was already opened with the same filename. */
    /* If no explicit filename requested then we'll try to reuse the */
    /* previously opened layer... this will happen in a msDrawMap() call. */
    if (pszGMLFilename == NULL ||
        (psInfo->pszGMLFilename && pszGMLFilename &&
         strcmp(psInfo->pszGMLFilename, pszGMLFilename) == 0) ) {
      if (lp->layerinfo == NULL) {
        if (msWFSLayerWhichShapes(lp, psInfo->rect, MS_FALSE) == MS_FAILURE) /* no access to context (draw vs. query) here, although I doubt it matters... */
          return MS_FAILURE;
      }
      return MS_SUCCESS;  /* Nothing to do... layer is already opened */
    } else {
      /* Hmmm... should we produce a fatal error? */
      /* For now we'll just close the layer and reopen it. */
      if (lp->debug)
        msDebug("msWFSLayerOpen(): Layer already opened (%s)\n",
                lp->name?lp->name:"(null)" );
      msWFSLayerClose(lp);
    }
  }

  /* ------------------------------------------------------------------
   * Alloc and fill msWFSLayerInfo inside layer obj
   * ------------------------------------------------------------------ */
  lp->wfslayerinfo = psInfo = msAllocWFSLayerInfo();

  if (pszGMLFilename)
    psInfo->pszGMLFilename = msStrdup(pszGMLFilename);
  else {
    psInfo->pszGMLFilename = msTmpFile(lp->map,
                                       lp->map->mappath,
                                       NULL,
                                       "tmp.gml");
  }

  if (defaultBBOX) {
    /* __TODO__ If new bbox differs from current one then we should */
    /* invalidate current GML file in cache */
    psInfo->rect = *defaultBBOX;
  } else {
    /* Use map bbox by default */
    psInfo->rect = lp->map->extent;
  }

  /* We will call whichshapes() now and force downloading layer right */
  /* away.  This saves from having to call DescribeFeatureType and */
  /* parsing the response (being lazy I guess) and anyway given the */
  /* way we work with layers right now the bbox is unlikely to change */
  /* between now and the time whichshapes() would have been called by */
  /* the MapServer core. */
#ifdef USE_PROJ
  if((lp->map->projection.numargs > 0) && (lp->projection.numargs > 0))
    msProjectRect(&lp->map->projection, &lp->projection, &psInfo->rect); /* project the searchrect to source coords */
#endif

  if (msWFSLayerWhichShapes(lp, psInfo->rect, MS_FALSE) == MS_FAILURE)  /* no access to context (draw vs. query) here, although I doubt it matters... */
    status = MS_FAILURE;


  return status;
#else
  /* ------------------------------------------------------------------
   * WFS CONNECTION Support not included...
   * ------------------------------------------------------------------ */
  msSetError(MS_WFSCONNERR, "WFS CLIENT CONNECTION support is not available.",
             "msWFSLayerOpen()");
  return(MS_FAILURE);

#endif /* USE_WFS_LYR */
}
Ejemplo n.º 8
0
static wfsParamsObj *msBuildRequestParams(mapObj *map, layerObj *lp,
    rectObj *bbox_ret)
{
  wfsParamsObj *psParams = NULL;
  rectObj bbox;
  const char *pszTmp;
  int nLength, i = 0;
  char *pszVersion, *pszTypeName;

  if (!map || !lp || !bbox_ret)
    return NULL;

  if (lp->connection == NULL)
    return NULL;

  psParams = msWFSCreateParamsObj();
  pszTmp = msOWSLookupMetadata(&(lp->metadata), "FO", "version");
  if (pszTmp)
    psParams->pszVersion = msStrdup(pszTmp);
  else {
    pszTmp = strstr(lp->connection, "VERSION=");
    if (!pszTmp)
      pszTmp = strstr(lp->connection, "version=");
    if (pszTmp) {
      pszVersion = strchr(pszTmp, '=')+1;
      if (strncmp(pszVersion, "0.0.14", 6) == 0)
        psParams->pszVersion = msStrdup("0.0.14");
      else if (strncmp(pszVersion, "1.0.0", 5) == 0)
        psParams->pszVersion = msStrdup("1.0.0");
    }
  }

  /*the service is always set to WFS : see bug 1302 */
  psParams->pszService = msStrdup("WFS");

  /*
  pszTmp = msOWSLookupMetadata(&(lp->metadata), "FO", "service");
  if (pszTmp)
    psParams->pszService = msStrdup(pszTmp);
  else
  {
      pszTmp = strstr(lp->connection, "SERVICE=");
      if (!pszTmp)
        pszTmp = strstr(lp->connection, "service=");
      if (pszTmp)
      {
          pszService = strchr(pszTmp, '=')+1;
          if (strncmp(pszService, "WFS", 3) == 0)
            psParams->pszService = msStrdup("WFS");
      }
  }
  */

  pszTmp = msOWSLookupMetadata(&(lp->metadata), "FO", "geometryname");
  if (pszTmp)
    psParams->pszGeometryName = msStrdup(pszTmp);

  pszTmp = msOWSLookupMetadata(&(lp->metadata), "FO", "typename");
  if (pszTmp)
    psParams->pszTypeName = msStrdup(pszTmp);
  else {
    pszTmp = strstr(lp->connection, "TYPENAME=");
    if (!pszTmp)
      pszTmp = strstr(lp->connection, "typename=");
    if (pszTmp) {
      pszTypeName = strchr(pszTmp, '=')+1;
      if (pszTypeName) {
        nLength = strlen(pszTypeName);
        if (nLength > 0) {
          for (i=0; i<nLength; i++) {
            if (pszTypeName[i] == '&')
              break;
          }

          if (i<nLength) {
            char *pszTypeNameTmp = NULL;
            pszTypeNameTmp = msStrdup(pszTypeName);
            pszTypeNameTmp[i] = '\0';
            psParams->pszTypeName = msStrdup(pszTypeNameTmp);
            free(pszTypeNameTmp);
          } else
            psParams->pszTypeName = msStrdup(pszTypeName);
        }
      }
    }
  }

  pszTmp = msOWSLookupMetadata(&(lp->metadata), "FO", "filter");
  if (pszTmp && strlen(pszTmp) > 0) {
    if (strstr(pszTmp, "<Filter>") !=NULL || strstr(pszTmp, "<ogc:Filter") != NULL)
      psParams->pszFilter = msStrdup(pszTmp);
    else {
      psParams->pszFilter = msStringConcatenate(psParams->pszFilter, "<ogc:Filter xmlns:ogc=\"http://www.opengis.net/ogc\">");
      psParams->pszFilter = msStringConcatenate(psParams->pszFilter, (char*)pszTmp);
      psParams->pszFilter = msStringConcatenate(psParams->pszFilter, "</ogc:Filter>");
    }
  }

  pszTmp = msOWSLookupMetadata(&(lp->metadata), "FO", "maxfeatures");
  if (pszTmp)
    psParams->nMaxFeatures = atoi(pszTmp);

  /* Request is always GetFeature; */
  psParams->pszRequest = msStrdup("GetFeature");


  /* ------------------------------------------------------------------
   * Figure the SRS we'll use for the request.
   * - Fetch the map SRS (if it's EPSG)
   * - Check if map SRS is listed in layer wfs_srs metadata
   * - If map SRS is valid for this layer then use it
   * - Otherwise request layer in its default SRS and we'll reproject later
   * ------------------------------------------------------------------ */

  /* __TODO__ WFS servers support only one SRS... need to decide how we'll */
  /* handle this and document it well. */
  /* It's likely that we'll simply reproject the BBOX to teh layer's projection. */

  /* ------------------------------------------------------------------
   * Set layer SRS and reproject map extents to the layer's SRS
   * ------------------------------------------------------------------ */
#ifdef __TODO__
  /* No need to set lp->proj if it's already set to the right EPSG code */
  if ((pszTmp = msGetEPSGProj(&(lp->projection), NULL, MS_TRUE)) == NULL ||
      strcasecmp(pszEPSG, pszTmp) != 0) {
    char szProj[20];
    snprintf(szProj, sizeof(szProj), "init=epsg:%s", pszEPSG+5);
    if (msLoadProjectionString(&(lp->projection), szProj) != 0)
      return NULL;
  }
#endif

  bbox = map->extent;
  if (msProjectionsDiffer(&(map->projection), &(lp->projection))) {
    msProjectRect(&(map->projection), &(lp->projection), &bbox);
  }

  if (bbox_ret != NULL)
    *bbox_ret = bbox;

  return psParams;

}
Ejemplo n.º 9
0
int msWFSLayerWhichShapes(layerObj *lp, rectObj rect, int isQuery)
{
#ifdef USE_WFS_LYR
  msWFSLayerInfo *psInfo;
  int status = MS_SUCCESS;
  const char *pszTmp;
  FILE *fp;

  if ( msCheckParentPointer(lp->map,"map")==MS_FAILURE )
    return MS_FAILURE;


  psInfo =(msWFSLayerInfo*)lp->wfslayerinfo;

  if (psInfo == NULL) {
    msSetError(MS_WFSCONNERR, "Assertion failed: WFS layer not opened!!!",
               "msWFSLayerWhichShapes()");
    return(MS_FAILURE);
  }

  /* ------------------------------------------------------------------
   * Check if layer overlaps current view window (using wfs_latlonboundingbox)
   * ------------------------------------------------------------------ */
  if ((pszTmp = msOWSLookupMetadata(&(lp->metadata),
                                    "FO", "latlonboundingbox")) != NULL) {
    char **tokens;
    int n;
    rectObj ext;

    tokens = msStringSplit(pszTmp, ' ', &n);
    if (tokens==NULL || n != 4) {
      msSetError(MS_WFSCONNERR, "Wrong number of values in 'wfs_latlonboundingbox' metadata.",
                 "msWFSLayerWhichShapes()");
      return MS_FAILURE;
    }

    ext.minx = atof(tokens[0]);
    ext.miny = atof(tokens[1]);
    ext.maxx = atof(tokens[2]);
    ext.maxy = atof(tokens[3]);

    msFreeCharArray(tokens, n);

    /* Reproject latlonboundingbox to the selected SRS for the layer and */
    /* check if it overlaps the bbox that we calculated for the request */

    msProjectRect(&(lp->map->latlon), &(lp->projection), &ext);
    if (!msRectOverlap(&rect, &ext)) {
      /* No overlap... nothing to do. If layer was never opened, go open it.*/
      if (lp->layerinfo)
        return MS_DONE;  /* No overlap. */
    }
  }


  /* ------------------------------------------------------------------
   * __TODO__ If new bbox differs from current one then we should
   * invalidate current GML file in cache
   * ------------------------------------------------------------------ */
  psInfo->rect = rect;


  /* ------------------------------------------------------------------
   * If file not downloaded yet then do it now.
   * ------------------------------------------------------------------ */
  if (psInfo->nStatus == 0) {
    httpRequestObj asReqInfo[2];
    int numReq = 0;

    msHTTPInitRequestObj(asReqInfo, 2);

    if ( msPrepareWFSLayerRequest(-1, lp->map, lp,
                                  asReqInfo, &numReq) == MS_FAILURE  ||
         msOWSExecuteRequests(asReqInfo, numReq,
                              lp->map, MS_TRUE) == MS_FAILURE ) {
      /* Delete tmp file... we don't want it to stick around. */
      unlink(asReqInfo[0].pszOutputFile);
      return MS_FAILURE;
    }

    /* Cleanup */
    msHTTPFreeRequestObj(asReqInfo, numReq);

  }

  if ( !MS_HTTP_SUCCESS( psInfo->nStatus ) ) {
    /* Delete tmp file... we don't want it to stick around. */
    unlink(psInfo->pszGMLFilename);

    msSetError(MS_WFSCONNERR,
               "Got HTTP status %d downloading WFS layer %s",
               "msWFSLayerWhichShapes()",
               psInfo->nStatus, lp->name?lp->name:"(null)");
    return(MS_FAILURE);
  }

  /* ------------------------------------------------------------------
   * Check that file is really GML... it could be an exception, or just junk.
   * ------------------------------------------------------------------ */
  if ((fp = fopen(psInfo->pszGMLFilename, "r")) != NULL) {
    char szHeader[2000];
    int  nBytes = 0;

    nBytes = fread( szHeader, 1, sizeof(szHeader)-1, fp );
    fclose(fp);

    if (nBytes < 0)
      nBytes = 0;
    szHeader[nBytes] = '\0';

    if ( nBytes == 0 ) {
      msSetError(MS_WFSCONNERR,
                 "WFS request produced no oputput for layer %s.",
                 "msWFSLayerWhichShapes()",
                 lp->name?lp->name:"(null)");
      return(MS_FAILURE);

    }
    if ( strstr(szHeader, "<WFS_Exception>") ||
         strstr(szHeader, "<ServiceExceptionReport>") ) {
      msOWSProcessException(lp, psInfo->pszGMLFilename,
                            MS_WFSCONNERR, "msWFSLayerWhichShapes()" );
      return MS_FAILURE;
    } else if ( strstr(szHeader,"opengis.net/gml") &&
                strstr(szHeader,"featureMember>") == NULL ) {
      /* This looks like valid GML, but contains 0 features. */
      return MS_DONE;
    } else if ( strstr(szHeader,"opengis.net/gml") == NULL ||
                strstr(szHeader,"featureMember>") == NULL ) {
      /* This is probably just junk. */
      msSetError(MS_WFSCONNERR,
                 "WFS request produced unexpected output (junk?) for layer %s.",
                 "msWFSLayerWhichShapes()",
                 lp->name?lp->name:"(null)");
      return(MS_FAILURE);
    }

    /* If we got this far, it must be a valid GML dataset... keep going */
  }


  /* ------------------------------------------------------------------
   * Open GML file using OGR.
   * ------------------------------------------------------------------ */
  if ((status = msOGRLayerOpen(lp, psInfo->pszGMLFilename)) != MS_SUCCESS)
    return status;

  status = msOGRLayerWhichShapes(lp, rect, isQuery);

  /* Mark that the OGR Layer is valid */
  psInfo->bLayerHasValidGML = MS_TRUE;

  return status;
#else
  /* ------------------------------------------------------------------
   * WFS CONNECTION Support not included...
   * ------------------------------------------------------------------ */
  msSetError(MS_WFSCONNERR, "WFS CLIENT CONNECTION support is not available.",
             "msWFSLayerWhichShapes()");
  return(MS_FAILURE);

#endif /* USE_WFS_LYR */
}
Ejemplo n.º 10
0
static int msContourLayerReadRaster(layerObj *layer, rectObj rect)
{
  mapObj *map = layer->map;  
  char **bands;
  char pointer[64], memDSPointer[128];
  int band = 1;
  double adfGeoTransform[6], adfInvGeoTransform[6];
  double llx, lly, urx, ury;  
  rectObj copyRect, mapRect;
  int dst_xsize, dst_ysize;
  int virtual_grid_step_x, virtual_grid_step_y;
  int src_xoff, src_yoff, src_xsize, src_ysize;  
  double map_cellsize_x, map_cellsize_y, dst_cellsize_x, dst_cellsize_y;
  GDALRasterBandH hBand = NULL;
  CPLErr eErr;
  
  contourLayerInfo *clinfo = (contourLayerInfo *) layer->layerinfo;

  if (layer->debug)
    msDebug("Entering msContourLayerReadRaster().\n");

  if (clinfo == NULL || clinfo->hOrigDS == NULL) {
    msSetError(MS_MISCERR, "Assertion failed: Contour layer not opened!!!",
               "msContourLayerReadRaster()");
    return MS_FAILURE;    
  }

  bands = CSLTokenizeStringComplex(
               CSLFetchNameValue(layer->processing,"BANDS"), " ,", FALSE, FALSE );
  if (CSLCount(bands) > 0) {
    band = atoi(bands[0]);
    if (band < 1 || band > GDALGetRasterCount(clinfo->hOrigDS)) {
      msSetError( MS_IMGERR,
                  "BANDS PROCESSING directive includes illegal band '%d', should be from 1 to %d.",
                  "msContourLayerReadRaster()",
                  band, GDALGetRasterCount(clinfo->hOrigDS));
      CSLDestroy(bands);
      return MS_FAILURE;
    }
  }
  CSLDestroy(bands);

  hBand = GDALGetRasterBand(clinfo->hOrigDS, band);
  if (hBand == NULL)
  {
    msSetError(MS_IMGERR,
               "Band %d does not exist on dataset.",
               "msContourLayerReadRaster()", band);
    return MS_FAILURE;
  }

  if (layer->projection.numargs > 0 &&
      EQUAL(layer->projection.args[0], "auto")) {
    const char *wkt;
    wkt = GDALGetProjectionRef(clinfo->hOrigDS);
    if (wkt != NULL && strlen(wkt) > 0) {
      if (msOGCWKT2ProjectionObj(wkt, &(layer->projection),
                                 layer->debug) != MS_SUCCESS) {
        char  msg[MESSAGELENGTH*2];
        errorObj *ms_error = msGetErrorObj();

        snprintf( msg, sizeof(msg),
                  "%s\n"
                  "PROJECTION AUTO cannot be used for this "
                  "GDAL raster (`%s').",
                  ms_error->message, layer->data);
        msg[MESSAGELENGTH-1] = '\0';

        msSetError(MS_OGRERR, "%s","msDrawRasterLayer()",
                   msg);
        return MS_FAILURE;
      }
    }
  }
  
  /*
   * Compute the georeferenced window of overlap, and read the source data
   * downsampled to match output resolution, or at full resolution if
   * output resolution is lower than the source resolution.
   *
   * A large portion of this overlap calculation code was borrowed from 
   * msDrawRasterLayerGDAL(). 
   * Would be possible to move some of this to a reusable function?
   *
   * Note: This code works only if no reprojection is involved. It would
   * need rework to support cases where output projection differs from source
   * data file projection.
   */
  
  src_xsize = GDALGetRasterXSize(clinfo->hOrigDS);
  src_ysize = GDALGetRasterYSize(clinfo->hOrigDS);

  /* set the Dataset extent */
  msGetGDALGeoTransform(clinfo->hOrigDS, map, layer, adfGeoTransform);  
  clinfo->extent.minx = adfGeoTransform[0];
  clinfo->extent.maxy = adfGeoTransform[3];
  clinfo->extent.maxx = adfGeoTransform[0] + src_xsize * adfGeoTransform[1];
  clinfo->extent.miny = adfGeoTransform[3] + src_ysize * adfGeoTransform[5];
  
  if (layer->transform) {
    if (layer->debug)
      msDebug("msContourLayerReadRaster(): Entering transform.\n");

    InvGeoTransform(adfGeoTransform, adfInvGeoTransform);

    mapRect = rect;
    map_cellsize_x = map_cellsize_y = map->cellsize;      
#ifdef USE_PROJ
    /* if necessary, project the searchrect to source coords */
    if (msProjectionsDiffer( &(map->projection), &(layer->projection)))  {
      if ( msProjectRect(&map->projection, &layer->projection, &mapRect)
          != MS_SUCCESS ) {
        msDebug("msContourLayerReadRaster(%s): unable to reproject map request rectangle into layer projection, canceling.\n", layer->name);
        return MS_FAILURE;
      }

      map_cellsize_x = MS_CELLSIZE(mapRect.minx, mapRect.maxx, map->width);
      map_cellsize_y = MS_CELLSIZE(mapRect.miny, mapRect.maxy, map->height);

      /* if the projection failed to project the extent requested, we need to
         calculate the cellsize to preserve the initial map cellsize ratio */
      if ( (mapRect.minx < GEO_TRANS(adfGeoTransform,0,src_ysize)) ||
           (mapRect.maxx > GEO_TRANS(adfGeoTransform,src_xsize,0)) ||
           (mapRect.miny < GEO_TRANS(adfGeoTransform+3,0,src_ysize)) || 
           (mapRect.maxy > GEO_TRANS(adfGeoTransform+3,src_xsize,0)) ) {

        int src_unit, dst_unit;
        src_unit = GetMapserverUnitUsingProj(&map->projection);
        dst_unit = GetMapserverUnitUsingProj(&layer->projection);
        if (src_unit == -1 || dst_unit == -1) {
          msDebug("msContourLayerReadRaster(%s): unable to reproject map request rectangle into layer projection, canceling.\n", layer->name);
          return MS_FAILURE;
        }

        map_cellsize_x =  MS_CONVERT_UNIT(src_unit, dst_unit,
                                          MS_CELLSIZE(rect.minx, rect.maxx, map->width)); 
        map_cellsize_y = MS_CONVERT_UNIT(src_unit, dst_unit,
                                         MS_CELLSIZE(rect.miny, rect.maxy, map->height));
      }       
    }
#endif
    
    if (map_cellsize_x == 0 || map_cellsize_y == 0) {
      if (layer->debug)
        msDebug("msContourLayerReadRaster(): Cellsize can't be 0.\n");
      return MS_FAILURE;
    }
    
    /* Adjust MapServer pixel model to GDAL pixel model */
    mapRect.minx -= map_cellsize_x*0.5;
    mapRect.maxx += map_cellsize_x*0.5;
    mapRect.miny -= map_cellsize_y*0.5;
    mapRect.maxy += map_cellsize_y*0.5;


    /*
     * If raw data cellsize (from geotransform) is larger than output map_cellsize
     * then we want to extract only enough data to match the output map resolution
     * which means that GDAL will automatically sample the data on read.
     *
     * To prevent bad contour effects on tile edges, we adjust the target cellsize 
     * to align the extracted window with a virtual grid based on the origin of the 
     * raw data and a virtual grid step size corresponding to an integer sampling step.
     *
     * If source data has a greater cellsize (i.e. lower res) that requested ouptut map
     * then we use the raw data cellsize as target cellsize since there is no point in 
     * interpolating the data for contours in this case.
     */

    virtual_grid_step_x = (int)floor(map_cellsize_x / ABS(adfGeoTransform[1]));
    if (virtual_grid_step_x < 1)
      virtual_grid_step_x = 1; /* Do not interpolate data if grid sampling step < 1 */

    virtual_grid_step_y = (int)floor(map_cellsize_y / ABS(adfGeoTransform[5]));
    if (virtual_grid_step_y < 1)
      virtual_grid_step_y = 1; /* Do not interpolate data if grid sampling step < 1 */
    
    /* target cellsize is a multiple of raw data cellsize based on grid step*/
    dst_cellsize_x = ABS(adfGeoTransform[1]) * virtual_grid_step_x;
    dst_cellsize_y = ABS(adfGeoTransform[5]) * virtual_grid_step_y;

    /* Compute overlap between source and target views */

    copyRect = mapRect;

    if (copyRect.minx < GEO_TRANS(adfGeoTransform,0,src_ysize))
      copyRect.minx = GEO_TRANS(adfGeoTransform,0,src_ysize);
    if (copyRect.maxx > GEO_TRANS(adfGeoTransform,src_xsize,0))
      copyRect.maxx = GEO_TRANS(adfGeoTransform,src_xsize,0);
    if (copyRect.miny < GEO_TRANS(adfGeoTransform+3,0,src_ysize))
      copyRect.miny = GEO_TRANS(adfGeoTransform+3,0,src_ysize);
    if (copyRect.maxy > GEO_TRANS(adfGeoTransform+3,src_xsize,0))
      copyRect.maxy = GEO_TRANS(adfGeoTransform+3,src_xsize,0);
    
    if (copyRect.minx >= copyRect.maxx || copyRect.miny >= copyRect.maxy) {
      if (layer->debug)
        msDebug("msContourLayerReadRaster(): No overlap.\n");
      return MS_SUCCESS;
    }

    /*
     * Convert extraction window to raster coordinates
     */
    llx = GEO_TRANS(adfInvGeoTransform+0,copyRect.minx,copyRect.miny);
    lly = GEO_TRANS(adfInvGeoTransform+3,copyRect.minx,copyRect.miny);
    urx = GEO_TRANS(adfInvGeoTransform+0,copyRect.maxx,copyRect.maxy);
    ury = GEO_TRANS(adfInvGeoTransform+3,copyRect.maxx,copyRect.maxy);

    /* 
     * Align extraction window with virtual grid 
     * (keep in mind raster coordinates origin is at upper-left)
     * We also add an extra buffer to fix tile boundarie issues when zoomed
     */
    llx = floor(llx / virtual_grid_step_x) * virtual_grid_step_x - (virtual_grid_step_x*5);
    urx = ceil(urx / virtual_grid_step_x) * virtual_grid_step_x + (virtual_grid_step_x*5);
    ury = floor(ury / virtual_grid_step_y) * virtual_grid_step_y - (virtual_grid_step_x*5);
    lly = ceil(lly / virtual_grid_step_y) * virtual_grid_step_y + (virtual_grid_step_x*5);
    
    src_xoff = MAX(0,(int) floor(llx+0.5));
    src_yoff = MAX(0,(int) floor(ury+0.5));
    src_xsize = MIN(MAX(0,(int) (urx - llx + 0.5)),
                    GDALGetRasterXSize(clinfo->hOrigDS) - src_xoff);
    src_ysize = MIN(MAX(0,(int) (lly - ury + 0.5)),
                    GDALGetRasterYSize(clinfo->hOrigDS) - src_yoff);

    /* Update the geographic extent (buffer added) */
    /* TODO: a better way to go the geo_trans */
    copyRect.minx = GEO_TRANS(adfGeoTransform+0,src_xoff,0);
    copyRect.maxx = GEO_TRANS(adfGeoTransform+0,src_xoff+src_xsize,0);
    copyRect.miny = GEO_TRANS(adfGeoTransform+3,0,src_yoff+src_ysize);
    copyRect.maxy = GEO_TRANS(adfGeoTransform+3,0,src_yoff);
    
    /* 
     * If input window is to small then stop here
     */
    if (src_xsize < 2 || src_ysize < 2)
    {
      if (layer->debug)
        msDebug("msContourLayerReadRaster(): input window too small, or no apparent overlap between map view and this window(1).\n");
      return MS_SUCCESS;
    }

    /* Target buffer size */
    dst_xsize = (int)ceil((copyRect.maxx - copyRect.minx) / dst_cellsize_x);
    dst_ysize = (int)ceil((copyRect.maxy - copyRect.miny) / dst_cellsize_y);

    if (dst_xsize == 0 || dst_ysize == 0) {
      if (layer->debug)
        msDebug("msContourLayerReadRaster(): no apparent overlap between map view and this window(2).\n");
      return MS_SUCCESS;
    }

    if (layer->debug)
      msDebug( "msContourLayerReadRaster(): src=%d,%d,%d,%d, dst=%d,%d,%d,%d\n",
               src_xoff, src_yoff, src_xsize, src_ysize,
               0, 0, dst_xsize, dst_ysize );
  } else {
    src_xoff = 0;
    src_yoff = 0;
    dst_xsize = src_xsize = MIN(map->width,src_xsize);
    dst_ysize = src_ysize = MIN(map->height,src_ysize);
    copyRect.minx = copyRect.miny = 0;
    copyRect.maxx = map->width;
    copyRect.maxy = map->height;
    dst_cellsize_y = dst_cellsize_x = 1;
  }

  /* -------------------------------------------------------------------- */
  /*      Allocate buffer, and read data into it.                         */
  /* -------------------------------------------------------------------- */

  clinfo->buffer = (double *) malloc(sizeof(double) * dst_xsize * dst_ysize);
  if (clinfo->buffer == NULL) {
    msSetError(MS_MEMERR, "Malloc(): Out of memory.", "msContourLayerReadRaster()");
    return MS_FAILURE;
  }

  eErr = GDALRasterIO(hBand, GF_Read,
                      src_xoff, src_yoff, src_xsize, src_ysize,
                      clinfo->buffer, dst_xsize, dst_ysize, GDT_Float64,
                      0, 0);

  if (eErr != CE_None) {
    msSetError( MS_IOERR, "GDALRasterIO() failed: %s",
                "msContourLayerReadRaster()", CPLGetLastErrorMsg() );
    free(clinfo->buffer);
    return MS_FAILURE;
  }

  memset(pointer, 0, sizeof(pointer));
  CPLPrintPointer(pointer, clinfo->buffer, sizeof(pointer));
  sprintf(memDSPointer,"MEM:::DATAPOINTER=%s,PIXELS=%d,LINES=%d,BANDS=1,DATATYPE=Float64",
          pointer, dst_xsize, dst_ysize);
  clinfo->hDS = GDALOpen(memDSPointer,  GA_ReadOnly);
  if (clinfo->hDS == NULL) {
    msSetError(MS_IMGERR,
               "Unable to open GDAL Memory dataset.",
               "msContourLayerReadRaster()");
    free(clinfo->buffer);
    return MS_FAILURE;
  }

  adfGeoTransform[0] = copyRect.minx;
  adfGeoTransform[1] = dst_cellsize_x;
  adfGeoTransform[2] = 0;
  adfGeoTransform[3] = copyRect.maxy;
  adfGeoTransform[4] = 0;
  adfGeoTransform[5] = -dst_cellsize_y;

  clinfo->cellsize = MAX(dst_cellsize_x, dst_cellsize_y);
  {
    char buf[64];
    sprintf(buf, "%lf", clinfo->cellsize);
    msInsertHashTable(&layer->metadata, "__data_cellsize__", buf);
  }
      
  GDALSetGeoTransform(clinfo->hDS, adfGeoTransform);
  return MS_SUCCESS;
}
Ejemplo n.º 11
0
/**
 * Generic function to render chart layers.
 */
int msDrawChartLayer(mapObj *map, layerObj *layer, imageObj *image)
{

    rectObj     searchrect;
    const char *chartTypeProcessingKey=msLayerGetProcessingKey( layer,"CHART_TYPE" );
    int chartType=MS_CHART_TYPE_PIE;
    int status = MS_FAILURE;

    if (image && map && layer)
    {
        if( !(MS_RENDERER_PLUGIN(image->format) )) {
            msSetError(MS_MISCERR, "chart drawing currently only supports GD and AGG renderers", "msDrawChartLayer()");
            return MS_FAILURE;
        }

        if( layer->numclasses < 2 ) {
            msSetError(MS_MISCERR,"chart drawing requires at least 2 classes in layer", "msDrawChartLayer()");
            return MS_FAILURE;
        }

        if(chartTypeProcessingKey!=NULL) {
            if( strcasecmp(chartTypeProcessingKey,"PIE") == 0 ) {
                chartType=MS_CHART_TYPE_PIE;
            }
            else if( strcasecmp(chartTypeProcessingKey,"BAR") == 0 ) {
                chartType=MS_CHART_TYPE_BAR;
            }
            else if( strcasecmp(chartTypeProcessingKey,"VBAR") == 0 ) {
                chartType=MS_CHART_TYPE_VBAR;
            }
            else {
                msSetError(MS_MISCERR,"unknown chart type for processing key \"CHART_TYPE\", must be one of \"PIE\" or \"BAR\"", "msDrawChartLayer()");
                return MS_FAILURE;
            }
        }
        if(chartType == MS_CHART_TYPE_PIE) {
            pieLayerProcessDynamicDiameter(layer);
        }

        /* open this layer */
        status = msLayerOpen(layer);
        if(status != MS_SUCCESS) return MS_FAILURE;

        status = msLayerWhichItems(layer, MS_FALSE, NULL);
        if(status != MS_SUCCESS) {
            msLayerClose(layer);
            return MS_FAILURE;
        }
        /* identify target shapes */
        if(layer->transform == MS_TRUE)
            searchrect = map->extent;
        else {
            searchrect.minx = searchrect.miny = 0;
            searchrect.maxx = map->width-1;
            searchrect.maxy = map->height-1;
        }

#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

        status = msLayerWhichShapes(layer, searchrect, MS_FALSE);
        if(status == MS_DONE) { /* no overlap */
            msLayerClose(layer);
            return MS_SUCCESS;
        } else if(status != MS_SUCCESS) {
            msLayerClose(layer);
            return MS_FAILURE;
        }
        switch(chartType) {
        case MS_CHART_TYPE_PIE:
            status = msDrawPieChartLayer(map, layer, image);
            break;
        case MS_CHART_TYPE_BAR:
            status = msDrawBarChartLayer(map, layer, image);
            break;
        case MS_CHART_TYPE_VBAR:
            status = msDrawVBarChartLayer(map, layer, image);
            break;
        default:
            return MS_FAILURE;/*shouldn't be here anyways*/
        }

        msLayerClose(layer);
    }
    return status;
}