【问题标题】:How to split linestring into parts every x meters with java JTS如何使用java JTS将线串分成每x米的部分
【发布时间】:2015-11-05 16:32:35
【问题描述】:

我正在尝试将 JTS 和 postgis 用于基于 spring 的后端。 虽然我知道 JTS 的基础知识,但我不知道如何实现

【问题讨论】:

    标签: java gis jts


    【解决方案1】:

    我编写了以下方法,可以满足您的要求,并使用 JTS LineSegment 对象来计算分割点:

    public ArrayList<LineString> splitLineStringIntoParts(LineString ls, double length){
        // result list for linestrings
        ArrayList<LineString> resultList = new ArrayList();
        // list for linesegments from input linestring
        ArrayList<LineSegment> lineSegmentList = new ArrayList();
        // create LineSegment objects from input linestring and add them to list
        for(int i = 1; i < ls.getCoordinates().length; i++){
            lineSegmentList.add(new LineSegment(ls.getCoordinates()[i-1], ls.getCoordinates()[i]));
        }
        LineString currentLineString = null;
        double neededLength = length;
        for(LineSegment s : lineSegmentList){
            while(s.getLength() > 0){
                // case: current segment is small enough to be added to the linestring
                if(s.getLength() <= neededLength){
                    // create linestring if it does not exist 
                    if(currentLineString == null){
                        currentLineString = new GeometryFactory().createLineString(new Coordinate[]{new Coordinate(s.p0), new Coordinate(s.p1)});
                    // just add the new endpoint otherwise
                    } else {
                        Coordinate[] coords = new Coordinate[currentLineString.getCoordinates().length + 1];
                        // copy old coordinates
                        System.arraycopy(currentLineString.getCoordinates(), 0, coords, 0, currentLineString.getCoordinates().length);
                        // add new coordinate at the end
                        coords[coords.length-1] = new Coordinate(s.p1);
                        // create new linestring
                        currentLineString = new GeometryFactory().createLineString(coords);
                    }
                    neededLength -= s.getLength();
                    s.setCoordinates(s.p1, s.p1);
                    // add linestring to result list if needed length is 0
                    if(neededLength == 0){
                        resultList.add(currentLineString);
                        currentLineString = null;
                        neededLength = length;
                    }
                // current segment needs to be cut and added to the linestring
                } else {
                    // get coordinate at desired distance (endpoint of linestring)
                    Coordinate endPoint = s.pointAlong(neededLength/s.getLength());
                    // create linestring if it does not exist 
                    if(currentLineString == null){
                        currentLineString = new GeometryFactory().createLineString(new Coordinate[]{new Coordinate(s.p0), endPoint});
                    // just add the new endpoint otherwise
                    } else {
                        // add new coordinate to linestring
                        Coordinate[] coords = new Coordinate[currentLineString.getCoordinates().length + 1];
                        // copy old coordinates
                        System.arraycopy(currentLineString.getCoordinates(), 0, coords, 0, currentLineString.getCoordinates().length);
                        // add new coordinate at the end
                        coords[coords.length-1] = endPoint;
                        currentLineString = new GeometryFactory().createLineString(coords);
                    }
                    // add linestring to result list
                    resultList.add(currentLineString);
                    // reset needed length
                    neededLength = length;
                    // reset current linestring
                    currentLineString = null;
                    // adjust segment (calculated endpoint is the new startpoint)
                    s.setCoordinates(endPoint, s.p1);
                }
            }
        }
        // add last linestring if there is a rest
        if(neededLength < length){
            resultList.add(currentLineString);
        }
        return resultList;
    }
    

    【讨论】:

      【解决方案2】:

      只需使用geographiclibJava implementation - 我相信你想要GeodesicLine;然后使用 JTS 和 postgis 将您生成的线串坐标输入到 postgresql 中。 JavaScript 中的 geodesic path example 应该可以帮助您入门。

      【讨论】:

      • 虽然这很有帮助,但我真的不明白如何使用这个库来满足我的需求。好的,我可以找到两点之间的中间点。但我实际上需要将这些点平均分布在有很多部分的 LineString 上。所以找到两点之间的点只是解决方案的一部分。你能提供更多帮助吗?如果没有实际代码或示例链接,那么我可以在其中了解所有这些 asimuts、测地线和其他东西的资源。
      • 听起来你需要使用 geolib 的其他对象/方法。您可以使用 Geodesic.Inverse 计算线串“部分”对之间的距离(Inverse 返回为 s12)。如果该距离 > X 米,则使用 Geodesic.Direct 查找从第一对到第二对的坐标 X 距离。有人猜测,当距离为
      • 坦率地说,我希望有更简单的解决方案。我已经在 python 中用 shapely(它使用 GEOS 和 GEOS AFAIK 是 JST 功能的子集到 C++ 的一个端口)和 pyproj 实现了这个。它就像 6 行代码。我不明白为什么它在 java 中这么难,因为它背后的库基本上是相同的。
      【解决方案3】:

      我还需要写拆分函数,所以我在stackoverflow上找到了解决方案,但没有找到一些有用的信息。所以我写了follow方法并回答你的问题;

      public List<LineString> lineSplit(LineString lineString,double meters) {
          List<LineString> results = new ArrayList<>();
          List<LineSegment> segments = new ArrayList<>();
          // first split linestring to segements[]
          for(int i = 1; i < lineString.getCoordinates().length; i++){
              segments.add(new LineSegment(lineString.getCoordinates()[i-1], lineString.getCoordinates()[i]));
          }
          // remainLegnth means that last segment's length dont enough to split to one segement which length is meters
          // neededLength means that current segment need how many meters to create a new segment
          double remainLength = 0D;
          double neededLength = 0D;
          // remainCoors means that if the last iteartor dont create a new segment,also mean  last segment
          // is too short ,even add remains length can't create a new segment;so, we should add this segment's start
          // point and end point to remainCoors
          List<Coordinate> remainCoors = new ArrayList<>();
          // netxStartPoint to store the next segment's start point 
          Coordinate netxStartPoint = null;
          for(int i=0;i<segments.size();i++) {
              LineSegment seg = segments.get(i);
              neededLength = meters-remainLength;
              remainLength += seg.getLength();
              netxStartPoint = seg.p0;
              while(remainLength>=meters) {
                  remainCoors.add(netxStartPoint);
                  Coordinate endPoint = seg.pointAlong(neededLength/seg.getLength());
                  // to remove the adjacent and same vertx
                  for(int j=0;j<remainCoors.size()-1;j++) {
                      if(remainCoors.get(j).equals(remainCoors.get(j+1))) {
                          remainCoors.remove(j);
                      }
                  }
                  remainCoors.add(endPoint);
                  results.add(lineString.getFactory().createLineString(remainCoors.toArray(new Coordinate[remainCoors.size()])));
                  remainCoors = new ArrayList<>();
                  netxStartPoint = endPoint;
                  remainLength -= meters;
                  neededLength += meters;
              }
              remainCoors.add(netxStartPoint);
              remainCoors.add(seg.p1);
          }
          for(int j=0;j<remainCoors.size()-1;j++) {
              if(remainCoors.get(j).equals(remainCoors.get(j+1))) {
                  remainCoors.remove(j);
              }
          }
          if(remainCoors.size()>=2) {
              results.add(lineString.getFactory().createLineString(remainCoors.toArray(new Coordinate[remainCoors.size()])));
          }
          return results;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-01-10
        • 2010-11-27
        • 1970-01-01
        • 2018-05-24
        • 2014-01-22
        • 2014-09-21
        • 2015-05-30
        • 1970-01-01
        相关资源
        最近更新 更多