2017-05-12 1 views
1

A partir d'un ensemble de coordonnées qui définissent un itinéraire, je souhaite tracer un Geometry qui imite une route théorique de cette voie, pour un nombre arbitraire de mètres (par exemple 20)Construction de GeoTools Géométrie "segments" à partir des coordonnées d'itinéraire

Je ne sais pas si GeoTools fournit des outils pour construire un Geometry avec de telles entrées, donc mon idée initiale est de diviser les coordonnées de la piste (plusieurs milliers) par paires (coord0, coord1), (coord1, coord2), ...., (coordN, coordN-1) et, avec chaque paire , construisez un rectangle en supposant que les deux points sont les points médians d'un segment de 20m de large (comme dans Knowing two points of a rectangle, how can I figure out the other two?), et en rejoignant tous les résultats geometries.

Peut-être qu'il est exagéré, mais je n'ai pas trouvé un moyen moins coûteux de faire

Toutes les idées seraient grandement appréciés!

Répondre

1

La manière la plus simple d'y parvenir est d'utiliser un tampon de 20 m autour d'une ligne créée à partir de vos points. Donc, un code comme celui-ci pour créer une ligne de points (:

String[] wkt = { 
    "Point (-0.13666168754467312 50.81919869153657743)", 
    "Point (-0.13622277073931291 50.82205165077141373)", 
    "Point (-0.13545466632993253 50.82512406840893959)", 
    "Point (-0.13457683271921211 50.82687973563037787)", 
    "Point (-0.13413791591385191 50.82907431965718104)", 
    "Point (-0.13951464677951447 50.8294035072611976)", 
    "Point (-0.14346489802775639 50.83082998687861931)", 
    "Point (-0.14697623247063807 50.83072025767727808)", 
    "Point (-0.15004865010815954 50.83390240451614517)", 
    "Point (-0.15740050659794308 50.8349996965295432)", 
    "Point (-0.16486209228906662 50.83741373895902171)", 
    "Point (-0.17276259478555042 50.83894994777778464)", 
    "Point (-0.18549118214099652 50.8387304893751022)" 
    }; 

    //build line 
    WKTReader2 reader = new WKTReader2(); 
    GeometryFactory gf = new GeometryFactory(); 
    Coordinate[] points = new Coordinate[wkt.length]; 
    int i=0; 
    for(String w:wkt) { 
     Point p; 
    try { 
    p = (Point) reader.read(w); 
    points[i++]=p.getCoordinate(); 
    } catch (ParseException e) { 
    // TODO Auto-generated catch block 
    e.printStackTrace(); 
    } 

    } 
    LineString line = gf.createLineString(points); 
    SimpleFeatureBuilder builder = new SimpleFeatureBuilder(schema); 
    builder.set("locations", line); 
    SimpleFeature feature = builder.buildFeature("1"); 

Et puis une méthode BufferLine comme:

public SimpleFeature bufferFeature(SimpleFeature feature, Measure<Double, Length> distance) { 
    // extract the geometry 
    GeometryAttribute gProp = feature.getDefaultGeometryProperty(); 
    CoordinateReferenceSystem origCRS = gProp.getDescriptor().getCoordinateReferenceSystem(); 

    Geometry geom = (Geometry) feature.getDefaultGeometry(); 
    Geometry pGeom = geom; 
    MathTransform toTransform, fromTransform = null; 
    // reproject the geometry to a local projection 
    if (!(origCRS instanceof ProjectedCRS)) { 

     Point c = geom.getCentroid(); 
     double x = c.getCoordinate().x; 
     double y = c.getCoordinate().y; 

     String code = "AUTO:42001," + x + "," + y; 
     // System.out.println(code); 
     CoordinateReferenceSystem auto; 
     try { 
      auto = CRS.decode(code); 
      toTransform = CRS.findMathTransform(DefaultGeographicCRS.WGS84, auto); 
      fromTransform = CRS.findMathTransform(auto, DefaultGeographicCRS.WGS84); 
      pGeom = JTS.transform(geom, toTransform); 
     } catch (MismatchedDimensionException | TransformException | FactoryException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 

    } 

    // buffer 
    Geometry out = buffer(pGeom, distance.doubleValue(SI.METER)); 
    Geometry retGeom = out; 
    // reproject the geometry to the original projection 
    if (!(origCRS instanceof ProjectedCRS)) { 
     try { 
      retGeom = JTS.transform(out, fromTransform); 
     } catch (MismatchedDimensionException | TransformException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
    } 
    // return a new feature containing the geom 
    SimpleFeatureType schema = feature.getFeatureType(); 
    SimpleFeatureTypeBuilder ftBuilder = new SimpleFeatureTypeBuilder(); 
    ftBuilder.setCRS(origCRS); 
    // ftBuilder.setDefaultGeometry("buffer"); 
    ftBuilder.addAll(schema.getAttributeDescriptors()); 
    ftBuilder.setName(schema.getName()); 

    SimpleFeatureType nSchema = ftBuilder.buildFeatureType(); 
    SimpleFeatureBuilder builder = new SimpleFeatureBuilder(nSchema); 
    List<Object> atts = feature.getAttributes(); 
    for (int i = 0; i < atts.size(); i++) { 
     if (atts.get(i) instanceof Geometry) { 
      atts.set(i, retGeom); 
     } 
    } 
    SimpleFeature nFeature = builder.buildFeature(null, atts.toArray()); 
    return nFeature; 
} 

/** 
* create a buffer around the geometry, assumes the geometry is in the same 
* units as the distance variable. 
* 
* @param geom 
*   a projected geometry. 
* @param dist 
*   a distance for the buffer in the same units as the projection. 
* @return 
*/ 
private Geometry buffer(Geometry geom, double dist) { 

    Geometry buffer = geom.buffer(dist); 

    return buffer; 

} 

La partie délicate est reprojeter dans un SIR plat localement afin que vous puissiez utiliser . mètres de la taille du tampon Si vous connaissez une projection bien localement que vous pouvez simplement utiliser que (dans ce cas, nous aurions pu utiliser OSGB (EPSG: 27700) pour de meilleurs résultats)

cela donne la carte suivante:.

enter image description here

+0

Cela a fonctionné totalement @iant, merci beaucoup! – jonayreyes