Ejemplo n.º 1
0
        /// <summary>
        /// Sets a vertex id for the given vertex.
        /// </summary>
        public void Set(long id, uint vertex)
        {
            var idx = TryGetIndex(id);

            _data.EnsureMinimumSize((idx * 2) + 2, int.MaxValue);
            _data[(idx * 2) + 0] = unchecked ((int)vertex);
            _data[(idx * 2) + 1] = int.MinValue;
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Switched two edges.
        /// </summary>
        private void SwitchEdge(uint oldId, uint newId)
        {
            var oldEdgePointer = oldId * _edgeDataSize;
            var newEdgePointer = newId * _edgeDataSize;

            _edgeData.EnsureMinimumSize(newEdgePointer + _edgeDataSize + 1);
            for (var i = 0; i < _edgeDataSize; i++)
            {
                _edgeData[newEdgePointer + i] = _edgeData[oldEdgePointer + i];
            }
        }
Ejemplo n.º 3
0
        /// <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;
            }

            _restrictions.EnsureMinimumSize(_nextRestrictionPointer + (uint)restriction.Length + 1);

            // 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++;
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Gets or sets the label.
        /// </summary>
        /// <param name="id">The label.</param>
        public uint this[uint id]
        {
            get
            {
                if (id >= _labels.Length)
                {
                    return(NotSet);
                }

                return(_labels[id]);
            }
            internal set
            {
                if (id >= _labels.Length)
                {
                    var l = _labels.Length;
                    _labels.EnsureMinimumSize(id + 1);
                    for (var i = l; i < _labels.Length; i++)
                    {
                        _labels[i] = NotSet;
                    }
                }

                if (id > _count)
                {
                    _count = id;
                }

                _labels[id] = value;
            }
        }
Ejemplo n.º 5
0
        /// <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.
                _index.EnsureMinimumSize(_nextId + 1);
                _index[_nextId] = id;
                id = _nextId;
                _nextId++;
            }
            if (_collectionReverseIndex != null)
            {
                _collectionReverseIndex.Add(collection, id);
            }
            return(id + 2);
        }
Ejemplo n.º 6
0
        /// <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;
            }

            GetPointerAndSize(id, out var pointer, out var size);
            if (pointer < 0 || shape.Count < size)
            { // add the coordinates at the end.
                SetPointerAndSize(id, _nextPointer, shape.Count);

                // increase the size of the coordinates if needed.
                _coordinates.EnsureMinimumSize(_nextPointer + (2 * shape.Count));
                _elevation?.EnsureMinimumSize((_nextPointer / 2) + shape.Count);

                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;

                    if (coordinate.Elevation.HasValue)
                    {
                        if (_elevation == null)
                        {
                            _elevation = _createElevation(_coordinates.Length / 2);
                        }
                        _elevation[_nextPointer / 2 + i] = coordinate.Elevation.Value;
                    }
                }
                _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;

                    if (coordinate.Elevation.HasValue)
                    {
                        if (_elevation == null)
                        {
                            _elevation = _createElevation(_coordinates.Length / 2);
                        }
                        _elevation[_nextPointer / 2 + i] = coordinate.Elevation.Value;
                    }
                }
            }
        }
Ejemplo n.º 7
0
        /// <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;
                _index.EnsureMinimumSize(_nextIndexPointer + 2);
                _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;
                    _index.EnsureMinimumSize(_nextIndexPointer + newSpace + 2);
                    _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;
            }
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Adds the given vertex.
        /// </summary>
        public void AddVertex(uint vertex, float latitude, float longitude)
        {
            _graph.AddVertex(vertex);

            // increase coordinates length, if needed.
            _coordinates.EnsureMinimumSize(vertex * 2 + 2, NO_COORDINATE);
            _coordinates[vertex * 2]     = latitude;
            _coordinates[vertex * 2 + 1] = longitude;
        }
