예제 #1
0
        private void ConnectNodes(VectorNodeStruct vectorNode1, VectorNodeStruct vectorNode2)
        {
            bool invert = leftHandTraffic;

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

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

            double angle1 = getAbsoluteAngle(vectorNode1.vector);
            double angle2 = getAbsoluteAngle(vectorNode2.vector);

            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);

            /* Sometime in the future ;) */

            try
            {
                SetupTMPE(newSegmentId);
            }
            catch (Exception e)
            {
                Debug.LogError(e);
            }
            //Debug.Log(string.Format("Building segment between nodes {0}, {1}, bezier scale {2}", node1, node2, scale));
        }
        private void BezierToSegment(Bezier2 bezier2, ushort oldSegmentId, ushort startNodeId, ushort endNodeId, bool invert)
        {
            NetSegment oldSegment = NetAccess.Segment(oldSegmentId);
            Vector2    startDirection2d;
            Vector2    endDirection2d;
            Vector2    nodePos2d = new Vector2(NetAccess.Node(startNodeId).m_position.x, NetAccess.Node(startNodeId).m_position.z);

            /*if ( Distance(nodePos2d,bezier2.Position(0f)) < 10e-3d)
             * {
             *  //0f is on the ellipse
             * }
             * else if(Distance(nodePos2d, bezier2.Position(1f)) < 10e-3d)
             * {
             *  //1f is on the ellipse
             *  bezier2 = bezier2.Invert();
             *  invert = true;
             * }
             * else
             * {
             *  throw new Exception(string.Format("Error - no intersection of bezier and point. Dist: {0}, {1}",Distance(nodePos2d,bezier2.Position(0f)), Distance(nodePos2d, bezier2.Position(1f))));
             * }*/
            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));
                if (nextSegmentInfo(endNodeId, oldSegmentId, out ushort endNodeIdNew, out Vector3 endDirectionNew))
                {
                    endNodeId    = endNodeIdNew;
                    endDirection = endDirectionNew;
                    //Debug.Log("The segment length should be " + VectorDistance(GetNode(startNodeId).m_position,GetNode(endNodeId).m_position));
                    //EllipseTool.Instance.debugDrawPositions.Add(GetNode(endNodeIdNew).m_position);
                }
            }

            // 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;
            }

            try
            {
                ushort newSegmentId = NetAccess.CreateSegment(startNodeId, endNodeId,
                                                              startDirection, endDirection, oldSegment.Info, invert);

                m_group.Actions.Add(new EnteringBlockedJunctionAllowedAction(newSegmentId, true, true));
                m_group.Actions.Add(new YieldSignAction(newSegmentId, true));
            }
            catch (Exception e)
            {
                UIWindow2.instance.ThrowErrorMsg("The game failed to create one of the road segments.");
                Debug.LogError(e.ToString());
            }
        }
        /* 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            = NetAccess.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);

                ushort newNodeId;
                ushort newSegmentId;

                newNodeId = NetAccess.CreateNode(CenterNode.Info, circleIntersection);

                Intersections.Add(new VectorNodeStruct(newNodeId));
                //EllipseTool.Instance.debugDrawPositions.Add(Intersections.Last().vector);

                NetSegment curSegment = NetAccess.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;
                }


                newSegmentId = NetAccess.CreateSegment(newNodeId, traveller.OuterNodes[i],
                                                       startDirection, endDirection, curSegment.Info, invert);

                m_group.Actions.Add(new EnteringBlockedJunctionAllowedAction(newSegmentId, true, true));
                m_group.Actions.Add(new YieldSignAction(newSegmentId, true));
                //Debug.Log(string.Format("Segment and node created... "));
            }
        }