Exemple #1
0
/*
 * VENTA3 This is a modified Segment() 
 */
int DrawArc(HDC hdc, long x, long y, int radius, RECT rc, 
	    double start,
	    double end)
{
  POINT pt[66];
  int i;
  int istart;
  int iend;

  rectObj rect;
  rect.minx = x-radius;
  rect.maxx = x+radius;
  rect.miny = y-radius;
  rect.maxy = y+radius;
  rectObj rcrect;
  rcrect.minx = rc.left;
  rcrect.maxx = rc.right;
  rcrect.miny = rc.top;
  rcrect.maxy = rc.bottom;

  if (msRectOverlap(&rect, &rcrect)!=MS_TRUE) {
    return FALSE;
  }

  // JMW added faster checking...

  start = AngleLimit360(start);
  end = AngleLimit360(end);

  istart = iround(start/360.0*64);
  iend = iround(end/360.0*64);

  int npoly = 0;

  if (istart>iend) {
    iend+= 64;
  }
  istart++;
  iend--;

  pt[npoly].x = x + (long) (radius * fastsine(start));
  pt[npoly].y = y - (long) (radius * fastcosine(start));
  npoly++;

  for(i=0;i<64;i++) {
    if (i<=iend-istart) {
      pt[npoly].x = x + (long) (radius * xcoords[(i+istart)%64]);
      pt[npoly].y = y - (long) (radius * ycoords[(i+istart)%64]);
      npoly++;
    }
  }
  pt[npoly].x = x + (long) (radius * fastsine(end));
  pt[npoly].y = y - (long) (radius * fastcosine(end));
  npoly++;
  if (npoly) {
    Polyline(hdc,pt,npoly); // TODO check ClipPolygon for HP31X
  }
  
  return TRUE;
}
Exemple #2
0
static void treeCollectShapeIds(treeNodeObj *node, rectObj aoi, ms_bitarray status)
{
  int i;

  /* -------------------------------------------------------------------- */
  /*      Does this node overlap the area of interest at all?  If not,    */
  /*      return without adding to the list at all.                       */
  /* -------------------------------------------------------------------- */
  if(!msRectOverlap(&node->rect, &aoi))
    return;

  /* -------------------------------------------------------------------- */
  /*      Add the local nodes shapeids to the list.                       */
  /* -------------------------------------------------------------------- */
  for(i=0; i<node->numshapes; i++)
    msSetBit(status, node->ids[i], 1);

  /* -------------------------------------------------------------------- */
  /*      Recurse to subnodes if they exist.                              */
  /* -------------------------------------------------------------------- */
  for(i=0; i<node->numsubnodes; i++) {
    if(node->subnode[i])
      treeCollectShapeIds(node->subnode[i], aoi, status);
  }
}
Exemple #3
0
int Circle(HDC hdc, long x, long y, int radius, RECT rc, bool clip, bool fill)
{
  POINT pt[65];
  unsigned int i;

  rectObj rect;
  rect.minx = x-radius;
  rect.maxx = x+radius;
  rect.miny = y-radius;
  rect.maxy = y+radius;
  rectObj rcrect;
  rcrect.minx = rc.left;
  rcrect.maxx = rc.right;
  rcrect.miny = rc.top;
  rcrect.maxy = rc.bottom;

  if (msRectOverlap(&rect, &rcrect)!=MS_TRUE) {
    return FALSE;
  }
  // JMW added faster checking...

  unsigned int step = 1;
  if (radius<20) {
    step = 2;
  }
  for(i=64/step;i--;) {
    pt[i].x = x + (long) (radius * xcoords[i*step]);
    pt[i].y = y + (long) (radius * ycoords[i*step]);
  }
  step = 64/step;
  pt[step].x = x + (long) (radius * xcoords[0]);
  pt[step].y = y + (long) (radius * ycoords[0]);

  if (clip) {
    ClipPolygon(hdc,pt,step+1,rc, fill);
  } else {
    if (fill) {
#ifdef PNA
    if (needclipping==true)
      	ClipPolygon(hdc,pt,step+1,rc, true); // VNT10 090909 fixed bug was false FIX CHECK IF WORKING 
    else
        Polygon(hdc,pt,step+1);
#else
      Polygon(hdc,pt,step+1); 
#endif 
    } else {
// VENTA3 FIX HP clipping bug
#ifdef PNA
      if (needclipping==true)
      	MapWindow::_Polyline(hdc,pt,step+1,rc);
      else
        Polyline(hdc,pt,step+1);
#else
      Polyline(hdc,pt,step+1);
#endif
    }
  }
  return TRUE;
}
Exemple #4
0
static void searchDiskTreeNode(SHPTreeHandle disktree, rectObj aoi, ms_bitarray status) 
{
  int i;
  ms_int32 offset;
  ms_int32 numshapes, numsubnodes;
  rectObj rect;

  int *ids=NULL;

  fread( &offset, 4, 1, disktree->fp );
  if ( disktree->needswap ) SwapWord ( 4, &offset );

  fread( &rect, sizeof(rectObj), 1, disktree->fp );
  if ( disktree->needswap ) SwapWord ( 8, &rect.minx );
  if ( disktree->needswap ) SwapWord ( 8, &rect.miny );
  if ( disktree->needswap ) SwapWord ( 8, &rect.maxx );
  if ( disktree->needswap ) SwapWord ( 8, &rect.maxy );
      
  fread( &numshapes, 4, 1, disktree->fp );
  if ( disktree->needswap ) SwapWord ( 4, &numshapes );

  if(!msRectOverlap(&rect, &aoi)) { /* skip rest of this node and sub-nodes */
    offset += numshapes*sizeof(ms_int32) + sizeof(ms_int32);
    fseek(disktree->fp, offset, SEEK_CUR);
    return;
  }
  if(numshapes > 0) {
    ids = (int *)msSmallMalloc(numshapes*sizeof(ms_int32));

    fread( ids, numshapes*sizeof(ms_int32), 1, disktree->fp );
    if (disktree->needswap )
    {
      for( i=0; i<numshapes; i++ )
      {
        SwapWord( 4, &ids[i] );    
        msSetBit(status, ids[i], 1);
      }
    }
    else
    {
      for(i=0; i<numshapes; i++)
        msSetBit(status, ids[i], 1);
    }
    free(ids);
  }

  fread( &numsubnodes, 4, 1, disktree->fp );
  if ( disktree->needswap ) SwapWord ( 4, &numsubnodes );

  for(i=0; i<numsubnodes; i++)
    searchDiskTreeNode(disktree, aoi, status);

  return;
}
Exemple #5
0
/* traverse the quadtree to find the neighbouring shapes and update some data
on the related shapes (when adding a new feature)*/
static void findRelatedShapes(msClusterLayerInfo* layerinfo,
                              clusterTreeNode *node, clusterInfo* current)
{
  int i;
  clusterInfo* s;

  /* -------------------------------------------------------------------- */
  /*      Does this node overlap the area of interest at all?  If not,    */
  /*      return without adding to the list at all.                       */
  /* -------------------------------------------------------------------- */
  if(!msRectOverlap(&node->rect, &current->bounds))
    return;

  /* Modify the feature count of the related shapes */
  s = node->shapes;
  while (s) {
    if (layerinfo->fnCompare(current, s)) {
      ++current->numsiblings;
      /* calculating the average positions */
      current->avgx = (current->avgx * current->numsiblings + s->x) / (current->numsiblings + 1);
      current->avgy = (current->avgy * current->numsiblings + s->y) / (current->numsiblings + 1);
      /* calculating the variance */
      current->varx = current->varx * current->numsiblings / (current->numsiblings + 1) +
                      (s->x - current->avgx) * (s->x - current->avgx) / (current->numsiblings + 1);
      current->vary = current->vary * current->numsiblings / (current->numsiblings + 1) +
                      (s->y - current->avgy) * (s->y - current->avgy) / (current->numsiblings + 1);

      if (layerinfo->fnCompare(s, current)) {
        /* this feature falls into the region of the other as well */
        ++s->numsiblings;
        /* calculating the average positions */
        s->avgx = (s->avgx * s->numsiblings + current->x) / (s->numsiblings + 1);
        s->avgy = (s->avgy * s->numsiblings + current->y) / (s->numsiblings + 1);
        /* calculating the variance */
        s->varx = s->varx * s->numsiblings / (s->numsiblings + 1) +
                  (current->x - s->avgx) * (current->x - s->avgx) / (s->numsiblings + 1);
        s->vary = s->vary * s->numsiblings / (s->numsiblings + 1) +
                  (current->y - s->avgy) * (current->y - s->avgy) / (s->numsiblings + 1);
      }
    }
    s = s->next;
  }

  if (node->subnode[0] == NULL)
    return;

  /* Recurse to subnodes if they exist */
  for (i = 0; i < 4; i++) {
    if (node->subnode[i])
      findRelatedShapes(layerinfo, node->subnode[i], current);
  }
}
Exemple #6
0
// Function to filter search results further against feature bboxes
void msFilterTreeSearch(shapefileObj *shp, char *status, rectObj search_rect)
{
    int i;
    rectObj shape_rect;

    for(i=0; i<shp->numshapes; i++) { /* for each shape */
        if(msGetBit(status, i)) {
            if(!msSHPReadBounds(shp->hSHP, i, &shape_rect))
                if(msRectOverlap(&shape_rect, &search_rect) != MS_TRUE)
                    msSetBit(status, i, 0);
        }
    }
}
Exemple #7
0
/* Function to filter search results further against feature bboxes */
void msFilterTreeSearch(shapefileObj *shp, ms_bitarray status, rectObj search_rect)
{
  int i;
  rectObj shape_rect;

  i = msGetNextBit(status, 0, shp->numshapes);
  while(i >= 0) {
    if(msSHPReadBounds(shp->hSHP, i, &shape_rect) == MS_SUCCESS) {
      if(msRectOverlap(&shape_rect, &search_rect) != MS_TRUE) {
        msSetBit(status, i, 0);
      }
    }
    i = msGetNextBit(status, i+1, shp->numshapes);
  }

}
/* static int intersectLabelPolygons(shapeObj *p1, shapeObj *p2) { */
int intersectLabelPolygons(shapeObj *p1, shapeObj *p2)
{
  int c1,v1,c2,v2;
  pointObj *point;

  /* STEP 0: check bounding boxes */
  if(!msRectOverlap(&p1->bounds, &p2->bounds)) { /* from [email protected] */
    return(MS_FALSE);
  }

  /* STEP 1: look for intersecting line segments */
  for(c1=0; c1<p1->numlines; c1++)
    for(v1=1; v1<p1->line[c1].numpoints; v1++)
      for(c2=0; c2<p2->numlines; c2++)
        for(v2=1; v2<p2->line[c2].numpoints; v2++)
          if(msIntersectSegments(&(p1->line[c1].point[v1-1]), &(p1->line[c1].point[v1]), &(p2->line[c2].point[v2-1]), &(p2->line[c2].point[v2])) ==  MS_TRUE) {
            return(MS_TRUE);
          }

  /* STEP 2: polygon one completely contains two (only need to check one point from each part) */
  for(c2=0; c2<p2->numlines; c2++) {
    point = &(p2->line[c2].point[0]);
    for(c1=0; c1<p1->numlines; c1++) {
      if(msPointInPolygon(point, &p1->line[c1]) == MS_TRUE) /* ok, the point is in a polygon */
        return(MS_TRUE);
    }
  }

  /* STEP 3: polygon two completely contains one (only need to check one point from each part) */
  for(c1=0; c1<p1->numlines; c1++) {
    point = &(p1->line[c1].point[0]);
    for(c2=0; c2<p2->numlines; c2++) {
      if(msPointInPolygon(point, &p2->line[c2]) == MS_TRUE) /* ok, the point is in a polygon */
        return(MS_TRUE);
    }
  }

  return(MS_FALSE);
}
Exemple #9
0
/* traverse the quadtree to find the neighbouring shapes and update some data
on the related shapes (when removing a feature) */
static void findRelatedShapesRemove(msClusterLayerInfo* layerinfo, clusterTreeNode *node, clusterInfo* current)
{
  int i;
  clusterInfo* s;

  /* -------------------------------------------------------------------- */
  /*      Does this node overlap the area of interest at all?  If not,    */
  /*      return without adding to the list at all.                       */
  /* -------------------------------------------------------------------- */
  if(!msRectOverlap(&node->rect, &current->bounds))
    return;

  /* Modify the feature count of the related shapes */
  s = node->shapes;
  while (s) {
    if (layerinfo->fnCompare(current, s)) {
      if (s->numsiblings > 0) {
        /* calculating the average positions */
        s->avgx = (s->avgx * (s->numsiblings + 1) - current->x) / s->numsiblings;
        s->avgy = (s->avgy * (s->numsiblings + 1) - current->y) / s->numsiblings;
        /* calculating the variance */
        s->varx = (s->varx - (current->x - s->avgx) * (current->x - s->avgx) / s->numsiblings) *
                  (s->numsiblings + 1) / s->numsiblings;
        s->vary = (s->vary - (current->y - s->avgy) * (current->y - s->avgy) / s->numsiblings) *
                  (s->numsiblings + 1) / s->numsiblings;
        --s->numsiblings;
        ++s->numremoved;
      }
    }
    s = s->next;
  }

  /* Recurse to subnodes if they exist */
  for (i = 0; i < 4; i++) {
    if (node->subnode[i])
      findRelatedShapesRemove(layerinfo, node->subnode[i], current);
  }
}
Exemple #10
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);
      }
    }