Ejemplo n.º 9
0
        /// <summary>
        /// Adds a stop with associated meta-data.
        /// </summary>
        public void AddStop(uint vertex, IAttributeCollection meta)
        {
            var stopsMetaId = _stopsMeta.Add(meta);

            _stops.EnsureMinimumSize(_stopsPointer + 2);
            _stops[_stopsPointer + 0] = vertex;
            _stops[_stopsPointer + 1] = stopsMetaId;

            _stopsPointer += 2;
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Adds a node id to the index.
        /// </summary>
        public void AddId(long id)
        {
            int int1, int2;

            long2doubleInt(id, out int1, out int2);

            _index.EnsureMinimumSize(_idx + 2);
            _index[_idx + 0] = int1;
            _index[_idx + 1] = int2;
            _idx            += 2;
        }
Ejemplo n.º 11
0
        /// <summary>
        /// Adds a new vertex.
        /// </summary>
        public void AddVertex(uint vertex)
        {
            if (_maxVertex == null || _maxVertex.Value < vertex)
            { // update max vertex.
                _maxVertex = vertex;
            }

            // increase space if needed.
            _vertices.EnsureMinimumSize(vertex + 1, Constants.NO_VERTEX);
            if (_vertices[vertex] == Constants.NO_VERTEX)
            { // only overwrite if this vertex is not there yet.
                _vertices[vertex] = Constants.NO_EDGE;
            }
        }
Ejemplo n.º 12
0
        /// <summary>
        /// Adds a new edge.
        /// </summary>
        /// <returns></returns>
        public uint AddEdge(uint vertex1, uint vertex2, EdgeData data, ShapeBase shape)
        {
            if (data.Distance > _maxEdgeDistance)
            {
                throw new ArgumentException("data.Distance too big for this network.");
            }

            var edgeId = _graph.AddEdge(vertex1, vertex2,
                                        Data.Edges.EdgeDataSerializer.Serialize(
                                            data.Distance, data.Profile), shape);

            _edgeData.EnsureMinimumSize(edgeId + 1);
            _edgeData[edgeId] = data.MetaId;
            return(edgeId);
        }
Ejemplo n.º 13
0
        /// <summary>
        /// Adds a new shortcut.
        /// </summary>
        public uint Add(uint[] vertices, IAttributeCollection meta)
        {
            var shortcutMetaId = _shortcutsMeta.Add(meta);
            var size           = (uint)vertices.Length + 2;

            _shortcuts.EnsureMinimumSize(_shortcutsPointer + 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);
        }
Ejemplo n.º 14
0
        /// <summary>
        /// Adds the given vertex.
        /// </summary>
        public void AddVertex(uint vertex, float latitude, float longitude,
                              short?elevation = null)
        {
            _graph.AddVertex(vertex);

            // increase coordinates length, if needed.
            _coordinates.EnsureMinimumSize(vertex * 2 + 2, NO_COORDINATE);
            _coordinates[vertex * 2]     = latitude;
            _coordinates[vertex * 2 + 1] = longitude;

            if (elevation != null)
            {
                if (_elevation == null)
                {
                    _elevation = _createElevation(_coordinates.Length / 2);
                    for (var i = 0; i < _elevation.Length; i++)
                    {
                        _elevation[i] = NO_ELEVATION;
                    }
                }
                _elevation[vertex] = elevation.Value;
            }
        }
Ejemplo n.º 15
0
        /// <summary>
        /// Adds a new entry in this index.
        /// </summary>
        public void Add(long id, int mask)
        {
            if (mask > MAX_MASK)
            {
                throw new ArgumentOutOfRangeException(nameof(mask));
            }

            if (_pointer > 0)
            {
                Decode(_data[_pointer - 1], out var previousId, out _);

                if (id < previousId)
                {
                    throw new ArgumentException("Id is smaller than the previous one, id's should be added in ascending order.");
                }
            }

            _data.EnsureMinimumSize(_pointer + 1);
            Encode(id, mask, out var data);
            _data[_pointer] = data;
            _pointer++;

            this.IsDirty = true;
        }
Ejemplo n.º 16
0
        /// <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);
        }
