/// <summary> /// Adds and arc to an existing vertex. /// </summary> /// <param name="from"></param> /// <param name="to"></param> /// <param name="data"></param> /// <param name="comparer">Comparator to compare edges and replace obsolete ones.</param> public void AddArc(uint from, uint to, TEdgeData data, IDynamicGraphEdgeComparer <TEdgeData> comparer) { if (_vertices.Length > from) { KeyValuePair <uint, TEdgeData>[] arcs = _vertices[from]; int idx = -1; if (arcs != null) { // check for an existing edge first. if (comparer != null) { // there is no comparer, just skip this check. for (int arcIdx = 0; arcIdx < arcs.Length; arcIdx++) { if (arcs[arcIdx].Key == to && comparer != null && comparer.Overlaps(data, arcs[arcIdx].Value)) { // an arc was found that represents the same directional information. arcs[arcIdx] = new KeyValuePair <uint, TEdgeData>( to, data); return; } } } // if here: there did not exist an edge yet! idx = arcs.Length; Array.Resize <KeyValuePair <uint, TEdgeData> >(ref arcs, arcs.Length + 1); _vertices[from] = arcs; } else { // create an arcs array. arcs = new KeyValuePair <uint, TEdgeData> [1]; idx = 0; _vertices[from] = arcs; } // set the arc. arcs[idx] = new KeyValuePair <uint, TEdgeData>( to, data); return; } throw new ArgumentOutOfRangeException("from"); }
/// <summary> /// Adds an edge with the associated data. /// </summary> /// <param name="vertex1"></param> /// <param name="vertex2"></param> /// <param name="data"></param> /// <param name="coordinates"></param> /// <param name="comparer">Comparator to compare edges and replace obsolete ones.</param> public void AddEdge(uint vertex1, uint vertex2, TEdgeData data, GeoCoordinateSimple[] coordinates, IDynamicGraphEdgeComparer <TEdgeData> comparer) { // if (!data.Forward) { throw new ArgumentOutOfRangeException("data", "Edge data has to be forward."); } if (vertex1 == vertex2) { throw new ArgumentException("Given vertices must be different."); } if (_nextVertexId <= vertex1) { throw new ArgumentOutOfRangeException("vertex1", "vertex1 is not part of this graph."); } if (_nextVertexId <= vertex2) { throw new ArgumentOutOfRangeException("vertex2", "vertex2 is not part of this graph."); } var edgeId = _vertices[vertex1]; if (_vertices[vertex1] != NO_EDGE) { // check for an existing edge first. // check if the arc exists already. edgeId = _vertices[vertex1]; uint nextEdgeSlot = 0; while (edgeId != 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]; forward = false; } if (otherVertexId == vertex2) { // this is the edge we need. if (!forward) { data = (TEdgeData)data.Reverse(); } if (comparer != null) { // there is a comparer. var existingData = _edgeData[previousEdgeId / 4]; if (comparer.Overlaps(data, existingData)) { // an arc was found that represents the same directional information. _edgeData[previousEdgeId / 4] = data; _edgeShapes[previousEdgeId / 4] = coordinates; } return; } _edgeData[previousEdgeId / 4] = data; _edgeShapes[previousEdgeId / 4] = coordinates; return; } } // create a new edge. edgeId = _nextEdgeId; if (_nextEdgeId + NEXTNODEB >= _edges.Length) { // there is a need to increase edges array. this.IncreaseEdgeSize(); } _edges[_nextEdgeId + NODEA] = vertex1; _edges[_nextEdgeId + NODEB] = vertex2; _edges[_nextEdgeId + NEXTNODEA] = NO_EDGE; _edges[_nextEdgeId + NEXTNODEB] = NO_EDGE; _nextEdgeId = _nextEdgeId + EDGE_SIZE; // append the new edge to the from list. _edges[nextEdgeSlot] = edgeId; // set data. _edgeData[edgeId / 4] = data; _edgeShapes[edgeId / 4] = coordinates; } else { // create a new edge and set. edgeId = _nextEdgeId; _vertices[vertex1] = _nextEdgeId; if (_nextEdgeId + NEXTNODEB >= _edges.Length) { // there is a need to increase edges array. this.IncreaseEdgeSize(); } _edges[_nextEdgeId + NODEA] = vertex1; _edges[_nextEdgeId + NODEB] = vertex2; _edges[_nextEdgeId + NEXTNODEA] = NO_EDGE; _edges[_nextEdgeId + NEXTNODEB] = NO_EDGE; _nextEdgeId = _nextEdgeId + EDGE_SIZE; // set data. _edgeData[edgeId / 4] = data; _edgeShapes[edgeId / 4] = coordinates; } var toEdgeId = _vertices[vertex2]; if (toEdgeId != NO_EDGE) { // there are existing edges. uint nextEdgeSlot = 0; while (toEdgeId != 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; }