随机地理坐标(在陆地上,避免海洋)

sdo*_*lgy 31 java gis geocoding

关于如何生成地球上的随机坐标(纬度/经度)的任何聪明的想法?纬度/经度.精确到5点,避免水体.

    double minLat = -90.00;
    double maxLat = 90.00;      
    double latitude = minLat + (double)(Math.random() * ((maxLat - minLat) + 1));
    double minLon = 0.00;
    double maxLon = 180.00;     
    double longitude = minLon + (double)(Math.random() * ((maxLon - minLon) + 1));
    DecimalFormat df = new DecimalFormat("#.#####");        
    log.info("latitude:longitude --> " + df.format(latitude) + "," + df.format(longitude));
Run Code Online (Sandbox Code Playgroud)

也许我生活在一个梦想的世界里,水话题是不可避免的......但希望有一个更好,更清洁,更有效的方法来做到这一点?

编辑

一些奇妙的答案/想法 - 然而,在规模上,让我们说我需要生成25,000个坐标.由于延迟,成本和一些其他因素,去外部服务提供商可能不是最佳选择.

phi*_*lwb 15

处理水体问题在很大程度上是一个数据问题,例如,你只是想错过海洋,还是你还需要错过小溪.您需要使用具有所需数据质量的服务,或者您需要自己获取数据并在本地运行.从你的编辑,听起来你想要去本地数据路线,所以我将专注于一种方法来做到这一点.

一种方法是获得陆地区域或水域的形状文件.然后,您可以生成一个随机点,并确定它是否与陆地区域相交(或者,不与水域相交).

首先,您可以在这里获得一些低分辨率数据,然后在这里获得更高分辨率的数据,以便在海岸线或湖泊/河流/等处获得更好的答案.你提到你希望你的点精度达到5位小数,这个位置略超过1米.请注意,如果您获得的数据与该精度相匹配,您将拥有一个巨大的数据集.而且,如果您想要非常好的数据,请准备好为此付费.

获得形状数据后,需要一些工具来帮助您确定随机点的交集. Geotools是一个很好的起点,可能会满足您的需求.您最终还会查看opengis代码(geotools网站下的文档 - 不确定它们是否消耗它们或者是什么)以及几何处理的JTS.使用此方法,您可以快速打开shapefile并开始执行一些交叉查询.

    File f = new File ( "world.shp" );
    ShapefileDataStore dataStore = new ShapefileDataStore ( f.toURI ().toURL () );
    FeatureSource<SimpleFeatureType, SimpleFeature> featureSource = 
        dataStore.getFeatureSource ();
    String geomAttrName = featureSource.getSchema ()
        .getGeometryDescriptor ().getLocalName ();

    ResourceInfo resourceInfo = featureSource.getInfo ();
    CoordinateReferenceSystem crs = resourceInfo.getCRS ();
    Hints hints = GeoTools.getDefaultHints ();
    hints.put ( Hints.JTS_SRID, 4326 );
    hints.put ( Hints.CRS, crs );

    FilterFactory2 ff = CommonFactoryFinder.getFilterFactory2 ( hints );
    GeometryFactory gf = JTSFactoryFinder.getGeometryFactory ( hints );

    Coordinate land = new Coordinate ( -122.0087, 47.54650 );
    Point pointLand = gf.createPoint ( land );
    Coordinate water = new Coordinate ( 0, 0 );
    Point pointWater = gf.createPoint ( water );

    Intersects filter = ff.intersects ( ff.property ( geomAttrName ), 
        ff.literal ( pointLand ) );
    FeatureCollection<SimpleFeatureType, SimpleFeature> features = featureSource
            .getFeatures ( filter );

    filter = ff.intersects ( ff.property ( geomAttrName ), 
        ff.literal ( pointWater ) );
    features = featureSource.getFeatures ( filter );
Run Code Online (Sandbox Code Playgroud)

快速解释:

  1. 这假定您获得的shapefile是多边形数据.线或点上的交叉点不会给你你想要的东西.
  2. 第一部分打开shapefile - 没有什么有趣的
  3. 您必须获取给定文件的几何属性名称
  4. 坐标系的东西 - 你在帖子中指定了lat/long,但GIS可能会复杂得多.一般来说,我指出的数据是地理,wgs84,这就是我在这里设置的.但是,如果您不是这种情况,那么您需要确保在正确的坐标系中处理数据.如果这听起来像胡言乱语,谷歌周围的GIS /坐标系/基准/椭圆体教程.
  5. 生成坐标几何和过滤器是非常明显的.由此产生的一组特征将为空,这意味着如果您的数据是土地覆盖,则坐标在水中,或者不是空的,这意味着相反.

注意:如果你用一组非常随机的点来做这件事,你会经常打水,这可能需要一段时间才能达到25k点.您可能希望尝试更好地确定您的点生成范围,而不是真正随机(例如移除大西洋/太平洋/印度洋的大块).

此外,您可能会发现您的交叉点查询太慢.如果是这样,您可能希望使用像GDAL这样的工具来创建四叉树索引(qix).我不记得geotools支持哪些索引类型.


Gee*_*982 5

很久以前就有人问过这个问题,我现在也有类似的需求。我正在研究两种可能性:

1. 定义随机发生器的表面范围。

在这里,确定您要达到的精度水平很重要。最简单的方法是采用一种非常轻松和近似的方法。在这种情况下,您可以将世界地图分成“盒子”:

在此处输入图片说明

每个盒子都有自己的纬度范围。然后你首先随机化得到一个随机框,然后你随机化得到一个随机 lat 和随机长在那个框的边界内。

精度在这里当然不是最好的......虽然这取决于:) 如果你做好功课并定义很多覆盖最复杂表面形状的盒子 - 你可能对精度很满意。

2. 列表项

一些 API 从坐标或地址或国家或地区返回大陆名称 = WATER 没有的东西。谷歌地图 API 可以在这里提供帮助。我没有更深入地研究这个,但我认为这是可能的,尽管您必须对每对生成的坐标进行检查,如果有误,则重新运行。因此,如果随机生成器不断将您扔进大海,您可能会陷入困境。

另外 - 一些水确实属于国家、地区......所以是的,不是很精确。

根据我的需要 - 我使用“盒子”,因为我还想控制从中获取随机坐标的确切区域,并且不介意它落在湖泊或河流上,而不是开阔的海洋:)