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; }
/* 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; }