예제 #1
0
        /// <summary>
        /// Obtain a starting configuration that is feasible with respect to the structural
        /// constraints.  This is necessary to avoid e.g. cycles in the constraint graph;
        /// for example, dragging the root of a downward-pointing tree downward below other
        /// nodes of the tree can result in auto-generation of constraints generating some
        /// constraints with the root on the right-hand side, and the structural constraints
        /// have it on the left-hand side.
        ///
        /// When AvoidOverlaps==true and we reach ConstraintLevel>=2 then we also need to remove
        /// overlaps... prior to this we need to force horizontal resolving of overlaps
        /// between *all* nodes involved in vertical equality constraints (i.e. no skipping),
        /// and then vertical overlap resolution of all nodes involved in horizontal equality
        /// constraints
        /// </summary>
        static internal void Enforce(FastIncrementalLayoutSettings settings, int currentConstraintLevel, IEnumerable <FiNode> nodes, List <IConstraint> horizontalConstraints, List <IConstraint> verticalConstraints, IEnumerable <Cluster> clusterHierarchies, Func <Cluster, LayoutAlgorithmSettings> clusterSettings)
        {
            foreach (LockPosition l in settings.locks)
            {
                l.Project();
            }

            ResetPositions(nodes);
            double dblVpad  = settings.NodeSeparation + Pad;
            double dblHpad  = settings.NodeSeparation;
            double dblCVpad = settings.ClusterMargin + Pad;
            double dblCHpad = settings.ClusterMargin;

            for (int level = settings.MinConstraintLevel; level <= currentConstraintLevel; ++level)
            {
                // to obtain a feasible solution when equality constraints are present we need to be extra careful
                // but the solution below is a little bit crummy, is not currently optimized when there are no
                // equality constraints and we do not really have any scenarios involving equality constraints at
                // the moment, and also the fact that it turns off DeferToVertical causes it to resolve too
                // many overlaps horizontally, so let's skip it for now.
                //if (level >= 2 && settings.AvoidOverlaps)
                //{
                //    RemoveOverlapsOnEqualityConstraints(dblVpad, dblHpad, horizontalConstraints, verticalConstraints);
                //}
                var hsSolver = new AxisSolver(true, nodes, clusterHierarchies,
                                              level >= 2 && settings.AvoidOverlaps, level, clusterSettings);
                hsSolver.structuralConstraints    = horizontalConstraints;
                hsSolver.OverlapRemovalParameters = new Core.Geometry.OverlapRemovalParameters
                {
                    AllowDeferToVertical        = true,
                    ConsiderProportionalOverlap = settings.IdealEdgeLength.EdgeDirectionConstraints != Core.Geometry.Directions.None
                };
                hsSolver.Initialize(dblHpad, dblVpad, dblCHpad, dblCVpad, v => v.Center);
                hsSolver.SetDesiredPositions();
                hsSolver.Solve();
                ResetPositions(nodes);
                var vsSolver = new AxisSolver(false, nodes, clusterHierarchies,
                                              level >= 2 && settings.AvoidOverlaps, level, clusterSettings);
                vsSolver.structuralConstraints = verticalConstraints;
                vsSolver.Initialize(dblHpad, dblVpad, dblCHpad, dblCVpad, v => v.Center);
                vsSolver.SetDesiredPositions();
                vsSolver.Solve();
                ResetPositions(nodes);
            }
        }
 /// <summary>
 /// Obtain a starting configuration that is feasible with respect to the structural 
 /// constraints.  This is necessary to avoid e.g. cycles in the constraint graph;
 /// for example, dragging the root of a downward-pointing tree downward below other
 /// nodes of the tree can result in auto-generation of constraints generating some
 /// constraints with the root on the right-hand side, and the structural constraints
 /// have it on the left-hand side.
 /// 
 /// When AvoidOverlaps==true and we reach ConstraintLevel>=2 then we also need to remove
 /// overlaps... prior to this we need to force horizontal resolving of overlaps 
 /// between *all* nodes involved in vertical equality constraints (i.e. no skipping), 
 /// and then vertical overlap resolution of all nodes involved in horizontal equality
 /// constraints
 /// </summary>
 static internal void Enforce(FastIncrementalLayoutSettings settings, int currentConstraintLevel, IEnumerable<FiNode> nodes, List<IConstraint> horizontalConstraints, List<IConstraint> verticalConstraints, IEnumerable<Cluster> clusterHierarchies, Func<Cluster, LayoutAlgorithmSettings> clusterSettings)
 {
     foreach (LockPosition l in settings.locks)
     {
         l.Project();
     }
     ResetPositions(nodes);
     double dblVpad = settings.NodeSeparation + Pad;
     double dblHpad = settings.NodeSeparation;
     double dblCVpad = settings.ClusterMargin + Pad;
     double dblCHpad = settings.ClusterMargin;
     for (int level = settings.MinConstraintLevel; level <= currentConstraintLevel; ++level)
     {
         // to obtain a feasible solution when equality constraints are present we need to be extra careful
         // but the solution below is a little bit crummy, is not currently optimized when there are no
         // equality constraints and we do not really have any scenarios involving equality constraints at
         // the moment, and also the fact that it turns off DeferToVertical causes it to resolve too
         // many overlaps horizontally, so let's skip it for now.
         //if (level >= 2 && settings.AvoidOverlaps)
         //{
         //    RemoveOverlapsOnEqualityConstraints(dblVpad, dblHpad, horizontalConstraints, verticalConstraints);
         //}
         var hsSolver = new AxisSolver(true, nodes, clusterHierarchies,
                                      level >= 2 && settings.AvoidOverlaps, level, clusterSettings);
         hsSolver.structuralConstraints = horizontalConstraints;
         hsSolver.OverlapRemovalParameters = new Core.Geometry.OverlapRemovalParameters
         {
             AllowDeferToVertical = true,
             ConsiderProportionalOverlap = settings.IdealEdgeLength.EdgeDirectionConstraints != Core.Geometry.Directions.None
         };
         hsSolver.Initialize(dblHpad, dblVpad, dblCHpad, dblCVpad, v => v.Center);
         hsSolver.SetDesiredPositions();
         hsSolver.Solve();
         ResetPositions(nodes);
         var vsSolver = new AxisSolver(false, nodes, clusterHierarchies,
                                      level >= 2 && settings.AvoidOverlaps, level, clusterSettings);
         vsSolver.structuralConstraints = verticalConstraints;
         vsSolver.Initialize(dblHpad, dblVpad, dblCHpad, dblCVpad, v => v.Center);
         vsSolver.SetDesiredPositions();
         vsSolver.Solve();
         ResetPositions(nodes);
     }
 }
