コード例 #1
0
        // Called before intersection is built
        private static void ReleaseCollidingSegments()
        {
            // We obtain a list of nodes adjacent to the deleted segment to know where to reconnect
            HashSet <ConnectionPoint> borderNodes = new HashSet <ConnectionPoint>();

            if (ToolControllerDetour.CollidingSegmentsCache2 == null)
            {
                return;
            }
            foreach (ushort segment in ToolControllerDetour.CollidingSegmentsCache2)
            {
                try
                {
                    //Debug.Log("Releasing segment " + segment);
                    NetSegment netSegment = NetUtil.Segment(segment);

                    // We keep untouchable segments
                    if ((netSegment.m_flags & NetSegment.Flags.Untouchable) != NetSegment.Flags.None)
                    {
                        continue;
                    }

                    bool inverted = ((netSegment.m_flags & NetSegment.Flags.Invert) != NetSegment.Flags.None);

                    borderNodes.Add(new ConnectionPoint(netSegment.m_startNode, netSegment.m_startDirection, netSegment.Info, inverted));
                    borderNodes.Add(new ConnectionPoint(netSegment.m_endNode, netSegment.m_endDirection, netSegment.Info, !inverted));

                    WrappedSegment segmentW = _networkDictionary.RegisterSegment(segment);
                    _actionGroup.Actions.Add(segmentW);
                    segmentW.IsBuildAction = false;
                    segmentW.Release();

                    if (segmentW.StartNode.TryRelease())
                    {
                        _actionGroup.Actions.Add(segmentW.StartNode);
                        segmentW.StartNode.IsBuildAction = false;
                    }

                    if (segmentW.EndNode.TryRelease())
                    {
                        _actionGroup.Actions.Add(segmentW.EndNode);
                        segmentW.EndNode.IsBuildAction = false;
                    }

                    //NetUtil.ReleaseSegment(segment, true);
                }
                catch (Exception e)
                {
                    Debug.LogError(e);
                }
            }

            borderNodes.RemoveWhere(n => !NetUtil.ExistsNode(n.Node));

            ToolControllerDetour.CollidingSegmentsCache2 = null;

            //Debug.Log("Border nodes (1): " + borderNodes.Count);

            BuildingDecorationDetour.borderNodes = borderNodes;
        }
コード例 #2
0
        private void Connect(ushort node1, ushort node2, Vector3 startDir, Vector3 endDir, NetInfo Info, bool invert = false)
        {
            //Debug.Log("Connectiong nodes " + node1 + " and " + node2);

            NetNode netNode1 = NetUtil.Node(node1);
            NetNode netNode2 = NetUtil.Node(node2);

            if ((netNode1.m_position - netNode2.m_position).magnitude < MIN_SEGMENT_LENGTH)
            {
                RepairShortSegment(ref endDir, ref node2);
            }

            //NetAccess.CreateSegment(node1,node2,(netNode2.m_position-netNode1.m_position).normalized, (netNode1.m_position - netNode2.m_position).normalized, info, invert);
            try
            {
                WrappedSegment segmentW = new WrappedSegment();
                segmentW.StartNode      = _networkDictionary.RegisterNode(node1);
                segmentW.EndNode        = _networkDictionary.RegisterNode(node2);
                segmentW.StartDirection = startDir;
                segmentW.EndDirection   = endDir;
                segmentW.NetInfo        = Info;
                segmentW.Invert         = invert;
                _actionGroup.Actions.Add(segmentW);

                segmentW.Create();
                //NetUtil.CreateSegment(node1, node2, startDir, endDir, Info, invert);
            }
            catch (Exception e)
            {
                Debug.LogWarning(e);
            }
        }
