public void testNormalizeLineString2() throws Exception {
   LineString l =
       (LineString)
           this.geometryFactory.geometry("LINESTRING(20 20,160 40,160 100,100 120,60 60)");
   l = l.normalize();
   final LineString expectedValue =
       (LineString)
           this.geometryFactory.geometry("LINESTRING (20 20,160 40,160 100,100 120,60 60)");
   assertEqualsExact(expectedValue, l);
 }
 public void testNormalizeLineString4() throws Exception {
   LineString l =
       (LineString)
           this.geometryFactory.geometry("LINESTRING(200 240,140 160,80 160,160 80,80 80)");
   l = l.normalize();
   final LineString expectedValue =
       (LineString)
           this.geometryFactory.geometry("LINESTRING(80 80,160 80,80 160,140 160,200 240)");
   assertEqualsExact(expectedValue, l);
 }
 public void testNormalizeLineString5() throws Exception {
   final LineString geometry =
       (LineString)
           this.geometryFactory.geometry(
               "LINESTRING(200 340,140 240,140 160,60 240,140 240,200 340)");
   final LineString normalized = geometry.normalize();
   final LineString expectedValue =
       (LineString)
           this.geometryFactory.geometry(
               "LINESTRING (200 340,140 240,60 240,140 160,140 240,200 340)");
   assertEqualsExact(expectedValue, normalized);
 }
 public static LineString removeRepeatedPoints(final LineString points) {
   final int axisCount = points.getAxisCount();
   final List<Double> coordinates = new ArrayList<>();
   double x = points.getX(0);
   double y = points.getY(0);
   coordinates.add(x);
   coordinates.add(y);
   for (int axisIndex = 2; axisIndex < axisCount; axisIndex++) {
     coordinates.add(points.getCoordinate(0, axisIndex));
   }
   for (int i = 0; i < points.getVertexCount(); i++) {
     final double x1 = points.getX(i);
     final double y1 = points.getY(i);
     if (x != x1 || y != y1) {
       coordinates.add(x1);
       coordinates.add(y1);
       for (int axisIndex = 2; axisIndex < axisCount; axisIndex++) {
         coordinates.add(points.getCoordinate(i, axisIndex));
       }
       x = x1;
       y = y1;
     }
   }
   return new LineStringDouble(axisCount, coordinates);
 }
 public static double angleToNext(final LineString points, final int i) {
   final double x1 = points.getX(i);
   final double y1 = points.getY(i);
   double x2;
   double y2;
   int j = i + 1;
   do {
     x2 = points.getX(j);
     y2 = points.getY(j);
     j++;
   } while (x1 == x2 && y1 == y2 && j < points.getVertexCount());
   final double angle = Angle.angle2d(x1, y1, x2, y2);
   return angle;
 }
 public static double angleToPrevious(final LineString points, final int i) {
   if (i > 0) {
     final double x1 = points.getX(i);
     final double y1 = points.getY(i);
     double x2;
     double y2;
     int j = i - 1;
     do {
       x2 = points.getX(j);
       y2 = points.getY(j);
       j--;
     } while (x1 == x2 && y1 == y2 && j > -1);
     final double angle = Angle.angle2d(x1, y1, x2, y2);
     return angle;
   } else {
     throw new IllegalArgumentException("Index must be > 0 to calculate previous angle");
   }
 }
 public static void setCoordinates(
     final double[] coordinates,
     final int axisCount,
     final int i,
     final LineString line,
     final int j) {
   for (int axisIndex = 0; axisIndex < axisCount; axisIndex++) {
     final double value = line.getCoordinate(j, axisIndex);
     coordinates[i * axisCount + axisIndex] = value;
   }
 }
 public static int appendReverse(
     final int axisCount,
     final LineString source,
     final int sourceStartIndex,
     final double[] targetCoordinates,
     final int targetStartIndex,
     final int vertexCount) {
   int coordIndex = targetStartIndex;
   final int sourceVertexCount = source.getVertexCount();
   double previousX;
   double previousY;
   if (targetStartIndex == 0) {
     previousX = Double.NaN;
     previousY = Double.NaN;
   } else {
     previousX = targetCoordinates[(targetStartIndex - 1) * axisCount];
     previousY = targetCoordinates[(targetStartIndex - 1) * axisCount + 1];
   }
   int coordinateIndex = coordIndex * axisCount;
   int sourceIndex = sourceVertexCount - 1 - sourceStartIndex;
   for (int i = 0; i < vertexCount; i++) {
     final double x = source.getX(sourceIndex);
     final double y = source.getY(sourceIndex);
     if (x != previousX || y != previousY) {
       targetCoordinates[coordinateIndex++] = x;
       targetCoordinates[coordinateIndex++] = y;
       for (int axisIndex = 2; axisIndex < axisCount; axisIndex++) {
         final double coordinate = source.getCoordinate(sourceIndex, axisIndex);
         targetCoordinates[coordinateIndex++] = coordinate;
       }
       coordIndex++;
     }
     sourceIndex--;
     previousX = x;
     previousY = y;
   }
   return coordIndex;
 }
 public static <T> Map<LineString, Map<String, Set<Edge<T>>>> edgesByLineAndTypeName(
     final Node<T> node) {
   final List<Edge<T>> edges = node.getEdges();
   final Map<LineString, Map<String, Set<Edge<T>>>> lineEdgeMap = new HashMap<>();
   for (final Edge<T> edge : new HashSet<>(edges)) {
     LineString line = edge.getLine();
     Map<String, Set<Edge<T>>> edgesByType = edgesByTypeForLine(lineEdgeMap, line);
     if (edgesByType == null) {
       edgesByType = new HashMap<>();
       if (edge.getEnd(node).isTo()) {
         line = line.reverse();
       }
       lineEdgeMap.put(line, edgesByType);
     }
     Set<Edge<T>> typeEdges = edgesByType.get(edge.getTypeName());
     if (typeEdges == null) {
       typeEdges = new HashSet<>();
       final String typePath = edge.getTypeName();
       edgesByType.put(typePath, typeEdges);
     }
     typeEdges.add(edge);
   }
   return lineEdgeMap;
 }
 public static int orientationIndex(
     final LineString ring, final int index1, final int index2, final int index) {
   return orientationIndex(
       ring.getX(index1),
       ring.getY(index1),
       ring.getX(index2),
       ring.getY(index2),
       ring.getX(index),
       ring.getY(index));
 }
 @Override
 public GeometryFactory getGeometryFactory() {
   final LineString line = getLine();
   return line.getGeometryFactory();
 }
 @Override
 public double[] getCoordinates() {
   final LineString line = getLine();
   return line.getCoordinates();
 }
 @Override
 public double getCoordinate(final int vertexIndex, final int axisIndex) {
   final LineString line = getLine();
   return line.getCoordinate(vertexIndex, axisIndex);
 }
  public static List<LineString> intersection(
      final GeometryFactory geometryFactory,
      final LineString points1,
      final LineString points2,
      final double maxDistance) {

    final LineStringGraph graph1 = new LineStringGraph(points1);
    graph1.setPrecisionModel(geometryFactory);
    final LineStringGraph graph2 = new LineStringGraph(points2);
    graph2.setPrecisionModel(geometryFactory);
    final Map<Point, Point> movedNodes = new HashMap<>();
    graph1.forEachNode((node) -> movePointsWithinTolerance(movedNodes, graph2, maxDistance, node));
    graph2.forEachNode((node) -> movePointsWithinTolerance(movedNodes, graph1, maxDistance, node));

    final Map<Edge<LineSegment>, List<Node<LineSegment>>> pointsOnEdge1 =
        graph1.getPointsOnEdges(graph2, maxDistance);
    final Map<Edge<LineSegment>, List<Node<LineSegment>>> pointsOnEdge2 =
        graph2.getPointsOnEdges(graph1, maxDistance);
    graph1.splitEdges(pointsOnEdge1);
    graph2.splitEdges(pointsOnEdge2);
    Point startPoint = points1.getPoint(0);
    if (movedNodes.containsKey(startPoint)) {
      startPoint = movedNodes.get(startPoint);
    }
    Point endPoint = points1.getPoint(points1.getVertexCount() - 1);
    if (movedNodes.containsKey(endPoint)) {
      endPoint = movedNodes.get(endPoint);
    }
    final List<LineString> intersections = new ArrayList<>();
    final List<Point> currentCoordinates = new ArrayList<>();
    Node<LineSegment> previousNode = graph1.getNode(startPoint);
    do {
      final List<Edge<LineSegment>> outEdges = previousNode.getOutEdges();
      if (outEdges.isEmpty()) {
        previousNode = null;
      } else if (outEdges.size() > 1) {
        throw new IllegalArgumentException("Cannot handle overlaps\n" + points1 + "\n " + points2);
      } else {
        final Edge<LineSegment> edge = outEdges.get(0);
        final LineSegment line = edge.getObject();
        final Node<LineSegment> nextNode = edge.getToNode();
        if (graph2.hasEdgeBetween(previousNode, nextNode)) {
          if (currentCoordinates.size() == 0) {
            currentCoordinates.add(line.getPoint(0));
          }
          currentCoordinates.add(line.getPoint(1));
        } else {
          if (currentCoordinates.size() > 0) {
            final LineString points =
                new LineStringDouble(points1.getAxisCount(), currentCoordinates);
            intersections.add(points);
            currentCoordinates.clear();
          }
        }
        previousNode = nextNode;
      }

    } while (previousNode != null && !endPoint.equals(2, startPoint));
    if (currentCoordinates.size() > 0) {
      final LineString points = new LineStringDouble(points1.getAxisCount(), currentCoordinates);
      intersections.add(points);
    }
    return intersections;
  }
 @Override
 public int getVertexCount() {
   final LineString line = getLine();
   return line.getVertexCount();
 }
 public void testNormalizeEmptyLineString() throws Exception {
   LineString l = (LineString) this.geometryFactory.geometry("LINESTRING EMPTY");
   l = l.normalize();
   final LineString expectedValue = (LineString) this.geometryFactory.geometry("LINESTRING EMPTY");
   assertEqualsExact(expectedValue, l);
 }
 @Override
 public boolean isEmpty() {
   final LineString line = getLine();
   return line.isEmpty();
 }