/// <summary> /// Decodes the given data into a location reference. /// </summary> public static PointAlongLineLocation Decode(byte[] data) { var pointAlongLine = new PointAlongLineLocation(); // decode first location reference point. var first = new LocationReferencePoint(); first.Coordinate = CoordinateConverter.Decode(data, 1); first.FuntionalRoadClass = FunctionalRoadClassConvertor.Decode(data, 7, 2); first.FormOfWay = FormOfWayConvertor.Decode(data, 7, 5); first.LowestFunctionalRoadClassToNext = FunctionalRoadClassConvertor.Decode(data, 8, 0); first.Bearing = BearingConvertor.DecodeAngleFromBearing(BearingConvertor.Decode(data, 8, 3)); first.DistanceToNext = DistanceToNextConvertor.Decode(data[9]); // decode second location reference point. var last = new LocationReferencePoint(); last.Coordinate = CoordinateConverter.DecodeRelative(first.Coordinate, data, 10); last.FuntionalRoadClass = FunctionalRoadClassConvertor.Decode(data, 14, 2); last.FormOfWay = FormOfWayConvertor.Decode(data, 14, 5); last.Bearing = BearingConvertor.DecodeAngleFromBearing(BearingConvertor.Decode(data, 15, 3)); pointAlongLine.First = first; pointAlongLine.Orientation = OrientationConverter.Decode(data, 7, 0); pointAlongLine.SideOfRoad = SideOfRoadConverter.Decode(data, 14, 0); pointAlongLine.PositiveOffsetPercentage = OffsetConvertor.Decode(data, 16); pointAlongLine.Last = last; return(pointAlongLine); }
/// <summary> /// Builds a location referenced point for the last vertex. /// </summary> /// <returns></returns> public LocationReferencePoint BuildLocationReferencePointLast(ReferencedLine referencedLocation, int before) { FormOfWay fow; FunctionalRoadClass frc; var end = referencedLocation.Vertices.Length - 1; // get all coordinates along the sequence starting at 'before' and ending at 'end'. var coordinates = referencedLocation.GetCoordinates(this.Graph, before, end - before + 1); // create location reference point. var locationReferencedPoint = new LocationReferencePoint(); locationReferencedPoint.Coordinate = this.GetVertexLocation(referencedLocation.Vertices[end]); var tags = this.GetTags(referencedLocation.Edges[end - 1].Tags); if (!this.TryMatching(tags, out frc, out fow)) { throw new ReferencedEncodingException(referencedLocation, "Could not find frc and/or fow for the given tags."); } locationReferencedPoint.FormOfWay = fow; locationReferencedPoint.FuntionalRoadClass = frc; locationReferencedPoint.Bearing = (int)BearingEncoder.EncodeBearing(coordinates, true).Value; return(locationReferencedPoint); }
/// <summary> /// Decodes the given data into a location reference. /// </summary> /// <param name="data"></param> /// <returns></returns> protected override ClosedLineLocation Decode(byte[] data) { // decode first location reference point. var first = new LocationReferencePoint(); first.Coordinate = CoordinateConverter.Decode(data, 1); first.FuntionalRoadClass = FunctionalRoadClassConvertor.Decode(data, 7, 2); first.FormOfWay = FormOfWayConvertor.Decode(data, 7, 5); first.LowestFunctionalRoadClassToNext = FunctionalRoadClassConvertor.Decode(data, 8, 0); first.Bearing = BearingConvertor.DecodeAngleFromBearing(BearingConvertor.Decode(data, 8, 3)); first.DistanceToNext = DistanceToNextConvertor.Decode(data[9]); // calculate the intermediate points count. var intermediateList = new List <LocationReferencePoint>(); int intermediates = (data.Length - 12) / 7; int location = 10; var reference = first.Coordinate; // the reference for the relative coordinates. for (int idx = 0; idx < intermediates; idx++) { // create an intermediate point. var intermediate = new LocationReferencePoint(); intermediate.Coordinate = CoordinateConverter.DecodeRelative(reference, data, location); reference = intermediate.Coordinate; location = location + 4; intermediate.FuntionalRoadClass = FunctionalRoadClassConvertor.Decode(data, location, 2); intermediate.FormOfWay = FormOfWayConvertor.Decode(data, location, 5); location = location + 1; intermediate.Bearing = BearingConvertor.DecodeAngleFromBearing(BearingConvertor.Decode(data, location, 3)); intermediate.LowestFunctionalRoadClassToNext = FunctionalRoadClassConvertor.Decode(data, location, 0); location = location + 1; intermediate.DistanceToNext = DistanceToNextConvertor.Decode(data[location]); location = location + 1; intermediateList.Add(intermediate); } // decode last location reference point. var last = new LocationReferencePoint(); // no last coordinates, identical to the first. last.Coordinate = first.Coordinate; last.FuntionalRoadClass = FunctionalRoadClassConvertor.Decode(data, location, 2); last.FormOfWay = FormOfWayConvertor.Decode(data, location, 5); location = location + 1; last.LowestFunctionalRoadClassToNext = FunctionalRoadClassConvertor.Decode(data, location, 0); last.Bearing = BearingConvertor.DecodeAngleFromBearing(BearingConvertor.Decode(data, location, 3)); location = location + 1; // create line location. var lineLocation = new ClosedLineLocation(); lineLocation.First = first; lineLocation.Intermediate = intermediateList.ToArray(); lineLocation.Last = last; return(lineLocation); }
/// <summary> /// Builds a location referenced point for the vertex at the given start-index. /// </summary> /// <returns></returns> public LocationReferencePoint BuildLocationReferencePoint(ReferencedLine referencedLocation, int start, int end) { FormOfWay fow; FunctionalRoadClass frc; // get all coordinates along the sequence starting at 'start' and ending at 'end'. var coordinates = referencedLocation.GetCoordinates(this.Graph, start, end - start + 1); // create location reference point. var locationReferencePoint = new LocationReferencePoint(); locationReferencePoint.Coordinate = this.GetVertexLocation(referencedLocation.Vertices[start]); var tags = this.GetTags(referencedLocation.Edges[start].Tags); if (!this.TryMatching(tags, out frc, out fow)) { throw new ReferencedEncodingException(referencedLocation, "Could not find frc and/or fow for the given tags."); } locationReferencePoint.FormOfWay = fow; locationReferencePoint.FuntionalRoadClass = frc; locationReferencePoint.Bearing = (int)BearingEncoder.EncodeBearing(coordinates).Value; locationReferencePoint.DistanceToNext = (int)coordinates.Length().Value; FunctionalRoadClass?lowest = null; for (var edge = start; edge < end; edge++) { tags = this.GetTags(referencedLocation.Edges[edge].Tags); if (!this.TryMatching(tags, out frc, out fow)) { throw new ReferencedEncodingException(referencedLocation, "Could not find frc and/or fow for the given tags."); } if (!lowest.HasValue || frc < lowest) { lowest = frc; } } locationReferencePoint.LowestFunctionalRoadClassToNext = lowest; return(locationReferencePoint); }
/// <summary> /// Finds all candidate vertex/edge pairs for a given location reference point. /// </summary> /// <param name="lrp"></param> /// <param name="forward"></param> /// <param name="maxVertexDistance"></param> /// <returns></returns> public virtual SortedSet <CandidateVertexEdge> FindCandidatesFor(LocationReferencePoint lrp, bool forward, Meter maxVertexDistance) { var vertexEdgeCandidates = new SortedSet <CandidateVertexEdge>(new CandidateVertexEdgeComparer()); var vertexCandidates = this.FindCandidateVerticesFor(lrp, maxVertexDistance); foreach (var vertexCandidate in vertexCandidates) { var edgeCandidates = this.FindCandidateEdgesFor(vertexCandidate.Vertex, forward, lrp.FormOfWay.Value, lrp.FuntionalRoadClass.Value, (Degree)lrp.Bearing.Value); foreach (var edgeCandidate in edgeCandidates) { vertexEdgeCandidates.Add(new CandidateVertexEdge() { Edge = edgeCandidate.Edge, Vertex = vertexCandidate.Vertex, TargetVertex = edgeCandidate.TargetVertex, Score = vertexCandidate.Score * edgeCandidate.Score }); } } return(vertexEdgeCandidates); }
/// <summary> /// Decodes the given data into a location reference. /// </summary> public static PoiWithAccessPointLocation Decode(byte[] data) { // decode first location reference point. var first = new LocationReferencePoint(); first.Coordinate = CoordinateConverter.Decode(data, 1); var orientation = OrientationConverter.Decode(data, 7, 0); first.FuntionalRoadClass = FunctionalRoadClassConvertor.Decode(data, 7, 2); first.FormOfWay = FormOfWayConvertor.Decode(data, 7, 5); first.LowestFunctionalRoadClassToNext = FunctionalRoadClassConvertor.Decode(data, 8, 0); first.Bearing = BearingConvertor.DecodeAngleFromBearing(BearingConvertor.Decode(data, 8, 3)); first.DistanceToNext = DistanceToNextConvertor.Decode(data[9]); // decode last location reference point. var last = new LocationReferencePoint(); // no last coordinates, identical to the first. last.Coordinate = CoordinateConverter.DecodeRelative(first.Coordinate, data, 10); var sideOfRoad = SideOfRoadConverter.Decode(data, 14, 0); last.FuntionalRoadClass = FunctionalRoadClassConvertor.Decode(data, 14, 2); last.FormOfWay = FormOfWayConvertor.Decode(data, 14, 5); last.Bearing = BearingConvertor.DecodeAngleFromBearing(BearingConvertor.Decode(data, 15, 3)); // poi details. var coordinate = CoordinateConverter.DecodeRelative(first.Coordinate, data, 17); // create line location. var poiWithAccessPointLocation = new PoiWithAccessPointLocation(); poiWithAccessPointLocation.First = first; poiWithAccessPointLocation.Last = last; poiWithAccessPointLocation.Coordinate = coordinate; poiWithAccessPointLocation.Orientation = orientation; poiWithAccessPointLocation.PositiveOffset = null; poiWithAccessPointLocation.SideOfRoad = sideOfRoad; return(poiWithAccessPointLocation); }
/// <summary> /// Finds candidate vertices for a location reference point. /// </summary> /// <param name="lrp"></param> /// <returns></returns> public override IEnumerable <CandidateVertex> FindCandidateVerticesFor(LocationReferencePoint lrp) { return(this.FindCandidateVerticesFor(lrp, this.MaxVertexDistance)); }
/// <summary> /// Finds candidate vertices for a location reference point. /// </summary> /// <param name="lrp"></param> /// <param name="maxVertexDistance"></param> /// <returns></returns> public virtual IEnumerable <CandidateVertex> FindCandidateVerticesFor(LocationReferencePoint lrp, Meter maxVertexDistance) { // convert to geo coordinate. var geoCoordinate = new GeoCoordinate(lrp.Coordinate.Latitude, lrp.Coordinate.Longitude); // build candidates list. var candidates = new HashSet <long>(); var scoredCandidates = new List <CandidateVertex>(); float latitude, longitude; // create a search box. var box = new GeoCoordinateBox(geoCoordinate, geoCoordinate); box = box.Resize(_candidateSearchBoxSize); // get arcs. var arcs = this.Graph.GetEdges(box); foreach (var arc in arcs) { long vertex = arc.Item1; if (!candidates.Contains(vertex)) { this.Graph.GetVertex(vertex, out latitude, out longitude); var distance = geoCoordinate.DistanceEstimate(new GeoCoordinate(latitude, longitude)); if (distance.Value < maxVertexDistance.Value) { candidates.Add(vertex); scoredCandidates.Add(new CandidateVertex() { Score = Score.New(Score.VERTEX_DISTANCE, string.Format("The vertex score compare to max distance {0}", _maxVertexDistance), (float)System.Math.Max(0, (1.0 - (distance.Value / _maxVertexDistance.Value))), 1), // calculate scoring compared to the fixed max distance. Vertex = vertex }); } } vertex = arc.Item2; if (!candidates.Contains(vertex)) { this.Graph.GetVertex(vertex, out latitude, out longitude); var distance = geoCoordinate.DistanceEstimate(new GeoCoordinate(latitude, longitude)); if (distance.Value < maxVertexDistance.Value) { candidates.Add(vertex); scoredCandidates.Add(new CandidateVertex() { Score = Score.New(Score.VERTEX_DISTANCE, string.Format("The vertex score compare to max distance {0}", _maxVertexDistance), (float)System.Math.Max(0, (1.0 - (distance.Value / _maxVertexDistance.Value))), 1), // calculate scoring compared to the fixed max distance. Vertex = vertex }); } } } if (scoredCandidates.Count == 0) { // no candidates, create a virtual candidate. var closestEdge = this.Graph.GetClosestEdge(geoCoordinate, maxVertexDistance, 0.1); if (closestEdge != null) { var coordinates = this.Graph.GetCoordinates(closestEdge); OsmSharp.Math.Primitives.PointF2D bestProjected; OsmSharp.Math.Primitives.LinePointPosition bestPosition; Meter bestOffset; int bestIndex; if (coordinates.ProjectOn(geoCoordinate, out bestProjected, out bestPosition, out bestOffset, out bestIndex)) { // successfully projected, insert virtual vertex. var distance = geoCoordinate.DistanceEstimate(new GeoCoordinate(bestProjected[1], bestProjected[0])); if (distance.Value < maxVertexDistance.Value) { this.Graph.RemoveEdge(closestEdge.Item1, closestEdge.Item2); this.Graph.RemoveEdge(closestEdge.Item2, closestEdge.Item1); var newVertex = this.Graph.AddVertex((float)bestProjected[1], (float)bestProjected[0]); // build distance before/after. var distanceBefore = bestOffset.Value; var distanceAfter = closestEdge.Item3.Distance - bestOffset.Value; // build coordinates before/after. var coordinatesBefore = new List <GeoCoordinateSimple>( coordinates.GetRange(1, bestIndex).Select(x => new GeoCoordinateSimple() { Latitude = (float)x.Latitude, Longitude = (float)x.Longitude })); var coordinatesAfter = new List <GeoCoordinateSimple>( coordinates.GetRange(bestIndex + 1, coordinates.Count - 1 - bestIndex - 1).Select(x => new GeoCoordinateSimple() { Latitude = (float)x.Latitude, Longitude = (float)x.Longitude })); this.Graph.AddEdge(closestEdge.Item1, newVertex, new LiveEdge() { Distance = (float)distanceBefore, Forward = closestEdge.Item3.Forward, Tags = closestEdge.Item3.Tags }, coordinatesBefore.Count > 0 ? coordinatesBefore.ToArray() : null); this.Graph.AddEdge(newVertex, closestEdge.Item2, new LiveEdge() { Distance = (float)distanceAfter, Forward = closestEdge.Item3.Forward, Tags = closestEdge.Item3.Tags }, coordinatesAfter.Count > 0 ? coordinatesAfter.ToArray() : null); scoredCandidates.Add(new CandidateVertex() { Score = Score.New(Score.VERTEX_DISTANCE, string.Format("The vertex score compare to max distance {0}", _maxVertexDistance), (float)System.Math.Max(0, (1.0 - (distance.Value / _maxVertexDistance.Value))), 1), // calculate scoring compared to the fixed max distance. Vertex = newVertex }); } } } } return(scoredCandidates); }
/// <summary> /// Finds all candidate vertex/edge pairs for a given location reference point. /// </summary> /// <param name="lrp"></param> /// <param name="forward"></param> /// <returns></returns> public virtual SortedSet <CandidateVertexEdge> FindCandidatesFor(LocationReferencePoint lrp, bool forward) { return(this.FindCandidatesFor(lrp, forward, _maxVertexDistance)); }
/// <summary> /// Finds candidate vertices for a location reference point. /// </summary> /// <param name="lrp"></param> /// <returns></returns> public virtual IEnumerable <CandidateVertex> FindCandidateVerticesFor(LocationReferencePoint lrp) { return(this.FindCandidateVerticesFor(lrp, _maxVertexDistance)); }
/// <summary> /// Finds candidate vertices for a location reference point. /// </summary> public static IEnumerable <CandidateLocation> FindCandidateLocationsFor(this Coder coder, LocationReferencePoint lrp, float maxVertexDistanceInMeter = 40, float candidateSearchBoxSize = 0.01f) { // build candidates list. var scoredCandidates = new List <CandidateLocation>(); var lrpCoordinate = new Itinero.LocalGeo.Coordinate((float)lrp.Coordinate.Latitude, (float)lrp.Coordinate.Longitude); // get vertices and check their edges. var vertices = coder.Router.Db.Network.GeometricGraph.Search((float)lrp.Coordinate.Latitude, (float)lrp.Coordinate.Longitude, candidateSearchBoxSize); var candidates = new HashSet <long>(); var edgeEnumerator = coder.Router.Db.Network.GetEdgeEnumerator(); foreach (var v in vertices) { if (candidates.Contains(v)) { // vertex was already considered. continue; } var vertexLocation = coder.Router.Db.Network.GetVertex(v); var distance = Itinero.LocalGeo.Coordinate.DistanceEstimateInMeter(vertexLocation, lrpCoordinate); if (distance < maxVertexDistanceInMeter) { candidates.Add(v); // check if there are edges that can be used for the given profile. edgeEnumerator.MoveTo(v); RouterPoint location; if (coder.Router.Db.TryCreateRouterPointForVertex(v, coder.Profile.Profile, out location)) { scoredCandidates.Add(new CandidateLocation() { Score = Score.New(Score.VERTEX_DISTANCE, string.Format("The vertex score compare to max distance {0}", maxVertexDistanceInMeter), (float)System.Math.Max(0, (1.0 - (distance / maxVertexDistanceInMeter))), 1), // calculate scoring compared to the fixed max distance. Location = location }); } } } var candidatesQualityOK = false; foreach (var candidate in scoredCandidates) { if (candidate.Score.Value / candidate.Score.Reference >= System.Math.Min(coder.Profile.ScoreThreshold + coder.Profile.ScoreThreshold, 0.7)) { // at least one above threshold, keep it. candidatesQualityOK = true; } } if (!candidatesQualityOK) { // no candidates, create a virtual candidate. var routerPoints = coder.Router.ResolveMultiple(new Itinero.Profiles.Profile[] { coder.Profile.Profile }, lrpCoordinate.Latitude, lrpCoordinate.Longitude, maxVertexDistanceInMeter); if (routerPoints.Count == 0) { throw new Exception("No candidates found for LRP: Could not resolve a point at the location."); } foreach (var routerPoint in routerPoints) { var distance = Itinero.LocalGeo.Coordinate.DistanceEstimateInMeter(routerPoint.LocationOnNetwork(coder.Router.Db), lrpCoordinate); scoredCandidates.Add(new CandidateLocation() { Score = Score.New(Score.VERTEX_DISTANCE, string.Format("The vertex score compare to max distance {0}", maxVertexDistanceInMeter), (float)System.Math.Max(0, (1.0 - (distance / maxVertexDistanceInMeter))), 1), // calculate scoring compared to the fixed max distance. Location = routerPoint }); } } return(scoredCandidates); }
/// <summary> /// Finds all candidate vertex/edge pairs for a given location reference point. /// </summary> public static Itinero.Algorithms.Collections.SortedSet <CandidatePathSegment> FindCandidatesFor(this Coder coder, LocationReferencePoint lrp, bool forward, float maxVertexDistance = 40) { var vertexEdgeCandidates = new Itinero.Algorithms.Collections.SortedSet <CandidatePathSegment>(new CandidateVertexEdgeComparer()); var vertexCandidates = coder.FindCandidateLocationsFor(lrp, maxVertexDistance); foreach (var vertexCandidate in vertexCandidates) { var edgeCandidates = coder.FindCandidatePathSegmentsFor(vertexCandidate, forward, lrp.FormOfWay.Value, lrp.FuntionalRoadClass.Value, lrp.Bearing.Value); foreach (var edgeCandidate in edgeCandidates) { vertexEdgeCandidates.Add(edgeCandidate); } } return(vertexEdgeCandidates); }