我正在尝试编写一个Java程序,将大量的GPS坐标捕捉到一个line shapefile(一个道路网络),并且不仅返回新的co从属,但是线段捕捉到的唯一标识符。这个标识符是否为FID,在其他语言中使用的“索引”(即1是第一个特征等)还是属性表中的任何列都无关紧要。Java地理工具:捕捉到线条识别线被捕获到
我已经使用maptools::snapPointsToLines功能R中做到了这一点,但这是不能扩展给定的数据我需要处理的体积,所以我在寻找Java来更快速地处理数据,分析R.
我的代码(下面)与geotools捕捉教程非常相似,我在GPS点(1900万行)CSV中读取的细微差异而不是生成它们,我写了一个CSV结果。它很好,比我得到的快得多,但我不知道如何识别对齐的线。可用的文档似乎涵盖了查询和功能集上的过滤功能,我不能特别适用于此代码创建的索引行对象,并且我的代码toString()
中的现有功能返回了一些难以理解的功能,例如[email protected]
。
基本上,我只想要lineID字段来产生任何其他GIS软件或语言可以匹配到特定路段的内容。
package org.geotools.tutorial.quickstart;
import java.io.*;
import java.util.List;
import java.util.Arrays;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Envelope;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.LineString;
import com.vividsolutions.jts.geom.MultiLineString;
import com.vividsolutions.jts.index.SpatialIndex;
import com.vividsolutions.jts.index.strtree.STRtree;
import com.vividsolutions.jts.linearref.LinearLocation;
import com.vividsolutions.jts.linearref.LocationIndexedLine;
import org.geotools.data.FeatureSource;
import org.geotools.data.FileDataStore;
import org.geotools.data.FileDataStoreFinder;
import org.geotools.feature.FeatureCollection;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.swing.data.JFileDataStoreChooser;
import org.geotools.util.NullProgressListener;
import org.opengis.feature.Feature;
import org.opengis.feature.FeatureVisitor;
import org.opengis.feature.simple.SimpleFeature;
import com.opencsv.*;
public class SnapToLine {
public static void main(String[] args) throws Exception {
/*
* Open a shapefile. You should choose one with line features
* (LineString or MultiLineString geometry)
*
*/
File file = JFileDataStoreChooser.showOpenFile("shp", null);
if (file == null) {
return;
}
FileDataStore store = FileDataStoreFinder.getDataStore(file);
FeatureSource source = store.getFeatureSource();
// Check that we have line features
Class<?> geomBinding = source.getSchema().getGeometryDescriptor().getType().getBinding();
boolean isLine = geomBinding != null
&& (LineString.class.isAssignableFrom(geomBinding) ||
MultiLineString.class.isAssignableFrom(geomBinding));
if (!isLine) {
System.out.println("This example needs a shapefile with line features");
return;
}
final SpatialIndex index = new STRtree();
FeatureCollection features = source.getFeatures();
//FeatureCollection featurecollection = source.getFeatures(Query.FIDS);
System.out.println("Slurping in features ...");
features.accepts(new FeatureVisitor() {
@Override
public void visit(Feature feature) {
SimpleFeature simpleFeature = (SimpleFeature) feature;
Geometry geom = (MultiLineString) simpleFeature.getDefaultGeometry();
// Just in case: check for null or empty geometry
if (geom != null) {
Envelope env = geom.getEnvelopeInternal();
if (!env.isNull()) {
index.insert(env, new LocationIndexedLine(geom));
}
}
}
}, new NullProgressListener());
/*
/*
* We defined the maximum distance that a line can be from a point
* to be a candidate for snapping
*/
ReferencedEnvelope bounds = features.getBounds();
final double MAX_SEARCH_DISTANCE = bounds.getSpan(0)/1000.0;
int pointsProcessed = 0;
int pointsSnapped = 0;
long elapsedTime = 0;
long startTime = System.currentTimeMillis();
double longiOut;
double latiOut;
int moved;
String lineID = "NA";
//Open up the CSVReader. Reading in line by line to avoid memory failure.
CSVReader csvReader = new CSVReader(new FileReader(new File("fakedata.csv")));
String[] rowIn;
//open up the CSVwriter
String outcsv = "fakedataOUT.csv";
CSVWriter writer = new CSVWriter(new FileWriter(outcsv));
while ((rowIn = csvReader.readNext()) != null) {
// Get point and create search envelope
pointsProcessed++;
double longi = Double.parseDouble(rowIn[0]);
double lati = Double.parseDouble(rowIn[1]);
Coordinate pt = new Coordinate(longi, lati);
Envelope search = new Envelope(pt);
search.expandBy(MAX_SEARCH_DISTANCE);
/*
* Query the spatial index for objects within the search envelope.
* Note that this just compares the point envelope to the line envelopes
* so it is possible that the point is actually more distant than
* MAX_SEARCH_DISTANCE from a line.
*/
List<LocationIndexedLine> lines = index.query(search);
// Initialize the minimum distance found to our maximum acceptable
// distance plus a little bit
double minDist = MAX_SEARCH_DISTANCE + 1.0e-6;
Coordinate minDistPoint = null;
for (LocationIndexedLine line : lines) {
LinearLocation here = line.project(pt);
Coordinate point = line.extractPoint(here);
double dist = point.distance(pt);
if (dist < minDist) {
minDist = dist;
minDistPoint = point;
lineID = line.toString();
}
}
if (minDistPoint == null) {
// No line close enough to snap the point to
System.out.println(pt + "- X");
longiOut = longi;
latiOut = lati;
moved = 0;
lineID = "NA";
} else {
System.out.printf("%s - snapped by moving %.4f\n",
pt.toString(), minDist);
longiOut = minDistPoint.x;
latiOut = minDistPoint.y;
moved = 1;
pointsSnapped++;
}
//write a new row
String [] rowOut = {Double.toString(longiOut), Double.toString(latiOut), Integer.toString(moved), lineID};
writer.writeNext(rowOut);
}
System.out.printf("Processed %d points (%.2f points per second). \n"
+ "Snapped %d points.\n\n",
pointsProcessed,
1000.0 * pointsProcessed/elapsedTime,
pointsSnapped);
writer.close();
}
}
我不仅是Java的新手,但只有自我训练的领域特定的语言,如R;我不是一个使用代码的编码人员,所以如果解决方案显而易见,我可能缺乏基本理论!
p.s我知道有更好的地图匹配解决方案(graphhopper等),我只是想开始eas!
谢谢!
谢谢!这两方面都让我走到了我需要去的地方,让事情变得更加容易理解。 – GeoWork