【问题标题】:Compute Intersection from multiple LineStrings using JTS使用 JTS 从多个 LineStrings 计算交点
【发布时间】:2015-10-09 19:32:21
【问题描述】:

我有 3 条线定义为线 A、线 B 和线 C,并且想计算线 B 和 C 与 A 之间的交点。来自 JTS 的函数 LineIntersector 应该有助于实现这一点。我需要帮助将此功能应用于线条以找到交点,即。类似computeIntersection(A线,B线)的东西。谢谢!

import com.vividsolutions.jts.geom.*;
import com.vividsolutions.jts.algorithm.*;

public class PointTest {

public static void main(String[] args){

// We have to have an even number of arguments - to have coordinate pairs for points.

if (args.length % 2 == 1) {
  System.out.println("Wrong input. You did not enter a list of coordinage pairs. Try again.");
}


else {

  int i=0;
  String[] coordA = {"12", "2", "12", "13", "12", "19"};
  String[] coordB = {"2", "10", "10", "10", "21", "11"};
  String[] coordC = {"1","1", "9","9", "20", "20"};





  // Create a new empty array of coordinates.

  //Coordinate[] coordinates = new Coordinate[args.length/2];     

  Coordinate[] coordinatesA = new Coordinate[coordA.length/2];
  Coordinate[] coordinatesB = new Coordinate[coordB.length/2];
  Coordinate[] coordinatesC = new Coordinate[coordC.length/2];
  // Go through the args and add each point as a Coordinate object to the coordinates array.

  //Geometry g1 = new GeometryFactory().createLineString(coordinatesA);

  //System.out.println(g1);

      while (i < coordA.length) {
    // transform string arguments into double values
    double x = Double.parseDouble(coordA[i]);
    double y = Double.parseDouble(coordA[i+1]);
    double xx = Double.parseDouble(coordB[i]);
    double yy = Double.parseDouble(coordB[i+1]);
    double xxx = Double.parseDouble(coordC[i]);
    double yyy = Double.parseDouble(coordC[i+1]);
    // create a new Coordinate object and add it to the coordinates array
    Coordinate newCoord = new Coordinate(x,y);
    coordinatesA[i/2] = newCoord;
    Coordinate newCoordB = new Coordinate(xx,yy);
    coordinatesB[i/2] = newCoordB;
    Coordinate newCoordC = new Coordinate(xxx,yyy);
    coordinatesC[i/2] = newCoordC;
    //System.out.println(newCoordB.toString());    
    i=i+2;
  } // while

  // Create a new Geometry from the array of coordinates.
  LineString lineA = new GeometryFactory().createLineString(coordinatesA);
  LineString lineB = new GeometryFactory().createLineString(coordinatesB);
  LineString lineC = new GeometryFactory().createLineString(coordinatesC);
  System.out.println("Line A is "+ lineA);
  System.out.println("Line B is "+ lineB);
  System.out.println("Line C is "+ lineC);

  // Read the start and end point of the line and write them on the screen.
  Point startPointA = lineA.getStartPoint();
  Point endPointA = lineA.getEndPoint();
  //System.out.println("The start point of the line is: " + startPointA.toString());    
  //System.out.println("The end point of the line is: " + endPointA.toString());


} // else

 } //main   

 }      