コード例 #3
0
        private void BezierToSegment(Bezier2 bezier2, WrappedSegment oldSegmentW, WrappedNode startNodeW, WrappedNode endNodeW, bool invert)
        {
            NetSegment oldSegment = oldSegmentW.Get;
            Vector2    startDirection2d;
            Vector2    endDirection2d;
            Vector2    nodePos2d = new Vector2(startNodeW.Position.x, startNodeW.Position.z);

            startDirection2d = bezier2.Tangent(0f);
            endDirection2d   = bezier2.Tangent(1f);

            Vector3 startDirection = (new Vector3(startDirection2d.x, 0, startDirection2d.y));
            Vector3 endDirection   = -(new Vector3(endDirection2d.x, 0, endDirection2d.y));

            /* Unlike from the old algorithm, we use no padding when looking for the segments. That means the obtained segments can be arbitrarily short.
             * In that case, we take one more segment away from the ellipse.*/
            if (VectorDistance(bezier2.a, bezier2.d) < MIN_BEZIER_LENGTH)
            {
                //Debug.Log("Segment is too short. Launching repair mechainsm." + VectorDistance(bezier2.a, bezier2.d));
                nextSegmentInfo(oldSegmentW, ref endNodeW, ref endDirection);
            }

            // Debug
            // EllipseTool.Instance.debugDrawVector(20*startDirection, GetNode(startNodeId).m_position);
            // EllipseTool.Instance.debugDrawVector(20*endDirection, GetNode(endNodeId).m_position);

            startDirection.Normalize();
            endDirection.Normalize();

            if (oldSegment.m_flags.IsFlagSet(NetSegment.Flags.Invert))
            {
                invert = !invert;
            }

            WrappedSegment newSegment = new WrappedSegment();

            newSegment.StartNode      = startNodeW;
            newSegment.EndNode        = endNodeW;
            newSegment.StartDirection = startDirection;
            newSegment.EndDirection   = endDirection;
            newSegment.NetInfo        = oldSegment.Info;
            newSegment.Invert         = invert;

            ActionGroupRoads.Actions.Add(newSegment);
            ActionGroupTMPE.Actions.Add(new EnteringBlockedJunctionAllowedAction(newSegment, true, true));
            ActionGroupTMPE.Actions.Add(new YieldSignAction(newSegment, true));

            /*try
             * {
             *  ushort newSegmentId = NetAccess.CreateSegment(startNodeId, endNodeId,
             * startDirection, endDirection, oldSegment.Info, invert);
             *
             *
             * }
             * catch(Exception e)
             * {
             *  UIWindow2.instance.ThrowErrorMsg("The game failed to create one of the road segments.");
             *  Debug.LogError(e.ToString());
             * }*/
        }
コード例 #4
0
        private void ConnectNodes(RoundaboutNode vectorNode1, RoundaboutNode vectorNode2)
        {
            bool invert = leftHandTraffic;

            vectorNode1.Create(actionGroupRoads, centerNodeNetInfo);
            vectorNode2.Create(actionGroupRoads, centerNodeNetInfo);

            /* NetNode node1 = GetNode(vectorNode1.nodeId);
             * NetNode node2 = GetNode(vectorNode2.nodeId);*/

            double angle1 = getAbsoluteAngle(vectorNode1.wrappedNode.Position);
            double angle2 = getAbsoluteAngle(vectorNode2.wrappedNode.Position);

            Vector3 vec1 = ellipse.TangentAtAbsoluteAngle(angle1);
            Vector3 vec2 = ellipse.TangentAtAbsoluteAngle(angle2);

            vec1.Normalize();
            vec2.Normalize();
            vec2 = -vec2;

            /*EllipseTool.Instance.debugDrawVector(10*vec1, vectorNode1.vector);
            *  EllipseTool.Instance.debugDrawVector(10*vec2, vectorNode2.vector);*/

            //NetInfo netPrefab = PrefabCollection<NetInfo>.FindLoaded("Oneway Road");
            NetInfo netPrefab = UI.UIWindow2.instance.dropDown.Value;
            //ushort newSegmentId = NetAccess.CreateSegment(vectorNode1.nodeId, vectorNode2.nodeId, vec1, vec2, netPrefab, invert, leftHandTraffic, true);
            WrappedSegment newSegment = new WrappedSegment();

            newSegment.StartNode              = vectorNode1.wrappedNode;
            newSegment.EndNode                = vectorNode2.wrappedNode;
            newSegment.StartDirection         = vec1;
            newSegment.EndDirection           = vec2;
            newSegment.NetInfo                = netPrefab;
            newSegment.Invert                 = invert;
            newSegment.SwitchStartAndEnd      = leftHandTraffic;
            newSegment.DeployPlacementEffects = true;

            actionGroupRoads.Actions.Add(newSegment);


            try
            {
                SetupTMPE(newSegment);
            }
            catch (Exception e)
            {
                Debug.LogError(e);
            }
            //Debug.Log(string.Format("Building segment between nodes {0}, {1}, bezier scale {2}", node1, node2, scale));
        }
