Пример #1
0
            public static VertexFindResults Reject()
            {
                VertexFindResults vfr = new VertexFindResults();

                vfr.ToUse   = null;
                vfr.EndRoad = true;
                return(vfr);
            }
Пример #2
0
            public static VertexFindResults Accept(Vertex toUse, bool endRoad)
            {
                VertexFindResults vfr = new VertexFindResults();

                vfr.ToUse   = toUse;
                vfr.EndRoad = endRoad;
                return(vfr);
            }
Пример #3
0
        /// <summary>
        /// Creates a new road from the given starting point along the given axis.
        /// Takes care of adding the vertices and segments to their respective BVH.
        /// </summary>
        private Road Trace(Vertex start, bool useMajorAxis, int dir)
        {
            float stepInterval = RoadStepInterval * (float)dir;

            //Step along the road in increments to build up the segments defining it.
            Vector2 currentPos = start.Pos;
            Vector2 currentVel = (float)dir * (useMajorAxis ?
                                               GetBasis(start).Major :
                                               GetBasis(start).Minor);

            Road r = new Road();

            r.Points.Add(start);
            start.ConnectTo(r);

            bool   keepGoing = true;
            Vertex newVert   = start;

            while (keepGoing)
            {
                //Get the next vertex along the road.
                Vector2           nextPos = GetNext(newVert, stepInterval, currentVel, useMajorAxis);
                VertexFindResults vfr     = FindOrMakeVertex(r, nextPos);
                newVert = vfr.ToUse;

                if (newVert != null)
                {
                    newVert.ConnectTo(r);
                    r.Points.Add(newVert);
                    Segments.Add(new Segment(r.Points[r.Points.Count - 2], newVert, r));

                    nextPos = newVert.Pos;
                }

                currentVel = nextPos - currentPos;

                currentPos = nextPos;
                keepGoing  = !vfr.EndRoad;
            }

            //If the road is a dud, exit.
            if (r.Points.Count < 2)
            {
                foreach (Vertex v in r.Points)
                {
                    v.DisconnectFrom(r);
                }
                return(null);
            }

            //Finalize the road's data and return it.
            r.UpdateBoundingBox();
            return(r);
        }
Пример #4
0
        /// <summary>
        /// Given a road and a new position to add to the road,
        ///     gets or creates a vertex to add to the road.
        /// The vertex will always already be added to the vertex BVH.
        /// If the returned vertex is null, it shouldn't be added to the road.
        /// If "EndRoad" is true, the road should not continue on.
        /// </summary>
        private VertexFindResults FindOrMakeVertex(Road r, Vector2 nextPos)
        {
            Vertex lastPoint = r.Points[r.Points.Count - 1];

            //Reject if the segment length is too short or its position is outside the city limits.
            if (lastPoint.Pos.DistSqr(nextPos) <= (SegmentMinLength * SegmentMinLength) ||
                !IsInBounds(nextPos))
            {
                return(VertexFindResults.Reject());
            }

            //If the next position is near another vertex, use that vertex and end the road there.
            foreach (Vertex v in Vertices.GetAllNearbyPos(nextPos))
            {
                //Don't let the road loop back onto itself.
                if (v.RoadsConnectedTo.Contains(r))
                {
                    continue;
                }

                //Don't create a segment that already exists.
                if (v.VertsConnectedTo.Contains(lastPoint))
                {
                    return(VertexFindResults.Reject());
                }

                v.ConnectTo(lastPoint);

                return(VertexFindResults.Accept(v, true));
            }


            Rect segBnds = new Rect().BoundByPoints(nextPos, lastPoint.Pos);

            //If the segment intersects another segment, turn it into an intersection and continue.
            List <Segment> segs = Segments.GetAllNearbyBnds(segBnds).ToList();
            float          t1   = float.NaN,
                           t2   = float.NaN;
            Segment?hitSeg      = null;

            //Get any intersected segments.
            //If we intersect with a previous part of this road, reject.
            for (int i = 0; i < segs.Count; ++i)
            {
                float temp1     = float.NaN,
                      temp2     = float.NaN;
                bool intersects = GeneratorUtils.SegmentsIntersect(lastPoint.Pos, nextPos,
                                                                   segs[i].P1.Pos, segs[i].P2.Pos,
                                                                   ref temp1, ref temp2);
                if (segs[i].Owner == r ||
                    segs[i].P1.RoadsConnectedTo.Contains(r) ||
                    segs[i].P2.RoadsConnectedTo.Contains(r))
                {
                    if (intersects)
                    {
                        return(VertexFindResults.Reject());
                    }
                }
                else if (intersects)
                {
                    t1     = temp1;
                    t2     = temp2;
                    hitSeg = segs[i];
                }
            }
            if (hitSeg.HasValue)
            {
                //Split up the road that the segment is a part of
                //    by adding a new vertex at the intersection.
                Vertex vtx = new Vertex(hitSeg.Value.P1.Pos +
                                        ((hitSeg.Value.P2.Pos - hitSeg.Value.P1.Pos) * t2));
                vtx.ConnectTo(lastPoint);
                Vertices.Add(vtx);
                SplitSegment(vtx, hitSeg.Value);

                return(VertexFindResults.Accept(vtx, false));
            }


            //This segment isn't special in any way.
            Vertex vert = new Vertex(nextPos);

            vert.ConnectTo(lastPoint);
            Vertices.Add(vert);
            return(VertexFindResults.Accept(vert, false));
        }