【问题讨论】:

    标签: java jts


    【解决方案1】:

    在使用此 API 方面,我可能比新手高出一个档次,但您的问题与我一直在研究的问题很接近,我可以分享到目前为止我发现的问题。我的问题是给出两个LineStrings,找到它们相交的点。我已经使用LineIntersector 解决了我的问题——它也可以解决你的问题——但是了解LineIntersector 帮助解决的更普遍的问题是很好的。

    首先要区分的是两个LineStrings 交叉还是相交。交叉时,没有共享的Coordinates,但连接至少两对Coordinates 的线相互跨骑。如果两个LineStrings 相交,则LineStrings 之一上将有一个点位于“容差”范围内。我使用buffer()方法来指定匹配的容差:

    if (lineStringA.buffer(0.0001).intersects(lineStringB)) { ... }
    

    同样用于测试(限制较少的)交叉:

    if (lineStringA.buffer(0.0001).crosses(lineStringB)) { ... }
    

    如果两个LineStrings 相交,我发现可以直接遍历每个坐标,直到找到位于第二个LineString 上的第一个坐标。那个共同点就是交叉点。

    如果两个LineStrings交叉但不相交,我会拿出LineIntersector.computeIntersection()方法来帮忙,但是这个方法的接口需要一些LineString的准备才能找到合适的Coordinate s 使用。

    这是我用来遍历第一个 LineString 以找到穿过第二个 LineString 的两个点的方法:

    private LineString findCrossingPair(LineString workingLineString,
            LineString fixedLineString) {
        // Pick up our factory instance
        GeometryFactory factory = fixedLineString.getFactory();
    
        Coordinate[] coordinates = workingLineString.getCoordinates();
        int length = coordinates.length;
        int indexOfCrossing = 0;
    
        // Walk the workingLineString for as long as it crosses the fixedLineString
        for (int i = 1; workingLineString.crosses(fixedLineString)
                && i < (length - 1); i++) {
            workingLineString = factory.createLineString(
                    Arrays.copyOfRange(coordinates, i, length));
            indexOfCrossing = i;
        }
    
        Coordinate[] crossingPair = Arrays.copyOfRange(coordinates,
                indexOfCrossing - 1, indexOfCrossing + 1);
        LineString crossingPiece = factory.createLineString(crossingPair);
    
        return crossingPiece;
    }
    

    我调用它一次以找到第一对Coordinates(返回为LineString),然后将其转过来以针对第二个LineString 运行它。下面是调用findCrossingPair()方法两次获取两对坐标的例子:

        LineString firstPiece = findCrossingPair(LineStringA,
                LineStringB);
        LineString secondPiece = findCrossingPair(LineStringB,
                firstPiece);
    
        // Now we have two 2-point LineStrings which we can pass to the
        // LineIntersector
    
        LineIntersector lineIntersector = new RobustLineIntersector();
        lineIntersector.computeIntersection(
                firstPiece.getStartPoint().getCoordinate(),
                firstPiece.getEndPoint().getCoordinate(),
                secondPiece.getStartPoint().getCoordinate(),
                secondPiece.getEndPoint().getCoordinate()
                );
        Coordinate intersect = lineIntersector.getIntersection(0);
        System.out.println("Intersection at " + intersect);
    

    请注意,在一般情况下,LineIntersector 可以找到 0、1 或 2 个相交点。这就是为什么LineIntersector 接口有一个传递给getIntersection() 方法的索引。交叉与相交的测试限制了此过程可以找到的交叉点的数量。

    【讨论】:

    • 这看起来超级复杂,为什么不简单地使用 Geometry#intersection() 并测试它的结果呢?您是否必须使用线的指定坐标而不是让线的“内部”相交?
    • 同意这个解决方案似乎比它应该的更复杂。我可能需要查看给我带来问题的场景,但是当我尝试仅使用 intersection() 时,它缺少 交叉 的 LineString 对。内部没有相交,但它们确实交叉。
    • 嗯!您的意思是一条线的端点位于另一条线的内部(afaik 那将是Geometry#touches())? Geometry#intersection() 应该会产生一个点。可能是浮点精度问题?
    • @bugmenot123,我发现Geometry#intersection() 确实在做我们想做的事。一旦我弄清楚为什么intersects()crosses() 返回true 时返回false,我将需要修改这个答案,但对于这个问题中描述的情况,我发现你的方法工作正常。
    【解决方案2】:

    任何几何对象都有可用的几何功能。您可以简单地使用geometryA.intersection(geometryB)。例如:

    Geometry ab = lineA.intersection(lineB);
    Geometry ac = lineA.intersection(lineC);
    

    如果您想将结果合并到一个对象中,您可以使用带有GeometryFactory#createGeometryCollection 的数组,或者测试您获得的几何类型并将它们相应地合并为例如 MultiPoint。

    【讨论】:

      【解决方案3】:

      在查看@bugmenot123 的答案后,我了解到我还有更多要学的东西,但我能够将这些放在一起,使用 bugmenot123 的方法回答了这个问题。

      我还不清楚在什么情况下我需要这个冗长而复杂的解决方案,但这里有一个似乎可以正常工作的已发布问题的解决方案:

      import com.vividsolutions.jts.geom.Coordinate;
      import com.vividsolutions.jts.geom.Geometry;
      import com.vividsolutions.jts.geom.GeometryFactory;
      import com.vividsolutions.jts.geom.LineString;
      
      public class LineStringIntersect {
      
          static Coordinate[] coordinateArrayA = {
                  new Coordinate(12.0, 2.0),
                  new Coordinate(12.0, 13.0),
                  new Coordinate(12.0, 19.0)
          };
      
          static Coordinate[] coordinateArrayB = {
                  new Coordinate(2.0, 10.0),
                  new Coordinate(10.0, 10.0),
                  new Coordinate(21.0, 11.0)
          };
      
          static Coordinate[] coordinateArrayC = {
                  new Coordinate(1.0, 1.0),
                  new Coordinate(9.0, 9.0),
                  new Coordinate(20.0, 20.0)
          };
      
          static GeometryFactory geometryFactory = new GeometryFactory();
      
          static LineString lineStringA = geometryFactory
                  .createLineString(coordinateArrayA);
          static LineString lineStringB = geometryFactory
                  .createLineString(coordinateArrayB);
          static LineString lineStringC = geometryFactory
                  .createLineString(coordinateArrayC);
      
          static Geometry geometryAB = lineStringA.intersection(lineStringB);
          static Geometry geometryAC = lineStringA.intersection(lineStringC);
          static Geometry geometryBC = lineStringB.intersection(lineStringC);
      
          public static void main(String args[]) {
              System.out.println("AB: " + geometryAB);
              System.out.println("AC: " + geometryAC);
              System.out.println("BC: " + geometryBC);
          }
      
      }
      

      【讨论】:

        猜你喜欢
        • 2016-04-17
        • 1970-01-01
        • 2017-05-01
        • 1970-01-01
        • 1970-01-01
        • 2021-09-27
        • 1970-01-01
        • 1970-01-01
        • 2012-02-17
        相关资源
        最近更新 更多