コード例 #5
0
        private void SetupTMPE(WrappedSegment segment)
        {
            /* None of this below works: */

            /*bool resultPrev1 = TrafficManager.Manager.Impl.JunctionRestrictionsManager.Instance.IsEnteringBlockedJunctionAllowed(segment,false);
            *  bool resultPrev2 = TrafficManager.Manager.Impl.JunctionRestrictionsManager.Instance.IsEnteringBlockedJunctionAllowed(segment,true);
            *  bool result1 = TrafficManager.Manager.Impl.JunctionRestrictionsManager.Instance.SetEnteringBlockedJunctionAllowed(segment, false, true);
            *  bool result2 = TrafficManager.Manager.Impl.JunctionRestrictionsManager.Instance.SetEnteringBlockedJunctionAllowed(segment, true, true);
            *  bool resultPost1 = TrafficManager.Manager.Impl.JunctionRestrictionsManager.Instance.IsEnteringBlockedJunctionAllowed(segment, false);
            *  bool resultPost2 = TrafficManager.Manager.Impl.JunctionRestrictionsManager.Instance.IsEnteringBlockedJunctionAllowed(segment, true);*/
            /*Debug.Log($"Setting up tmpe segment {segment}. Result: {resultPrev1}, {resultPrev2}, {result1}, {result2}, {resultPost1}, {resultPost2}");
             * ModThreading.Timer(segment);*/
            actionGroupTMPE.Actions.Add(new EnteringBlockedJunctionAllowedAction(segment, true, false));
            actionGroupTMPE.Actions.Add(new EnteringBlockedJunctionAllowedAction(segment, false, false));
            actionGroupTMPE.Actions.Add(new NoCrossingsAction(segment, true));
            actionGroupTMPE.Actions.Add(new NoCrossingsAction(segment, false));
            actionGroupTMPE.Actions.Add(new NoParkingAction(segment));
        }
コード例 #6
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);
        }
コード例 #7
0
        private void SnappingAlgorithmNew()
        {
            //Debug
            //EllipseTool.Instance.debugDraw = segmentBeziers;

            List <Bezier2> segmentBeziers    = makeBeziers(traveller.OuterSegments);
            List <Bezier2> ellipseBeziers    = traveller.Ellipse.Beziers;
            List <ushort>  processedSegments = new List <ushort>();

            /* We find all intersections between roads and ellipse beziers */
            for (int i = 0; i < segmentBeziers.Count; i++)
            {
                for (int j = 0; j < ellipseBeziers.Count; j++)
                {
                    if (ellipseBeziers[j].Intersect(segmentBeziers[i], out float t1, out float t2, ITERATIONS))
                    {
                        if (processedSegments.Contains(traveller.OuterSegments[i]))
                        {
                            continue;
                        }
                        else
                        {
                            processedSegments.Add(traveller.OuterSegments[i]);
                        }

                        //Debug.Log("Segment " + i.ToString() + " intersects ellipse bezier " + j.ToString());
                        Vector3 intersection = new Vector3(ellipseBeziers[j].Position(t1).x, CenterNode.m_position.y, ellipseBeziers[j].Position(t1).y);
                        segmentBeziers[i].Divide(out Bezier2 segementBezier1, out Bezier2 segementBezier2, t2);
                        Bezier2 outerBezier;
                        Vector2 outerNodePos = new Vector2(NetUtil.Node(traveller.OuterNodes[i]).m_position.x, NetUtil.Node(traveller.OuterNodes[i]).m_position.z);
                        bool    invert       = false;
                        // outerBezier - the bezier outside the ellipse (not the one inside)
                        if (segementBezier1.Position(0f) == outerNodePos || segementBezier1.Position(1f) == outerNodePos)
                        {
                            //Debug.Log("first is outer");
                            outerBezier = segementBezier1.Invert();
                            invert      = true;
                        }
                        else if (segementBezier2.Position(0f) == outerNodePos || segementBezier2.Position(1f) == outerNodePos)
                        {
                            //Debug.Log("second is probably outer");
                            outerBezier = segementBezier2;
                            invert      = false;
                        }
                        else
                        {
                            throw new Exception("Error - Failed to determine segment geometry.");
                        }

                        //debug:
                        //EllipseTool.Instance.debugDraw.Add(outerBezier);

                        /* We create a node at the intersection. */
                        WrappedNode newNode = new WrappedNode();
                        newNode.Position = intersection;
                        newNode.NetInfo  = CenterNode.Info;
                        RoundaboutNode raNode = new RoundaboutNode(newNode);
                        raNode.Create(ActionGroupRoads);
                        Intersections.Add(raNode);

                        WrappedNode    outerNode    = networkDictionary.RegisterNode(traveller.OuterNodes[i]);
                        WrappedSegment outerSegment = networkDictionary.RegisterSegment(traveller.OuterSegments[i]);

                        BezierToSegment(outerBezier, outerSegment, newNode, outerNode, invert);
                    }
                }
            }
        }
