public static DotGraph AddQuadTree <T>(this DotGraph dotGraph, GMacQuadTree <T> quadTree, bool showFullGraph) { var maxTreeDepth = quadTree.TreeDepth; var activeIDs = quadTree.LeafNodeIDs.ToArray(); var inactiveColor = DotColor.Rgb(Color.Gray); var activeColor = DotColor.Rgb(Color.Black); dotGraph.SetRankDir(DotRankDirection.LeftToRight); dotGraph.SetSplines(DotSplines.Spline); dotGraph.SetOverlap(DotOverlap.False); dotGraph.SetNodeMarginDelta(12); var nodeDefaults = dotGraph.AddNodeDefaults(); nodeDefaults.SetShape(DotNodeShape.Circle); nodeDefaults.SetStyle(DotNodeStyle.Solid); nodeDefaults.SetColor(inactiveColor); nodeDefaults.SetFontColor(inactiveColor); nodeDefaults.SetPenWidth(1.0f); var edgeDefaults = dotGraph.AddEdgeDefaults(); edgeDefaults.SetArrowHead(DotArrowType.Vee); edgeDefaults.SetStyle(DotEdgeStyle.Dashed); edgeDefaults.SetColor(inactiveColor); edgeDefaults.SetFontColor(inactiveColor); edgeDefaults.SetPenWidth(1.0f); var idsStack1 = new Stack <ulong>(); idsStack1.Push(0ul); var idsStack2 = new Stack <ulong>(); idsStack2.Push(0ul); var treeDepthStack = new Stack <int>(); treeDepthStack.Push(maxTreeDepth); var s = "".PadRight(maxTreeDepth, '-'); var dotNodeName = s + ", " + s; var dotNodeLabel = s + '\n' + s; var dotNode = dotGraph.AddNode(dotNodeName); dotNode.SetShape(DotNodeShape.DoubleCircle); dotNode.SetStyle(DotNodeStyle.Solid); dotNode.SetColor(activeColor); dotNode.SetFontColor(activeColor); dotNode.SetPenWidth(2.0f); dotNode.SetLabel(dotNodeLabel); while (idsStack1.Count > 0) { var idPart1 = idsStack1.Pop(); var idPart2 = idsStack2.Pop(); var treeDepth = treeDepthStack.Pop(); var s1 = treeDepth == maxTreeDepth ? "".PadRight(treeDepth, '-') : idPart1.PatternToStringPadRight(maxTreeDepth, treeDepth); var s2 = treeDepth == maxTreeDepth ? "".PadRight(treeDepth, '-') : idPart2.PatternToStringPadRight(maxTreeDepth, treeDepth); dotNodeName = s1 + ", " + s2; dotNode = dotGraph.AddNode(dotNodeName); var childNodesBitMask = 1ul << (treeDepth - 1); //Add child node 00 var childNodeId = Tuple.Create(idPart1, idPart2); var isActive = childNodeId.IsActiveQuadTreeNodeId(childNodesBitMask, activeIDs); if (showFullGraph || isActive) { AddChildNode( dotNode, childNodeId, treeDepth - 1, maxTreeDepth, isActive, activeColor ); if (treeDepth > 1) { idsStack1.Push(childNodeId.Item1); idsStack2.Push(childNodeId.Item2); treeDepthStack.Push(treeDepth - 1); } } //Add child node 01 childNodeId = Tuple.Create(idPart1 | childNodesBitMask, idPart2); isActive = childNodeId.IsActiveQuadTreeNodeId(childNodesBitMask, activeIDs); if (showFullGraph || isActive) { AddChildNode( dotNode, childNodeId, treeDepth - 1, maxTreeDepth, isActive, activeColor ); if (treeDepth > 1) { idsStack1.Push(childNodeId.Item1); idsStack2.Push(childNodeId.Item2); treeDepthStack.Push(treeDepth - 1); } } //Add child node 10 childNodeId = Tuple.Create(idPart1, idPart2 | childNodesBitMask); isActive = childNodeId.IsActiveQuadTreeNodeId(childNodesBitMask, activeIDs); if (showFullGraph || isActive) { AddChildNode( dotNode, childNodeId, treeDepth - 1, maxTreeDepth, isActive, activeColor ); if (treeDepth > 1) { idsStack1.Push(childNodeId.Item1); idsStack2.Push(childNodeId.Item2); treeDepthStack.Push(treeDepth - 1); } } //Add child node 11 childNodeId = Tuple.Create(idPart1 | childNodesBitMask, idPart2 | childNodesBitMask); isActive = childNodeId.IsActiveQuadTreeNodeId(childNodesBitMask, activeIDs); if (showFullGraph || isActive) { AddChildNode( dotNode, childNodeId, treeDepth - 1, maxTreeDepth, isActive, activeColor ); if (treeDepth > 1) { idsStack1.Push(childNodeId.Item1); idsStack2.Push(childNodeId.Item2); treeDepthStack.Push(treeDepth - 1); } } } return(dotGraph); }
/// <summary> /// Try to get a child node if it exists, else create a new internal child and return it /// </summary> /// <param name="rightChild1"></param> /// <param name="rightChild2"></param> /// <returns></returns> public GMacQuadTree <T> GetOrAddInternalChildNode(bool rightChild1, bool rightChild2) { Debug.Assert(TreeDepth > 1); if (rightChild1) { if (rightChild2) { var childNode = ChildNode11 as GMacQuadTree <T>; if (!ReferenceEquals(childNode, null)) { return(childNode); } childNode = new GMacQuadTree <T>(TreeDepth - 1); ChildNode11 = childNode; return(childNode); } else { var childNode = ChildNode01 as GMacQuadTree <T>; if (!ReferenceEquals(childNode, null)) { return(childNode); } childNode = new GMacQuadTree <T>(TreeDepth - 1); ChildNode01 = childNode; return(childNode); } } else { if (rightChild2) { var childNode = ChildNode10 as GMacQuadTree <T>; if (!ReferenceEquals(childNode, null)) { return(childNode); } childNode = new GMacQuadTree <T>(TreeDepth - 1); ChildNode10 = childNode; return(childNode); } else { var childNode = ChildNode00 as GMacQuadTree <T>; if (!ReferenceEquals(childNode, null)) { return(childNode); } childNode = new GMacQuadTree <T>(TreeDepth - 1); ChildNode00 = childNode; return(childNode); } } }