Exemple #1
0
        /* For circles only. */
        private RoundaboutNode CheckAngularDistance(RoundaboutNode p1, RoundaboutNode p2)
        {
            RoundaboutNode prevNode = p1;
            double         angDif   = NormalizeAngle(prevNode.angle - p2.angle);

            if (p1 == p2)
            {
                angDif = 2 * Math.PI;
            }

            /* If the distance between two nodes is too great, we put in an intermediate node inbetween */
            while (angDif > m_maxAngDistance)
            {
                recursionGuard();

                double  angle  = NormalizeAngle(prevNode.angle - angDif / Math.Ceiling(angDif / m_maxAngDistance));
                Vector3 vector = ellipse.VectorAtAbsoluteAngle(angle);

                //ushort newNodeId = NetAccess.CreateNode(centerNodeNetInfo, vector);
                WrappedNode newNodeW = new WrappedNode();
                newNodeW.Position = vector;
                newNodeW.NetInfo  = centerNodeNetInfo;
                actionGroupRoads.Actions.Add(newNodeW);

                RoundaboutNode newNode = new RoundaboutNode(newNodeW);
                newNode.angle = angle;

                ConnectNodes(newNode, prevNode);

                prevNode = newNode;
                angDif   = NormalizeAngle(prevNode.angle - p2.angle);
            }

            return(prevNode);
        }
Exemple #2
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));
        }
        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);
                    }
                }
            }
        }
        /* 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... "));
            }
        }
Exemple #5
0
        public FinalConnector(NetInfo centerNodeNetInfo, EdgeIntersections2 edgeIntersections, Ellipse ellipse, bool insertControllingVertices)
        {
            intersections      = edgeIntersections?.Intersections ?? new List <RoundaboutNode>();
            actionGroupTMPE    = edgeIntersections?.ActionGroupTMPE ?? new ActionGroup("Set up TMPE");
            actionGroupRoads   = edgeIntersections?.ActionGroupRoads ?? new ActionGroup("Build roundabout");
            wrappersDictionary = edgeIntersections?.networkDictionary ?? new WrappersDictionary();

            this.ellipse = ellipse;
            pleasenoinfiniterecursion = 0;
            this.centerNodeNetInfo    = centerNodeNetInfo;
            leftHandTraffic           = Singleton <SimulationManager> .instance.m_metaData.m_invertTraffic ==
                                        SimulationMetaData.MetaBool.True;

            // We ensure that the segments are not too long. For circles only (with ellipses it would be more difficult)
            m_maxAngDistance = Math.Min(Math.PI * 25 / ellipse.RadiusMain, Math.PI / 2 + 0.1d);

            bool isCircle = ellipse.IsCircle();

            if (!isCircle && insertControllingVertices)
            {
                /* See doc in the method below */
                InsertIntermediateNodes();
            }

            /* If the list of edge nodes is empty, we add one default intersection. */
            if (isCircle && intersections.Count == 0)
            {
                Vector3 defaultIntersection = new Vector3(ellipse.RadiusMain, 0, 0) + ellipse.Center;
                //ushort newNodeId = NetAccess.CreateNode(centerNodeNetInfo, defaultIntersection);

                WrappedNode newNodeW = new WrappedNode();
                newNodeW.Position = defaultIntersection;
                newNodeW.NetInfo  = centerNodeNetInfo;
                RoundaboutNode raNode = new RoundaboutNode(newNodeW);
                raNode.Create(actionGroupRoads);
                intersections.Add(raNode);
            }

            int count = intersections.Count;

            foreach (RoundaboutNode item in intersections)
            {
                item.angle = Ellipse.VectorsAngle(item.wrappedNode.Position - ellipse.Center);
            }

            /* We sort the nodes according to their angles */
            intersections.Sort();

            /* Goes over all the nodes and conntets each of them to the angulary closest neighbour. (In a given direction) */

            for (int i = 0; i < count; i++)
            {
                RoundaboutNode prevNode = intersections[i];
                if (isCircle)
                {
                    prevNode = CheckAngularDistance(intersections[i], intersections[(i + 1) % count]);
                }
                ConnectNodes(intersections[(i + 1) % count], prevNode);
            }

            // Charge player
            var chargePlayerAction = new ChargePlayerAction(actionGroupRoads.DoCost(), centerNodeNetInfo.m_class);

            if (!chargePlayerAction.CheckMoney())
            {
                throw new PlayerException("Not enough money!");
            }

            actionGroupRoads.Actions.Add(chargePlayerAction);

            // Create
            ModThreading.PushAction(actionGroupRoads, actionGroupTMPE);
        }