コード例 #8
0
        /* Sometimes it happens that we split the road too close to another segment. If that occur, the roads do glitch. In that case
         * we remove one more segment up the road. This method is still glitchy, would need improvement. */
        /* intersection - node outside the ellipse */
        private bool nextSegmentInfo(WrappedSegment closeSegmentW, ref WrappedNode outerNodeW, ref Vector3 endDirection)
        {
            NetSegment closeSegment = closeSegmentW.Get;
            //outerNodeId = 0;
            //directions = new Vector3(0,0,0);
            NetNode node         = outerNodeW.Get;
            int     segmentcount = node.CountSegments();

            /* If there is an intersection right behind the ellipse, we can't go on as we can merge only segments which are in fact
             * only one road without an intersection. */
            if (segmentcount != 2)
            {
                //Debug.Log("Ambiguous node.");
                return(false);
            }

            /*string debugString = "Close segment id: " + closeSegmentId + "; ";
             * for(int i = 0; i < 8; i++)
             * {
             *  debugString += node.GetSegment(i) + ", ";
             * }
             * Debug.Log(debugString);*/
            ushort nextSegmentId = NetUtil.GetNonzeroSegment(node, 0);

            /* We need the segment that goes away from the ellipse, not the one we already have. */
            if (closeSegmentW.Id == nextSegmentId)
            {
                //Debug.Log("Taking the other of the two segments. " + node.GetSegment(1));
                nextSegmentId = NetUtil.GetNonzeroSegment(node, 1);
                if (nextSegmentId == 0)
                {
                    return(false);
                }
            }
            NetSegment nextSegment = NetUtil.Segment(nextSegmentId);

            ushort  outerNodeId = nextSegment.m_startNode;
            Vector3 directions  = nextSegment.m_startDirection;

            /* We need the node further away */
            if (outerNodeId == outerNodeW.Id)
            {
                //Debug.Log("Taking the other of the nodes.");
                outerNodeId = nextSegment.m_endNode;
                directions  = nextSegment.m_endDirection;
                if (outerNodeId == 0)
                {
                    return(false);
                }
            }

            WrappedSegment nextSegmentW = networkDictionary.RegisterSegment(nextSegmentId);

            // Release old
            ToBeReleasedNodes.Add(outerNodeW);
            ToBeReleasedSegments.Add(nextSegmentW);

            // Return values
            outerNodeW   = networkDictionary.RegisterNode(outerNodeId);
            endDirection = directions;

            /* After merging the roads, we release the segment and intersection inbetween. When I was debugging this method, I tried to release them after
             * everything is done. It might not be necessary.*/
            return(true);
        }