Ejemplo n.º 17
0
        /// <summary>
        /// Adds an edge with the associated data.
        /// </summary>
        public uint AddEdge(uint vertex1, uint vertex2, params uint[] data)
        {
            if (vertex1 == vertex2)
            {
                throw new ArgumentException("Given vertices must be different.");
            }
            if (vertex1 > _vertices.Length - 1)
            {
                throw new ArgumentException(string.Format("Vertex {0} does not exist.", vertex1));
            }
            if (vertex2 > _vertices.Length - 1)
            {
                throw new ArgumentException(string.Format("Vertex {0} does not exist.", vertex2));
            }
            if (_vertices[vertex1] == Constants.NO_VERTEX)
            {
                throw new ArgumentException(string.Format("Vertex {0} does not exist.", vertex1));
            }
            if (_vertices[vertex2] == Constants.NO_VERTEX)
            {
                throw new ArgumentException(string.Format("Vertex {0} does not exist.", vertex2));
            }
            if (data.Length != _edgeDataSize)
            {
                throw new ArgumentException("Data block has incorrect size, needs to match exactly edge data size.");
            }

            var edgeId = _vertices[vertex1];

            if (_vertices[vertex1] != Constants.NO_EDGE)
            { // check for an existing edge first.
                // check if the arc exists already.
                edgeId = _vertices[vertex1];
                uint nextEdgeSlot = 0;
                while (edgeId != Constants.NO_EDGE)
                { // keep looping.
                    uint otherVertexId  = 0;
                    uint previousEdgeId = edgeId;
                    //bool forward = true;
                    if (_edges[edgeId + NODEA] == vertex1)
                    {
                        otherVertexId = _edges[edgeId + NODEB];
                        nextEdgeSlot  = edgeId + NEXTNODEA;
                        edgeId        = _edges[edgeId + NEXTNODEA];
                    }
                    else
                    {
                        otherVertexId = _edges[edgeId + NODEA];
                        nextEdgeSlot  = edgeId + NEXTNODEB;
                        edgeId        = _edges[edgeId + NEXTNODEB];
                    }
                    //if (otherVertexId == vertex2)
                    //{ // this is the edge we need.
                    //    if(!forward)
                    //    { // switch things around.
                    //        var temp = _edges[previousEdgeId + NODEA];
                    //        _edges[previousEdgeId + NODEA] = _edges[previousEdgeId + NODEB];
                    //        _edges[previousEdgeId + NODEB] = temp;
                    //        temp = _edges[previousEdgeId + NEXTNODEA];
                    //        _edges[previousEdgeId + NEXTNODEA] = _edges[previousEdgeId + NEXTNODEB];
                    //        _edges[previousEdgeId + NEXTNODEB] = temp;
                    //    }

                    //    // overwrite data.
                    //    for (var i = 0; i < _edgeDataSize; i++)
                    //    {
                    //        _edges[previousEdgeId + MINIMUM_EDGE_SIZE + i] =
                    //            data[i];
                    //    }
                    //    return (uint)(previousEdgeId / _edgeSize);
                    //}
                }

                // create a new edge.
                edgeId = _nextEdgeId;

                // there may be a need to increase edges array.
                _edges.EnsureMinimumSize(_nextEdgeId + NEXTNODEB + 1, Constants.NO_EDGE);
                _edges[_nextEdgeId + NODEA]     = vertex1;
                _edges[_nextEdgeId + NODEB]     = vertex2;
                _edges[_nextEdgeId + NEXTNODEA] = Constants.NO_EDGE;
                _edges[_nextEdgeId + NEXTNODEB] = Constants.NO_EDGE;
                _nextEdgeId = (uint)(_nextEdgeId + _edgeSize);

                // append the new edge to the from list.
                _edges[nextEdgeSlot] = edgeId;

                // set data.
                for (var i = 0; i < _edgeDataSize; i++)
                {
                    _edges[edgeId + MINIMUM_EDGE_SIZE + i] =
                        data[i];
                }
                _edgeCount++;
            }
            else
            { // create a new edge and set.
                edgeId             = _nextEdgeId;
                _vertices[vertex1] = _nextEdgeId;

                // there may be a need to increase edges array.
                _edges.EnsureMinimumSize(_nextEdgeId + NEXTNODEB + 1, Constants.NO_EDGE);
                _edges[_nextEdgeId + NODEA]     = vertex1;
                _edges[_nextEdgeId + NODEB]     = vertex2;
                _edges[_nextEdgeId + NEXTNODEA] = Constants.NO_EDGE;
                _edges[_nextEdgeId + NEXTNODEB] = Constants.NO_EDGE;
                _nextEdgeId = (uint)(_nextEdgeId + _edgeSize);

                // set data.
                for (var i = 0; i < _edgeDataSize; i++)
                {
                    _edges[edgeId + MINIMUM_EDGE_SIZE + i] =
                        data[i];
                }
                _edgeCount++;
            }

            var toEdgeId = _vertices[vertex2];

            if (toEdgeId != Constants.NO_EDGE)
            { // there are existing edges.
                uint nextEdgeSlot = 0;
                while (toEdgeId != Constants.NO_EDGE)
                { // keep looping.
                    uint otherVertexId = 0;
                    if (_edges[toEdgeId + NODEA] == vertex2)
                    {
                        otherVertexId = _edges[toEdgeId + NODEB];
                        nextEdgeSlot  = toEdgeId + NEXTNODEA;
                        toEdgeId      = _edges[toEdgeId + NEXTNODEA];
                    }
                    else
                    {
                        otherVertexId = _edges[toEdgeId + NODEA];
                        nextEdgeSlot  = toEdgeId + NEXTNODEB;
                        toEdgeId      = _edges[toEdgeId + NEXTNODEB];
                    }
                }
                _edges[nextEdgeSlot] = edgeId;
            }
            else
            { // there are no existing edges point the vertex straight to it's first edge.
                _vertices[vertex2] = edgeId;
            }

            return((uint)(edgeId / _edgeSize));
        }
