/************************************************************************/ /* SHPTreeTrimExtraNodes() */ /* */ /* Trim empty nodes from the tree. Note that we never trim an */ /* empty root node. */ /************************************************************************/ public void TrimExtraNodes() { SHPTree hTree = this; /* do not free! */ NodeTrim(hTree.psRoot); }
/************************************************************************/ /* SHPTreeFindLikelyShapes() */ /* */ /* Find all shapes within tree nodes for which the tree node */ /* bounding box overlaps the search box. The return value is */ /* an array of shapeids terminated by a -1. The shapeids will */ /* be in order, as hopefully this will result in faster (more */ /* sequential) reading from the file. */ /************************************************************************/ public int[] FindLikelyShapes( double[] padfBoundsMin, double[] padfBoundsMax, out int pnShapeCount) { SHPTree hTree = this; /* do not free! */ int[] panShapeList = null; int nMaxShapes = 0; /* -------------------------------------------------------------------- */ /* Perform the search by recursive descent. */ /* -------------------------------------------------------------------- */ pnShapeCount = 0; CollectShapeIds(hTree.psRoot, padfBoundsMin, padfBoundsMax, ref pnShapeCount, ref nMaxShapes, ref panShapeList); /* -------------------------------------------------------------------- */ /* Sort the id array */ /* -------------------------------------------------------------------- */ Array.Sort(panShapeList); return(panShapeList); }
/************************************************************************/ /* SHPTreeAddShapeId() */ /* */ /* Add a shape to the tree, but don't keep a pointer to the */ /* object data, just keep the shapeid. */ /************************************************************************/ public bool AddShapeId(SHPObject psObject) { SHPTree psTree = this; /* do not free! */ return(NodeAddShapeId(psTree.psRoot, psObject, psTree.nMaxDepth, psTree.nDimension)); }
/************************************************************************/ /* SHPDestroyTree() */ /************************************************************************/ public void Destroy() { SHPTree psTree = this; /* do not free! */ DestroyNode(ref psTree.psRoot); //c.free( ref psTree ); }
/************************************************************************/ /* SHPTreeCollectShapesIds() */ /* */ /* Work function implementing SHPTreeFindLikelyShapes() on a */ /* tree node by tree node basis. */ /************************************************************************/ public void CollectShapeIds(SHPTreeNode psTreeNode, double[] padfBoundsMin, double[] padfBoundsMax, ref int pnShapeCount, ref int pnMaxShapes, ref int[] ppanShapeList) { SHPTree hTree = this; /* do not free! */ int i; /* -------------------------------------------------------------------- */ /* Does this node overlap the area of interest at all? If not, */ /* return without adding to the list at all. */ /* -------------------------------------------------------------------- */ if (!CheckBoundsOverlap(psTreeNode.adfBoundsMin, psTreeNode.adfBoundsMax, padfBoundsMin, padfBoundsMax, hTree.nDimension)) { return; } /* -------------------------------------------------------------------- */ /* Grow the list to hold the shapes on this node. */ /* -------------------------------------------------------------------- */ if (pnShapeCount + psTreeNode.nShapeCount > pnMaxShapes) { pnMaxShapes = (pnShapeCount + psTreeNode.nShapeCount) * 2 + 20; ppanShapeList = SfRealloc(ref ppanShapeList, pnMaxShapes); } /* -------------------------------------------------------------------- */ /* Add the local nodes shapeids to the list. */ /* -------------------------------------------------------------------- */ for (i = 0; i < psTreeNode.nShapeCount; i++) { ppanShapeList[pnShapeCount++] = psTreeNode.panShapeIds[i]; } /* -------------------------------------------------------------------- */ /* Recurse to subnodes if they exist. */ /* -------------------------------------------------------------------- */ for (i = 0; i < psTreeNode.nSubNodes; i++) { if (psTreeNode.apsSubNode[i] != null) { CollectShapeIds(psTreeNode.apsSubNode[i], padfBoundsMin, padfBoundsMax, ref pnShapeCount, ref pnMaxShapes, ref ppanShapeList); } } }
/************************************************************************/ /* SHPCreateTree() */ /************************************************************************/ public static SHPTree Create(SHPHandle hSHP, int nDimension, int nMaxDepth, double[] padfBoundsMin, double[] padfBoundsMax) { SHPTree psTree; if (padfBoundsMin == null && hSHP == null) { return(null); } /* -------------------------------------------------------------------- */ /* Allocate the tree object */ /* -------------------------------------------------------------------- */ psTree = new SHPTree(); psTree.hSHP = hSHP; psTree.nMaxDepth = nMaxDepth; psTree.nDimension = nDimension; /* -------------------------------------------------------------------- */ /* If no max depth was defined, try to select a reasonable one */ /* that implies approximately 8 shapes per node. */ /* -------------------------------------------------------------------- */ if (psTree.nMaxDepth == 0 && hSHP != null) { int nMaxNodeCount = 1; int nShapeCount; SHPT nShapeType; hSHP.GetInfo(out nShapeCount, out nShapeType, null, null); while (nMaxNodeCount * 4 < nShapeCount) { psTree.nMaxDepth += 1; nMaxNodeCount = nMaxNodeCount * 2; } } /* -------------------------------------------------------------------- */ /* Allocate the root node. */ /* -------------------------------------------------------------------- */ psTree.psRoot = NodeCreate(padfBoundsMin, padfBoundsMax); /* -------------------------------------------------------------------- */ /* Assign the bounds to the root node. If none are passed in, */ /* use the bounds of the provided file otherwise the create */ /* function will have already set the bounds. */ /* -------------------------------------------------------------------- */ if (padfBoundsMin == null) { int nShapeCount; SHPT nShapeType; hSHP.GetInfo(out nShapeCount, out nShapeType, psTree.psRoot.adfBoundsMin, psTree.psRoot.adfBoundsMax); } /* -------------------------------------------------------------------- */ /* If we have a file, insert all it's shapes into the tree. */ /* -------------------------------------------------------------------- */ if (hSHP != null) { int iShape, nShapeCount; SHPT nShapeType; hSHP.GetInfo(out nShapeCount, out nShapeType, null, null); for (iShape = 0; iShape < nShapeCount; iShape++) { SHPObject psShape; psShape = hSHP.ReadObject(iShape); psTree.AddShapeId(psShape); psShape = null; } } return(psTree); }