FindEdgeByNodes() public static method

public static FindEdgeByNodes ( Node n1, Node n2, List _edges ) : Edge
n1 Node
n2 Node
_edges List
return Edge
Ejemplo n.º 1
0
        public void CutAcuteAngles()
        {
            if (type != PrimitiveType.MinimalCycle)
            {
                return;
            }

            List <Node> _nodesToRemove = new List <Node>();
            List <Node> _newNodes      = new List <Node>();
            List <Edge> _newEdges      = new List <Edge>();

            // Old edges are kept in the edges list, but node changes are saved here and refreshed to the edges once all angles are checked
            Dictionary <string, List <NodePair> > nodesToSwitchInEdges = new Dictionary <string, List <NodePair> >();

            for (int i = 0; i < nodes.Count; i++)
            {
                Node prevNode = EdgeGraphUtility.GetNode(nodes[i].adjacents[0], ref nodes);
                Node nextNode = EdgeGraphUtility.GetNode(nodes[i].adjacents[1], ref nodes);

                Vector3 dirToPrev = (prevNode.Position - nodes[i].Position).normalized;
                Vector3 dirToNext = (nextNode.Position - nodes[i].Position).normalized;

                Edge prevEdge = EdgeGraphUtility.FindEdgeByNodes(nodes[i], prevNode, edges);
                Edge nextEdge = EdgeGraphUtility.FindEdgeByNodes(nodes[i], nextNode, edges);

                float angle = Vector3.Angle(dirToPrev, dirToNext);
                if (angle < 45f)
                {
                    // Move nodes so that the cut side is 1f wide
                    float distanceToMove = .55f / Mathf.Sin(Mathf.Deg2Rad * angle / 2f);

                    float distToPrev = Vector3.Distance(prevNode.Position, nodes[i].Position);
                    float distToNext = Vector3.Distance(nextNode.Position, nodes[i].Position);

                    if (distanceToMove > distToPrev)
                    {
                        distanceToMove = distToPrev * .8f;
                    }

                    if (distanceToMove > distToNext)
                    {
                        distanceToMove = distToNext * .8f;
                    }

                    Vector3 newNodePrevPos = (nodes[i].Position + dirToPrev * distanceToMove);
                    Vector3 newNodeNextPos = (nodes[i].Position + dirToNext * distanceToMove);

                    string oldNodeID = nodes[i].ID;

                    // Remove old node
                    _nodesToRemove.Add(nodes[i]);

                    // Make new nodes
                    Node newNodeToPrev = new Node(newNodePrevPos);

                    Node newNodeToNext = new Node(newNodeNextPos);

                    if (!nodesToSwitchInEdges.ContainsKey(prevEdge.ID))
                    {
                        nodesToSwitchInEdges.Add(prevEdge.ID, new List <NodePair>());
                    }

                    nodesToSwitchInEdges[prevEdge.ID].Add(new NodePair(oldNodeID, newNodeToPrev.ID));

                    if (!nodesToSwitchInEdges.ContainsKey(nextEdge.ID))
                    {
                        nodesToSwitchInEdges.Add(nextEdge.ID, new List <NodePair>());
                    }

                    nodesToSwitchInEdges[nextEdge.ID].Add(new NodePair(oldNodeID, newNodeToNext.ID));

                    // Add the new edge
                    Edge newEdge = new Edge(newNodeToNext.ID, newNodeToPrev.ID);

                    _newEdges.Add(newEdge);

                    // Add new nodes to the dict
                    _newNodes.Add(newNodeToPrev);
                    _newNodes.Add(newNodeToNext);
                }
            }

            foreach (var n in _nodesToRemove)
            {
                for (int i = 0; i < nodes.Count; i++)
                {
                    if (nodes[i].ID == n.ID)
                    {
                        nodes.RemoveAt(i);
                        i--;
                    }
                }
            }

            foreach (var kvp in nodesToSwitchInEdges)
            {
                for (int i = 0; i < edges.Count; i++)
                {
                    if (edges[i].ID == kvp.Key)
                    {
                        Edge e = edges[i];
                        for (int j = 0; j < kvp.Value.Count; j++)
                        {
                            NodePair pair = kvp.Value[j];
                            if (e.Node1 == pair.oldNode)
                            {
                                e.Node1 = pair.newNode;
                            }
                            if (e.Node2 == pair.oldNode)
                            {
                                e.Node2 = pair.newNode;
                            }
                        }
                    }
                }
            }

            _newEdges.ForEach((e) => edges.Add(e));
            _newNodes.ForEach((n) => nodes.Add(n));

            EdgeGraphUtility.CleanUpEdges(ref nodes, ref edges);
            EdgeGraphUtility.CheckAdjacentNodes(ref nodes, ref edges);
        }
