Beispiel #1
0
        public void TestAddWithElevation()
        {
            using (var map = new MemoryMapStream())
            {
                var array = new ShapesArray(map, 1024);
                array.Set(0, new Coordinate(0, 0.1f, 10),
                          new Coordinate(1, 1.1f, 11));

                var shape = array[0];
                Assert.IsNotNull(shape);
                Assert.AreEqual(2, shape.Count);
                Assert.AreEqual(0, shape[0].Latitude, .00001);
                Assert.AreEqual(0.1, shape[0].Longitude, .00001);
                Assert.AreEqual(10, shape[0].Elevation);
                Assert.AreEqual(1, shape[1].Latitude, .00001);
                Assert.AreEqual(1.1, shape[1].Longitude, .00001);
                Assert.AreEqual(11, shape[1].Elevation);
            }

            using (var map = new MemoryMapStream())
            {
                var box = new Box(
                    new Coordinate(-90, -180),
                    new Coordinate(90, 180));
                var refArray = new ShapeBase[1024];
                var array    = new ShapesArray(map, 1024);

                var rand = new Randomizer(1587341311);
                for (var i = 0; i < 1024; i++)
                {
                    var count    = rand.Next(10);
                    var newShape = new List <Coordinate>(count);
                    for (var j = 0; j < count; j++)
                    {
                        newShape.Add(box.GenerateRandomIn());
                    }

                    var shape = new ShapeEnumerable(newShape);
                    refArray[i] = shape;
                    array[i]    = shape;
                }

                for (var i = 0; i < refArray.Length; i++)
                {
                    var refShape = refArray[i];
                    var shape    = array[i];
                    Assert.IsNotNull(shape);

                    for (var j = 0; j < shape.Count; j++)
                    {
                        Assert.AreEqual(refShape[j].Latitude, shape[j].Latitude);
                        Assert.AreEqual(refShape[j].Longitude, shape[j].Longitude);
                        Assert.AreEqual(refShape[j].Elevation, shape[j].Elevation);
                    }
                }
            }
        }
Beispiel #2
0
        public void TestCopyToCreateFrom()
        {
            var box = new Box(
                new Coordinate(-90, -180),
                new Coordinate(90, 180));
            var refArray = new ShapesArray(1024);

            var rand = new System.Random(46541577);
            var totalCoordinateCount = 0;

            for (var i = 0; i < 1024; i++)
            {
                var count = rand.Next(10);
                totalCoordinateCount += count;
                var newShape = new List <Coordinate>(count);
                for (var j = 0; j < count; j++)
                {
                    newShape.Add(box.GenerateRandomIn());
                }

                var shape = new ShapeEnumerable(newShape);
                refArray[i] = shape;
            }

            using (var stream = new MemoryStream())
            {
                Assert.AreEqual(16 + (1024 * 8) + (totalCoordinateCount * 8),
                                refArray.CopyTo(stream));
                stream.Seek(0, SeekOrigin.Begin);

                var array = ShapesArray.CreateFrom(stream, true);
                for (var i = 0; i < refArray.Length; i++)
                {
                    var refShape = refArray[i];
                    if (refShape.Count == 0)
                    {
                        continue;
                    }
                    var shape = array[i];
                    Assert.IsNotNull(shape);

                    for (var j = 0; j < shape.Count; j++)
                    {
                        Assert.AreEqual(refShape[j].Latitude, shape[j].Latitude);
                        Assert.AreEqual(refShape[j].Longitude, shape[j].Longitude);
                    }
                }

                stream.Seek(0, SeekOrigin.Begin);
                array = ShapesArray.CreateFrom(stream, false);
                for (var i = 0; i < refArray.Length; i++)
                {
                    var refShape = refArray[i];
                    if (refShape.Count == 0)
                    {
                        continue;
                    }
                    var shape = array[i];
                    Assert.IsNotNull(shape);

                    for (var j = 0; j < shape.Count; j++)
                    {
                        Assert.AreEqual(refShape[j].Latitude, shape[j].Latitude);
                        Assert.AreEqual(refShape[j].Longitude, shape[j].Longitude);
                    }
                }
            }
        }
