/// <summary> /// Deserializes all edges. /// </summary> /// <param name="stream"></param> /// <param name="size"></param> /// <param name="graph"></param> protected override void DeserializeEdges(LimitedStream stream, long size, DynamicGraphRouterDataSource <LiveEdge> graph) { var typeModel = RuntimeTypeModel.Create(); typeModel.Add(typeof(SerializableEdge), true); typeModel.Add(typeof(GeoCoordinateSimple), true); long position = stream.Position; while (stream.Position < position + size) { // keep looping until the appropriate number of bytes have been read. var serializableEdges = typeModel.DeserializeWithSize(stream, null, typeof(SerializableEdge[])) as SerializableEdge[]; for (int idx = 0; idx < serializableEdges.Length; idx++) { ICoordinateCollection coordinateCollection = null; if (serializableEdges[idx].Coordinates != null) { coordinateCollection = new CoordinateArrayCollection <GeoCoordinateSimple>(serializableEdges[idx].Coordinates); } graph.AddEdge(serializableEdges[idx].FromId, serializableEdges[idx].ToId, new LiveEdge() { Distance = serializableEdges[idx].Distance, Value = serializableEdges[idx].Value }, coordinateCollection); } } }
/// <summary> /// Returns true if the given vertex has the given neighbour. /// </summary> /// <param name="vertex1"></param> /// <param name="vertex2"></param> /// <param name="shape"></param> /// <returns></returns> public bool GetEdgeShape(uint vertex1, uint vertex2, out ICoordinateCollection shape) { Tile tile; if (_tilesPerVertex.TryGetValue(vertex1, out tile)) { // load missing tile if needed. this.LoadMissingTile(tile); _tilesPerVertex.Remove(vertex1); } // get the arcs and return. if (_vertices.Length > vertex1) { var vertex = _vertices[(int)vertex1]; if (vertex != null && vertex.Arcs != null) { for (int idx = 0; idx < vertex.Arcs.Length; idx++) { if (vertex.Arcs[idx].Item1 == vertex2) { shape = null; if (vertex.Arcs[idx].Item3 != null) { shape = new CoordinateArrayCollection <GeoCoordinateSimple>(vertex.Arcs[idx].Item3); } return(true); } } } } shape = null; return(false); }
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { try { JObject jsonObj = JObject.Load(reader); ITypedCoordinateContainer typedCoorContainerResult = (ITypedCoordinateContainer)Activator.CreateInstance(objectType); if (jsonObj.HasValues) { JProperty typeProp = jsonObj.Property("type"); JProperty coordinatesProp = jsonObj.Property("coordinates"); if (typeProp != null && coordinatesProp != null) { string type = typeProp.Value.ToString(); JArray coorArray = string.IsNullOrWhiteSpace(coordinatesProp.Value.ToString()) ? null : JArray.FromObject(coordinatesProp.Value); if (coorArray != null) { ICoordinateCollection coorResult = null; ITypedCoordinate typedCoorResult = null; if (type == "Point") { //TJM: Assume simple array of coordinate pairs... coorResult = GetPointFromJArray(coorArray, _isLegacyFormat); //TJM: It's ok if the coorResult is null. typedCoorResult = new PointCoordinate(coorResult); } else if (type == "LineString") { //TJM: Assume array of "Point". coorResult = GetLineStringFromJArray(coorArray, _isLegacyFormat); typedCoorResult = new LineStringCoordinate(coorResult); } else if (type == "Polygon") { //TJM: Assume array of "LineString". coorResult = GetPolygonFromJArray(coorArray, _isLegacyFormat); typedCoorResult = new PolygonCoordinate(coorResult); } typedCoorContainerResult.Coordinates = typedCoorResult; return(typedCoorContainerResult); } } } } catch (Exception ex) { //TJM: Should we do anything here?? } return(null); }
/// <summary> /// Gets the shape for the arc in from the given vertex and at the given index. /// </summary> /// <param name="vertexId">The vertex id.</param> /// <param name="arcIdx">The index of the arc.</param> /// <param name="shape">The shape.</param> /// <returns>True if there was a shape.</returns> private bool GetShapeForArc(uint vertexId, uint arcIdx, out ICoordinateCollection shape) { var vertex = _vertices[(int)vertexId]; var arcCoordinates = vertex.Arcs[arcIdx]; shape = null; if (arcCoordinates.Item3 != null) { shape = new CoordinateArrayCollection <GeoCoordinateSimple>(arcCoordinates.Item3); } return(true); }
/// <summary> /// Returns the coordinate collection at the given id. /// </summary> /// <param name="id"></param> /// <param name="coordinates"></param> /// <returns></returns> public bool Get(long id, out ICoordinateCollection coordinates) { long index, size; if (this.TryGetIndexAndSize(id, out index, out size)) { coordinates = new HugeCoordinateCollection(_coordinates, index, size); return(true); } coordinates = null; return(false); }
private void AssertCoordinateFormatForTypedCoordinateContainer(TypedCoordinateContainer coordContainer) { //TJM: The result should be dealing with a Point type for simplicity to check the coordinates. ICoordinateCollection coordColl = coordContainer.Coordinates.Coordinates; while (coordColl.Children != null) { coordColl = coordColl.Children.FirstOrDefault(); } CoordinatePair coordPair = coordColl as CoordinatePair; string expectedResult = DummyTimeLineJson.GetCoordinateTestValueFromType("Point", coordPair.IsLegacyFormat); //TJM: Kind of a hack, but whatever...I want to get the exact result from our sample data. expectedResult = expectedResult.Replace("[", "").Replace("]", ""); string[] coordinateSplit = expectedResult.Split(','); // Set values based on whether we're using legacy format for the coordinate. decimal latitude = 0; decimal longitude = 0; for (int i = 0; i < coordinateSplit.Length; i++) { decimal coordNum; if (decimal.TryParse(coordinateSplit[i], out coordNum)) { if (i == 0) { if (coordPair.IsLegacyFormat) { latitude = coordNum; } else { longitude = coordNum; } } else if (i == 1) { if (coordPair.IsLegacyFormat) { longitude = coordNum; } else { latitude = coordNum; } } } } AssertLatitudeandLongitude(latitude, longitude, coordPair); }
/// <summary> /// Sets the coordinates starting at the given index. /// </summary> /// <param name="index"></param> /// <param name="coordinates"></param> private void DoSet(long index, ICoordinateCollection coordinates) { long idx = index; coordinates.Reset(); while (coordinates.MoveNext()) { _coordinates[idx] = coordinates.Latitude; _coordinates[idx + 1] = coordinates.Longitude; idx = idx + 2; } }
/// <summary> /// Returns a simple array. /// </summary> /// <param name="simples"></param> /// <returns></returns> public static SerializableCoordinate[] FromSimpleArray(ICoordinateCollection shape) { if (shape == null) { return(null); } var simples = shape.ToArray(); var coordinates = new SerializableCoordinate[simples.Length]; for (int idx = 0; idx < simples.Length; idx++) { coordinates[idx] = new SerializableCoordinate(); coordinates[idx].Latitude = simples[idx].Latitude; coordinates[idx].Longitude = simples[idx].Longitude; } return(coordinates); }
/// <summary> /// Adds the new coordinates at the end of the current coordinates. /// </summary> /// <param name="coordinates"></param> /// <returns></returns> private ulong DoAdd(ICoordinateCollection coordinates) { var newId = (ulong)(_nextIdx * MAX_COLLECTION_SIZE) + (ulong)coordinates.Count; coordinates.Reset(); while (coordinates.MoveNext()) { if (_coordinates.Length <= (_nextIdx * 2) + 1) { // make sure they fit! this.IncreaseCoordinates(); } _coordinates[(_nextIdx * 2)] = coordinates.Latitude; _coordinates[(_nextIdx * 2) + 1] = coordinates.Longitude; _nextIdx = _nextIdx + 1; } return(newId); }
/// <summary> /// Gets the shape associated with the given edge and returns true if it exists. /// </summary> /// <param name="vertex1"></param> /// <param name="vertex2"></param> /// <param name="shape"></param> /// <returns></returns> public bool GetEdgeShape(uint vertex1, uint vertex2, out ICoordinateCollection shape) { long edgeDataIdx; bool edgeDataForward; if (this.GetEdgeIdx(vertex1, vertex2, out edgeDataIdx, out edgeDataForward)) { // the edge exists. shape = _edgeShapes[edgeDataIdx]; if (shape != null && !edgeDataForward) { // invert shape. shape = shape.Reverse(); } return(true); } shape = null; return(false); }
/// <summary> /// Returns the edge shape between the two given vertices. /// </summary> /// <param name="vertex1"></param> /// <param name="vertex2"></param> /// <param name="shape"></param> public bool GetEdgeShape(long vertex1, long vertex2, out ICoordinateCollection shape) { if (vertex1 > 0 && vertex2 > 0) { if (_datasource.ContainsEdges((uint)vertex1, (uint)vertex2)) { // has the arc. if (!_removedArcs.Contains(new Arc() { Vertex1 = vertex1, Vertex2 = vertex2 })) { // edge was not removed, only now return it's shape from the source. if (_datasource.GetEdgeShape((uint)vertex1, (uint)vertex2, out shape)) { if (shape != null) { shape.Reset(); } return(true); } return(false); } } } // also check new arcs. foreach (var newArc in _newEdges) { if (newArc.Key == vertex1 && newArc.Value.Key == vertex2) { shape = newArc.Value.Value.Item2; if (shape != null) { shape.Reset(); } return(true); } } shape = null; return(false); }
/// <summary> /// Adds/updates the coordinate collection at the given id. /// </summary> /// <param name="id"></param> /// <param name="coordinates"></param> public void Add(long id, ICoordinateCollection coordinates) { long index, size; if (this.TryGetIndexAndSize(id, out index, out size)) { if (size == coordinates.Count * 2) { // just update in-place. this.DoSet(index, coordinates); } else { // remove and add new. _index[id] = this.DoAdd(coordinates); } } else { // add new coordinates. _index[id] = this.DoAdd(coordinates); } }
/// <summary> /// Returns the simple array. /// </summary> /// <returns></returns> public static GeoCoordinateSimple[] ToSimpleArray(this ICoordinateCollection collection) { if (collection == null) { return(null); } var array = new GeoCoordinateSimple[collection.Count]; int idx = 0; collection.Reset(); while (collection.MoveNext()) { array[idx] = new GeoCoordinateSimple() { Latitude = collection.Latitude, Longitude = collection.Longitude }; idx++; } return(array); }
/// <summary> /// Gets an edge-shape based on the from vertex and the index of the edge. /// </summary> /// <param name="vertex">The vertex where the edge is incident.</param> /// <param name="index">The index of the edge.</param> /// <param name="shape">The shape, if any, to return.</param> /// <returns></returns> internal bool GetShapeForArc(uint vertex, uint index, out ICoordinateCollection shape) { var localArcs = this.GetEdges(vertex); uint edgeIdx = 0; while (localArcs.MoveNext() && edgeIdx < index) { edgeIdx++; } //if(localArcs.isInverted) //{ // make sure to return the inverse edge. // shape = null; // if(localArcs.Intermediates != null) // { // shape = localArcs.Intermediates.Reverse(); // } // return true; //} shape = localArcs.Intermediates; return(true); }
/// <summary> /// Gets the shape for the arc in the given block and at the given index. /// </summary> /// <param name="blockId">The index of the block to search.</param> /// <param name="arcIdx">The index of the arc in the block.</param> /// <param name="shape">The shape.</param> /// <returns>True if there was a shape.</returns> private bool GetShapeForArc(uint blockId, uint arcIdx, out ICoordinateCollection shape) { CHBlockCoordinates blockCoordinates; if (!_blockShapes.TryGet(blockId, out blockCoordinates)) { // damn block not cached! blockCoordinates = this.DeserializeShape(blockId); if (blockCoordinates == null) { // oops even now the block is not found! shape = null; return(false); } _blockShapes.Add(blockId, blockCoordinates); } var arcCoordinates = blockCoordinates.Arcs[arcIdx]; shape = null; if (arcCoordinates.Coordinates != null) { shape = new CoordinateArrayCollection <GeoCoordinateSimple>(arcCoordinates.Coordinates); } return(true); }
/// <summary> /// Gets an edge from the given graph taking into account 'can have duplicates'. /// </summary> /// <param name="graph"></param> /// <param name="from"></param> /// <param name="to"></param> /// <param name="existingData"></param> /// <param name="shape"></param> /// <returns></returns> private bool GetEdge(GraphBase <TEdgeData> graph, uint from, uint to, out TEdgeData existingData, out ICoordinateCollection shape) { if (!graph.CanHaveDuplicates) { graph.GetEdgeShape(from, to, out shape); return(graph.GetEdge(from, to, out existingData)); } else { var edges = graph.GetEdges(from, to); while (edges.MoveNext()) { if (edges.Neighbour == to) { existingData = edges.EdgeData; shape = edges.Intermediates; return(true); } } existingData = default(TEdgeData); shape = null; return(false); } }
/// <summary> /// Adds an edge. /// </summary> /// <param name="forward"></param> /// <param name="from"></param> /// <param name="to"></param> /// <param name="tags"></param> /// <param name="intermediates"></param> protected virtual void AddRoadEdge(TagsCollectionBase tags, uint from, uint to, List <GeoCoordinateSimple> intermediates) { float latitude; float longitude; GeoCoordinate fromCoordinate = null; if (_graph.GetVertex(from, out latitude, out longitude)) { // fromCoordinate = new GeoCoordinate(latitude, longitude); } GeoCoordinate toCoordinate = null; if (_graph.GetVertex(to, out latitude, out longitude)) { // toCoordinate = new GeoCoordinate(latitude, longitude); } if (fromCoordinate != null && toCoordinate != null) { // calculate the edge data. TEdgeData existingData; ICoordinateCollection forwardShape; if (this.GetEdge(_graph, from, to, out existingData, out forwardShape)) { // oeps, an edge already exists! if (intermediates != null && intermediates.Count > 0) { // add one of the intermediates as new vertex. uint newVertex; if (forwardShape != null && forwardShape.Count > 0) { // the other edge also has a shape, make sure to also split it. var existingIntermediates = new List <GeoCoordinateSimple>(forwardShape.ToSimpleArray()); newVertex = _graph.AddVertex(existingIntermediates[0].Latitude, existingIntermediates[0].Longitude); // add edge before. var beforeEdgeData = this.CalculateEdgeData(_interpreter.EdgeInterpreter, _tagsIndex, tags, true, fromCoordinate, new GeoCoordinate(existingIntermediates[0].Latitude, existingIntermediates[0].Longitude), null); _graph.AddEdge(from, newVertex, beforeEdgeData, null); if (_graph.IsDirected) { // also the need to add the reverse edge. beforeEdgeData = (TEdgeData)beforeEdgeData.Reverse(); _graph.AddEdge(newVertex, from, beforeEdgeData, null); } // add edge after. var afterIntermediates = existingIntermediates.GetRange(1, existingIntermediates.Count - 1); var afterEdgeData = this.CalculateEdgeData(_interpreter.EdgeInterpreter, _tagsIndex, tags, true, new GeoCoordinate(existingIntermediates[0].Latitude, existingIntermediates[0].Longitude), toCoordinate, afterIntermediates); _graph.AddEdge(newVertex, to, afterEdgeData, new CoordinateArrayCollection <GeoCoordinateSimple>(afterIntermediates.ToArray())); if (_graph.IsDirected) { // also the need to add the reverse edge. afterIntermediates.Reverse(); afterEdgeData = (TEdgeData)afterEdgeData.Reverse(); _graph.AddEdge(to, newVertex, afterEdgeData, new CoordinateArrayCollection <GeoCoordinateSimple>(afterIntermediates.ToArray())); } // remove original edge. _graph.RemoveEdge(from, to, existingData); if (_graph.IsDirected && _graph.CanHaveDuplicates) { // also remove opposite edges. _graph.RemoveEdge(to, from, (TEdgeData)existingData.Reverse()); } } newVertex = _graph.AddVertex(intermediates[0].Latitude, intermediates[0].Longitude); var newEdgeData = this.CalculateEdgeData(_interpreter.EdgeInterpreter, _tagsIndex, tags, true, fromCoordinate, new GeoCoordinate(intermediates[0].Latitude, intermediates[0].Longitude), null); _graph.AddEdge(from, newVertex, newEdgeData, null); if (_graph.IsDirected) { // also the need to add the reverse edge. newEdgeData = (TEdgeData)newEdgeData.Reverse(); _graph.AddEdge(newVertex, from, newEdgeData, null); } from = newVertex; fromCoordinate = new GeoCoordinate(intermediates[0].Latitude, intermediates[0].Longitude); intermediates = intermediates.GetRange(1, intermediates.Count - 1); } else { // hmm, no intermediates, the other edge should have them. if (forwardShape != null && forwardShape.Count > 0) { // there is a shape, add one of the intermediates as a new vertex. var existingIntermediates = new List <GeoCoordinateSimple>(forwardShape.ToSimpleArray()); var newVertex = _graph.AddVertex(existingIntermediates[0].Latitude, existingIntermediates[0].Longitude); // add edge before. var beforeEdgeData = this.CalculateEdgeData(_interpreter.EdgeInterpreter, _tagsIndex, tags, true, fromCoordinate, new GeoCoordinate(existingIntermediates[0].Latitude, existingIntermediates[0].Longitude), null); _graph.AddEdge(from, newVertex, beforeEdgeData, null); if (_graph.IsDirected) { // also the need to add the reverse edge. beforeEdgeData = (TEdgeData)beforeEdgeData.Reverse(); _graph.AddEdge(newVertex, from, beforeEdgeData, null); } // add edge after. var afterIntermediates = existingIntermediates.GetRange(1, existingIntermediates.Count - 1); var afterEdgeData = this.CalculateEdgeData(_interpreter.EdgeInterpreter, _tagsIndex, tags, true, new GeoCoordinate(existingIntermediates[0].Latitude, existingIntermediates[0].Longitude), toCoordinate, afterIntermediates); _graph.AddEdge(newVertex, to, afterEdgeData, new CoordinateArrayCollection <GeoCoordinateSimple>(afterIntermediates.ToArray())); if (_graph.IsDirected) { // also the need to add the reverse edge. afterIntermediates.Reverse(); afterEdgeData = (TEdgeData)afterEdgeData.Reverse(); _graph.AddEdge(to, newVertex, afterEdgeData, new CoordinateArrayCollection <GeoCoordinateSimple>(afterIntermediates.ToArray())); } if (_graph.CanHaveDuplicates) { // make sure to remove the existing edge if graph allows duplicates. _graph.RemoveEdge(from, to); if (_graph.IsDirected) { // also remove the reverse. _graph.RemoveEdge(to, from); } } } else { // do nothing just overwrite what is there, probably a bug in OSM, two overlapping ways, sharing nodes. } } // edge was there already but was removed,split or needs to be replaced. var edgeData = this.CalculateEdgeData(_interpreter.EdgeInterpreter, _tagsIndex, tags, true, fromCoordinate, toCoordinate, intermediates); _graph.AddEdge(from, to, edgeData, new CoordinateArrayCollection <GeoCoordinateSimple>(intermediates.ToArray())); if (_graph.IsDirected) { // also the need to add the reverse edge. intermediates.Reverse(); edgeData = (TEdgeData)edgeData.Reverse(); _graph.AddEdge(to, from, edgeData, new CoordinateArrayCollection <GeoCoordinateSimple>(intermediates.ToArray())); } } else { // edge is not there yet, just add it. ICoordinateCollection intermediatesCollection = null; if (intermediates != null) { intermediatesCollection = new CoordinateArrayCollection <GeoCoordinateSimple>(intermediates.ToArray()); } // add new edge. var edgeData = this.CalculateEdgeData(_interpreter.EdgeInterpreter, _tagsIndex, tags, true, fromCoordinate, toCoordinate, intermediates); _graph.AddEdge(from, to, edgeData, intermediatesCollection); if (_graph.IsDirected) { // also the need to add the reverse edge. if (intermediates != null) { intermediates.Reverse(); intermediatesCollection = new CoordinateArrayCollection <GeoCoordinateSimple>(intermediates.ToArray()); } edgeData = (TEdgeData)edgeData.Reverse(); _graph.AddEdge(to, from, edgeData, intermediatesCollection); } } } }
/// <summary> /// Gets the shape associated with the given edge and returns true if it exists. /// </summary> /// <param name="vertex1"></param> /// <param name="vertex2"></param> /// <param name="shape"></param> /// <returns></returns> public override bool GetEdgeShape(uint vertex1, uint vertex2, out ICoordinateCollection shape) { throw new InvalidOperationException("Cannot use GetEdgeShape on a graph that can have duplicate edges."); }
/// <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> /// <remarks>This only adds edge vertex1->vertex2 NOT vertex2->vertex1</remarks> public override void AddEdge(uint vertex1, uint vertex2, TEdgeData data, ICoordinateCollection coordinates) { if (_readonly) { throw new Exception("Graph is readonly."); } 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 vertex1Idx = vertex1 * VERTEX_SIZE; var edgeCount = _vertices[vertex1Idx + EDGE_COUNT]; var edgeId = _vertices[vertex1Idx + FIRST_EDGE]; if ((edgeCount & (edgeCount - 1)) == 0) { // edgeCount is a power of two, increase space. // update vertex. uint newEdgeId = _nextEdgeId; _vertices[vertex1Idx + FIRST_EDGE] = newEdgeId; // move edges. if (edgeCount > 0) { if (newEdgeId + (2 * edgeCount) >= _edges.Length) { // edges need to be increased. this.IncreaseEdgeSize(); } for (uint toMoveIdx = edgeId; toMoveIdx < edgeId + edgeCount; toMoveIdx = toMoveIdx + EDGE_SIZE) { _edges[newEdgeId] = _edges[toMoveIdx]; _edgeData[newEdgeId] = _edgeData[toMoveIdx]; _edgeShapes[newEdgeId] = _edgeShapes[toMoveIdx]; newEdgeId++; } // the edge id is the last new edge id. edgeId = newEdgeId; // increase the nextEdgeId, these edges have been added at the end of the edge-array. _nextEdgeId = _nextEdgeId + (2 * edgeCount); } else { // just add next edge id. if (_nextEdgeId + 1 >= _edges.Length) { // edges need to be increased. this.IncreaseEdgeSize(); } edgeId = _nextEdgeId; _nextEdgeId++; } } else { // calculate edgeId of new edge. if (_nextEdgeId + 1 >= _edges.Length) { // edges need to be increased. this.IncreaseEdgeSize(); } edgeId = edgeId + edgeCount; _nextEdgeId++; } // update edge count in vertex. edgeCount++; _vertices[vertex1Idx + EDGE_COUNT] = edgeCount; // update edge. _edges[edgeId] = vertex2; _edgeData[edgeId] = data; _edgeShapes[edgeId] = coordinates; return; }
/// <summary> /// Adds a new edge. /// </summary> /// <param name="vertex1"></param> /// <param name="vertex2"></param> /// <param name="data"></param> /// <param name="coordinates"></param> public override void AddEdge(uint vertex1, uint vertex2, TEdgeData data, ICoordinateCollection coordinates) { _graph.AddEdge(vertex1, vertex2, data, coordinates); }
/// <summary> /// Adds the coordinate collection at the given id. /// </summary> public void Add(long id, ICoordinateCollection coordinates) { long index, size; if (this.TryGetIndexAndSize(id, out index, out size)) { throw new InvalidOperationException("Item with same key already exists."); } _index[id] = this.DoAdd(coordinates); if (_nextId <= id) { // update max id. _nextId = id + 1; } }
/// <summary> /// Returns true if the given vertex has the given neighbour. /// </summary> /// <param name="vertex1"></param> /// <param name="vertex2"></param> /// <param name="shape"></param> /// <returns></returns> public bool GetEdgeShape(uint vertex1, uint vertex2, out ICoordinateCollection shape) { return(this.LoadArcShape(vertex1, vertex2, out shape)); }
public PolygonCoordinate(ICoordinateCollection coordinates) { Coordinates = coordinates; }
/// <summary> /// Sets the coordinates starting at the given index. /// </summary> private ulong DoSet(long index, ICoordinateCollection coordinates) { if (coordinates == null) { // just return the null-pointer if null. return NULL; } var id = (ulong)(index * MAX_COLLECTION_SIZE) + (ulong)coordinates.Count; coordinates.Reset(); while(coordinates.MoveNext()) { _coordinates[index * 2] = coordinates.Latitude; _coordinates[index * 2 + 1] = coordinates.Longitude; index++; } return id; }
/// <summary> /// Loads the edge between the given vertices. /// </summary> /// <param name="vertex1"></param> /// <param name="vertex2"></param> /// <param name="shape"></param> /// <returns></returns> private bool LoadArcShape(uint vertex1, uint vertex2, out ICoordinateCollection shape) { uint blockId = CHBlock.CalculateId(vertex1, _blockSize); CHBlockCoordinates blockCoordinates; if (!_blockShapes.TryGet(blockId, out blockCoordinates)) { // damn block not cached! blockCoordinates = this.DeserializeShape(blockId); if (blockCoordinates == null) { // oops even now the block is not found! shape = null; return(false); } _blockShapes.Add(blockId, blockCoordinates); } CHBlock block; if (!_blocks.TryGet(blockId, out block)) { // damn block not cached! block = this.DeserializeBlock(blockId); if (block == null) { // oops even now the block is not found! shape = null; return(false); } _blocks.Add(blockId, block); } uint blockIdx = vertex1 - blockId; if (block.Vertices != null && blockIdx < block.Vertices.Length) { // block is found and the vertex is there! for (int arcIdx = block.Vertices[blockIdx].ArcIndex; arcIdx < block.Vertices[blockIdx].ArcIndex + block.Vertices[blockIdx].ArcCount; arcIdx++) { // loop over all arcs. var chArc = block.Arcs[arcIdx]; if (chArc.TargetId == vertex2) { var arcCoordinates = blockCoordinates.Arcs[arcIdx]; shape = null; if (arcCoordinates.Coordinates != null) { shape = new CoordinateArrayCollection <GeoCoordinateSimple>(arcCoordinates.Coordinates); } return(true); } } } blockId = CHBlock.CalculateId(vertex2, _blockSize); if (!_blocks.TryGet(blockId, out block)) { // damn block not cached! block = this.DeserializeBlock(blockId); if (block == null) { // oops even now the block is not found! shape = null; return(false); } _blocks.Add(blockId, block); } if (!_blockShapes.TryGet(blockId, out blockCoordinates)) { // damn block not cached! blockCoordinates = this.DeserializeShape(blockId); if (blockCoordinates == null) { // oops even now the block is not found! shape = null; return(false); } _blockShapes.Add(blockId, blockCoordinates); } blockIdx = vertex2 - blockId; if (block.Vertices != null && blockIdx < block.Vertices.Length) { // block is found and the vertex is there! for (int arcIdx = block.Vertices[blockIdx].ArcIndex; arcIdx < block.Vertices[blockIdx].ArcIndex + block.Vertices[blockIdx].ArcCount; arcIdx++) { // loop over all arcs. var chArc = block.Arcs[arcIdx]; if (chArc.TargetId == vertex1) { var arcCoordinates = blockCoordinates.Arcs[arcIdx]; shape = null; if (arcCoordinates.Coordinates != null) { shape = new CoordinateArrayCollection <GeoCoordinateSimple>(arcCoordinates.Coordinates); } return(true); } } } shape = null; return(false); }
/// <summary> /// Adds/updates the coordinate collection at the given id. /// </summary> /// <param name="id"></param> /// <param name="coordinates"></param> public void Add(long id, ICoordinateCollection coordinates) { long index, size; if (this.TryGetIndexAndSize(id, out index, out size)) { if(size == coordinates.Count * 2) { // just update in-place. this.DoSet(index, coordinates); } else { // remove and add new. _index[id] = this.DoAdd(coordinates); } } else { // add new coordinates. _index[id] = this.DoAdd(coordinates); } }
/// <summary> /// Adds the new coordinates at the end of the current coordinates. /// </summary> /// <param name="coordinates"></param> /// <returns></returns> private ulong DoAdd(ICoordinateCollection coordinates) { var newId = (ulong)(_nextIdx * MAX_COLLECTION_SIZE) + (ulong)coordinates.Count; coordinates.Reset(); while(coordinates.MoveNext()) { _coordinates[(_nextIdx * 2)] = coordinates.Latitude; _coordinates[(_nextIdx * 2) + 1] = coordinates.Longitude; _nextIdx = _nextIdx + 1; } return newId; }
public LineStringCoordinate(ICoordinateCollection coordinates) { Coordinates = coordinates; }
/// <summary> /// Starts pre-processing all nodes. /// </summary> public void Start() { // build the empty coordinate list. var emptyCoordinateList = new GeoCoordinateSimple[0]; var verticesList = new HashSet <uint>(); // initialize status variables. uint nextToProcess = 0; uint nextPosition = 0; // search edge until a real node. double latestProgress = 0; while (nextToProcess < _graph.VertexCount) { // keep looping until all vertices have been processed. // select a new vertext to select. var vertexToProcess = nextToProcess; var edges = _graph.GetEdges(vertexToProcess).ToList(); if (edges.Count == 2) { // find one of the neighbours that is usefull. vertexToProcess = edges[0].Neighbour; edges = _graph.GetEdges(vertexToProcess).ToList(); verticesList.Clear(); verticesList.Add(vertexToProcess); while (edges.Count == 2) { // keep looping until there is a vertex that is usefull. vertexToProcess = edges[0].Neighbour; if (verticesList.Contains(vertexToProcess)) { // take the other vertex. vertexToProcess = edges[1].Neighbour; if (verticesList.Contains(vertexToProcess)) { // an island was detected with only vertices having two neighbours. // TODO: find a way to handle this! edges = new List <Edge <LiveEdge> >(0); break; } } verticesList.Add(vertexToProcess); edges = _graph.GetEdges(vertexToProcess).ToList(); } } if (edges.Count > 0) { // ok, the vertex was not already processed. nextPosition++; var oldEdges = new List <Edge <LiveEdge> >(edges); var ignoreList = new HashSet <uint>(); foreach (var oldEdge in oldEdges) { if (ignoreList.Contains(oldEdge.Neighbour)) { // ignore this edge: already removed in a previous iteration. break; } // don't re-process edges that already have coordinates. ICoordinateCollection oldEdgeValueCoordinates; _graph.GetEdgeShape(vertexToProcess, oldEdge.Neighbour, out oldEdgeValueCoordinates); if (oldEdgeValueCoordinates != null) { // this edge has already been processed. break; } // STEP1: Build list of vertices that are only for form. // set current/previous. var distance = oldEdge.EdgeData.Distance; var current = oldEdge.Neighbour; var previous = vertexToProcess; // build list of vertices. var vertices = new List <uint>(); vertices.Add(previous); vertices.Add(current); // get next edges list. var nextEdges = _graph.GetEdges(current).ToList(); while (nextEdges.Count == 2) { // ok the current vertex can be removed. var nextEdge = nextEdges[0]; if (nextEdge.Neighbour == previous) { // it's the other edge! nextEdge = nextEdges[1]; } // compare edges. if (nextEdge.EdgeData.Forward != oldEdge.EdgeData.Forward || nextEdge.EdgeData.Tags != oldEdge.EdgeData.Tags) { // oeps, edges are different! break; } // check for intermediates. ICoordinateCollection nextEdgeValueCoordinates; _graph.GetEdgeShape(current, nextEdge.Neighbour, out nextEdgeValueCoordinates); if (nextEdgeValueCoordinates != null) { // oeps, there are intermediates already, this can occur when two osm-ways are drawn on top of eachother. break; } // add distance. distance = distance + nextEdge.EdgeData.Distance; // set current/previous. previous = current; current = nextEdge.Neighbour; vertices.Add(current); // get next edges. nextEdges = _graph.GetEdges(current).ToList(); } // check if the edge contains intermediate points. if (vertices.Count == 2) { // no intermediate points: add the empty coordinate list. var oldEdgeValue = oldEdge.EdgeData; // keep edges that already have intermediates. ICoordinateCollection edgeToKeepValueCoordinates = null; var edgesToKeep = new List <Tuple <uint, LiveEdge, ICoordinateCollection> >(); foreach (var edgeToKeep in _graph.GetEdges(vertexToProcess).ToList()) { edgeToKeepValueCoordinates = null; if (edgeToKeep.Neighbour == oldEdge.Neighbour && _graph.GetEdgeShape(vertexToProcess, edgeToKeep.Neighbour, out edgeToKeepValueCoordinates)) { edgesToKeep.Add(new Tuple <uint, LiveEdge, ICoordinateCollection>( edgeToKeep.Neighbour, edgeToKeep.EdgeData, edgeToKeepValueCoordinates)); } } // delete olds arcs. _graph.RemoveEdge(vertexToProcess, oldEdge.Neighbour); // add new arc. if (oldEdgeValue.Forward) { _graph.AddEdge(vertexToProcess, oldEdge.Neighbour, oldEdgeValue, null); } else { _graph.AddEdge(vertexToProcess, oldEdge.Neighbour, (LiveEdge)oldEdgeValue.Reverse(), null); } // add edges to keep. foreach (var edgeToKeep in edgesToKeep) { _graph.AddEdge(vertexToProcess, edgeToKeep.Item1, edgeToKeep.Item2, edgeToKeep.Item3); } } else { // intermediate points: build array. // STEP2: Build array of coordinates. var coordinates = new GeoCoordinateSimple[vertices.Count - 2]; float latitude, longitude; for (int idx = 1; idx < vertices.Count - 1; idx++) { _graph.GetVertex(vertices[idx], out latitude, out longitude); coordinates[idx - 1] = new GeoCoordinateSimple() { Latitude = latitude, Longitude = longitude }; } // STEP3: Remove all unneeded edges. _graph.RemoveEdge(vertices[0], vertices[1]); // remove first edge. for (int idx = 1; idx < vertices.Count - 1; idx++) { // delete all intermidiate arcs. _graph.RemoveEdges(vertices[idx]); } _graph.RemoveEdge(vertices[vertices.Count - 1], vertices[vertices.Count - 2]); // remove last edge. if (vertices[0] == vertices[vertices.Count - 1]) { // also remove outgoing edge. ignoreList.Add(vertices[vertices.Count - 2]); // make sure this arc is ignored in next iteration. } // STEP4: Add new edge. if (oldEdge.EdgeData.Forward) { _graph.AddEdge(vertices[0], vertices[vertices.Count - 1], new LiveEdge() { Forward = oldEdge.EdgeData.Forward, Tags = oldEdge.EdgeData.Tags, Distance = distance }, new CoordinateArrayCollection <GeoCoordinateSimple>(coordinates)); } else { var reverse = new GeoCoordinateSimple[coordinates.Length]; coordinates.CopyToReverse(reverse, 0); _graph.AddEdge(vertices[vertices.Count - 1], vertices[0], new LiveEdge() { Forward = !oldEdge.EdgeData.Forward, Tags = oldEdge.EdgeData.Tags, Distance = distance }, new CoordinateArrayCollection <GeoCoordinateSimple>(reverse)); } } } } // move to the next position. nextToProcess++; // report progress. float progress = (float)System.Math.Round((((double)nextToProcess / (double)_graph.VertexCount) * 100)); if (progress != latestProgress) { OsmSharp.Logging.Log.TraceEvent("LiveEdgePreprocessor", TraceEventType.Information, "Removing edges... {0}%", progress); latestProgress = progress; } } // compress the graph. this.CompressGraph(); }
/// <summary> /// Creates a new edge by copying the given edge. /// </summary> /// <param name="neighbour"></param> /// <param name="edgeData"></param> /// <param name="intermediates"></param> public Edge(uint neighbour, TEdgeData edgeData, ICoordinateCollection intermediates) { this.Neighbour = neighbour; this.EdgeData = edgeData; this.Intermediates = intermediates; }
/// <summary> /// Returns true if the given vertex has the given neighbour. /// </summary> /// <param name="vertex1"></param> /// <param name="vertex2"></param> /// <param name="shape"></param> /// <returns></returns> public override bool GetEdgeShape(uint vertex1, uint vertex2, out ICoordinateCollection shape) { return(_graph.GetEdgeShape(vertex1, vertex2, out shape)); }
public PointCoordinate(ICoordinateCollection coordinates) { Coordinates = coordinates; }
/// <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> public void AddEdge(uint vertex1, uint vertex2, TEdgeData data, ICoordinateCollection coordinates) { 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 (coordinates != null) { // also reverse coordinates! coordinates = coordinates.Reverse(); } } _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; }
/// <summary> /// Adds the new coordinates at the end of the current coordinates. /// </summary> /// <param name="coordinates"></param> /// <returns></returns> private ulong DoAdd(ICoordinateCollection coordinates) { var newId = (ulong)(_nextIdx * MAX_COLLECTION_SIZE) + (ulong)coordinates.Count; coordinates.Reset(); while(coordinates.MoveNext()) { if (_coordinates.Length <= (_nextIdx * 2) + 1) { // make sure they fit! this.IncreaseCoordinates(); } _coordinates[(_nextIdx * 2)] = coordinates.Latitude; _coordinates[(_nextIdx * 2) + 1] = coordinates.Longitude; _nextIdx = _nextIdx + 1; } return newId; }
/// <summary> /// Sets the coordinates starting at the given index. /// </summary> /// <param name="index"></param> /// <param name="coordinates"></param> private void DoSet(long index, ICoordinateCollection coordinates) { long idx = index; coordinates.Reset(); while(coordinates.MoveNext()) { _coordinates[idx] = coordinates.Latitude; _coordinates[idx + 1] = coordinates.Longitude; idx = idx + 2; } }
/// <summary> /// Returns the coordinate collection at the given id. /// </summary> /// <param name="id"></param> /// <param name="coordinates"></param> /// <returns></returns> public bool Get(long id, out ICoordinateCollection coordinates) { long index, size; if (this.TryGetIndexAndSize(id, out index, out size)) { coordinates = new HugeCoordinateCollection(_coordinates, index, size); return true; } coordinates = null; return false; }
/// <summary> /// Adds the new coordinates at the end of the current coordinates. /// </summary> /// <returns></returns> private ulong DoAdd(ICoordinateCollection coordinates) { if(coordinates == null) { // just return the null-pointer if null. return NULL; } var id = (ulong)(_nextIdx * MAX_COLLECTION_SIZE) + (ulong)coordinates.Count; coordinates.Reset(); while(coordinates.MoveNext()) { if (_coordinates.Length <= (_nextIdx * 2) + 1) { // make sure they fit! this.IncreaseCoordinates(); } _coordinates[(_nextIdx * 2)] = coordinates.Latitude; _coordinates[(_nextIdx * 2) + 1] = coordinates.Longitude; _nextIdx = _nextIdx + 1; } return id; }