internal void Insert(OverlapRemovalNode node)
            {
                Debug.Assert(null == this.nodeTree.Find(node), "node already exists in the rbtree");

                // RBTree's internal operations on insert/remove etc. mean the node can't cache the
                // RBNode returned by insert(); instead we must do find() on each call.
                this.nodeTree.Insert(node);
            }
예제 #2
0
 internal void SetOlapNode(bool horizontal, OverlapRemovalNode olapNode)
 {
     if (horizontal)
     {
         mOlapNodeX = olapNode;
     }
     else
     {
         mOlapNodeY = olapNode;
     }
 }
 internal void SetOlapNode(bool horizontal, OverlapRemovalNode olapNode) {
     if (horizontal)
         mOlapNodeX = olapNode;
     else
         mOlapNodeY = olapNode;
 }
예제 #4
0
 internal OlapTestNode(OverlapRemovalNode node)
 {
     this.Node = node;
 }
        } // end GetRightNeighbours

         bool AddNeighbour(OverlapRemovalParameters parameters, OverlapRemovalNode currentNode, OverlapRemovalNode nextNode,
                        List<OverlapRemovalNode> neighbors, bool isLeftNeighbor, bool isHorizontal)
        {
            // Sanity check to be sure that the borders are past all other nodes.
            Debug.Assert(currentNode != (isLeftNeighbor ? this.LeftBorderNode : this.RightBorderNode), "currentNode must != BorderNode");

            double overlap = Overlap(currentNode, nextNode, NodePadding);
            if (overlap <= 0)
            {
                // This is the first node encountered on this neighbour-traversal that did not
                // overlap within the required padding. Add it to the list and we're done with
                // this traversal, unless this is a vertical pass and it is not an overlap on
                // the horizontal axis; in that case, pretend we never saw it and return true
                // so the next non-overlapping node will be found.  (See below for more information
                // on why this is necessary).
                if (!isHorizontal && (OverlapP(currentNode, nextNode, NodePaddingP) <= parameters.SolverParameters.GapTolerance))
                {
#if VERBOSE
                    Console.WriteLine(" V {0}nbourHTolSkipNO: {1}", isLeftNeighbor ? "L" : "R", nextNode);
#endif // VERBOSE
                    return true;
                }
                neighbors.Add(nextNode);
#if VERBOSE
                Console.WriteLine("{0}nbourAddNO: {1}", isLeftNeighbor ? "L" : "R", nextNode);
#endif // VERBOSE
                return false;
            }

            if (isHorizontal)
            {
                if (parameters.AllowDeferToVertical)
                {
                    // We are doing horizontal constraints so examine the vertical overlap and see which
                    // is the smallest (normalized by total node size in that orientation) such that the
                    // least amount of movement required.  this.padding is currently the same in both
                    // directions; if this changes, we'll have to add different padding values here for
                    // each direction.  @@DCR: consider adding weights to the defer-to-vertical calculation;
                    // this would allow two nodes to pop up/down if they're being squeezed, rather than
                    // force apart the borders (which happens regardless of their weight).
                    double overlapP = OverlapP(currentNode, nextNode, NodePaddingP);
                    bool isOverlapping =
                         parameters.ConsiderProportionalOverlap
                        ? overlap / (currentNode.Size + nextNode.Size) > overlapP / (currentNode.SizeP + nextNode.SizeP)
                        : overlap > overlapP;
                    if (isOverlapping)
                    {
                        // Don't skip if either of these is a border node.
                        if ((currentNode != this.LeftBorderNode)
                                && (currentNode != this.RightBorderNode)
                                && (nextNode != this.LeftBorderNode)
                                && (nextNode != this.RightBorderNode))
                        {
                            // Moving in the horizontal direction requires more movement than in the vertical
                            // direction to remove the overlap, so skip this node on horizontal constraint
                            // generation and we'll pick it up on vertical constraint generation.  Return true
                            // to keep looking for more overlapping nodes.
                            // Note: it is still possible that we'll pick up a constraint in both directions,
                            // due to either or both of this.padding and the "create a constraint to the first
                            // non-overlapping node" logic.  This is expected and the latter helps retain stability.
#if VERBOSE
                            Console.WriteLine("{0}nbourDeferToV: {1}", isLeftNeighbor ? "L" : "R", nextNode);
#endif // VERBOSE
                            // We need to track whether we skipped these so that we don't have a broken transition chain.
                            // See Test_OverlapRemoval.cs, Test_DeferToV_Causing_Missing_Cst() for more information.
                            if (isLeftNeighbor)
                            {
                                currentNode.DeferredLeftNeighborToV = true;
                                nextNode.DeferredRightNeighborToV = true;
                            }
                            else
                            {
                                currentNode.DeferredRightNeighborToV = true;
                                nextNode.DeferredLeftNeighborToV = true;
                            }
                            return true;
                        }
                    } // endif Overlap is greater than OverlapP
                } // endif AllowDeferToVertical
            }
            else
            {
                // We're on the vertical pass so make sure we match up with the Solver's tolerance in the
                // scanline direction, because it is possible that there was a horizontal constraint between
                // these nodes that was within the Solver's tolerance and thus was not enforced.  In that
                // case, we could spuriously add a vertical constraint here that would result in undesired
                // and possibly huge vertical movement.  There is a corresponding Assert during constraint
                // generation when the node is Closed. We have to do this here rather than at runtime because
                // doing it then may skip a Neighbour that replaced other Neighbors by transitivity.
                if (OverlapP(currentNode, nextNode, NodePaddingP) <= parameters.SolverParameters.GapTolerance)
                {
#if VERBOSE
                    Console.WriteLine(" V {0}nbourHTolSkipO: {1}", isLeftNeighbor ? "L" : "R", nextNode);
#endif // VERBOSE
                    return true;
                }
            }

            // Add this overlapping neighbour and return true to keep looking for more overlapping neighbours.
            neighbors.Add(nextNode);
#if VERBOSE
            Console.WriteLine("{0}nbourAddO: {1}", isLeftNeighbor ? "L" : "R", nextNode);
#endif // VERBOSE
            return true;
        }
        } // end GetLeftNeighbours

         List<OverlapRemovalNode> GetRightNeighbours(OverlapRemovalParameters parameters, ScanLine scanLine,
                                    OverlapRemovalNode currentNode, bool isHorizontal)
        {
            var lstNeighbours = new List<OverlapRemovalNode>();
            OverlapRemovalNode nextNode = scanLine.NextRight(currentNode);
            for (; null != nextNode; nextNode = scanLine.NextRight(nextNode))
            {
                // AddNeighbor returns false if we are done adding them.
                if (!AddNeighbour(parameters, currentNode, nextNode, lstNeighbours, false /* isLeftNeighbor */
                                , isHorizontal))
                {
                    if (!nextNode.DeferredRightNeighborToV)
                    {
                        break;
                    }
                }
            } // endfor NextLeft
            return lstNeighbours;
        } // end GetRightNeighbours
 internal static OverlapRemovalNode GetRightConstraintNode(OverlapRemovalNode node)
 {
     var cluster = node as OverlapRemovalCluster;
     return (null != cluster) ? cluster.LeftBorderNode : node;
 }
 // Adds an open/close event pair for the node. paddingP is either cluster or node padding.
  void AddEvents(OverlapRemovalNode node, List<Event> events)
 {
     // Add/subtract only half the padding so they meet in the middle of the padding.
     events.Add(new Event(true /* fForOpen */, node, node.OpenP - (NodePaddingP / 2)));
     events.Add(new Event(false /* fForOpen */, node, node.CloseP + (NodePaddingP / 2)));
 }
 // newNode may be a cluster in which case we add it to the cluster list.  We never call this to
 // add the fake border nodes to nodeList; the caller never sees them.
 internal void AddNode(OverlapRemovalNode newNode)
 {
     this.nodeList.Add(newNode);
     var newCluster = newNode as OverlapRemovalCluster;
     if (null != newCluster)
     {
         this.clusterList.Add(newCluster);
     }
 }
 internal OverlapRemovalNode NextRight(OverlapRemovalNode node)
 {
     var succ = this.nodeTree.Next(this.nodeTree.Find(node));
     return (null != succ) ? succ.Item : null;
 }
 internal OverlapRemovalNode NextLeft(OverlapRemovalNode node)
 {
     var pred = this.nodeTree.Previous(this.nodeTree.Find(node));
     return (null != pred) ? pred.Item : null;
 }
 internal void Remove(OverlapRemovalNode node)
 {
     this.nodeTree.Remove(node);
 }