예제 #3
0
        void SolveSeparationConstraints()
        {
            if (this.NeedSolve())
            {
                // Increasing the padding effectively increases the size of the rectangle, so it will lead to more overlaps,
                // and therefore tighter packing once the overlap is removed and therefore more apparent "columnarity".
                // We don't want to drastically change the shape of the rectangles, just increase them ever so slightly so that
                // there is a bit more space in the horizontal than vertical direction, thus reducing the likelihood that
                // the vertical constraint generation will detect spurious overlaps, which should allow the nodes to slide
                // smoothly around each other.  ConGen padding args are:  First pad is in direction of the constraints being
                // generated, second pad is in the perpendicular direction.
                double dblVpad  = settings.NodeSeparation;
                double dblHpad  = dblVpad + Feasibility.Pad;
                double dblCVpad = settings.ClusterMargin;
                double dblCHpad = dblCVpad + Feasibility.Pad;

                // The centers are our desired positions, but we need to find a feasible configuration
                foreach (FiNode v in nodes)
                {
                    v.desiredPosition = v.Center;
                }

                // Set up horizontal non-overlap constraints based on the (feasible) starting configuration
                horizontalSolver.Initialize(dblHpad, dblVpad, dblCHpad, dblCVpad, v => v.previousCenter);
                horizontalSolver.SetDesiredPositions();
                horizontalSolver.Solve();

                // generate y constraints
                verticalSolver.Initialize(dblHpad, dblVpad, dblCHpad, dblCVpad, v => v.Center);
                verticalSolver.SetDesiredPositions();
                verticalSolver.Solve();

                // If we have multiple locks (hence multiple high-weight nodes), there can still be some
                // movement of the locked variables - so update all lock positions.
                foreach (LockPosition l in settings.locks.Where(l => !l.Sticky))
                {
                    l.Bounds = l.node.BoundingBox;
                }
            }
        }