Beispiel #3
0
        /// <summary>
        /// Returns the part of the edge between the two offsets not including the vertices at the start or the end.
        /// </summary>
        /// <param name="enumerator">The enumerator.</param>
        /// <param name="offset1">The start offset.</param>
        /// <param name="offset2">The end offset.</param>
        /// <param name="includeVertices">Include vertices in case the range start at min offset or ends at max.</param>
        /// <returns>The shape points between the given offsets. Includes the vertices by default when offsets at min/max.</returns>
        public static IEnumerable <Coordinate> GetShapeBetween(this RouterDbEdgeEnumerator enumerator,
                                                               ushort offset1 = 0, ushort offset2 = ushort.MaxValue, bool includeVertices = true)
        {
            if (offset1 > offset2)
            {
                throw new ArgumentException($"{nameof(offset1)} has to smaller than or equal to {nameof(offset2)}");
            }

            // get edge and shape details.
            var shape = enumerator.GetShape();

            if (shape == null)
            {
                shape = new ShapeEnumerable(Enumerable.Empty <Coordinate>());
            }

            // return the entire edge if requested.
            if (offset1 == 0 && offset2 == ushort.MaxValue)
            {
                foreach (var s in enumerator.GetCompleteShape())
                {
                    yield return(s);
                }
                yield break;
            }

            // calculate offsets in meters.
            var edgeLength    = enumerator.EdgeLength();
            var offset1Length = (offset1 / (double)ushort.MaxValue) * edgeLength;
            var offset2Length = (offset2 / (double)ushort.MaxValue) * edgeLength;

            // TODO: can we make this easier with the complete shape enumeration?
            // calculate coordinate shape.
            var before   = offset1 > 0; // when there is a start offset.
            var length   = 0.0;
            var previous = enumerator.FromLocation();

            if (offset1 == 0 && includeVertices)
            {
                yield return(previous);
            }
            for (var i = 0; i < shape.Count + 1; i++)
            {
                Coordinate next;
                if (i < shape.Count)
                { // the
                    next = shape[i];
                }
                else
                { // the last location.
                    next = enumerator.ToLocation();
                }

                var segmentLength = Coordinate.DistanceEstimateInMeter(previous, next);
                if (before)
                { // check if offset1 length has exceeded.
                    if (segmentLength + length >= offset1Length &&
                        offset1 > 0)
                    { // we are before, but not we have move to after.
                        var segmentOffset = offset1Length - length;
                        var location      = Coordinate.PositionAlongLine(previous, next, (segmentOffset / segmentLength));
                        previous = next;
                        before   = false;
                        yield return(location);
                    }
                }

                if (!before)
                { // check if offset2 length has exceeded.
                    if (segmentLength + length > offset2Length &&
                        offset2 < ushort.MaxValue)
                    { // we are after but now we are after.
                        var segmentOffset = offset2Length - length;
                        var location      = Coordinate.PositionAlongLine(previous, next, (segmentOffset / segmentLength));
                        yield return(location);

                        yield break;
                    }

                    // the case where include vertices is false.
                    if (i == shape.Count && !includeVertices)
                    {
                        yield break;
                    }
                    yield return(next);
                }

                // move to the next segment.
                previous = next;
                length  += segmentLength;
            }
        }
        /// <summary>
        /// Adds a new edge and it's inline data.
        /// </summary>
        /// <param name="vertex1">The first vertex.</param>
        /// <param name="vertex2">The second vertex.</param>
        /// <param name="data">The inline data.</param>
        /// <param name="shape">The edge shape.</param>
        /// <returns>The edge id.</returns>
        public uint AddEdge(VertexId vertex1, VertexId vertex2, IReadOnlyList <byte> data = null,
                            IEnumerable <Coordinate> shape = null)
        {
            // try to find vertex1.
            var(vertex1Pointer, capacity1) = FindTile(vertex1.TileId);
            if (vertex1Pointer == GraphConstants.TileNotLoaded ||
                vertex1.LocalId >= capacity1)
            {
                throw new ArgumentException($"{vertex1} does not exist.");
            }

            // try to find vertex2.
            var(vertex2Pointer, capacity2) = FindTile(vertex2.TileId);
            if (vertex2Pointer == GraphConstants.TileNotLoaded ||
                vertex2.LocalId >= capacity2)
            {
                throw new ArgumentException($"{vertex2} does not exist.");
            }

            // get edge pointers.
            var edgePointer1 = _edgePointers[vertex1Pointer + vertex1.LocalId];
            var edgePointer2 = _edgePointers[vertex2Pointer + vertex2.LocalId];

            // make sure there is enough space.
            var rawPointer = (_edgePointer * _edgeSize);

            if (rawPointer + _edgeSize > _edges.Length)
            {
                _edges.EnsureMinimumSize(rawPointer + _edgeSize);
            }

            // add edge pointers with new edge.
            rawPointer += WriteToEdges(rawPointer, vertex1);
            rawPointer += WriteToEdges(rawPointer, vertex2);
            // write pointer to previous edge.
            if (edgePointer1 == GraphConstants.NoEdges)
            { // if there is no previous edge, write 0
                rawPointer += WriteToEdges(rawPointer, 0);
            }
            else
            { // write pointer but offset by 1.
                rawPointer += WriteToEdges(rawPointer, edgePointer1 + 1);
            }
            // write pointer to previous edge.
            if (edgePointer2 == GraphConstants.NoEdges)
            { // if there is no previous edge, write 0
                rawPointer += WriteToEdges(rawPointer, 0);
            }
            else
            { // write pointer but offset by 1.
                rawPointer += WriteToEdges(rawPointer, edgePointer2 + 1);
            }
            rawPointer += WriteToEdges(rawPointer, data); // write data package.

            // update edge pointers.
            var newEdgePointer = _edgePointer;

            _edgePointers[vertex1Pointer + vertex1.LocalId] = newEdgePointer;
            _edgePointers[vertex2Pointer + vertex2.LocalId] = newEdgePointer;
            _edgePointer += 1;

            // add shape if any.
            if (shape != null)
            {
                if (_shapes.Length <= newEdgePointer)
                { // TODO: this resizing should be in the shapes array.
                    _shapes.Resize(newEdgePointer + 1024);
                }
                _shapes[newEdgePointer] = new ShapeEnumerable(shape);
            }

            return(newEdgePointer);
        }
