public void TestEdgeConstraintSplitsNonIntersection()
        {
            EdgeConstraints        constraints = new EdgeConstraints(3, 5);
            List <EdgeConstraints> split       = constraints.Split();

            Assert.IsTrue(split.Count == 2);

            Range range1 = new Range(split[0].MinWidth, split[0].MaxWidth, false);
            Range range2 = new Range(split[1].MinWidth, split[1].MaxWidth, false);

            Assert.IsFalse(range1.IntersectsWith(range2));
        }
        /// <summary>
        /// Creates a VerticalSeparationConstraint for each edge in the given set to structural constraints,
        /// to require these edges to be downward pointing.  Also checks for cycles, and edges involved
        /// in a cycle receive no VerticalSeparationConstraint, but can optionally receive a circle constraint.
        /// </summary>
        /// <param name="edges"></param>
        /// <param name="settings"></param>
        /// <param name="horizontalSolver"></param>
        /// <param name="verticalSolver"></param>
        internal static void GenerateEdgeConstraints(
            IEnumerable <Edge> edges,
            EdgeConstraints settings,
            AxisSolver horizontalSolver,
            AxisSolver verticalSolver)
        {
            if (settings.Direction == Direction.None)
            {
                return;
            }
            EdgeConstraintGenerator g = new EdgeConstraintGenerator(edges, settings, horizontalSolver, verticalSolver);

            g.GenerateSeparationConstraints();
        }
        private Image DrawConstraintsOnTopOfImage(
            Image backgroundImage, float drawSizeRatio, ShapeConstraints shapeConstraints, bool drawVertexConstraints, bool drawMinEdgeWidth, bool drawMaxEdgeWidth, bool drawAverageEdgeWidth)
        {
            const float pointRadius = 4;
            const float lineWidth   = 2;

            Bitmap statusImage = new Bitmap((int)(backgroundImage.Width * drawSizeRatio), (int)(backgroundImage.Height * drawSizeRatio));

            using (Graphics graphics = Graphics.FromImage(statusImage))
            {
                graphics.DrawImage(backgroundImage, 0, 0, statusImage.Width, statusImage.Height);

                if (drawVertexConstraints)
                {
                    foreach (VertexConstraints vertexConstraint in shapeConstraints.VertexConstraints)
                    {
                        graphics.DrawRectangle(
                            new Pen(Color.Orange, lineWidth),
                            (float)vertexConstraint.MinCoord.X * drawSizeRatio,
                            (float)vertexConstraint.MinCoord.Y * drawSizeRatio,
                            (float)(vertexConstraint.MaxCoord.X - vertexConstraint.MinCoord.X) * drawSizeRatio,
                            (float)(vertexConstraint.MaxCoord.Y - vertexConstraint.MinCoord.Y) * drawSizeRatio);
                    }
                }

                foreach (VertexConstraints vertexConstraint in shapeConstraints.VertexConstraints)
                {
                    graphics.FillEllipse(
                        Brushes.Black,
                        (float)vertexConstraint.MiddleCoord.X * drawSizeRatio - pointRadius,
                        (float)vertexConstraint.MiddleCoord.Y * drawSizeRatio - pointRadius,
                        2 * pointRadius,
                        2 * pointRadius);
                }

                for (int i = 0; i < shapeConstraints.ShapeStructure.Edges.Count; ++i)
                {
                    ShapeEdge edge   = shapeConstraints.ShapeStructure.Edges[i];
                    Vector    point1 = shapeConstraints.VertexConstraints[edge.Index1].MiddleCoord * drawSizeRatio;
                    Vector    point2 = shapeConstraints.VertexConstraints[edge.Index2].MiddleCoord * drawSizeRatio;
                    graphics.DrawLine(new Pen(Color.Black, lineWidth), MathHelper.VecToPointF(point1), MathHelper.VecToPointF(point2));

                    if (drawMinEdgeWidth || drawMaxEdgeWidth || drawAverageEdgeWidth)
                    {
                        EdgeConstraints edgeConstraint = shapeConstraints.EdgeConstraints[i];
                        Vector          diff           = point2 - point1;
                        Vector          edgeNormal     = (new Vector(diff.Y, -diff.X)).GetNormalized();

                        if (drawMaxEdgeWidth)
                        {
                            DrawOrientedRectange(graphics, point1, point2, edgeNormal, (float)edgeConstraint.MaxWidth * drawSizeRatio, new Pen(Color.Cyan, lineWidth));
                        }
                        if (drawMinEdgeWidth)
                        {
                            DrawOrientedRectange(graphics, point1, point2, edgeNormal, (float)edgeConstraint.MinWidth * drawSizeRatio, new Pen(Color.Red, lineWidth));
                        }
                        if (drawAverageEdgeWidth)
                        {
                            DrawOrientedRectange(graphics, point1, point2, edgeNormal, (float)(edgeConstraint.MinWidth + edgeConstraint.MaxWidth) * drawSizeRatio * 0.5f, new Pen(Color.Blue, lineWidth));
                        }
                    }
                }
            }

            return(statusImage);
        }
        internal EdgeConstraintGenerator(
            IEnumerable <Edge> edges,
            EdgeConstraints settings,
            AxisSolver horizontalSolver,
            AxisSolver verticalSolver)
        {
            // filter out self edges
            this.edges = edges.Where(e => e.Source != e.Target);

            this.settings         = settings;
            this.horizontalSolver = horizontalSolver;
            this.verticalSolver   = verticalSolver;

            foreach (var e in this.edges)
            {
                TNode u = CreateTNode(e.Source), v = CreateTNode(e.Target);
                u.outNeighbours.Add(v);
                v.inNeighbours.Add(u);
            }

            foreach (var v in nodeMap.Values)
            {
                if (v.stackNode == null)
                {
                    DFS(v);
                }
            }

            while (stack.Count > 0)
            {
                component = new List <TNode>();
                RDFS(stack.Last.Value);
                if (component.Count > 1)
                {
                    var cyclicComponent = new Set <Node>();
                    foreach (var v in component)
                    {
                        cyclicComponent.Insert(v.v);
                    }
                    cyclicComponents.Add(cyclicComponent);
                }
            }

            switch (settings.Direction)
            {
            case Direction.South:
                this.addConstraint = this.AddSConstraint;
                break;

            case Direction.North:
                this.addConstraint = this.AddNConstraint;
                break;

            case Direction.West:
                this.addConstraint = this.AddWConstraint;
                break;

            case Direction.East:
                this.addConstraint = this.AddEConstraint;
                break;
            }
        }
        public void TestEdgeConstraintSplitsNonIntersection()
        {
            EdgeConstraints constraints = new EdgeConstraints(3, 5);
            List<EdgeConstraints> split = constraints.Split();
            Assert.IsTrue(split.Count == 2);

            Range range1 = new Range(split[0].MinWidth, split[0].MaxWidth, false);
            Range range2 = new Range(split[1].MinWidth, split[1].MaxWidth, false);
            Assert.IsFalse(range1.IntersectsWith(range2));
        }