GetNode() public static method

public static GetNode ( List nodes, string id ) : Node
nodes List
id string
return Node
Ejemplo n.º 1
0
        void OnDrawGizmosSelected()
        {
            //Primitives
            if (mainPrimitives != null && mainPrimitives.Count > 0)
            {
                int primitiveCount = 0;
                foreach (var p in mainPrimitives)
                {
                    //Primitive sub edge targets
                    if (p.subEdgeTargets != null && p.subEdgeTargets.Count > 0)
                    {
                        //Gizmos.color = Color.magenta;
                        for (int i = 0; i < p.subEdgeTargets.Count; i++)
                        {
                            Gizmos.color = Color.blue;
                            Vector3 pointPos = transform.TransformPoint(p.subEdgeTargets[i]);
                            Gizmos.DrawSphere(pointPos, .15f);
                            //Gizmos.DrawLine(pointOutside, pointPos);
                        }
                    }

                    //Subedges
                    if (p.subEdges != null && p.subEdges.Count > 0)
                    {
                        Gizmos.color = Color.magenta;

                        // Edges
                        for (int j = 0; j < p.subEdges.Count; j++)
                        {
                            Node n1 = Node.GetNode(p.subNodes, p.subEdges[j].Node1);
                            Node n2 = Node.GetNode(p.subNodes, p.subEdges[j].Node2);

                            if (n1 != null && n2 != null)
                            {
                                Gizmos.DrawLine(transform.TransformPoint(n1.Position), transform.TransformPoint(n2.Position));
                            }
                        }

                        for (int k = 0; k < p.subNodes.Count; k++)
                        {
                            if (p.subNodes[k].adjacents.Count >= 2)
                            {
                                Gizmos.color = Color.green;
                            }
                            else
                            {
                                Gizmos.color = Color.blue;
                            }
                            Gizmos.DrawSphere(transform.TransformPoint(p.subNodes[k].Position), .05f);
                        }
                    }

                    primitiveCount++;
                }
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Splits given edge into two edges at given point
        /// If a node is given, it will be used to split the edges
        /// Otherwise make a new node
        /// </summary>
        public static Node SplitEdge(Edge edge, Vector3 point, List <Node> nodes, List <Edge> edges, Node node = null)
        {
            bool isNewNode = false;

            // Create new node
            if (node == null)
            {
                node      = new Node(point);
                isNewNode = true;
            }

            // Get start and end nodes of the edge
            Node start = Node.GetNode(nodes, edge.Node1);
            Node end   = Node.GetNode(nodes, edge.Node2);

            // Add new node between start and end
            start.adjacents.Remove(end.ID);
            end.adjacents.Remove(start.ID);

            start.adjacents.Add(node.ID);
            end.adjacents.Add(node.ID);

            int startIndex = nodes.IndexOf(start);

            if (startIndex == -1)
            {
                Debug.LogError("Edge::SplitEdge() - StartIndex not found. Are you sure you gave the right node list?");
                return(null);
            }

            if (isNewNode)
            {
                if (startIndex == nodes.Count - 1)
                {
                    nodes.Add(node);
                }
                else
                {
                    nodes.Insert(startIndex + 1, node);
                }
            }

            // Remove original edge from edges
            edges.Remove(edge);

            // Create new edges
            Edge e1 = new Edge(start.ID, node.ID, edge.width);
            Edge e2 = new Edge(node.ID, end.ID, edge.width);

            edges.Add(e1);
            edges.Add(e2);

            return(node);
        }
Ejemplo n.º 3
0
        public static void CleanUpEdges(ref List <Node> nodes, ref List <Edge> edges)
        {
            for (int i = 0; i < edges.Count; i++)
            {
                // Make sure the edge is still an existing one
                Node n1 = Node.GetNode(nodes, edges[i].Node1);
                Node n2 = Node.GetNode(nodes, edges[i].Node2);

                if (n1 == null || n2 == null)
                {
                    edges.RemoveAt(i);
                    i--;
                    continue;
                }

                // Remove edges that have the same node twice
                if (edges[i].Node1 == edges[i].Node2)
                {
                    edges.RemoveAt(i);
                    i--;
                    continue;
                }

                // Remove duplicate edges
                for (int j = 0; j < edges.Count; j++)
                {
                    if (j != i && j < edges.Count - 1 && i < edges.Count - 1 && i > 0 && j > 0)
                    {
                        if ((edges[i].Node1 == edges[j].Node1 && edges[i].Node2 == edges[j].Node2) ||
                            (edges[i].Node1 == edges[j].Node2 && edges[i].Node2 == edges[j].Node1))
                        {
                            edges.RemoveAt(i);
                            i--;
                        }
                    }
                }
            }
        }
Ejemplo n.º 4
0
        void ConnectEndPoints(List <Node> _nodes, List <Edge> _edges)
        {
            // Find endpoints
            List <Node> endNodes = new List <Node>();

            for (int i = 1; i < _nodes.Count; i++)
            {
                if (_nodes[i].adjacents.Count == 1)
                {
                    endNodes.Add(_nodes[i]);
                }
            }

            // Connect endpoints to edges or other nodes
            for (int i = 0; i < endNodes.Count; i++)
            {
                // End node direction
                Node    adjacent = Node.GetNode(_nodes, endNodes[i].adjacents[0]);
                Vector3 nodeDir  = (endNodes[i].Position - adjacent.Position).normalized;

                //Check if there is any nodes in the rough direction of the end node
                float       roughAngle = 30f;
                List <Node> nodesInDir = new List <Node>();

                for (int j = 0; j < _nodes.Count; j++)
                {
                    if (_nodes[j] == endNodes[i])
                    {
                        continue;
                    }

                    Vector3 dirToNode = (_nodes[j].Position - endNodes[i].Position).normalized;
                    if (Vector3.Angle(nodeDir, dirToNode) < roughAngle && Vector3.Angle(nodeDir, dirToNode) > 30f)
                    {
                        nodesInDir.Add(_nodes[j]);
                    }
                }

                // The node with which this endpoint is connected to
                Node connectTo = null;

                // If there are some nodes in the rough direction, pick the one that is closest
                if (nodesInDir.Count > 0)
                {
                    float toClosest = Mathf.Infinity;
                    Node  closest   = null;
                    for (int j = 0; j < nodesInDir.Count; j++)
                    {
                        float toCurrent = Vector3.Distance(endNodes[i].Position, nodesInDir[j].Position);
                        if (toCurrent < toClosest)
                        {
                            toClosest = toCurrent;
                            closest   = nodesInDir[j];
                        }
                    }

                    if (toClosest < subEdgeEndConnectionRange)
                    {
                        connectTo = closest;
                    }
                }
                // Else get intersection with closest edge in the direction of this endpoint
                if (connectTo == null)
                {
                    // Ending point for tested segment in the direction of this endpoint
                    Vector3 segmentEnd = endNodes[i].Position + nodeDir * 1000f;

                    // Get the intersection
                    Vector3 intersectPoint = Vector3.zero;
                    // Convert all used points to XZ space
                    Vector3 intersectPointXZ = Vector2.zero;
                    Vector2 endPointXZ       = new Vector2(endNodes[i].Position.x, endNodes[i].Position.z);
                    Vector2 segmentEndXZ     = new Vector2(segmentEnd.x, segmentEnd.z);

                    List <Edge>    intersectedEdges = new List <Edge>();
                    List <Vector3> intersectPoints  = new List <Vector3>();

                    // Ignore the edge that starts on this endpoint
                    Edge endEdge = _edges.Find(e => (e.Node1 == endNodes[i].ID || e.Node2 == endNodes[i].ID));

                    for (int j = 0; j < _edges.Count; j++)
                    {
                        if (_edges[j] == endEdge)
                        {
                            continue;
                        }

                        Node n1 = Node.GetNode(_nodes, _edges[j].Node1);
                        Node n2 = Node.GetNode(_nodes, _edges[j].Node2);

                        Vector2 node1XZ = new Vector2(n1.Position.x, n1.Position.z);
                        Vector2 node2XZ = new Vector2(n2.Position.x, n2.Position.z);

                        if (UtilityTools.MathHelper.AreIntersecting(out intersectPointXZ, endPointXZ, segmentEndXZ, node1XZ, node2XZ) == 1)
                        {
                            intersectPoints.Add(new Vector3(intersectPointXZ.x, n1.Position.y, intersectPointXZ.y));
                            intersectedEdges.Add(_edges[j]);
                        }
                    }

                    // Get closest intersect point
                    float toClosest = Mathf.Infinity;
                    Edge  closestIntersectedEdge = null;
                    for (int j = 0; j < intersectPoints.Count; j++)
                    {
                        float toPoint = Vector3.Distance(endNodes[i].Position, intersectPoints[j]);
                        if (toPoint < toClosest)
                        {
                            toClosest              = toPoint;
                            intersectPoint         = intersectPoints[j];
                            closestIntersectedEdge = intersectedEdges[j];
                        }
                    }

                    // Split the intersected edge on the intersection
                    if (closestIntersectedEdge == null || intersectPoint == Vector3.zero)
                    {
                        Debug.Log("Primitive::ConnectEndPoints() - Intersect point not found.");
                        continue;
                    }
                    else
                    {
                        connectTo = Edge.SplitEdge(closestIntersectedEdge, intersectPoint, _nodes, _edges);
                    }
                }

                _edges.Add(new Edge(endNodes[i].ID, connectTo.ID, subEdgeWidth));
            }

            // Refresh adjacent nodes after all the endpoint connections
            EdgeGraphUtility.CheckAdjacentNodes(ref _nodes, ref _edges);
        }
Ejemplo n.º 5
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.º 6
0
        /// <summary>
        /// Advances forward by segmentLength from current node
        /// </summary>
        /// <param name="_node"></param>
        /// <param name="_dir"></param>
        /// <returns>True if new node was made</returns>
        bool Advance(ref Node _node, Vector3 _dir)
        {
            bool retval = false;

            Vector3 newPos = _node.Position + _dir * m_segmentLength;

            if (newPos == _node.Position)
            {
                return(retval);
            }

            bool addNew = false;

            if (_node.adjacents.Count > 0)
            {
                Node adj = Node.GetNode(nodes, _node.adjacents[0]);
                if (adj != null)
                {
                    Vector3 dirToPrevious = (adj.Position - _node.Position).normalized;
                    // If direction stays the same, just move current node
                    float dot = Vector3.Dot(_dir.normalized, dirToPrevious);

                    if (Mathf.Approximately(dot, -1f))
                    {
                        _node.Position = newPos;
                    }
                    else
                    {
                        // If resulting angle is too sharp, make a 90 degree turn
                        Vector3 referenceRight = Vector3.Cross(Vector3.up, dirToPrevious);
                        // Pick adjacent with which current direction creates the smallest angle
                        float angle = Mathf.Infinity;
                        for (int i = 0; i < _node.adjacents.Count; i++)
                        {
                            adj = Node.GetNode(nodes, _node.adjacents[0]);
                            Vector3 dirToCur = (adj.Position - _node.Position).normalized;
                            float   toCur    = Vector3.Angle(dirToCur, _dir);
                            if (toCur < angle)
                            {
                                angle         = toCur;
                                dirToPrevious = dirToCur;
                            }
                        }
                        if (angle < m_minAngle)
                        {
                            //Check if current direction points left or right from previous and make a 90 degree turn to that direction
                            if (Vector3.Dot(referenceRight, _dir) > 0) // Right
                            {
                                _dir = Vector3.Cross(Vector3.up, dirToPrevious);
                            }
                            else
                            {
                                _dir = Vector3.Cross(dirToPrevious, Vector3.up);
                            }

                            newPos = _node.Position + _dir * m_segmentLength;
                        }

                        addNew = true;
                    }
                }
                else
                {
                    addNew = true;
                }
            }
            else
            {
                addNew = true;
            }

            if (addNew)
            {
                Node newNode = new Node(newPos);
                nodes.Add(newNode);

                newNode.adjacents.Add(_node.ID);
                _node.adjacents.Add(newNode.ID);

                edges.Add(new Edge(_node.ID, newNode.ID, m_edgeWidth));

                _node = newNode;

                retval = true;
            }

            return(retval);
        }
Ejemplo n.º 7
0
        /// Goes through all the edges and finds intersections
        /// If intersections are found, splits both edges in the intersection point
        /// </summary>
        /// <returns>True if an edge was fixed</returns>
        public static bool FixIntersectingEdges(ref List <Node> nodes, ref List <Edge> edges)
        {
            bool retval = false;

            CleanUpEdges(ref nodes, ref edges);

            int limit = edges.Count;

            for (int i = 0; i < edges.Count; i++)
            {
                if (i > limit)
                {
                    break;
                }

                Vector3 intersectPoint = Vector3.zero;

                Node n1 = Node.GetNode(nodes, edges[i].Node1);
                Node n2 = Node.GetNode(nodes, edges[i].Node2);

                if (n1 == null || n2 == null)
                {
                    continue;
                }

                Vector2 node1XZ = new Vector2(n1.Position.x, n1.Position.z);
                Vector2 node2XZ = new Vector2(n2.Position.x, n2.Position.z);

                for (int j = 0; j < edges.Count; j++)
                {
                    if (i == j)
                    {
                        continue;
                    }

                    Node otherN1 = Node.GetNode(nodes, edges[j].Node1);
                    Node otherN2 = Node.GetNode(nodes, edges[j].Node2);

                    if (otherN1 == null || otherN2 == null ||
                        otherN1.adjacents.Contains(n1.ID) ||
                        otherN2.adjacents.Contains(n1.ID) ||
                        otherN1.adjacents.Contains(n2.ID) ||
                        otherN2.adjacents.Contains(n2.ID))
                    {
                        continue;
                    }

                    Vector2 otherN1XZ = new Vector2(otherN1.Position.x, otherN1.Position.z);
                    Vector2 otherN2XZ = new Vector2(otherN2.Position.x, otherN2.Position.z);

                    Vector3 intersectPointXZ;

                    if (UtilityTools.MathHelper.AreIntersecting(out intersectPointXZ, node1XZ, node2XZ, otherN1XZ, otherN2XZ) == 1)
                    {
                        intersectPoint = new Vector3(intersectPointXZ.x, otherN1.Position.y, intersectPointXZ.y);
                        Node intersectNode = Edge.SplitEdge(edges[i], intersectPoint, nodes, edges);
                        Edge.SplitEdge(edges[j], intersectPoint, nodes, edges, intersectNode);

                        retval = true;
                        break;
                    }
                }
            }

            return(retval);
        }