예제 #13
0
 internal OlapTestNode(OverlapRemovalNode node)
 {
     this.Node = node;
 }
        public void AddNodeToCluster(OverlapRemovalCluster cluster, OverlapRemovalNode node)
        {
            // Node derives from Cluster so make sure we don't have this - the only way to create
            // cluster hierarchies is by AddCluster.
            ValidateArg.IsNotNull(cluster, "cluster");
            if (node is OverlapRemovalCluster)
            {
                throw new InvalidOperationException(
#if DEBUG
                        "Argument 'node' must not be a Cluster"
#endif // DEBUG
                        );
            }
            cluster.AddNode(node);
        }
 /// <summary>
 /// Add a new variable to the ConstraintGenerator.
 /// </summary>
 /// <param name="initialCluster">The cluster this node is to be a member of.  It may not be null; pass
 ///                     DefaultClusterHierarchy to create a node at the lowest level.  Subsequently a node 
 ///                     may be added to additional clusters, but only to one cluster per hierarchy.</param>
 /// <param name="userData">An object that is passed through.</param>
 /// <param name="position">Position of the node in the primary axis; if isHorizontal, it contains horizontal
 ///                     position and size, else it contains vertical position and size.</param>
 /// <param name="size">Size of the node in the primary axis.</param>
 /// <param name="positionP">Position of the node in the secondary (Perpendicular) axis.</param>
 /// <param name="sizeP">Size of the node in the secondary (Perpendicular) axis.</param>
 /// <param name="weight">Weight of the node (indicates how freely it should move).</param>
 /// <returns>The created node.</returns>
 public OverlapRemovalNode AddNode(OverlapRemovalCluster initialCluster, object userData, double position,
                     double positionP, double size, double sizeP, double weight)
 {
     ValidateArg.IsNotNull(initialCluster, "initialCluster");
     // @@PERF: Currently every node will have at least one constraint generated if there are any
     // other nodes along its line, regardless of whether the perpendicular coordinates result in overlap.
     // It might be worthwhile to add a check to avoid constraint generation in the case that there cannot
     // be such an overlap on a line, or if the nodes are separated by some amount of distance.
     Debug.Assert(null != initialCluster, "initialCluster must not be null");
     var nodNew = new OverlapRemovalNode(this.nextNodeId++, userData, position, positionP, size, sizeP, weight);
     initialCluster.AddNode(nodNew);
     return nodNew;
 }