- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在尝试编写一个 Java 程序,它将大量 GPS 坐标捕捉到线形文件(道路网络),并且不仅返回新坐标,还返回捕捉到的线段的唯一标识符。该标识符是否是 FID、其他语言中使用的“索引”(即,其中 1 是第一个特征等)或属性表中的任何列都无关紧要。
我在 R 中使用 maptools::snapPointsToLines 完成了此操作函数,但考虑到我需要处理的数据量,这是不可扩展的,因此我正在寻找 Java 来更快地处理数据,以便在 R 中进行分析。
我的代码(如下)目前与用于捕捉的 geotools 教程非常相似,其中的细微差别是我在 GPS 点的(1900 万行)CSV 中读取而不是生成它们,并编写了结果的 CSV。它捕捉得很好,而且比我得到的要快得多,但我不知道如何识别捕捉到的线。可用的文档似乎涵盖了功能集的查询和过滤,我无法特别适用于此代码创建的索引行对象,并且我的代码中的现有函数 toString()
返回一些对于我的目的而言难以理解的内容,例如 com.vividsolutions.jts.linearreff.LocationIndexedLine@74cec793
。
基本上,我只是希望 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 我知道有更好的 map 匹配解决方案(graphhopper 等),我只是想开始 eas!
谢谢!
最佳答案
我会尽量避免在 JTS 兔子洞中走得太远,并坚持使用 GeoTools(当然我是一个 GeoTools 开发人员,所以我会这么说)。
首先我会使用SpatialIndexFeatureCollection
保存我的行(假设它们适合内存,否则 PostGIS 表是可行的方法)。这使我不必建立自己的索引。
然后我会使用CSVDataStore
避免从 GPS 流中解析我自己的点(因为我很懒,而且那里也有很多出错的地方)。
这意味着大部分工作都归结为这个循环,DWITHIN
查找指定距离内的所有要素:
try (SimpleFeatureIterator itr = pointFeatures.getFeatures().features()) {
while (itr.hasNext()) {
SimpleFeature f = itr.next();
Geometry snapee = (Geometry) f.getDefaultGeometry();
Filter filter = ECQL.toFilter("DWITH(\"the_geom\",'" + writer.write(snapee) + "'," + MAX_SEARCH_DISTANCE + ")");
SimpleFeatureCollection possibles = indexed.subCollection(filter);
double minDist = Double.POSITIVE_INFINITY;
SimpleFeature bestFit = null;
Coordinate bestPoint = null;
try (SimpleFeatureIterator pItr = possibles.features()) {
while (pItr.hasNext()) {
SimpleFeature p = pItr.next();
Geometry line = (Geometry) p.getDefaultGeometry();
double dist = snapee.distance(line);
if (dist < minDist) {
minDist = dist;
bestPoint = DistanceOp.nearestPoints(snapee, line)[1];
bestFit = p;
}
}
}
在循环结束时,您应该知道距离线最近的特征(bestFit)(包括其 ID 和名称等)、最近的点(bestPoint)和移动的距离(minDist)。
我可能也会使用 CSVDatastore
将功能写回。
如果您有数百万个点,我可能会考虑使用 FilterFactory
直接创建过滤器,而不是使用 ECQL
解析器。
关于Java地理工具: Snap to line identifiying line that was snapped to,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41580197/
我该如何解决?我尝试创建“软链接(soft link)”,如 sudo ln /snap /var/lib/snapd/snap还有sudo ln /var/lib/snapd/snap /snap
index.html 文件如下: 这个 HTML 是用 Handlebars 编译的 index.js 文件如下: var s = Snap("#svg"); var bigCircle = s.c
在 vala 中,我将像这样启动基本操作系统设置: var appinfo = AppInfo.create_from_commandline ("switchboard", null, AppInf
我正在尝试使用 http://snapsvg.io/ 为序列中的几个对象设置动画。 我希望第一个物体移动,一旦完成,第二个物体移动等等。 相反,使用以下代码,所有内容都会同时动画。 var s
我正在尝试创建一个具有多个变化阶段的动画,Snap.animation() 是否允许这样做,或者我必须使用 css3 动画?感觉文档仍然缺少一些东西 最佳答案 最好的方法是创建一个排序函数或插件来依次
我正在尝试编写一个 Java 程序,它将大量 GPS 坐标捕捉到线形文件(道路网络),并且不仅返回新坐标,还返回捕捉到的线段的唯一标识符。该标识符是否是 FID、其他语言中使用的“索引”(即,其中 1
抽象的 我正在使用可滚动元素创建一个图片库。我正在使用 CSS 的 scroll-snap功能,它允许我捕捉到滚动条中的元素(图像)。 通过绑定(bind)到元素的 scroll事件,当用户滚动元素时
使用 Snap!编程语言,脚本在它们自己的 Sprite 的上下文中运行。我需要知道 Sprite 相对于另一个 Sprite 的位置。我如何找到另一个 Sprite 的位置? 最佳答案 有一个名为“
“确保定义了 window.Snap 或使用 SnapConstructorProvider.use(MySnap) 提供您自己的。” 这就是我尝试使用 Angular 捕捉时所拥有的。我按照他们在g
在拉斐尔中有一个 Paper.getById()方法,效果很好,但在 Snap 中没有这样的方法,我找不到任何类似的方法。 我看到 Snap 为纸上的每个元素设置了唯一 ID,类似于 pathSian
我想准备一些 snap 元素,然后将它们附加到一些 svg 上。 Snap()文档说 Snap() 只能包装现有的 svg 对象或创建一个新对象。如果不实际创建 svg 对象,我找不到创建 Snap
我尝试使用两个依赖项: "snap.svg": "~0.2.0", # snapsvg.io "angular-snap": "~1.4.1", # jtrussell.github.io/angul
我正在处理一些可拖动的元素,这些元素应该捕捉到其他元素,这些元素都有类,例如 ".classes" 以及唯一的 id,"#class_id “。一旦可拖动元素被拖动完成,我想找出可拖动元素已捕捉到哪些
如何在 snap-content 元素中创建固定位置例如制作 ... { position: fixed; top: 5rem; right: 0; } Toggle Right in this ex
我尝试安装 Hugo与 Snap在 Ubuntu 16.04.3 LTS (GNU/Linux 2.6.32-042stab125.5 x86_64)。服务 snapd正在运行,但我收到以下错误: c
有人可以展示如何在 reader monad 中使用 snap monad 吗? Monad 转换器让我很困惑。 (或者,我很乐意接受有关 monad 转换器的教程建议,以及了解并最终理解它们的方法。
This Fiddle显示我面临的错误。这真的是一个错误还是我做错了什么? 在 fiddle 中,将两个圆圈悬停,白色的圆圈正确动画,黑色的圆圈消失,无限循环开始在控制台中抛出错误。 var anim
无论我更改 scroll-snap-type 还是 scroll-snap-align,Safari 都会丢失滚动位置并从第一个 scroll-snap 元素开始。这个问题可以在这里的滚动示例中轻松重
我只是在玩 Snap 框架,想看看它与其他框架相比如何(在完全人为的情况下)。 我发现我的 Snap 应用程序以大约 1500 个请求/秒的速度达到最高(该应用程序只是 snap init; snap
.snap 包从快照商店自动更新需要什么? 它是 ubuntu 核心上的一些配置吗? .snap 包(应用程序)是否应该有代码来处理商店和更新 最佳答案 首先,在撰写本文时,桌面快照不会自动更新(必须
我是一名优秀的程序员,十分优秀!