Exemple #11
0
/* collecting the cluster shapes, returns true if this subnode must be removed */
static int collectClusterShapes(msClusterLayerInfo* layerinfo, clusterTreeNode *node, clusterInfo* current)
{
  int i;
  clusterInfo* prev = NULL;
  clusterInfo* s = node->shapes;

  if(!msRectOverlap(&node->rect, &current->bounds))
    return (!node->shapes && !node->subnode[0] && !node->subnode[1]
            && !node->subnode[2] && !node->subnode[3]);

  /* removing the shapes from this node if overlap with the cluster */
  while (s) {
    if (s == current || layerinfo->fnCompare(current, s)) {
      if (s != current && current->filter == 0) {
        /* skip siblings of the filtered shapes */
        prev = s;
        s = prev->next;
        continue;
      }

      /* removing from the list */
      if (!prev)
        node->shapes = s->next;
      else
        prev->next = s->next;

      ++current->numcollected;

      /* adding the shape to the finalization list */
      if (s == current) {
        if (s->filter) {
          s->next = layerinfo->finalized;
          layerinfo->finalized = s;
          ++layerinfo->numFinalized;
        } else {
          /* this shape is filtered */
          s->next = layerinfo->filtered;
          layerinfo->filtered = s;
          ++layerinfo->numFiltered;
        }
      } else {
        s->next = layerinfo->finalizedSiblings;
        layerinfo->finalizedSiblings = s;
        ++layerinfo->numFinalizedSiblings;
      }

      if (!prev)
        s = node->shapes;
      else
        s = prev->next;
    } else {
      prev = s;
      s = prev->next;
    }
  }

  /* Recurse to subnodes if they exist */
  for (i = 0; i < 4; i++) {
    if (node->subnode[i] && collectClusterShapes(layerinfo, node->subnode[i], current)) {
      /* placing this empty node to the finalization queue */
      node->subnode[i]->subnode[0] = layerinfo->finalizedNodes;
      layerinfo->finalizedNodes = node->subnode[i];
      node->subnode[i] = NULL;
      ++layerinfo->numFinalizedNodes;
    }
  }

  /* returns true is this subnode must be removed */
  return (!node->shapes && !node->subnode[0] && !node->subnode[1]
          && !node->subnode[2] && !node->subnode[3]);
}
Exemple #12
0
// This is checking boundaries based on lat/lon values. 
// It is not enough for screen overlapping verification.
bool Topology::checkVisible(shapeObj& shape, rectObj &screenRect) {
  return (msRectOverlap(&shape.bounds, &screenRect) == MS_TRUE);
}
Exemple #13
0
void Topology::updateCache(rectObj thebounds, bool purgeonly) {
  if (!triggerUpdateCache) return;

  if (!shapefileopen) return;

  in_scale = CheckScale();

  if (!in_scale) {
    // not visible, so flush the cache
    // otherwise we waste time on looking up which shapes are in bounds
    flushCache();
    triggerUpdateCache = false;
    in_scale_last = false;
    return;
  }

  if (purgeonly) {
    in_scale_last = in_scale;
    return;
  }

  triggerUpdateCache = false;

#ifdef DEBUG_TFC
#ifdef TOPOFASTCACHE
  StartupStore(TEXT("---UpdateCache() starts, mode%d%s"),cache_mode,NEWLINE);
#else
  StartupStore(TEXT("---UpdateCache() starts, original code%s"),NEWLINE);
#endif
  int starttick = GetTickCount();
#endif

#ifdef TOPOFASTCACHE
  if(msRectOverlap(&shpfile.bounds, &thebounds) != MS_TRUE) {
    // this happens if entire shape is out of range
    // so clear buffer.
    flushCache();
    in_scale_last = in_scale;
    return;
  }

  bool smaller = false;
  bool bigger = false;
  bool in_scale_again = in_scale && !in_scale_last;
  int shapes_loaded = 0;
  shapes_visible_count = 0;
  in_scale_last = in_scale;
  
  switch (cache_mode) {
    case 0: // Original code plus one special case
      smaller = (msRectContained(&thebounds, &lastBounds) == MS_TRUE);
      if (smaller) { //Special case, search inside, we don't need to load additional shapes, just remove
        shapes_visible_count = 0;
        for (int i=0; i<shpfile.numshapes; i++) {
          if (shpCache[i]) {
            if(msRectOverlap(&(shpCache[i]->shape.bounds), &thebounds) != MS_TRUE) {
              removeShape(i);
            } else shapes_visible_count++;
          }
        }//for
      } else { 
        //In this case we have to run the original algoritm
        msSHPWhichShapes(&shpfile, thebounds, 0);
        shapes_visible_count = 0;
        for (int i=0; i<shpfile.numshapes; i++) {
          if (msGetBit(shpfile.status, i)) {
            if (shpCache[i]==NULL) {
              // shape is now in range, and wasn't before
              shpCache[i] = addShape(i);
              shapes_loaded++;
            }
            shapes_visible_count++;
          } else {
            removeShape(i);
          }
        }//for
      }
      break;

    case 1:  // Bounds array in memory
      bigger = (msRectContained(&lastBounds, &thebounds) == MS_TRUE);
      smaller = (msRectContained(&thebounds, &lastBounds) == MS_TRUE);
      if (bigger || in_scale_again) { //We don't need to remove shapes, just load, so skip loaded ones
        for (int i=0; i<shpfile.numshapes; i++) {
          if (shpCache[i]) continue;
          if(msRectOverlap(&shpBounds[i], &thebounds) == MS_TRUE) {
            // shape is now in range, and wasn't before
            shpCache[i] = addShape(i);
            shapes_loaded++;
          }
        }//for
        shapes_visible_count+=shapes_loaded;
      } else
      if (smaller) { //Search inside, we don't need to load additional shapes, just remove
        for (int i=0; i<shpfile.numshapes; i++) {
          if (shpCache[i]==NULL) continue;
          if(msRectOverlap(&shpBounds[i], &thebounds) != MS_TRUE) {
            removeShape(i);
          } else shapes_visible_count++;
        }//for
      } else { 
        //Otherwise we have to search the all array
        for (int i=0; i<shpfile.numshapes; i++) {
          if(msRectOverlap(&shpBounds[i], &thebounds) == MS_TRUE) {
            if (shpCache[i]==NULL) {
              // shape is now in range, and wasn't before
              shpCache[i] = addShape(i);
              shapes_loaded++;
            }
            shapes_visible_count++;
          } else {
            removeShape(i);
          }
        }//for
      }
      break;

    case 2: // All shapes in memory	
      XShape *pshp;
      shapes_visible_count = 0;
      for (int i=0; i<shpfile.numshapes; i++) {
        pshp = shps[i];
        if(msRectOverlap(&(pshp->shape.bounds), &thebounds) == MS_TRUE) {
          shpCache[i] = pshp;
          shapes_visible_count++;
        } else {
          shpCache[i] = NULL;
        }
      }//for
      break;
    }//sw

    lastBounds = thebounds;
#else

  msSHPWhichShapes(&shpfile, thebounds, 0);
  if (!shpfile.status) {
    // this happens if entire shape is out of range
    // so clear buffer.
    flushCache();
    return;
  }

  shapes_visible_count = 0;

  for (int i=0; i<shpfile.numshapes; i++) {

    if (msGetBit(shpfile.status, i)) {
      
      if (shpCache[i]==NULL) {
	// shape is now in range, and wasn't before
	shpCache[i] = addShape(i);
      }
      shapes_visible_count++;
    } else {
      removeShape(i);
    }
  }
#endif

#ifdef DEBUG_TFC
  long free_size = CheckFreeRam();
  StartupStore(TEXT("   UpdateCache() ends, shps_visible=%d ram=%li (%dms)%s"),shapes_visible_count, free_size, GetTickCount()-starttick,NEWLINE);
#endif
}
int msTestLabelCacheCollisions(mapObj *map, labelCacheMemberObj *cachePtr, shapeObj *poly,
                               int mindistance, int current_priority, int current_label)
{
  labelCacheObj *labelcache = &(map->labelcache);
  int i, p, ll, pp;
  double label_width = 0;
  labelCacheMemberObj *curCachePtr=NULL;

  /*
   * Check against image bounds first
   */
  if(!cachePtr->labels[0].partials) {
    if(labelInImage(map->width, map->height, poly, labelcache->gutter) == MS_FALSE) {
      return MS_FALSE;
    }
  }

  /* compute start index of first label to test: only test against rendered labels */
  if(current_label>=0) {
    i = current_label+1;
  } else {
    i = 0;
    current_label = -current_label;
  }

  /* Compare against all rendered markers from this priority level and higher.
  ** Labels can overlap their own marker and markers from lower priority levels
  */
  for (p=current_priority; p < MS_MAX_LABEL_PRIORITY; p++) {
    labelCacheSlotObj *markerslot;
    markerslot = &(labelcache->slots[p]);

    for ( ll = 0; ll < markerslot->nummarkers; ll++ ) {
      if ( !(p == current_priority && current_label == markerslot->markers[ll].id ) ) {  /* labels can overlap their own marker */
        if ( intersectLabelPolygons(markerslot->markers[ll].poly, poly ) == MS_TRUE ) {
          return MS_FALSE;
        }
      }
    }
  }

  if(mindistance > 0)
    label_width = poly->bounds.maxx - poly->bounds.minx;

  for(p=current_priority; p<MS_MAX_LABEL_PRIORITY; p++) {
    labelCacheSlotObj *cacheslot;
    cacheslot = &(labelcache->slots[p]);

    for(  ; i < cacheslot->numlabels; i++) {
      curCachePtr = &(cacheslot->labels[i]);

      if(curCachePtr->status == MS_TRUE) { /* compare bounding polygons and check for duplicates */

        /* skip testing against ourself */
        assert(p!=current_priority || i != current_label);

        /*
        ** Note 1: We add the label_size to the mindistance value when comparing because we do want the mindistance
        ** value between the labels and not only from point to point.
        **
        ** Note 2: We only check the first label (could be multiples (RFC 77)) since that is *by far* the most common
        ** use case. Could change in the future but it's not worth the overhead at this point.
        */
        if(mindistance >0  &&
            (cachePtr->layerindex == curCachePtr->layerindex) &&
            (cachePtr->classindex == curCachePtr->classindex) &&
            (cachePtr->labels[0].annotext && curCachePtr->labels[0].annotext &&
             strcmp(cachePtr->labels[0].annotext, curCachePtr->labels[0].annotext) == 0) &&
            (msDistancePointToPoint(&(cachePtr->point), &(curCachePtr->point)) <= (mindistance + label_width))) { /* label is a duplicate */
          return MS_FALSE;
        }

        if(intersectLabelPolygons(curCachePtr->poly, poly) == MS_TRUE) { /* polys intersect */
          return MS_FALSE;
        }
        if(curCachePtr->leaderline) {
          /* our poly against rendered leader lines */
          /* first do a bbox check */
          if(msRectOverlap(curCachePtr->leaderbbox, &(poly->bounds))) {
            /* look for intersecting line segments */
            for(ll=0; ll<poly->numlines; ll++)
              for(pp=1; pp<poly->line[ll].numpoints; pp++)
                if(msIntersectSegments(
                      &(poly->line[ll].point[pp-1]),
                      &(poly->line[ll].point[pp]),
                      &(curCachePtr->leaderline->point[0]),
                      &(curCachePtr->leaderline->point[1])) ==  MS_TRUE) {
                  return(MS_FALSE);
                }
          }

        }
        if(cachePtr->leaderline) {
          /* does our leader intersect current label */
          /* first do a bbox check */
          if(msRectOverlap(cachePtr->leaderbbox, &(curCachePtr->poly->bounds))) {
            /* look for intersecting line segments */
            for(ll=0; ll<curCachePtr->poly->numlines; ll++)
              for(pp=1; pp<curCachePtr->poly->line[ll].numpoints; pp++)
                if(msIntersectSegments(
                      &(curCachePtr->poly->line[ll].point[pp-1]),
                      &(curCachePtr->poly->line[ll].point[pp]),
                      &(cachePtr->leaderline->point[0]),
                      &(cachePtr->leaderline->point[1])) ==  MS_TRUE) {
                  return(MS_FALSE);
                }

          }
          if(curCachePtr->leaderline) {
            /* TODO: check intersection of leader lines, not only bbox test ? */
            if(msRectOverlap(curCachePtr->leaderbbox, cachePtr->leaderbbox)) {
              return MS_FALSE;
            }

          }
        }
      }
    } /* i */

    i = 0; /* Start over with 1st label of next slot */
  } /* p */
  return MS_TRUE;
}
Exemple #15
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 */
}
Exemple #16
0
void MapWindow::DrawTaskAAT(LKSurface& Surface, const RECT& rc) {
    int i;
    double tmp1 = 0.0;

    if (WayPointList.empty()) return;
    if (!AATEnabled) return;

    LockTaskData(); // protect from external task changes
    /**********************************************/
    /* Check if not Validated Waypoint is visible */
    bool bDraw = false;
    int maxTp = 1;
    rectObj rcrect = (rectObj){(double) rc.left, (double) rc.top, (double) rc.right, (double) rc.bottom};
    RECT rcDraw = (RECT){rc.right, rc.bottom, rc.left, rc.top};

    for (maxTp = std::max(1, ActiveTaskPoint); ValidTaskPoint(maxTp + 1); ++maxTp) {
        if (ValidTaskPoint(maxTp)) {
            int Type = 0;
            double Radius = 0.;
            GetTaskSectorParameter(maxTp, &Type, &Radius);
            switch (Type) {
                case CONE:
                case CIRCLE:
                    tmp1 = Task[maxTp].AATCircleRadius * zoom.ResScaleOverDistanceModify();
                    break;
                case SECTOR:
                    tmp1 = Task[maxTp].AATSectorRadius * zoom.ResScaleOverDistanceModify();
                    break;
                default:
                    tmp1 = 0.0;
                    break;
            }
        }

        PixelScalar x = WayPointList[Task[maxTp].Index].Screen.x;
        PixelScalar y = WayPointList[Task[maxTp].Index].Screen.y;
        rectObj rect = (rectObj){x - tmp1, y - tmp1, x + tmp1, y + tmp1};

        if (msRectOverlap(&rect, &rcrect) == MS_TRUE) {
            rcDraw.top = std::min((PixelScalar)rect.miny, rcDraw.top);
            rcDraw.bottom = std::max((PixelScalar) rect.maxy, rcDraw.bottom);
            rcDraw.left = std::min((PixelScalar) rect.minx, rcDraw.left);
            rcDraw.right = std::max((PixelScalar) rect.maxx, rcDraw.right);
            bDraw = true;
        }
    }
    /**********************************************/

    if (bDraw) { // Draw Only if one is Visible
#ifdef USE_GDI
        rcDraw.top = std::max(rc.top, rcDraw.top);
        rcDraw.bottom = std::min(rc.bottom, rcDraw.bottom);
        rcDraw.left = std::max(rc.left, rcDraw.left);
        rcDraw.right = std::min(rc.right, rcDraw.right);


        LKColor whitecolor = RGB_WHITE;
        LKColor origcolor = TempSurface.SetTextColor(whitecolor);

        const auto oldpen = TempSurface.SelectObject(LK_WHITE_PEN);
        const auto oldbrush = TempSurface.SelectObject(LKBrush_White);
        if(LKSurface::AlphaBlendSupported()) {
            // copy original bitmap into temp (for saving fully transparent areas)
            TempSurface.Copy(rcDraw.left, rcDraw.top,
                    rcDraw.right - rcDraw.left, rcDraw.bottom - rcDraw.top, 
                    Surface, rcDraw.left, rcDraw.top);
        } else {
            TempSurface.Rectangle(rcDraw.left, rcDraw.top, rcDraw.right, rcDraw.bottom);
        }
        
        TempSurface.SelectObject(LK_NULL_PEN);
#ifdef HAVE_HATCHED_BRUSH          
        TempSurface.SelectObject(hAirspaceBrushes[iAirspaceBrush[AATASK]]);
#else
        TempSurface.SelectObject(LKBrush_Yellow);
#endif  
        // this color is used as the black bit
        TempSurface.SetTextColor(Colours[iAirspaceColour[AATASK]]);
        // this color is the transparent bit
        TempSurface.SetBkColor(whitecolor);
        
        LKSurface & AliasSurface = TempSurface;
#else
        LKSurface & AliasSurface = Surface;
        Surface.SelectObject(LKBrush(LKColor(255U,255U,0U).WithAlpha(AlphaLevel)));
#endif
        for (i = maxTp - 1; i > std::max(0, ActiveTaskPoint - 1); i--) {
        if (ValidTaskPoint(i)) {
            int Type = 0;
            double Radius = 0.;
            GetTaskSectorParameter(i, &Type, &Radius);

            switch (Type) {
                case CONE:
                case CIRCLE:
                    tmp1 = Radius * zoom.ResScaleOverDistanceModify();
                    AliasSurface.DrawCircle(
                            WayPointList[Task[i].Index].Screen.x,
                            WayPointList[Task[i].Index].Screen.y,
                            (int) tmp1, rc, true);
                    break;
                case SECTOR:
                    tmp1 = Radius * zoom.ResScaleOverDistanceModify();
                    AliasSurface.Segment(
                            WayPointList[Task[i].Index].Screen.x,
                            WayPointList[Task[i].Index].Screen.y, (int) tmp1, rc,
                            Task[i].AATStartRadial - DisplayAngle,
                            Task[i].AATFinishRadial - DisplayAngle);
                    break;
            }
        }
        }
#ifdef USE_GDI
        // restore original color
        TempSurface.SetTextColor(origcolor);
        TempSurface.SelectObject(oldpen);
        TempSurface.SelectObject(oldbrush);
        
        if(!Surface.AlphaBlend(rcDraw, TempSurface,rcDraw, AlphaLevel)) {
            // if AlphaBlend is not supported, use TransparentBld
            Surface.TransparentCopy(
                    rcDraw.left, rcDraw.top,
                    rcDraw.right - rcDraw.left, rcDraw.bottom - rcDraw.top,
                    TempSurface,
                    rcDraw.left, rcDraw.top);
        }
#endif
	}
    
    {
        UnlockTaskData();
    }
}