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