/// <summary> /// Initialize a tree node. /// </summary> private static SHPTreeNode NodeCreate(double[] padfBoundsMin, double[] padfBoundsMax) { SHPTreeNode psTreeNode; psTreeNode = new SHPTreeNode(); psTreeNode.nShapeCount = 0; psTreeNode.panShapeIds = null; psTreeNode.papsShapeObj = null; psTreeNode.nSubNodes = 0; if (padfBoundsMin != null) { c.memcpy(psTreeNode.adfBoundsMin, padfBoundsMin, sizeof(double) * 4); } if (padfBoundsMax != null) { c.memcpy(psTreeNode.adfBoundsMax, padfBoundsMax, sizeof(double) * 4); } return(psTreeNode); }
/************************************************************************/ /* SHPTreeNodeTrim() */ /* */ /* This is the recurve version of SHPTreeTrimExtraNodes() that */ /* walks the tree cleaning it up. */ /************************************************************************/ private static bool NodeTrim(SHPTreeNode psTreeNode) { int i; /* -------------------------------------------------------------------- */ /* Trim subtrees, and free subnodes that come back empty. */ /* -------------------------------------------------------------------- */ for (i = 0; i < psTreeNode.nSubNodes; i++) { if (NodeTrim(psTreeNode.apsSubNode[i])) { DestroyNode(ref psTreeNode.apsSubNode[i]); psTreeNode.apsSubNode[i] = psTreeNode.apsSubNode[psTreeNode.nSubNodes - 1]; psTreeNode.nSubNodes--; i--; /* process the new occupant of this subnode entry */ } } /* -------------------------------------------------------------------- */ /* We should be trimmed if we have no subnodes, and no shapes. */ /* -------------------------------------------------------------------- */ return(psTreeNode.nSubNodes == 0 && psTreeNode.nShapeCount == 0); }
/************************************************************************/ /* SHPDestroyTreeNode() */ /************************************************************************/ private static void DestroyNode(ref SHPTreeNode psTreeNode) { int i; for (i = 0; i < psTreeNode.nSubNodes; i++) { if (psTreeNode.apsSubNode[i] != null) { DestroyNode(ref psTreeNode.apsSubNode[i]); } } if (psTreeNode.panShapeIds != null) { c.free(ref psTreeNode.panShapeIds); } if (psTreeNode.papsShapeObj != null) { for (i = 0; i < psTreeNode.nShapeCount; i++) { if (psTreeNode.papsShapeObj[i] != null) { psTreeNode.papsShapeObj[i] = null; } } c.free(ref psTreeNode.papsShapeObj); } c.free(ref psTreeNode); }
/************************************************************************/ /* 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); } } }
public static void free(ref SHPTreeNode memblock) { memblock = null; }
/************************************************************************/ /* SHPTreeNodeAddShapeId() */ /************************************************************************/ private static bool NodeAddShapeId( SHPTreeNode psTreeNode, SHPObject psObject, int nMaxDepth, int nDimension) { int i; /* -------------------------------------------------------------------- */ /* If there are subnodes, then consider wiether this object */ /* will fit in them. */ /* -------------------------------------------------------------------- */ if (nMaxDepth > 1 && psTreeNode.nSubNodes > 0) { for (i = 0; i < psTreeNode.nSubNodes; i++) { if (CheckObjectContained(psObject, nDimension, psTreeNode.apsSubNode[i].adfBoundsMin, psTreeNode.apsSubNode[i].adfBoundsMax)) { return(NodeAddShapeId(psTreeNode.apsSubNode[i], psObject, nMaxDepth - 1, nDimension)); } } } /* -------------------------------------------------------------------- */ /* Otherwise, consider creating four subnodes if could fit into */ /* them, and adding to the appropriate subnode. */ /* -------------------------------------------------------------------- */ #if MAX_SUBNODE_QUAD else if (nMaxDepth > 1 && psTreeNode.nSubNodes == 0) { double[] adfBoundsMinH1 = new double[4], adfBoundsMaxH1 = new double[4]; double[] adfBoundsMinH2 = new double[4], adfBoundsMaxH2 = new double[4]; double[] adfBoundsMin1 = new double[4], adfBoundsMax1 = new double[4]; double[] adfBoundsMin2 = new double[4], adfBoundsMax2 = new double[4]; double[] adfBoundsMin3 = new double[4], adfBoundsMax3 = new double[4]; double[] adfBoundsMin4 = new double[4], adfBoundsMax4 = new double[4]; SplitBounds(psTreeNode.adfBoundsMin, psTreeNode.adfBoundsMax, adfBoundsMinH1, adfBoundsMaxH1, adfBoundsMinH2, adfBoundsMaxH2); SplitBounds(adfBoundsMinH1, adfBoundsMaxH1, adfBoundsMin1, adfBoundsMax1, adfBoundsMin2, adfBoundsMax2); SplitBounds(adfBoundsMinH2, adfBoundsMaxH2, adfBoundsMin3, adfBoundsMax3, adfBoundsMin4, adfBoundsMax4); if (CheckObjectContained(psObject, nDimension, adfBoundsMin1, adfBoundsMax1) || CheckObjectContained(psObject, nDimension, adfBoundsMin2, adfBoundsMax2) || CheckObjectContained(psObject, nDimension, adfBoundsMin3, adfBoundsMax3) || CheckObjectContained(psObject, nDimension, adfBoundsMin4, adfBoundsMax4)) { psTreeNode.nSubNodes = 4; psTreeNode.apsSubNode[0] = NodeCreate(adfBoundsMin1, adfBoundsMax1); psTreeNode.apsSubNode[1] = NodeCreate(adfBoundsMin2, adfBoundsMax2); psTreeNode.apsSubNode[2] = NodeCreate(adfBoundsMin3, adfBoundsMax3); psTreeNode.apsSubNode[3] = NodeCreate(adfBoundsMin4, adfBoundsMax4); /* recurse back on this node now that it has subnodes */ return(NodeAddShapeId(psTreeNode, psObject, nMaxDepth, nDimension)); } } #else // MAX_SUBNODE_QUAD /* -------------------------------------------------------------------- */ /* Otherwise, consider creating two subnodes if could fit into */ /* them, and adding to the appropriate subnode. */ /* -------------------------------------------------------------------- */ else if (nMaxDepth > 1 && psTreeNode.nSubNodes == 0) { double[] adfBoundsMin1 = new double[4], adfBoundsMax1 = new double[4]; double[] adfBoundsMin2 = new double[4], adfBoundsMax2 = new double[4]; SplitBounds(psTreeNode.adfBoundsMin, psTreeNode.adfBoundsMax, adfBoundsMin1, adfBoundsMax1, adfBoundsMin2, adfBoundsMax2); if (CheckObjectContained(psObject, nDimension, adfBoundsMin1, adfBoundsMax1)) { psTreeNode.nSubNodes = 2; psTreeNode.apsSubNode[0] = NodeCreate(adfBoundsMin1, adfBoundsMax1); psTreeNode.apsSubNode[1] = NodeCreate(adfBoundsMin2, adfBoundsMax2); return(NodeAddShapeId(psTreeNode.apsSubNode[0], psObject, nMaxDepth - 1, nDimension)); } else if (CheckObjectContained(psObject, nDimension, adfBoundsMin2, adfBoundsMax2)) { psTreeNode.nSubNodes = 2; psTreeNode.apsSubNode[0] = NodeCreate(adfBoundsMin1, adfBoundsMax1); psTreeNode.apsSubNode[1] = NodeCreate(adfBoundsMin2, adfBoundsMax2); return(NodeAddShapeId(psTreeNode.apsSubNode[1], psObject, nMaxDepth - 1, nDimension)); } } #endif // MAX_SUBNODE_QUAD /* -------------------------------------------------------------------- */ /* If none of that worked, just add it to this nodes list. */ /* -------------------------------------------------------------------- */ psTreeNode.nShapeCount++; psTreeNode.panShapeIds = SfRealloc(ref psTreeNode.panShapeIds, psTreeNode.nShapeCount); psTreeNode.panShapeIds[psTreeNode.nShapeCount - 1] = psObject.nShapeId; if (psTreeNode.papsShapeObj != null) { psTreeNode.papsShapeObj = SfRealloc(ref psTreeNode.papsShapeObj, psTreeNode.nShapeCount); psTreeNode.papsShapeObj[psTreeNode.nShapeCount - 1] = null; } return(true); }