/// <summary> /// Relocates data internally in the most compact way possible. /// </summary> public void Compress(bool toReadonly) { long maxEdgeId; _graph.Compress(toReadonly, out maxEdgeId); _edgeData.Resize(maxEdgeId * _edgeDataSize); }
/// <summary> /// Adds a new restriction. /// </summary> public void Add(params uint[] restriction) { if (restriction == null) { throw new ArgumentNullException("restriction"); } if (restriction.Length == 0) { throw new ArgumentException("Restriction should contain one or more vertices.", "restriction"); } if (restriction.Length > 1) { _hasComplexRestrictions = true; } while (_nextRestrictionPointer + (uint)restriction.Length + 1 >= _restrictions.Length) { _restrictions.Resize(_restrictions.Length + BLOCKSIZE); } // add the data. _restrictions[_nextRestrictionPointer] = (uint)restriction.Length; for (var i = 0; i < restriction.Length; i++) { _restrictions[_nextRestrictionPointer + i + 1] = restriction[i]; } // add by pointer. this.AddByPointer(_nextRestrictionPointer); _nextRestrictionPointer = _nextRestrictionPointer + 1 + (uint)restriction.Length; _count++; }
/// <summary> /// Adds a new collection, it's assumed to be sorted. /// </summary> private uint AddCollection(int[] collection) { uint id; if (_collectionReverseIndex != null) { // check duplicates. if (_collectionReverseIndex.TryGetValue(collection, out id)) { // collection already exists. return(id + 2); } } id = (uint)_collectionIndex.Add(collection); if (_index != null) { // use next id. if (_nextId >= _index.Length) { _index.Resize(_index.Length + 1024); } _index[_nextId] = id; id = _nextId; _nextId++; } if (_collectionReverseIndex != null) { _collectionReverseIndex.Add(collection, id); } return(id + 2); }
/// <summary> /// Relocates data internally in the most compact way possible. /// </summary> public void Compress() { _graph.Compress((originalId, newId) => { _edgeData[newId] = _edgeData[originalId]; }); _edgeData.Resize(_graph.EdgeCount); }
/// <summary> /// Increase edge data size to fit at least the given edge. /// </summary> private void IncreaseSizeEdgeData(uint edgeId) { var size = _edgeData.Length; while (edgeId >= size) { size += BLOCK_SIZE; } _edgeData.Resize(size); }
/// <summary> /// Increases the memory allocation. /// </summary> private void IncreaseEdgeSize(long size) { var oldLength = _edges.Length; _edges.Resize(size); for (long idx = oldLength; idx < size; idx++) { _edges[idx] = Constants.NO_EDGE; } }
/// <summary> /// Relocates data internally in the most compact way possible. /// </summary> /// <param name="updateEdgeId">The edge id's may change. This action can be used to hook into every change.</param> public void Compress(Action <uint, uint> updateEdgeId) { _graph.Compress((originalId, newId) => { updateEdgeId(originalId, newId); _shapes.Switch(originalId, newId); }); _shapes.Resize(_graph.EdgeCount); _coordinates.Resize(_graph.VertexCapacity * 2); }
/// <summary> /// Increases the memory allocation. /// </summary> /// <param name="size"></param> private void SetVertexSize(long size) { if (_readonly) { throw new Exception("Graph is readonly."); } var oldLength = _vertices.Length; _vertices.Resize(size); }
/// <summary> /// Increases the memory allocation. /// </summary> private void IncreaseEdgeSize(long size) { if (_readonly) { throw new Exception("Graph is readonly."); } var oldLength = _edges.Length; _edges.Resize(size); }
/// <summary> /// Adds a pointer for the given vertex. /// </summary> private void AddPointer(uint vertex, uint pointer) { var hash = CalculateHash(vertex); var hashPointer = _hashes[hash]; if (hashPointer == NO_DATA) { // add at the end. _hashes[hash] = _nextIndexPointer; while (_index.Length <= _nextIndexPointer + 1) { _index.Resize(_index.Length + BLOCKSIZE); } _index[_nextIndexPointer] = 1; _index[_nextIndexPointer + 1] = pointer; _nextIndexPointer += 2; } else { // add to the existing structure. var size = _index[hashPointer]; // check if pointer is not already there. for (var i = 0; i < size; i++) { if (_index[hashPointer + i + 1] == pointer) { // pointer is already there. return; } } // add the pointer. if ((size & (size - 1)) == 0) { // a power of two, copy to the end. var newSpace = size * 2; while (_index.Length <= _nextIndexPointer + newSpace + 1) { _index.Resize(_index.Length + BLOCKSIZE); } _index[_nextIndexPointer] = size; for (var i = 0; i < size; i++) { _index[_nextIndexPointer + 1 + i] = _index[hashPointer + 1 + i]; } hashPointer = _nextIndexPointer; _hashes[hash] = hashPointer; _nextIndexPointer += newSpace + 1; } _index[hashPointer + 1 + size] = pointer; size++; _index[hashPointer] = size; } }
/// <summary> /// Adds a stop with associated meta-data. /// </summary> public void AddStop(uint vertex, IAttributeCollection meta) { var stopsMetaId = _stopsMeta.Add(meta); if (_stopsPointer + 2 >= _stops.Length) { _stops.Resize(_stops.Length + 100); } _stops[_stopsPointer + 0] = vertex; _stops[_stopsPointer + 1] = stopsMetaId; _stopsPointer += 2; }
/// <summary> /// Adds a node id to the index. /// </summary> public void AddId(long id) { int int1, int2; long2doubleInt(id, out int1, out int2); if (_idx + 2 >= _index.Length) { _index.Resize(_index.Length + (1024 * 1024)); } _index[_idx + 0] = int1; _index[_idx + 1] = int2; _idx += 2; }
/// <summary> /// Increases the size of the vector-array. /// </summary> private void IncreaseVertexSize(long size) { if (_readonly) { throw new Exception("Graph is readonly."); } var oldLength = _vertices.Length; _vertices.Resize(size); for (var i = oldLength; i < _vertices.Length; i++) { _vertices[i] = NO_EDGE; } }
private uint _nextConnectionId; // holds the maximum connection id. /// <summary> /// Adds a connection. /// </summary> public uint Add(uint stop1, uint stop2, uint tripId, uint departureTime, uint arrivalTime) { if (arrivalTime <= departureTime) { throw new ArgumentException("Departure time must be smaller than arrival time."); } var duration = arrivalTime - departureTime; if (duration > CONNECTION_MAX_DURATION) { throw new ArgumentException(string.Format("A connection with a duration > {0}s cannot be stored.", CONNECTION_MAX_DURATION)); } var id = _nextConnectionId; _nextConnectionId++; var size = _connections.Length; while ((id * CONNECTION_SIZE + CONNECTION_SIZE) > size) { size += CONNECTIONS_BLOCK_SIZE; } if (size != _connections.Length) { _connections.Resize(size); } _connections[id * CONNECTION_SIZE + 0] = stop1; _connections[id * CONNECTION_SIZE + 1] = stop2; _connections[id * CONNECTION_SIZE + 2] = tripId; _connections[id * CONNECTION_SIZE + 3] = ConnectionsDb.Encode(departureTime, duration); return(id); }
/// <summary> /// Increases the size of the vertex-array. /// </summary> private void IncreaseVertexSize(long min) { var newSize = (long)(System.Math.Floor((double)min / BLOCKSIZE) + 1) * (long)BLOCKSIZE; if (newSize < _vertices.Length) { // no need to increase, already big enough. return; } var oldLength = _vertices.Length; _vertices.Resize(newSize); for (long idx = oldLength; idx < newSize; idx++) { _vertices[idx] = Constants.NO_VERTEX; } }
/// <summary> /// Adds a new schedule. /// </summary> public uint Add() { var id = _nextPointer; _nextPointer++; var size = _data.Length; if (id >= size) { _data.Resize(size + BLOCK_SIZE); } _data[id] = 0; return(id); }
/// <summary> /// Relocates data internally in the most compact way possible. /// </summary> /// <param name="updateEdgeId">The edge id's may change. This action can be used to hook into every change.</param> public void Compress(Action <uint, uint> updateEdgeId) { _graph.Compress((originalId, newId) => { updateEdgeId(originalId, newId); _shapes.Switch(originalId, newId); }); _shapes.Resize(_graph.EdgeCount); if (_coordinates.Length > _graph.VertexCapacity * 2) { _coordinates.Resize(_graph.VertexCapacity * 2); } if (_elevation != null && _elevation.Length > _graph.VertexCapacity) { _elevation?.Resize(_graph.VertexCapacity); } }
/// <summary> /// Sets a vertex id for the given vertex. /// </summary> public void Set(long id, uint vertex) { var idx = TryGetIndex(id); if ((idx * 2) + 1 >= _data.Length) { var start = _data.Length; _data.Resize((idx * 2) + 1 + 1024); for (var i = start; i < ((idx * 2) + 1 + 1024); i++) { _data[i] = int.MaxValue; } } _data[(idx * 2) + 0] = unchecked ((int)vertex); _data[(idx * 2) + 1] = int.MinValue; }
/// <summary> /// Resizes this array. /// </summary> public sealed override void Resize(long size) { if (!this.CanResize) { throw new InvalidOperationException("Cannot resize a fixed-sized array."); } _index.Resize(size); }
/// <summary> /// Sets the coordinates for the given id. /// </summary> private void Set(long id, ShapeBase shape) { if (id < 0 || id >= _index.Length) { throw new IndexOutOfRangeException(); } if (shape == null) { // reset. _index[id] = 0; return; } long pointer; int size; GetPointerAndSize(id, out pointer, out size); if (pointer < 0 || shape.Count < size) { // add the coordinates at the end. SetPointerAndSize(id, _nextPointer, shape.Count); while (_nextPointer + (2 * (shape.Count + 1)) >= _coordinates.Length) { // increase the size of the coordinates. _coordinates.Resize(_coordinates.Length + 1024); } for (var i = 0; i < shape.Count; i++) { var coordinate = shape[i]; _coordinates[_nextPointer + (i * 2)] = coordinate.Latitude; _coordinates[_nextPointer + (i * 2) + 1] = coordinate.Longitude; } _nextPointer += (2 * shape.Count); } else { // update coordinates in-place. SetPointerAndSize(id, pointer, shape.Count); for (var i = 0; i < shape.Count; i++) { var coordinate = shape[i]; _coordinates[pointer + (i * 2)] = coordinate.Latitude; _coordinates[pointer + (i * 2) + 1] = coordinate.Longitude; } } }
/// <summary> /// Trims the internal data structures of this graph. /// </summary> public void Trim(out long maxEdgeId) { // remove all vertices without edges at the end. var maxVertexId = uint.MinValue; for (uint i = 0; i < _vertices.Length; i++) { var pointer = _vertices[i]; if (pointer == NO_EDGE) { continue; } while (_edges[pointer] == NO_EDGE) { pointer++; } do { var vertex = _edges[pointer]; if (maxVertexId < vertex) { // also take into account the largest vertex pointing down. maxVertexId = vertex; } pointer = MoveNextEdge(pointer); } while (pointer != NO_EDGE); if (maxVertexId < i) { // also take into account the largest vertex pointing down. maxVertexId = i; } } _vertices.Resize(maxVertexId + 1); // resize edges. var edgesLength = _nextEdgePointer; if (edgesLength == 0) { // keep minimum room for one edge. edgesLength = (uint)_fixedEdgeDataSize; } _edges.Resize(edgesLength); // store the max edge id. maxEdgeId = _edges.Length; }
private (uint vertexPointer, int capacity) IncreaseCapacityForTile(uint localTileId, uint pointer) { // copy current data, we assume current capacity is at max. var tilePointer = (long)localTileId * TileSizeInIndex; // get current capacity and double it. var capacityInBits = _tiles[tilePointer + 4]; _tiles[tilePointer + 4] = (byte)(capacityInBits + 1); var capacity = 1 << capacityInBits; // get the current pointer and update it. var newVertexPointer = _vertexPointer; _vertexPointer += (uint)(capacity * 2); var pointerBytes = BitConverter.GetBytes(newVertexPointer); for (var b = 0; b < 4; b++) { _tiles[tilePointer + b] = pointerBytes[b]; } // make sure edge pointers array and vertex coordinates arrays are the proper sizes. var length = _edgePointers.Length; while (_vertexPointer + capacity >= length) { length += 1024; } if (length != _edgePointers.Length) { var sizeBefore = _edgePointers.Length; _edgePointers.Resize(length); for (var p = sizeBefore; p < _edgePointers.Length; p++) { _edgePointers[p] = GraphConstants.NoVertex; } sizeBefore = _vertices.Length; _vertices.Resize(length * CoordinateSizeInBytes); for (var p = sizeBefore; p < _vertices.Length; p++) { _vertices[p] = byte.MaxValue; } } // copy all the data over. for (uint p = 0; p < capacity; p++) { _edgePointers[newVertexPointer + p] = _edgePointers[pointer + p]; CopyEncodedVertex(pointer + p, newVertexPointer + p); } return(newVertexPointer, capacity * 2); }
/// <summary> /// Pushes a new element. /// </summary> public void Push(T element) { if (_pointer >= _data.Length - 1) { _data.Resize(_data.Length + 1024); } _pointer++; _data[_pointer] = element; }
/// <summary> /// Sorts and converts the index. /// </summary> public void SortAndConvertIndex() { _index.Resize(_idx); Itinero.Logging.Logger.Log("NodeIndex", Logging.TraceEventType.Information, "Sorting node id's..."); QuickSort.Sort((i) => { var int1 = _index[i * 2 + 0]; var int2 = _index[i * 2 + 1]; return(doubleInt2long(int1, int2)); }, (i, j) => { var int1 = _index[i * 2 + 0]; var int2 = _index[i * 2 + 1]; _index[i * 2 + 0] = _index[j * 2 + 0]; _index[i * 2 + 1] = _index[j * 2 + 1]; _index[j * 2 + 0] = int1; _index[j * 2 + 1] = int2; }, 0, (_index.Length / 2) - 1); for (long i = 0; i < _index.Length / 2; i++) { var int1 = _index[i * 2 + 0]; var int2 = _index[i * 2 + 1]; var id = doubleInt2long(int1, int2); if (id == 30976106) { System.Diagnostics.Debug.WriteLine(string.Empty); } if (id >= (long)int.MaxValue * (long)(_overflows.Count + 1)) { // nodes are overflowing again. _overflows.Add(i); } _index[i] = (int)(id - ((long)int.MaxValue * (long)_overflows.Count)); } _index.Resize(_index.Length / 2); _idx = _index.Length; }
/// <summary> /// Resizes the internal data structures to their smallest size possible. /// </summary> public void Trim() { _graph.Trim(); _coordinates.Resize(_graph.VertexCount * 2); if (_elevation != null) { _elevation.Resize(_graph.VertexCount); } _shapes.Resize(_graph.EdgeCount); }
/// <summary> /// Adds the given vertex. /// </summary> public void AddVertex(uint vertex, float latitude, float longitude) { _graph.AddVertex(vertex); if (vertex * 2 + 1 >= _coordinates.Length) { // increase coordinates length. var newBlocks = 1; while (vertex * 2 + 1 >= _coordinates.Length + (newBlocks * BLOCKSIZE * 2)) { // increase more. newBlocks++; } var oldLength = _coordinates.Length; _coordinates.Resize(_coordinates.Length + (newBlocks * BLOCKSIZE * 2)); for (var i = oldLength; i < _coordinates.Length; i++) { _coordinates[i] = NO_COORDINATE; } } _coordinates[vertex * 2] = latitude; _coordinates[vertex * 2 + 1] = longitude; }
/// <summary> /// Resizes the internal array for a future count. /// </summary> private void ResizeFor(int count) { var current = _data.Length; while (count > current) { current += _block; } if (current != _data.Length) { // resize if needed. _data.Resize(current); } }
/// <summary> /// Adds a new shortcut. /// </summary> public uint Add(uint[] vertices, IAttributeCollection meta) { var shortcutMetaId = _shortcutsMeta.Add(meta); while (_shortcutsPointer + vertices.Length + 1 >= _shortcuts.Length) { _shortcuts.Resize(_shortcuts.Length + 100); } var size = (uint)vertices.Length + 2; _shortcuts[_shortcutsPointer + 0] = size; _shortcuts[_shortcutsPointer + 1] = shortcutMetaId; for (uint i = 0; i < vertices.Length; i++) { _shortcuts[_shortcutsPointer + 2 + i] = vertices[i]; } var id = _shortcutsPointer; _shortcutsPointer += size; return(id); }
/// <summary> /// Optimizes this index once it's fully loaded. /// </summary> public void Optimize() { // sort array. Itinero.Algorithms.Sorting.QuickSort.Sort(i => { return(_data[i * 2]); }, (i, j) => { var t1 = _data[i * 2 + 0]; var t2 = _data[i * 2 + 1]; _data[i * 2 + 0] = _data[j * 2 + 0]; _data[i * 2 + 1] = _data[j * 2 + 1]; _data[j * 2 + 0] = t1; _data[j * 2 + 1] = t2; }, 0, (_pointer / 2) - 1); // remove reverse index. _reverseIndex = null; // reduce array size to exact data size. _data.Resize(_pointer); }
/// <summary> /// Trims the internal data structures of this graph. /// </summary> public void Trim(out long maxEdgeId) { // remove all vertices without edges at the end. var maxVertexId = uint.MinValue; for (uint i = 0; i < _vertices.Length / VERTEX_SIZE; i++) { var pointer = _vertices[i * VERTEX_SIZE + FIRST_EDGE] * _edgeSize; var count = _vertices[i * VERTEX_SIZE + EDGE_COUNT]; for (var e = pointer; e < pointer + (count * _edgeSize); e += _edgeSize) { var vertex = _edges[e]; if (maxVertexId < vertex) { maxVertexId = vertex; } } if (count > 0 && maxVertexId < i) { // also take into account the largest vertex pointing down. maxVertexId = i; } } _vertices.Resize((maxVertexId + 1) * VERTEX_SIZE); // resize edges. var edgesLength = _nextEdgePointer; if (edgesLength == 0) { // keep minimum room for one edge. edgesLength = _edgeSize; } _edges.Resize(edgesLength); // store the max edge id. maxEdgeId = _edges.Length / _edgeSize; }