Example #1
0
        private static LinkedList <Circle> InitFrontchain(UiInnerNode node)
        {
            var frontChain = new LinkedList <Circle>();

            if (node.Children.Count == 0)
            {
                return(frontChain);
            }

            var c1 = node.Children[0].Circle;

            frontChain.AddLast(c1);

            if (node.Children.Count == 1)
            {
                return(frontChain);
            }

            var c2 = node.Children[1].Circle;

            c2.Position.Value = TreeGeometry.CalcTangentCircleCenter(c1.Position.Value, c1.Radius,
                                                                     c2.Radius,
                                                                     TreeGeometry.GetRandomAngle());
            frontChain.AddLast(c2);

            return(frontChain);
        }
Example #2
0
        private List <GameObject> AddBranchObjects(UiInnerNode node, Transform parent, float scale)
        {
            var branches = new List <GameObject>();

            var count = node.Children.Count;

            for (var i = 0; i < count; i++)
            {
                // Add a new branch and subsequent edge and node
                branches.Add(AddBranchObject(node.Children[i], parent, count, i, scale));
            }

            return(branches);
        }
Example #3
0
        private void DistributeSunflower(UiInnerNode innerNode, Transform parent)
        {
            var rndAngle = TreeGeometry.GetRandomAngle();

            for (var i = 0; i < innerNode.Children.Count; i++)
            {
                var child      = innerNode.Children[i];
                var nodeObject = AddChildContainer(child, parent, i, rndAngle);

                GenerateBranches(child, nodeObject.transform);
            }

            innerNode.Circle.Radius = innerNode.Children.Count == 1
                ? TreeGeometry.NodeDistanceFactor
                : TreeGeometry.CalcSunflowerRadius(innerNode.Children.Count - 1);
        }
Example #4
0
        /// <summary>
        /// From Wang's circle packing algorithm, see "Visualization of large hierarchical data by circle packing"
        /// </summary>
        /// <param name="innerNode"></param>
        internal LinkedList <Circle> CirclePacking(UiInnerNode innerNode)
        {
            var frontChain = InitFrontchain(innerNode);

            for (var i = 2; i < innerNode.Children.Count; i++)
            {
                // circle with minimal distance to origin
                var tangentCircle1 = GetClosestFromOrigin(frontChain);

                // circle after tangent circle 1
                var tangentCircle2 = tangentCircle1.Next();

                // circle of current inner node, claculate potential position
                var currentCircleRad = innerNode.Children[i].Circle.Radius;
                var currentCirclePos = TreeGeometry.CalcTangentCircleCenter(tangentCircle1.Value.Position.Value,
                                                                            tangentCircle2.Value.Position.Value, tangentCircle1.Value.Radius, tangentCircle2.Value.Radius,
                                                                            currentCircleRad);

                // circle that intersects current circle
                var intersectingCircle = GetIntersectingCircle(frontChain, currentCirclePos, currentCircleRad);

                // No intersection, place current circle
                if (intersectingCircle == null)
                {
                    innerNode.Children[i].Circle.Position.Value = currentCirclePos;
                    frontChain.AddBefore(tangentCircle2, innerNode.Children[i].Circle);
                    continue;
                }

                // Delete old circles from front chain
                if (intersectingCircle.IsAfter(tangentCircle2))
                {
                    tangentCircle1.DeleteAfterUntil(intersectingCircle);
                }
                else
                {
                    intersectingCircle.DeleteAfterUntil(tangentCircle2);
                }

                // Proceed with current circle again, position is calculated according to updated front chain
                i--;
            }

            innerNode.Circle.Radius = GetEnclosingRadius(frontChain);

            return(frontChain);
        }
Example #5
0
        private void GenerateUnsdistributedBranches(UiInnerNode innerNode, Transform parent)
        {
            var nodeHeight        = innerNode.GetHeight();
            var centralEdgeHeight = manipulator.DefaultEdgeHeight * GetYScalingFactor(nodeHeight);
            var edgeThickness     = manipulator.DefaultEdgeScale.x * GetXScalingFactor(nodeHeight);

            foreach (var child in innerNode.Children)
            {
                var branchObject = manipulator.AddEmptyBranchObject(parent);
                // Edge length doesn't matter at this point. It is set properly at subscription of node position.
                var edgeObject = manipulator.AddEdgeObject(branchObject.transform, 1, 0, 0, edgeThickness);
                var nodeObject = manipulator.AddEmptyNodeObject(child, branchObject.transform,
                                                                Vector3.up * centralEdgeHeight, edgeObject);

                // Rotate and stretch edge according to corresponding node.
                manipulator.SubscribeNodePosition(child.Circle, nodeObject, edgeObject, centralEdgeHeight);

                GenerateBranches(child, nodeObject.transform);
            }
        }
Example #6
0
 private static bool HasOnlyLeaves(UiInnerNode node)
 {
     return(node.Children.TrueForAll(n => n is UiLeaf));
 }
Example #7
0
        private void DistributeCirclePacking(UiInnerNode innerNode, Transform parent)
        {
            GenerateUnsdistributedBranches(innerNode, parent);

            CirclePacking(innerNode);
        }