Ejemplo n.º 2
0
        // Algorithms from http://www.geometrictools.com/Documentation/MinimalCycleBasis.pdf
        // The Minimal Cycle Basis for a Planar Graph by David Eberly

        /// <summary>
        /// Attempts to find minimal cycles
        /// </summary>
        public static void ExtractPrimitive(Node _n0, ref List <Node> _nodes, ref List <Edge> _edges, ref List <Primitive> _primitives)
        {
            List <Node> visited  = new List <Node>();
            List <Node> sequence = new List <Node>();

            EdgeGraphUtility.CheckAdjacentNodes(ref _nodes, ref _edges);

            if (_n0.adjacents.Count == 0)
            {
                EdgeGraphUtility.RemoveNodeAndCleanAdjacents(_n0, ref _nodes, ref _edges);
                return;
            }

            sequence.Add(_n0);
            Node _n1  = GetClockwiseMostAdjacent(null, _n0, ref _nodes);
            Node prev = _n0;
            Node curr = _n1;

            while (curr != null && curr != _n0 && !visited.Contains(curr))
            {
                sequence.Add(curr);
                visited.Add(curr);
                Node next = GetCounterClockwiseMostAdjacent(prev, curr, ref _nodes);
                prev = curr;
                curr = next;
            }

            if (curr == null)
            {
                // Filament found, not necessarily rooted at prev
                ExtractFilament(prev, EdgeGraphUtility.GetNode(prev.adjacents[0], ref _nodes), ref _nodes, ref _edges, ref _primitives);
            }
            else if (curr == _n0)
            {
                // Minimal cycle found
                Primitive primitive = new Primitive(Primitive.PrimitiveType.MinimalCycle);
                primitive.nodes.AddRange(sequence);

                for (int i = 0; i < sequence.Count; i++)
                {
                    Node n1;
                    Node n2;
                    if (i == sequence.Count - 1)
                    {
                        n1 = sequence[i];
                        n2 = sequence[0];
                    }
                    else
                    {
                        n1 = sequence[i];
                        n2 = sequence[i + 1];
                    }
                    Edge e = EdgeGraphUtility.FindEdgeByNodes(n1, n2, _edges);
                    if (e != null)
                    {
                        primitive.edges.Add(e);
                        e.isPartOfCycle = true;
                    }
                }

                EdgeGraphUtility.RemoveEdgeAndCleanAdjacents(_n0, _n1, ref _nodes, ref _edges);

                if (_n0.adjacents.Count == 1)
                {
                    // Remove the filament rooted at v0
                    ExtractFilament(_n0, EdgeGraphUtility.GetNode(_n0.adjacents[0], ref _nodes), ref _nodes, ref _edges, ref _primitives);
                }

                if (_n1.adjacents.Count == 1)
                {
                    // Remove the filament rooted at v1
                    ExtractFilament(_n1, EdgeGraphUtility.GetNode(_n1.adjacents[0], ref _nodes), ref _nodes, ref _edges, ref _primitives);
                }

                _primitives.Add(primitive);
            }
            else   // curr was visited earlier
            {
                // A cycle has been found, but is not guaranteed to be a minimal cycle.
                // This implies v0 is part of a filament
                // Locate the starting point for the filament by traversing from v0 away from the initial v1

                while (_n0.adjacents.Count == 2)
                {
                    if (_n0.adjacents[0] != _n1.ID)
                    {
                        _n1 = _n0;
                        _n0 = EdgeGraphUtility.GetNode(_n0.adjacents[0], ref _nodes);
                    }
                    else
                    {
                        _n1 = _n0;
                        _n0 = EdgeGraphUtility.GetNode(_n0.adjacents[1], ref _nodes);
                    }
                }

                ExtractFilament(_n0, _n1, ref _nodes, ref _edges, ref _primitives);
            }
        }