Ejemplo n.º 18
0
        /// <summary>
        /// Adds an edge with the associated data.
        /// </summary>
        public uint AddEdge(uint vertex1, uint vertex2, uint data)
        {
            if (_readonly)
            {
                throw new Exception("Graph is readonly.");
            }
            if (vertex1 == vertex2)
            {
                throw new ArgumentException("Given vertices must be different.");
            }
            _vertices.EnsureMinimumSize(Math.Max(vertex1, vertex2) * VERTEX_SIZE + EDGE_COUNT + 1);
            if (_edgeDataSize != 1)
            {
                throw new ArgumentOutOfRangeException("Dimension of data doesn't match.");
            }

            if ((_nextEdgePointer / _edgeSize) > uint.MaxValue)
            {
                throw new Exception($"Cannot add another edge, this graph can only handle a max of {uint.MaxValue} edges.");
            }

            var vertexPointer = vertex1 * VERTEX_SIZE;
            var edgeCount     = _vertices[vertexPointer + EDGE_COUNT];
            var edgePointer   = _vertices[vertexPointer + FIRST_EDGE] * _edgeSize;
            var edgeId        = uint.MaxValue;

            if (edgeCount == 0)
            { // no edge yet, just add the end.
                _vertices[vertexPointer + EDGE_COUNT] = 1;
                _vertices[vertexPointer + FIRST_EDGE] = (uint)(_nextEdgePointer / _edgeSize);
                edgeId = (uint)(_nextEdgePointer / _edgeSize);

                // make sure we can add another edge.
                _edges.EnsureMinimumSize(_nextEdgePointer + (1 * _edgeSize) + 1);

                _edges[_nextEdgePointer] = vertex2;
                _edges[_nextEdgePointer + MINIMUM_EDGE_SIZE + 0] = data;
                _nextEdgePointer += _edgeSize;
            }
            else if ((edgeCount & (edgeCount - 1)) == 0)
            { // edgeCount is a power of two, increase space.
                // make sure we can add another edge.
                _edges.EnsureMinimumSize(_nextEdgePointer + (edgeCount * _edgeSize) + 1);

                if (edgePointer == (_nextEdgePointer - (edgeCount * _edgeSize)))
                { // these edge are at the end of the edge-array, don't copy just increase size.
                    _edges[_nextEdgePointer] = vertex2;
                    edgeId = (uint)(_nextEdgePointer / _edgeSize);
                    _edges[_nextEdgePointer + MINIMUM_EDGE_SIZE + 0] = data;
                    _nextEdgePointer += (edgeCount * _edgeSize); // duplicate space for this vertex.
                    _vertices[vertexPointer + EDGE_COUNT] = edgeCount + 1;
                }
                else
                { // not at the end, copy edges to the end.
                    _vertices[vertexPointer + FIRST_EDGE] = (uint)(_nextEdgePointer / _edgeSize);
                    _vertices[vertexPointer + EDGE_COUNT] = edgeCount + 1;

                    // keep new pointer & duplicate space for this vertex.
                    var newNextEdgePointer = _nextEdgePointer + (edgeCount * 2 * _edgeSize);

                    // make sure we can add another edge.
                    _edges.EnsureMinimumSize(_nextEdgePointer + (edgeCount * _edgeSize) + 1);

                    for (var edge = 0; edge < edgeCount; edge++)
                    {
                        _edges[_nextEdgePointer] = _edges[edgePointer + (edge * _edgeSize)];
                        for (uint i = 0; i < _edgeDataSize; i++)
                        {
                            _edges[_nextEdgePointer + MINIMUM_EDGE_SIZE + i] =
                                _edges[edgePointer + MINIMUM_EDGE_SIZE + i + (edge * _edgeSize)];
                        }
                        if (_switchEdge != null)
                        { // report on the edge switch.
                            _switchEdge((uint)((edgePointer + (edge * _edgeSize)) / (long)_edgeSize),
                                        (uint)(_nextEdgePointer / _edgeSize));
                        }
                        _nextEdgePointer += _edgeSize;

                        // make sure we can add another edge.
                        _edges.EnsureMinimumSize(_nextEdgePointer + 1);
                    }

                    // make sure we can add another edge.
                    _edges.EnsureMinimumSize(_nextEdgePointer + (edgeCount * _edgeSize) + 1);

                    // add at the end.
                    _edges[_nextEdgePointer] = vertex2;
                    edgeId = (uint)(_nextEdgePointer / _edgeSize);
                    _edges[_nextEdgePointer + MINIMUM_EDGE_SIZE + 0] = data;
                    _nextEdgePointer = newNextEdgePointer;
                }
            }
            else
            { // just add the edge.
                _edges[edgePointer + (edgeCount * _edgeSize)] = vertex2;
                edgeId = (uint)((edgePointer + (edgeCount * _edgeSize)) / _edgeSize);
                _edges[edgePointer + (edgeCount * _edgeSize) + MINIMUM_EDGE_SIZE + 0] = data;

                _vertices[vertexPointer + EDGE_COUNT] = edgeCount + 1;
            }
            _edgeCount++;

            return(edgeId);
        }
