private void HandleTwoLinesCase(GpxProlongerExecutorInput input, SegmentWithLines segment, List <ILineString> linesToProlong) { var bothLinesAreInList = linesToProlong.Contains(segment.Start.Line) && linesToProlong.Contains(segment.End.Line); if (bothLinesAreInList && segment.Start.Line.Coordinates.Last().Distance(segment.Start.Coordinate) < input.MinimalDistance && segment.End.Line.Coordinates.First().Distance(segment.End.Coordinate) < input.MinimalDistance) { linesToProlong.Remove(segment.Start.Line); linesToProlong.Remove(segment.End.Line); linesToProlong.Add(_geometryFactory.CreateLineString( segment.Start.Line.Coordinates .Concat(segment.OriginalCoordinates) .Concat(segment.End.Line.Coordinates) .Distinct() .ToArray())); } else if (!AddSegmentToLine(segment.Start.Line, segment, linesToProlong, input.MinimalDistance)) { if (!AddSegmentToLine(segment.End.Line, segment, linesToProlong, input.MinimalDistance)) { linesToProlong.Add(CreateLineString(segment.StartProjected, segment.OriginalCoordinates, segment.EndProjected)); } } }
private void HandleTwoLinesCase(GpxProlongerExecutorInput input, LineAndCoordinate current, LineAndCoordinate next, List <ILineString> linesToProlong) { var currentLengthIndexedLine = new LengthIndexedLine(current.Line); var currentCoordinate = currentLengthIndexedLine.ExtractPoint(currentLengthIndexedLine.Project(current.Coordinate)); var nextLengthIndexedLine = new LengthIndexedLine(next.Line); var nextCoordinate = nextLengthIndexedLine.ExtractPoint(nextLengthIndexedLine.Project(next.Coordinate)); var bothLinesAreInList = linesToProlong.Contains(current.Line) && linesToProlong.Contains(next.Line); if (bothLinesAreInList && current.Line.Coordinates.Last().Distance(current.Coordinate) < input.MinimalDistance && next.Line.Coordinates.First().Distance(next.Coordinate) < input.MinimalDistance) { linesToProlong.Remove(current.Line); linesToProlong.Remove(next.Line); linesToProlong.Add(_geometryFactory.CreateLineString(current.Line.Coordinates .Concat(next.Line.Coordinates).ToArray())); } else if (bothLinesAreInList && current.Line.Coordinates.First().Distance(current.Coordinate) < input.MinimalDistance && next.Line.Coordinates.Last().Distance(next.Coordinate) < input.MinimalDistance) { linesToProlong.Remove(current.Line); linesToProlong.Remove(next.Line); linesToProlong.Add(_geometryFactory.CreateLineString(next.Line.Coordinates .Concat(current.Line.Coordinates).ToArray())); } else if (!AddCoordinate(current.Line, currentCoordinate, nextCoordinate, linesToProlong, input.MinimalDistance)) { if (!AddCoordinate(next.Line, currentCoordinate, nextCoordinate, linesToProlong, input.MinimalDistance)) { linesToProlong.Add(_geometryFactory.CreateLineString(new[] { currentCoordinate, nextCoordinate })); } } }
private void HandleSelfClosingCase(GpxProlongerExecutorInput input, LineAndCoordinate current, LineAndCoordinate next, List <ILineString> linesToProlong) { var lengthIndexedLine = new LengthIndexedLine(current.Line); var closestCoordinateCurrentIndex = lengthIndexedLine.Project(current.Coordinate); var closestCoordinateNextIndex = lengthIndexedLine.Project(next.Coordinate); var segment = lengthIndexedLine.ExtractLine(closestCoordinateCurrentIndex, closestCoordinateNextIndex); var coordinates = segment.Coordinates.Concat(new[] { segment.Coordinates.First() }).ToArray(); if (coordinates.Length < 4) { return; } var polygon = new Polygon(new LinearRing(coordinates)); if (polygon.Area < input.MinimalAreaSize) { return; } var currentCoordinate = lengthIndexedLine.ExtractPoint(closestCoordinateCurrentIndex); var nextCoordinate = lengthIndexedLine.ExtractPoint(closestCoordinateNextIndex); if (!AddCoordinate(current.Line, currentCoordinate, nextCoordinate, linesToProlong, input.MinimalDistance)) { linesToProlong.Add(_geometryFactory.CreateLineString(new[] { currentCoordinate, nextCoordinate })); } }
/// <inheritdoc/> public List <ILineString> Prolong(GpxProlongerExecutorInput input) { // going from end to start. var endTostart = input.OriginalCoordinates.Reverse().ToList(); var linesToProlong = input.LinesToProlong.Select(l => l.Reverse() as ILineString).Reverse().ToList(); var allLines = input.ExistingItmHighways.Concat(linesToProlong).ToList(); var current = GetClosest(endTostart, allLines, input); if (current == null) { return(input.LinesToProlong); } endTostart = endTostart.Skip(endTostart.IndexOf(current.Coordinate) + 1).ToList(); while (endTostart.Any()) { var next = GetClosest(endTostart, allLines, input); if (next == null) { break; } var endIndex = endTostart.IndexOf(next.Coordinate); var originalBridgingSegment = new [] { current.Coordinate }.Concat(endTostart.Take(endIndex + 1)).ToArray(); var segmentWithLines = CreateSegmentWithLines(originalBridgingSegment, current, next); if (next.Line == current.Line && linesToProlong.Contains(current.Line)) { HandleSelfClosingCase(input, segmentWithLines, linesToProlong); } else if (current.Line.Intersects(next.Line) || current.Line.Distance(next.Line) < 0.1) { HandleIntersectionCase(input, segmentWithLines, linesToProlong); } else { HandleTwoLinesCase(input, segmentWithLines, linesToProlong); } allLines = input.ExistingItmHighways.Concat(linesToProlong).ToList(); endTostart = endTostart.Skip(endTostart.IndexOf(next.Coordinate) + 1).ToList(); current.Coordinate = next.Coordinate; current.Line = next.Line; } return(linesToProlong.Select(l => l.Reverse() as ILineString).Reverse().ToList()); }
private void HandleIntersectionCase(GpxProlongerExecutorInput input, SegmentWithLines segment, List <ILineString> linesToProlong) { var intersection = segment.Start.Line.Intersection(segment.End.Line).Coordinates .OrderBy(c => c.Distance(segment.Start.Coordinate) + c.Distance(segment.End.Coordinate)).FirstOrDefault(); if (intersection == null) { var distance = new DistanceOp(segment.Start.Line, segment.End.Line); intersection = distance.NearestPoints().First(); } var currentLengthIndexedLine = new LengthIndexedLine(segment.Start.Line); var closestCoordinateCurrentIndex = currentLengthIndexedLine.Project(segment.Start.Coordinate); var closestCoordinateCurrentIntersectionIndex = currentLengthIndexedLine.Project(intersection); var currentSegment = currentLengthIndexedLine.ExtractLine(closestCoordinateCurrentIndex, closestCoordinateCurrentIntersectionIndex); var nextLengthIndexedLine = new LengthIndexedLine(segment.End.Line); var closestCoordinateNextIndex = nextLengthIndexedLine.Project(segment.End.Coordinate); var closestCoordinateNextIntersectionIndex = nextLengthIndexedLine.Project(intersection); var nextSegment = nextLengthIndexedLine.ExtractLine(closestCoordinateNextIntersectionIndex, closestCoordinateNextIndex); var coordinates = currentSegment.Coordinates.Concat(nextSegment.Coordinates) .Concat(new[] { currentSegment.Coordinates.First() }).ToArray(); if (coordinates.Length < 4) { return; } var polygon = new Polygon(new LinearRing(coordinates)); if (polygon.Area < input.MinimalAreaSize) { return; } var currentCoordinate = currentLengthIndexedLine.ExtractPoint(closestCoordinateCurrentIndex); var nextCoordinate = nextLengthIndexedLine.ExtractPoint(closestCoordinateNextIndex); var line = CreateLineString(currentCoordinate, segment.OriginalCoordinates, nextCoordinate); linesToProlong.Add(line); }
private void HandleSelfClosingCase(GpxProlongerExecutorInput input, SegmentWithLines segment, List <ILineString> linesToProlong) { var lengthIndexedLine = new LengthIndexedLine(segment.Start.Line); var closestCoordinateCurrentIndex = lengthIndexedLine.Project(segment.Start.Coordinate); var closestCoordinateNextIndex = lengthIndexedLine.Project(segment.End.Coordinate); var indexedSegment = lengthIndexedLine.ExtractLine(closestCoordinateCurrentIndex, closestCoordinateNextIndex); var coordinates = indexedSegment.Coordinates.Concat(new[] { indexedSegment.Coordinates.First() }).ToArray(); if (coordinates.Length < 4) { return; } var polygon = new Polygon(new LinearRing(coordinates)); if (polygon.Area < input.MinimalAreaSize) { return; } if (!AddSegmentToLine(segment.Start.Line, segment, linesToProlong, input.MinimalDistance)) { linesToProlong.Add(CreateLineString(segment.StartProjected, segment.OriginalCoordinates, segment.EndProjected)); } }
/// <summary> /// Get the closest line and the coordinate that is close to that line on the original list. /// </summary> /// <param name="endTostart"></param> /// <param name="allLines"></param> /// <param name="input"></param> /// <returns></returns> private LineAndCoordinate GetClosest(List <Coordinate> endTostart, List <ILineString> allLines, GpxProlongerExecutorInput input) { foreach (var coordinate in endTostart) { var point = new Point(coordinate); var lineString = allLines.FirstOrDefault(l => l.Distance(point) < input.MinimalDistance); if (lineString == null) { continue; } return(new LineAndCoordinate { Coordinate = coordinate, Line = lineString }); } return(null); }