Ejemplo n.º 3
0
        void ShiftNodes()
        {
            if (type != PrimitiveType.MinimalCycle)
            {
                return;
            }

            Dictionary <string, Vector3> newNodePositionDict = new Dictionary <string, Vector3>();

            for (int i = 0; i < nodes.Count; i++)
            {
                position += nodes[i].Position;

                if (nodes[i].adjacents.Count != 2)
                {
                    continue;
                }

                Node prevNode = null;
                Node nextNode = null;

                if (i == 0)
                {
                    prevNode = nodes[nodes.Count - 1];
                    nextNode = nodes[i + 1];
                }
                else if (i == nodes.Count - 1)
                {
                    prevNode = nodes[i - 1];
                    nextNode = nodes[0];
                }
                else
                {
                    prevNode = nodes[i - 1];
                    nextNode = nodes[i + 1];
                }

                Vector3 dirToPrev = (prevNode.Position - nodes[i].Position).normalized;
                Vector3 dirToNext = (nextNode.Position - nodes[i].Position).normalized;

                Edge prevEdge = EdgeGraphUtility.FindEdgeByNodes(nodes[i], prevNode, edges);
                Edge nextEdge = EdgeGraphUtility.FindEdgeByNodes(nodes[i], nextNode, edges);

                Node prevEdgeOtherNode = prevEdge.Node1 == nodes[i].ID ? Node.GetNode(nodes, prevEdge.Node2) : Node.GetNode(nodes, prevEdge.Node1);
                Node nextEdgeOtherNode = nextEdge.Node1 == nodes[i].ID ? Node.GetNode(nodes, nextEdge.Node2) : Node.GetNode(nodes, nextEdge.Node1);

                if (prevEdgeOtherNode == null || nextEdgeOtherNode == null)
                {
                    continue;
                }

                Vector3 prevLeftNormal = Edge.GetLeftPerpendicular(prevEdgeOtherNode.Position, nodes[i].Position);
                Vector3 nextLeftNormal = Edge.GetLeftPerpendicular(nodes[i].Position, nextEdgeOtherNode.Position);

                Vector3 newNodePos = nodes[i].Position;

                // In case the next and edge create a 180 degree angle, just shift this node towards the left normal
                if (Mathf.Approximately(Vector3.Dot(dirToNext, dirToPrev), -1f))
                {
                    float avgEdgeWidth = (prevEdge.Width + nextEdge.Width) / 2f;
                    newNodePos = nodes[i].Position + prevLeftNormal * avgEdgeWidth / 2f;
                }
                else
                {
                    // Shifted edges, streched a bit to ensure the intersection point
                    Vector3 prevEdgeNormalPoint = EdgeGraphUtility.GetEdgePosition(prevEdge.ID, ref nodes, ref edges) + prevLeftNormal * (prevEdge.Width / 2f);
                    float   prevEdgeLength      = Vector3.Distance(nodes[i].Position, prevEdgeOtherNode.Position);
                    Vector3 prevEdgeFar         = prevEdgeNormalPoint + dirToPrev * prevEdgeLength * 2f;
                    Vector3 prevEdgeNear        = prevEdgeNormalPoint - dirToPrev * prevEdgeLength * 2f;

                    Vector3 nextEdgeNormalPoint = EdgeGraphUtility.GetEdgePosition(nextEdge.ID, ref nodes, ref edges) + nextLeftNormal * (nextEdge.Width / 2f);
                    float   nextEdgeLength      = Vector3.Distance(nodes[i].Position, nextEdgeOtherNode.Position);
                    Vector3 nextEdgeFar         = nextEdgeNormalPoint + dirToNext * nextEdgeLength * 2f;
                    Vector3 nextEdgeNear        = nextEdgeNormalPoint - dirToNext * nextEdgeLength * 2f;

                    // Get intersect point of the shifted edges
                    Vector3 intersectPoint = nodes[i].Position;

                    Vector3 intersectPointXZ;

                    if (UtilityTools.MathHelper.AreIntersecting(out intersectPointXZ, prevEdgeFar, prevEdgeNear, nextEdgeFar, nextEdgeNear) == 1)
                    {
                        intersectPoint = new Vector3(intersectPointXZ.x, nodes[i].Position.y, intersectPointXZ.y);
                    }

                    //Vector3 nodeToNew = (intersectPoint - nodes[i].Position).normalized;
                    //Vector3 prevToNew = (intersectPoint - prevEdgeOtherNode.Position).normalized;
                    //Vector3 nextToNew = (intersectPoint - nextEdgeOtherNode.Position).normalized;

                    newNodePos = intersectPoint;
                }

                newNodePositionDict.Add(nodes[i].ID, newNodePos);
            }

            position /= nodes.Count;

            //Set shifted positions
            for (int i = 0; i < nodes.Count; i++)
            {
                if (newNodePositionDict.ContainsKey(nodes[i].ID))
                {
                    nodes[i].Position = newNodePositionDict[nodes[i].ID];
                }
            }
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Extracts filament consisting of nodes and edges
        /// </summary>
        public static void ExtractFilament(Node _n0, Node _n1, ref List <Node> _nodes, ref List <Edge> _edges, ref List <Primitive> _primitives)
        {
            Edge e = EdgeGraphUtility.FindEdgeByNodes(_n0, _n1, _edges);

            if (e != null && e.isPartOfCycle)
            {
                if (_n0.adjacents.Count >= 3)
                {
                    EdgeGraphUtility.RemoveEdgeAndCleanAdjacents(_n0, _n1, ref _nodes, ref _edges);
                    _n0 = _n1;
                    if (_n0.adjacents.Count == 1)
                    {
                        _n1 = EdgeGraphUtility.GetNode(_n0.adjacents[0], ref _nodes);
                    }
                }

                while (_n0.adjacents.Count == 1)
                {
                    _n1 = EdgeGraphUtility.GetNode(_n0.adjacents[0], ref _nodes);
                    Edge ee = EdgeGraphUtility.FindEdgeByNodes(_n0, _n1, _edges);
                    if (ee != null && e.isPartOfCycle)
                    {
                        EdgeGraphUtility.RemoveNodeAndCleanAdjacents(_n0, ref _nodes, ref _edges);
                        EdgeGraphUtility.RemoveEdgeAndCleanAdjacents(_n0, _n1, ref _nodes, ref _edges);
                    }
                    else
                    {
                        break;
                    }
                }

                if (_n0.adjacents.Count == 0)
                {
                    EdgeGraphUtility.RemoveNodeAndCleanAdjacents(_n0, ref _nodes, ref _edges);
                }
            }
            else
            {
                Primitive primitive = new Primitive(Primitive.PrimitiveType.Filament);

                if (_n0.adjacents.Count >= 3)
                {
                    primitive.nodes.Add(_n0);
                    primitive.edges.Add(e);
                    EdgeGraphUtility.RemoveEdgeAndCleanAdjacents(_n0, _n1, ref _nodes, ref _edges);
                    _n0 = _n1;
                    if (_n0.adjacents.Count == 1)
                    {
                        _n1 = EdgeGraphUtility.GetNode(_n0.adjacents[0], ref _nodes);
                    }
                }

                while (_n0.adjacents.Count == 1)
                {
                    primitive.nodes.Add(_n0);
                    _n1 = EdgeGraphUtility.GetNode(_n0.adjacents[0], ref _nodes);
                    EdgeGraphUtility.RemoveNodeAndCleanAdjacents(_n0, ref _nodes, ref _edges);
                    Edge _e = EdgeGraphUtility.RemoveEdgeAndCleanAdjacents(_n0, _n1, ref _nodes, ref _edges);
                    if (_e != null)
                    {
                        primitive.edges.Add(_e);
                    }
                    _n0 = _n1;
                }

                primitive.nodes.Add(_n0);
                if (_n0.adjacents.Count == 0)
                {
                    EdgeGraphUtility.RemoveNodeAndCleanAdjacents(_n0, ref _nodes, ref _edges);
                }

                _primitives.Add(primitive);
            }
        }