/* * 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; }
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); } }
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; }
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; }
/* 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, ¤t->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); } }
// 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); } } }
/* 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); }
/* 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, ¤t->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); } }
/* 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, ¤t->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, ¤t->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, ¤t->bounds)) { msFreeShape(¤t->shape); msInitShape(¤t->shape); msDebug("Skipping an invalid shape falling outside of the given extent\n"); continue; } /* construct the item array */ if (layer->iteminfo) BuildFeatureAttributes(layer, layerinfo, ¤t->shape); /* evaluate the group expression */ if (layer->cluster.group.string) current->group = msClusterGetGroupText(&layer->cluster.group, ¤t->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); } }
/* 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, ¤t->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]); }
// 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); }
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; }
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 */ }
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(); } }