コード例 #9
0
        /* Old algorithm. Originally intended only for circles. From older documentation: */

        /* "For now, the intersection isn't created at the exact point where the segment crosses the circle, but rather on the intersection of
         * the circle and straight line, which goes from origin and ends at outer node of that segment. That could be unfortunately very
         * inaccurate, as the first note outside the circle could be quite far away". */
        private void SnappingAlgorithmOld()
        {
            float centerX = CenterNode.m_position.x;
            float centerY = CenterNode.m_position.y;
            float centerZ = CenterNode.m_position.z;

            for (int i = 0; i < traveller.OuterNodes.Count; i++)
            {
                NetNode curNode            = NetUtil.Node(traveller.OuterNodes[i]);
                Vector3 circleIntersection = new Vector3();

                float directionX = (curNode.m_position.x - centerX) / VectorDistance(CenterNode.m_position, curNode.m_position);
                float directionZ = (curNode.m_position.z - centerZ) / VectorDistance(CenterNode.m_position, curNode.m_position);

                float radius = (float)ellipse.RadiusAtAbsoluteAngle(Math.Abs(Ellipse.VectorsAngle(curNode.m_position - ellipse.Center)));
                if (radius > 10000)
                {
                    throw new Exception("Algortithm error");
                }

                circleIntersection.x = (directionX * radius + centerX);
                circleIntersection.y = centerY;
                circleIntersection.z = (directionZ * radius + centerZ);

                WrappedNode    newNode;
                WrappedSegment newSegment;

                newNode          = new WrappedNode();
                newNode.NetInfo  = CenterNode.Info;
                newNode.Position = circleIntersection;
                RoundaboutNode raNode = new RoundaboutNode(newNode);
                raNode.Create(ActionGroupRoads);
                Intersections.Add(raNode);
                //EllipseTool.Instance.debugDrawPositions.Add(Intersections.Last().vector);

                NetSegment curSegment = NetUtil.Segment(traveller.OuterSegments[i]);

                /* For now ignoring anything regarding Y coordinate */
                //float directionY2 = (GetNode(newNodeId).m_position.y - curNode.m_position.z) / NodeDistance(GetNode(newNodeId), curNode);
                float directionY2 = 0f;

                Vector3 startDirection = new Vector3();
                startDirection.x = (directionX /** NodeDistance( GetNode( newNodeId ), curNode ) / 2*/);
                startDirection.y = directionY2;
                startDirection.z = (directionZ /** NodeDistance(GetNode(newNodeId), curNode) / 2*/);
                Vector3 endDirection = new Vector3();
                endDirection.x = -startDirection.x;
                endDirection.y = -startDirection.y;
                endDirection.z = -startDirection.z;

                bool invert;
                //Debug.Log(string.Format("same node: {0}, invert: {1}", curSegment.m_startNode == traveller.OuterNodes[i], curSegment.m_flags.IsFlagSet(NetSegment.Flags.Invert)));
                if (curSegment.m_startNode == traveller.OuterNodes[i] ^ curSegment.m_flags.IsFlagSet(NetSegment.Flags.Invert))
                {
                    invert = true;
                }
                else
                {
                    invert = false;
                }

                newSegment                = new WrappedSegment();
                newSegment.StartNode      = newNode;
                newSegment.EndNode        = networkDictionary.RegisterNode(traveller.OuterNodes[i]);
                newSegment.StartDirection = startDirection;
                newSegment.EndDirection   = endDirection;
                newSegment.NetInfo        = curSegment.Info;
                newSegment.Invert         = invert;
                ActionGroupRoads.Actions.Add(newSegment);

                ActionGroupTMPE.Actions.Add(new EnteringBlockedJunctionAllowedAction(newSegment, true, true));
                ActionGroupTMPE.Actions.Add(new YieldSignAction(newSegment, true));
                //Debug.Log(string.Format("Segment and node created... "));
            }
        }
コード例 #10
0
        /* Sometimes the intersection end snaps to an existing road. But it can happen that the intersection road and the road it snaps to are (more or
         * less) parallel. Then we are left with a piece of old road overlapping the new road because the old segment for some reason doesn't show up as
         * colliding. We have to find it and release it. I think that it shouldn't happen more than once per intersection tho. */
        private static void ReleaseQuestionableSegments(FastList <ushort> newNodes, FastList <ushort> newSegments)
        {
            foreach (ushort node in newNodes)
            {
                NetNode netNode      = NetUtil.Node(node);
                ushort  foundSegment = 0;
                for (int i = 0; i < 8; i++)
                {
                    ushort segment = netNode.GetSegment(i);
                    if (segment != 0 && newSegments.Contains(segment))
                    {
                        if (foundSegment != 0)
                        {
                            goto continueOuterLoop;
                        }
                        else
                        {
                            foundSegment = segment;
                        }
                    }
                }

                Vector3 direction = NetUtil.Segment(foundSegment).GetDirection(node);
                for (int i = 0; i < 8; i++)
                {
                    ushort segment = netNode.GetSegment(i);
                    if (segment != 0 && segment != foundSegment)
                    {
                        float angle = Vector3.Angle(direction, NetUtil.Segment(segment).GetDirection(node));
                        if (angle < 10)
                        {
                            //Debug.Log("Releasing questionable segment " + segment);
                            //NetUtil.ReleaseSegment(segment);
                            WrappedSegment segmentW = _networkDictionary.RegisterSegment(segment);
                            _actionGroup.Actions.Add(segmentW);
                            segmentW.IsBuildAction = false;
                            segmentW.Release();

                            if (segmentW.StartNode.TryRelease())
                            {
                                _actionGroup.Actions.Add(segmentW.StartNode);
                                segmentW.StartNode.IsBuildAction = false;
                            }

                            if (segmentW.EndNode.TryRelease())
                            {
                                _actionGroup.Actions.Add(segmentW.EndNode);
                                segmentW.EndNode.IsBuildAction = false;
                            }

                            /*WrappedSegment segmentW = _networkDictionary.RegisterSegment(segment);
                             * segmentW.Release();*/

                            goto breakOuterLoop;
                        }
                    }
                }

                continueOuterLoop :;
            }
            breakOuterLoop :;
        }