Beispiel #5
0
        /// <summary>
        /// Gets a trip, all it's connections, stops and shape points.
        /// </summary>
        public static FeatureCollection GetTripFeatures(this TransitDb transitDb, uint tripId)
        {
            var tripEnumerator = transitDb.GetTripsEnumerator();

            if (!tripEnumerator.MoveTo(tripId))
            {
                return(new FeatureCollection());
            }

            var features = new FeatureCollection();

            var stopsEnumerator      = transitDb.GetStopsEnumerator();
            var stops                = new HashSet <uint>();
            var connectionEnumerator = transitDb.GetConnectionsEnumerator(DefaultSorting.DepartureTime);

            while (connectionEnumerator.MoveNext())
            {
                if (connectionEnumerator.TripId == tripId)
                {
                    var shape = transitDb.ShapesDb.Get(connectionEnumerator.DepartureStop, connectionEnumerator.ArrivalStop);
                    if (shape == null || shape.Count == 0)
                    {
                        stopsEnumerator.MoveTo(connectionEnumerator.DepartureStop);
                        var stop1 = new Coordinate(stopsEnumerator.Latitude, stopsEnumerator.Longitude);
                        stopsEnumerator.MoveTo(connectionEnumerator.ArrivalStop);
                        var stop2 = new Coordinate(stopsEnumerator.Latitude, stopsEnumerator.Longitude);
                        shape = new ShapeEnumerable(new Coordinate[]
                        {
                            stop1,
                            stop2
                        });
                    }

                    if (!stops.Contains(connectionEnumerator.DepartureStop))
                    {
                        stopsEnumerator.MoveTo(connectionEnumerator.DepartureStop);
                        var meta = transitDb.GetStopMeta(connectionEnumerator.DepartureStop).ToAttributesTable();
                        meta.AddAttribute("internal_id", connectionEnumerator.DepartureStop);
                        features.Add(new Feature(new Point(new GeoAPI.Geometries.Coordinate(stopsEnumerator.Longitude, stopsEnumerator.Latitude)),
                                                 meta));
                        stops.Add(connectionEnumerator.DepartureStop);
                    }
                    if (!stops.Contains(connectionEnumerator.ArrivalStop))
                    {
                        stopsEnumerator.MoveTo(connectionEnumerator.ArrivalStop);
                        var meta = transitDb.GetStopMeta(connectionEnumerator.ArrivalStop).ToAttributesTable();
                        meta.AddAttribute("internal_id", connectionEnumerator.ArrivalStop);
                        features.Add(new Feature(new Point(new GeoAPI.Geometries.Coordinate(stopsEnumerator.Longitude, stopsEnumerator.Latitude)),
                                                 meta));
                        stops.Add(connectionEnumerator.ArrivalStop);
                    }

                    var tripMeta = transitDb.TripAttributes.Get(tripEnumerator.MetaId).ToAttributesTable();

                    tripMeta.AddAttribute("internal_stop1", connectionEnumerator.DepartureStop);
                    tripMeta.AddAttribute("internal_stop2", connectionEnumerator.ArrivalStop);

                    features.Add(new Feature(new LineString(shape.ToArray().ToCoordinatesArray()), tripMeta));
                }
            }

            return(features);
        }