Beispiel #1
0
        public MakeConnections(HashSet <ConnectionPoint> borderNodes, FastList <ushort> createdNodes, WrappersDictionary dictionary, ActionGroup actionGroup)
        {
            if (!UIWindow.instance.m_connectRoadsCheckBox.isChecked)
            {
                return;
            }

            if (borderNodes == null)
            {
                return;
            }

            _networkDictionary = dictionary;
            _actionGroup       = actionGroup;

            HashSet <ushort> filteredCreatedNodes = FilterCreatedNodes(createdNodes);
            // (Border nodes are already filtered)

            HashSet <ConnectionPoint> usedPoints = new HashSet <ConnectionPoint>();
            HashSet <ushort>          usedNodes  = new HashSet <ushort>();

            List <ConnectionPair> connectionPairs = new List <ConnectionPair>();

            /* For each pair of nodes we make an attempt to connect them */
            foreach (ushort node1 in filteredCreatedNodes)
            {
                foreach (ConnectionPoint cpoint in borderNodes)
                {
                    if (RankConnection(node1, cpoint, out int rank))
                    {
                        connectionPairs.Add(new ConnectionPair(node1, cpoint, rank));
                    }
                }
            }

            connectionPairs.Sort((a, b) => - a.rank.CompareTo(b.rank));

            foreach (var pair in connectionPairs)
            {
                if (!usedPoints.Contains(pair.point2) && !usedNodes.Contains(pair.node1))
                {
                    ushort     segment1    = NetUtil.GetFirstSegment(NetUtil.Node(pair.node1));
                    NetSegment netSegment1 = NetUtil.Segment(segment1);
                    Connect(pair.node1, pair.point2.Node, -netSegment1.GetDirection(pair.node1), pair.point2.Direction, pair.point2.NetInfo, !pair.point2.DirectionBool);

                    usedNodes.Add(pair.node1);
                    usedPoints.Add(pair.point2);
                }
            }
        }
Beispiel #2
0
        /* If node distance is too short, we travel one segment up from the border node and set the new node as the one to connect to */
        private void RepairShortSegment(ref Vector3 direction, ref ushort node)
        {
            //Debug.Log("Repairing short segment...");

            NetNode netNode = NetUtil.Node(node);

            // If there is more than one segment we cannot safely delete it (we don't even know from which segment we should pick)
            if (netNode.CountSegments() != 1)
            {
                return;
            }

            ushort     segmentId  = NetUtil.GetFirstSegment(netNode);
            NetSegment netSegment = NetUtil.Segment(segmentId);

            WrappedNode nodeW = _networkDictionary.RegisterNode(node);

            if (node == netSegment.m_startNode)
            {
                direction = netSegment.m_endDirection;
                node      = netSegment.m_endNode;
            }
            else
            {
                direction = netSegment.m_startDirection;
                node      = netSegment.m_startNode;
            }

            WrappedSegment segmentW = _networkDictionary.RegisterSegment(segmentId);

            _actionGroup.Actions.Add(segmentW);
            _actionGroup.Actions.Add(nodeW);
            segmentW.Release();
            nodeW.Release();
            segmentW.IsBuildAction = false;
            nodeW.IsBuildAction    = false;

            //NetUtil.ReleaseSegment(segmentId, true);
        }
Beispiel #3
0
        private bool TryConnect(ushort node1, ConnectionPoint cpoint)
        {
            NetNode netNode1 = NetUtil.Node(node1);
            NetNode netNode2 = NetUtil.Node(cpoint.Node);

            Vector3 differenceVector = netNode2.m_position - netNode1.m_position;

            //Debug.Log("TryConnect: " + node1 + ", " + cpoint.Node + ", dist: " + differenceVector.magnitude);

            // 1) Check max distance
            if (differenceVector.magnitude > MAX_NODE_DISTANCE)
            {
                return(false);
            }

            ushort segment1 = NetUtil.GetFirstSegment(netNode1);
            //ushort segment2 = NetAccess.GetFirstSegment(netNode2);
            NetSegment netSegment1 = NetUtil.Segment(segment1);

            //NetSegment netSegment2 = NetAccess.GetSegment(segment2);

            // 2) Check if both segments are roads
            if (!((netSegment1.Info.m_hasForwardVehicleLanes || netSegment1.Info.m_hasBackwardVehicleLanes) && (cpoint.NetInfo.m_hasForwardVehicleLanes || cpoint.NetInfo.m_hasBackwardVehicleLanes)))
            {
                //Debug.Log("Not roads!");
                return(false);
            }

            // 3) Check max angle (if segments are too close we skip this as it won't give good data)
            Vector3 direction1 = netSegment1.GetDirection(node1);
            Vector3 direction2 = cpoint.Direction;
            float   angle1     = Vector3.Angle(direction1, -differenceVector);
            float   angle2     = Vector3.Angle(direction2, -differenceVector);

            if (differenceVector.magnitude > MIN_SEGMENT_LENGTH)
            {
                if (angle1 > MAX_ANGLE || angle2 > MAX_ANGLE)
                {
                    //Debug.Log("Angle too big: " + angle1 + " " + angle2);
                    return(false);
                }
            }

            // 4) Check if directions of one-way roads match (if so connect)
            if (NetUtil.IsOneWay(netSegment1.Info) && cpoint.NetInfo)
            {
                if (SegmentDirectionBool(netSegment1, node1) ^ cpoint.DirectionBool)
                {
                    Connect(node1, cpoint.Node, -netSegment1.GetDirection(node1), cpoint.Direction, cpoint.NetInfo, !cpoint.DirectionBool);
                    return(true);
                }
                else
                {
                    return(false); // We won't connect one-way roads whose directions don't match
                }
            }

            // 5) We will favor roads with same NetIfno (if so connect)
            if (netSegment1.Info == cpoint.NetInfo)
            {
                Connect(node1, cpoint.Node, -netSegment1.GetDirection(node1), cpoint.Direction, cpoint.NetInfo, !cpoint.DirectionBool);
                return(true);
            }

            // 6) Lastly we set smaller max distance and angle and try again
            if (differenceVector.magnitude < (MAX_NODE_DISTANCE * 3 / 4) && angle1 < MAX_ANGLE / 2 && angle2 < MAX_ANGLE / 2)
            {
                Connect(node1, cpoint.Node, -netSegment1.GetDirection(node1), cpoint.Direction, cpoint.NetInfo, !cpoint.DirectionBool);
                return(true);
            }

            return(false);
        }
