bool TopographyFile::Update(const WindowProjection &map_projection) { if (IsEmpty()) return false; if (map_projection.GetMapScale() > scale_threshold) /* not visible, don't update cache now */ return false; const GeoBounds screenRect = map_projection.GetScreenBounds(); if (cache_bounds.IsValid() && cache_bounds.IsInside(screenRect)) /* the cache is still fresh */ return false; cache_bounds = map_projection.GetScreenBounds().Scale(fixed(2)); rectObj deg_bounds = ConvertRect(cache_bounds); // Test which shapes are inside the given bounds and save the // status to file.status msShapefileWhichShapes(&file, dir, deg_bounds, 0); // If not a single shape is inside the bounds if (!file.status) { // ... clear the whole buffer ClearCache(); return false; } // Iterate through the shapefile entries const ShapeList **current = &first; auto it = shapes.begin(); for (int i = 0; i < file.numshapes; ++i, ++it) { if (!msGetBit(file.status, i)) { // If the shape is outside the bounds // delete the shape from the cache delete it->shape; it->shape = NULL; } else { // is inside the bounds if (it->shape == NULL) // shape isn't cached yet -> cache the shape it->shape = new XShape(&file, i, label_field); // update list pointer *current = it; current = &it->next; } } // end of list marker *current = NULL; ++serial; return true; }
// 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); } } }
void Topology::updateCache(MapWindowProjection &map_projection, rectObj thebounds, bool purgeonly) { if (!triggerUpdateCache) return; if (!shapefileopen) return; in_scale = CheckScale(map_projection.GetMapScaleUser()); if (!in_scale) { // not visible, so flush the cache // otherwise we waste time on looking up which shapes are in bounds flushCache(); triggerUpdateCache = false; return; } if (purgeonly) return; triggerUpdateCache = false; 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); } } }
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 }
bool TopographyFile::Update(const WindowProjection &map_projection) { if (IsEmpty()) return false; if (map_projection.GetMapScale() > scale_threshold) /* not visible, don't update cache now */ return false; const GeoBounds screenRect = map_projection.GetScreenBounds(); if (cache_bounds.IsValid() && cache_bounds.IsInside(screenRect)) /* the cache is still fresh */ return false; cache_bounds = screenRect.Scale(2); rectObj deg_bounds = ConvertRect(cache_bounds); // Test which shapes are inside the given bounds and save the // status to file.status switch (msShapefileWhichShapes(&file, dir, deg_bounds, 0)) { case MS_FAILURE: ClearCache(); return false; case MS_DONE: /* screen is outside of map bounds */ return false; case MS_SUCCESS: break; } assert(file.status != nullptr); // Iterate through the shapefile entries const ShapeList **current = &first; auto it = shapes.begin(); for (int i = 0; i < file.numshapes; ++i, ++it) { if (!msGetBit(file.status, i)) { // If the shape is outside the bounds // delete the shape from the cache if (it->shape != nullptr) { assert(*current == it); /* remove from linked list (protected) */ { const ScopeLock lock(mutex); *current = it->next; ++serial; } /* now it's unreachable, and we can delete the XShape without holding a lock */ delete it->shape; it->shape = nullptr; } } else { // is inside the bounds if (it->shape == nullptr) { assert(*current != it); // shape isn't cached yet -> cache the shape it->shape = LoadShape(&file, center, i, label_field); it->next = *current; /* insert into linked list (protected) */ { const ScopeLock lock(mutex); *current = it; ++serial; } } current = &it->next; } } // end of list marker assert(*current == nullptr); return true; }
bool TopographyFile::Update(const WindowProjection &map_projection) { if (IsEmpty()) return false; if (map_projection.GetMapScale() > scale_threshold) /* not visible, don't update cache now */ return false; const GeoBounds screenRect = map_projection.GetScreenBounds(); if (cache_bounds.inside(screenRect)) /* the cache is still fresh */ return false; cache_bounds = map_projection.GetScreenBounds().scale(fixed_two); rectObj deg_bounds = ConvertRect(cache_bounds); // Test which shapes are inside the given bounds and save the // status to file.status msShapefileWhichShapes(&file, dir, deg_bounds, 0); // If not a single shape is inside the bounds if (!file.status) { // ... clear the whole buffer ClearCache(); return false; } // Iterate through the shapefile entries for (int i = 0; i < file.numshapes; i++) { if (!msGetBit(file.status, i)) { // If the shape is outside the bounds // delete the shape from the cache delete shapes[i].shape; shapes[i].shape = NULL; } else if (shapes[i].shape == NULL) { // If the shape is inside the bounds and if the // shape isn't cached yet -> cache the shape shapes[i].shape = new XShape(&file, i, label_field); } } ShapeList::NotNull not_null; XShapePointerArray::iterator end = shapes.end(), it = shapes.begin(); it = std::find_if(it, end, not_null); if (it != shapes.end()) { ShapeList *current = &*it; first = current; while (true) { ++it; it = std::find_if(it, end, not_null); if (it == end) { current->next = NULL; break; } ShapeList *next = &*it; current->next = next; current = next; } } else first = NULL; return true; }
int main( int argc, char ** argv ) { SHPTreeHandle qix; int i, j; rectObj rect; int pos; ms_bitarray bitmap = NULL; char mBigEndian; treeNodeObj *node = NULL; /* -------------------------------------------------------------------- */ /* Display a usage message. */ /* -------------------------------------------------------------------- */ if( argc <= 1 ) { printf( "shptreetst shapefile {minx miny maxx maxy}\n" ); exit( 1 ); } i = 1; if( *((unsigned char *) &i) == 1 ) mBigEndian = 0; else mBigEndian = 1; qix = msSHPDiskTreeOpen (AddFileSuffix(argv[1],".qix"), 0 /* no debug*/); if( qix == NULL ) { printf("unable to open index file %s \n", argv[1]); exit(-1); } printf ("This %s %s index supports a shapefile with %d shapes, %d depth \n", (qix->version ? "new": "old"), (qix->LSB_order? "LSB": "MSB"), (int) qix->nShapes, (int) qix->nDepth); /* -------------------------------------------------------------------- */ /* Skim over the list of shapes, printing all the vertices. */ /* -------------------------------------------------------------------- */ pos = ftell (qix->fp); j = 0; while( pos && j < 20) { j ++; /* fprintf (stderr,"box %d, at %d pos \n", j, (int) ftell(qix)); */ node = readTreeNode (qix); if (node ) { fprintf (stdout,"shapes %d, node %d, %f,%f,%f,%f \n",(int) node->numshapes,node->numsubnodes,node->rect.minx, node->rect.miny, node->rect.maxx, node->rect.maxy); } else { pos = 0; } } printf ("read entire file now at quad box rec %d file pos %ld\n", j, ftell (qix->fp)); j = qix->nShapes; msSHPDiskTreeClose (qix); if( argc >= 5 ) { rect.minx = atof (argv[2]); rect.miny = atof (argv[3]); rect.maxx = atof (argv[4]); rect.maxy = atof (argv[5]); } else { printf ("using last read box as a search \n"); rect.minx = node->rect.minx; rect.miny = node->rect.miny; rect.maxx = node->rect.maxx; rect.maxy = node->rect.maxy; } bitmap = msSearchDiskTree( argv[1], rect, 0 /* no debug*/ ); if ( bitmap ) { printf ("result of rectangle search was \n"); for ( i=0; i<j; i++) { if ( msGetBit(bitmap,i) ) { printf(" %d,",i); } } } printf("\n"); return(0); }