Ejemplo n.º 19
0
        /// <summary>
        /// Adds an edge with the associated data.
        /// </summary>
        public uint AddEdge(uint vertex1, uint vertex2, uint data)
        {
            if (_readonly)
            {
                throw new Exception("Graph is readonly.");
            }
            if (vertex1 == vertex2)
            {
                throw new ArgumentException("Given vertices must be different.");
            }
            if (data > MAX_DYNAMIC_PAYLOAD)
            {
                throw new ArgumentOutOfRangeException("data", "Data payload too big.");
            }
            _vertices.EnsureMinimumSize(Math.Max(vertex1, vertex2) + 1, NO_EDGE);

            var vertexPointer = vertex1;
            var edgePointer   = _vertices[vertexPointer];
            var edgeId        = uint.MaxValue;

            if (edgePointer == NO_EDGE)
            { // no edge yet, just add the end.
                _vertices[vertexPointer] = _nextEdgePointer;
                edgeId = _nextEdgePointer;

                // make sure we can add another edge.
                _edges.EnsureMinimumSize(_nextEdgePointer + 2);
                _edges[_nextEdgePointer]     = vertex2;
                _edges[_nextEdgePointer + 1] = DirectedDynamicGraph.AddLastEdgeAndLastFieldFlag(data);
                _nextEdgePointer            += 2;
            }
            else
            { // there are already edges present for this vertex.
                var startPointer = edgePointer;
                edgePointer += (uint)(_fixedEdgeDataSize - 1);
                while (true)
                {
                    var e = _edges[edgePointer];
                    if (e != NO_EDGE && IsLastFieldInLastEdge(e))
                    {
                        break;
                    }
                    edgePointer++;
                }

                // check size and allocate new space or move if needed.
                var size          = edgePointer - startPointer + 1;
                var totalSpace    = NextPowerOfTwoOrPowerOfTwo(size);
                var requiredSpace = size + 2;
                if (requiredSpace > totalSpace)
                { // allocate enough space.
                    var newTotalSpace = NextPowerOfTwoOrPowerOfTwo(requiredSpace);
                    if (startPointer + totalSpace == _nextEdgePointer)
                    { // at the end, just make sure the edges array is big enough.
                        _edges.EnsureMinimumSize(newTotalSpace + startPointer + 1);
                        _nextEdgePointer += (newTotalSpace - totalSpace);
                    }
                    else
                    { // move everything to the end, there isn't enough free space here.
                        // make sure the edges array is big enough.
                        _edges.EnsureMinimumSize(newTotalSpace + _nextEdgePointer + 1);

                        // move existing data to the end and update pointer.
                        _vertices[vertexPointer] = _nextEdgePointer;
                        for (uint i = 0; i < size; i++)
                        {
                            _edges[_nextEdgePointer + i] = _edges[startPointer + i];
                        }
                        edgePointer       = _nextEdgePointer + size - 1;
                        _nextEdgePointer += newTotalSpace;
                    }
                }

                // mark the current field as the non-last field.
                _edges[edgePointer] = RemoveLastEdgeFlag(_edges[edgePointer]);

                // add new data.
                edgeId = edgePointer + 1;
                _edges[edgePointer + 1] = vertex2;
                _edges[edgePointer + 2] = DirectedDynamicGraph.AddLastEdgeAndLastFieldFlag(data);
            }
            _edgeCount++;

            return(edgeId);
        }