Beispiel #4
0
        private bool RankConnection(ushort node1, ConnectionPoint cpoint, out int rank)
        {
            NetNode netNode1 = NetUtil.Node(node1);
            NetNode netNode2 = NetUtil.Node(cpoint.Node);

            Vector3 differenceVector = netNode2.m_position - netNode1.m_position;

            //Debug.Log("TryConnect: " + node1 + ", " + cpoint.Node + ", dist: " + differenceVector.magnitude);

            rank = 0;

            // 1) Check max distance
            if (differenceVector.magnitude > MAX_NODE_DISTANCE)
            {
                return(false);
            }

            ushort segment1 = NetUtil.GetFirstSegment(netNode1);
            //ushort segment2 = NetAccess.GetFirstSegment(netNode2);
            NetSegment netSegment1 = NetUtil.Segment(segment1);
            //NetSegment netSegment2 = NetAccess.GetSegment(segment2);

            bool quays = netSegment1.Info.m_netAI is QuayAI && cpoint.NetInfo.m_netAI is QuayAI;

            // 2) Check if both segments are roads
            if (!((netSegment1.Info.m_hasForwardVehicleLanes || netSegment1.Info.m_hasBackwardVehicleLanes) && (cpoint.NetInfo.m_hasForwardVehicleLanes || cpoint.NetInfo.m_hasBackwardVehicleLanes)) &&
                !quays)
            {
                //Debug.Log("Not roads!");
                return(false);
            }

            // 3) Check max angle (if segments are too close we skip this as it won't give good data)
            Vector3 direction1 = netSegment1.GetDirection(node1).normalized;
            Vector3 direction2 = cpoint.Direction.normalized;
            float   angle1     = Vector3.Angle(direction1, -differenceVector);
            float   angle2     = Vector3.Angle(direction2, -differenceVector);

            float differenceDot = Vector2.Dot(direction1.xz(), direction2.xz());
            float shearDot      = Mathf.Abs(Vector2.Dot(direction1.xz(), differenceVector.xz().normalized) * Vector2.Dot(direction2.xz(), differenceVector.xz().normalized));
            float weight        = differenceDot * shearDot;

            if (differenceVector.magnitude > MIN_SEGMENT_LENGTH)
            {
                if (angle1 > MAX_ANGLE || angle2 > MAX_ANGLE)
                {
                    //Debug.Log("Angle too big: " + angle1 + " " + angle2);
                    return(false);
                }
            }

            // 4) Check if directions of one-way roads match (if so connect)
            if (NetUtil.IsOneWay(netSegment1.Info) && NetUtil.IsOneWay(cpoint.NetInfo))
            {
                if (SegmentDirectionBool(netSegment1, node1) ^ cpoint.DirectionBool)
                {
                    if (netSegment1.Info == cpoint.NetInfo)
                    {
                        rank = (int)(weight * 2000);
                    }
                    else
                    {
                        rank = (int)(weight * 1000);
                    }
                    return(true);
                }
                else
                {
                    return(false); // We won't connect one-way roads whose directions don't match
                }
            }

            // 5) We will favor roads with same NetIfno (if so connect)
            if (netSegment1.Info == cpoint.NetInfo)
            {
                rank = (int)(weight * 1000);
                return(true);
            }

            if (quays)
            {
                return(false);
            }

            // 6) Lastly we set smaller max distance and angle and try again
            if (differenceVector.magnitude < (MAX_NODE_DISTANCE * 3 / 4) && angle1 < MAX_ANGLE / 2 && angle2 < MAX_ANGLE / 2)
            {
                rank = (int)(weight * 500);
                return(true);
            }

            return(false);
        }