Exemple #1
0
/* adding the shape based on the shape bounds (point) */
static int treeNodeAddShape(msClusterLayerInfo* layerinfo, clusterTreeNode* node, clusterInfo* shape, int depth)
{
  int i;

  /* -------------------------------------------------------------------- */
  /*      If there are subnodes, then consider whether this object        */
  /*      will fit in them.                                               */
  /* -------------------------------------------------------------------- */
  if( depth > 1 && node->subnode[0] != NULL ) {
    for(i = 0; i < 4; i++ ) {
      if( msRectContained(&shape->shape.bounds, &node->subnode[i]->rect)) {
        return treeNodeAddShape( layerinfo, node->subnode[i], shape, depth-1);
      }
    }
  }

  /* -------------------------------------------------------------------- */
  /*      Otherwise, consider creating four subnodes if could fit into    */
  /*      them, and adding to the appropriate subnode.                    */
  /* -------------------------------------------------------------------- */
  else if( depth > 1 && node->subnode[0] == NULL ) {
    rectObj half1, half2, quad1, quad2, quad3, quad4;
    int subnode = -1;

    treeSplitBounds(&node->rect, &half1, &half2);
    treeSplitBounds(&half1, &quad1, &quad2);
    treeSplitBounds(&half2, &quad3, &quad4);

    if(msRectContained(&shape->shape.bounds, &quad1))
      subnode = 0;
    else if(msRectContained(&shape->shape.bounds, &quad2))
      subnode = 1;
    else if(msRectContained(&shape->shape.bounds, &quad3))
      subnode = 2;
    else if(msRectContained(&shape->shape.bounds, &quad4))
      subnode = 3;

    if (subnode >= 0) {
      if ((node->subnode[0] = clusterTreeNodeCreate(layerinfo, quad1)) == NULL)
        return MS_FAILURE;
      node->subnode[0]->position = node->position * 4;

      if ((node->subnode[1] = clusterTreeNodeCreate(layerinfo, quad2)) == NULL)
        return MS_FAILURE;
      node->subnode[1]->position = node->position * 4 + 1;

      if ((node->subnode[2] = clusterTreeNodeCreate(layerinfo, quad3)) == NULL)
        return MS_FAILURE;
      node->subnode[2]->position = node->position * 4 + 2;

      if ((node->subnode[3] = clusterTreeNodeCreate(layerinfo, quad4)) == NULL)
        return MS_FAILURE;
      node->subnode[3]->position = node->position * 4 + 3;

      /* add to subnode */
      return treeNodeAddShape(layerinfo, node->subnode[subnode], shape, depth-1);
    }
  }

  /* found the right place, add this shape to the node */
  node->numshapes++;
  shape->next = node->shapes;
  node->shapes = shape;
  shape->node = node;

  return MS_SUCCESS;
}
Exemple #2
0
static int treeNodeAddShapeId( treeNodeObj *node, int id, rectObj rect, int maxdepth)
{
  int i;

  /* -------------------------------------------------------------------- */
  /*      If there are subnodes, then consider whether this object        */
  /*      will fit in them.                                               */
  /* -------------------------------------------------------------------- */
  if( maxdepth > 1 && node->numsubnodes > 0 ) {
    for(i=0; i<node->numsubnodes; i++ ) {
      if( msRectContained(&rect, &node->subnode[i]->rect)) {
        return treeNodeAddShapeId( node->subnode[i], id, rect, maxdepth-1);
      }
    }
  }

  /* -------------------------------------------------------------------- */
  /*      Otherwise, consider creating four subnodes if could fit into    */
  /*      them, and adding to the appropriate subnode.                    */
  /* -------------------------------------------------------------------- */
#if MAX_SUBNODES == 4
  else if( maxdepth > 1 && node->numsubnodes == 0 ) {
    rectObj half1, half2, quad1, quad2, quad3, quad4;

    treeSplitBounds(&node->rect, &half1, &half2);
    treeSplitBounds(&half1, &quad1, &quad2);
    treeSplitBounds(&half2, &quad3, &quad4);

    if(msRectContained(&rect, &quad1) || msRectContained(&rect, &quad2) ||  msRectContained(&rect, &quad3) || msRectContained(&rect, &quad4)) {
      node->numsubnodes = 4;
      node->subnode[0] = treeNodeCreate(quad1);
      node->subnode[1] = treeNodeCreate(quad2);
      node->subnode[2] = treeNodeCreate(quad3);
      node->subnode[3] = treeNodeCreate(quad4);

      /* recurse back on this node now that it has subnodes */
      return(treeNodeAddShapeId(node, id, rect, maxdepth));
    }
  }
#endif

  /* -------------------------------------------------------------------- */
  /*      Otherwise, consider creating two subnodes if could fit into     */
  /*      them, and adding to the appropriate subnode.                    */
  /* -------------------------------------------------------------------- */
#if MAX_SUBNODE == 2
  else if( maxdepth > 1 && node->numsubnodes == 0 ) {
    rectObj half1, half2;

    treeSplitBounds(&node->rect, &half1, &half2);

    if( msRectContained(&rect, &half1)) {
      node->numsubnodes = 2;
      node->subnode[0] = treeNodeCreate(half1);
      node->subnode[1] = treeNodeCreate(half2);

      return(treeNodeAddShapeId(node->subnode[0], id, rect, maxdepth-1));
    } else if(msRectContained(&rect, &half2)) {
      node->numsubnodes = 2;
      node->subnode[0] = treeNodeCreate(&half1);
      node->subnode[1] = treeNodeCreate(&half2);

      return(treeNodeAddShapeId(node->subnode[1], id, rect, maxdepth-1));
    }
  }
#endif /* MAX_SUBNODE == 2 */

  /* -------------------------------------------------------------------- */
  /*      If none of that worked, just add it to this nodes list.         */
  /* -------------------------------------------------------------------- */
  node->numshapes++;

  node->ids = SfRealloc( node->ids, sizeof(ms_int32) * node->numshapes );
  node->ids[node->numshapes-1] = id;

  return MS_TRUE;
}
Exemple #3
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
}