Apache Sedona和Spark将geojson瓦片化例子

Apache Sedona很方便读取geojson、ShapeFile、geopackage等文件,提供了很多spark sql函数和rdd算子。下面例子主要用于熟悉spark和sedona的使用。

引入的maven包

<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.example</groupId><artifactId>GeoJsonToMvt</artifactId><version>0.1</version><packaging>jar</packaging><properties><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target><scala.version>2.13.8</scala.version><geotrellis.version>3.7.1</geotrellis.version><spark.version>3.3.4</spark.version><spray.json.version>1.3.6</spray.json.version></properties><dependencies><dependency><groupId>org.scala-lang</groupId><artifactId>scala-library</artifactId><version>${scala.version}</version></dependency><dependency><groupId>org.apache.spark</groupId><artifactId>spark-core_2.13</artifactId><version>${spark.version}</version></dependency><dependency><groupId>org.apache.spark</groupId><artifactId>spark-sql_2.13</artifactId><version>${spark.version}</version></dependency><dependency><groupId>org.apache.spark</groupId><artifactId>spark-sql_2.13</artifactId><version>${spark.version}</version></dependency><dependency><groupId>io.spray</groupId><artifactId>spray-json_2.13</artifactId><version>${spray.json.version}</version></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-core</artifactId><version>2.13.4</version></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.13.4</version></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-annotations</artifactId><version>2.13.4</version></dependency><dependency><groupId>org.locationtech.jts</groupId><artifactId>jts-core</artifactId><version>1.19.0</version></dependency><dependency><groupId>org.geotools</groupId><artifactId>gt-main</artifactId><version>25.4</version></dependency><dependency><groupId>org.geotools</groupId><artifactId>gt-epsg-hsql</artifactId><version>25.4</version></dependency><dependency><groupId>org.apache.sedona</groupId><artifactId>sedona-viz-3.0_2.13</artifactId><version>1.4.1</version></dependency><dependency><groupId>org.apache.sedona</groupId><artifactId>sedona-core-3.0_2.13</artifactId><version>1.4.1</version></dependency><dependency><groupId>org.apache.sedona</groupId><artifactId>sedona-sql-3.0_2.13</artifactId><version>1.4.1</version></dependency><dependency><groupId>org.apache.sedona</groupId><artifactId>sedona-spark-3.0_2.13</artifactId> <!-- 替换为你的 Spark 和 Scala 版本 --><version>1.6.1</version> <!-- 替换为你的 Sedona 版本 --></dependency><dependency><groupId>org.locationtech.proj4j</groupId><artifactId>proj4j</artifactId><version>1.1.0</version></dependency></dependencies><repositories><repository><id>osgeo</id><name>OSGeo Release Repository</name><url>https://repo.osgeo.org/repository/release/</url></repository></repositories><build><plugins><plugin><groupId>org.scala-tools</groupId><artifactId>maven-scala-plugin</artifactId><version>2.15.2</version><executions><execution><goals><goal>compile</goal><goal>testCompile</goal></goals></execution></executions></plugin></plugins></build>
</project>

下面是java实现的spark代码 部分是由AI(Gemini2.0)生成代码

import org.apache.sedona.spark.SedonaContext;
import org.apache.sedona.viz.core.Serde.SedonaVizKryoRegistrator;
import org.apache.spark.sql.Dataset;
import org.apache.spark.sql.Row;
import org.apache.spark.sql.RowFactory;
import org.apache.spark.sql.SparkSession;
import org.apache.spark.sql.types.DataTypes;
import org.apache.spark.sql.types.Metadata;
import org.apache.spark.sql.types.StructField;
import org.apache.spark.sql.types.StructType;
import org.geotools.referencing.CRS;
import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.jts.io.WKTReader;
import scala.Tuple3;import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;import static java.lang.Math.cos;
import static java.lang.Math.floor;
import static java.lang.Math.pow;
import static java.lang.Math.toRadians;
import static org.apache.spark.sql.functions.*;public class GeoJsonToTilesJava {public static void main(String[] args) throws Exception {System.setProperty("org.geotools.referencing.forceXY", "true");// 创建SparkSessionSparkSession config = SedonaContext.builder().master("local[*]") // Delete this if run in cluster mode.appName("readTestJava") // Change this to a proper name.config("spark.kryo.registrator", SedonaVizKryoRegistrator.class.getName()).config("spark.sql.extensions", "org.apache.sedona.viz.sql.SedonaVizExtensions,org.apache.sedona.sql.SedonaSqlExtensions").config("spark.serializer", "org.apache.spark.serializer.KryoSerializer").getOrCreate();SparkSession sedona = SedonaContext.create(config);Dataset<Row> df = sedona.read().format("geojson").option("multiPolygon", "true").load("src/main/resources/guangdong.json").selectExpr("explode(features) as features") // Explode the envelope to get one feature per row..select("features.*") // Unpack the features struct..withColumn("name", expr("properties['name']")).drop("properties").drop("type");Dataset<Row> df1 = df;df1.show();//Dataset<Row> filteredDF = df.filter(expr("ST_Y(ST_Centroid(ST_GeomFromGeoJSON(geometry))) BETWEEN -85.05 AND 85.05"));// 创建坐标转换器try {Dataset<Row> geomDF = df.withColumn("sedona_geom",expr("ST_AsEWKT(ST_Transform(geometry,'epsg:4326','epsg:3857',true))"));// 使用 UDF 创建 Sedona Geometry 列//Dataset<Row> geomDF = df.withColumn("sedona_geom", callUDF("createSedonaGeometry", col("geometry")));geomDF.show();// 修改: getTileIndexUDF 的返回值类型, 并保证如果坐标为空,则返回一个 null structorg.apache.spark.sql.api.java.UDF2<String, Integer, Row> getTileIndexUDF = (centroidStr, zoom)->{if (centroidStr == null || centroidStr.isEmpty()) {return RowFactory.create(null, null, null);} else {String[] str = centroidStr.replace("POINT (", "").replace(")", "").split(" ");List<Double> coordinates = new ArrayList<>();coordinates.add(Double.parseDouble(str[0]));coordinates.add(Double.parseDouble(str[1]));Tuple3<Integer,Integer,Integer> tileIndex = getTileIndex(coordinates,zoom);return RowFactory.create(tileIndex._1(), tileIndex._2(), tileIndex._3());}};//CRS.decode("EPSG:4326", true);// 注册 UDFStructType tileIndexSchema = new StructType(new StructField[]{new StructField("x", DataTypes.IntegerType, true, Metadata.empty()),new StructField("y", DataTypes.IntegerType, true, Metadata.empty()),new StructField("z", DataTypes.IntegerType, true, Metadata.empty())});sedona.udf().register("getTileIndexUDF", getTileIndexUDF, tileIndexSchema);org.apache.spark.sql.api.java.UDF1<String,String> getCentroid = (geomStr)->{if (geomStr == null || geomStr.isEmpty()) {return null;} else {GeometryFactory factory = new GeometryFactory();WKTReader wktReader = new WKTReader(factory);org.locationtech.jts.geom.Geometry geom = wktReader.read(geomStr);return geom.getCentroid().toString();}};// 注册 UDFsedona.udf().register("getCentroid", getCentroid, DataTypes.StringType);List<Integer> zooms = Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14);//  关键修改:直接在原始的 geomDF 上面进行循环操作for (Integer zoom : zooms){Dataset<Row> tilesDF = geomDF.withColumn("centroid",callUDF("getCentroid", col("sedona_geom"))).withColumn("tile", callUDF("getTileIndexUDF", col("centroid"), lit(zoom)));tilesDF.show();Dataset<Row>  groupedTiles = tilesDF.filter(col("tile").isNotNull()).groupBy(col("tile")).agg(collect_list("sedona_geom").alias("features"));groupedTiles.write().format("json").mode("overwrite").save("D:/temp/output/zoom_" + zoom);}sedona.stop();}catch (Exception e){e.printStackTrace();}}private static Tuple3<Integer, Integer, Integer> getTileIndex(List<Double> coordinates, int zoom) {if (coordinates == null || coordinates.isEmpty()) {return null;} else {double x = coordinates.get(0);double y = coordinates.get(1);double res = 156543.03392 * cos(toRadians(0)) / pow(2, zoom);int tileX = (int) floor((x + 20037508.34) / (res * 256));int tileY = (int) floor((20037508.34 - y) / (res * 256));return new Tuple3<>(tileX,tileY,zoom);}}
}

参考链接
https://sedona.apache.org/1.7.0/tutorial/sql/
https://sedona.apache.org/1.7.0/api/sql/Function/
谷歌双子座AIhttps://aistudio.google.com/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/66826.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于高斯混合模型的数据分析及其延伸应用(具体代码分析)

一、代码分析 &#xff08;一&#xff09;清除工作区和命令行窗口 clear; clc;clear;&#xff1a;该命令用于清除 MATLAB 工作区中的所有变量&#xff0c;确保代码运行环境的清洁&#xff0c;避免之前遗留的变量对当前代码运行产生干扰。例如&#xff0c;如果之前运行的代码中…

天气app的收获

天气app的收获 无论如何&#xff0c;是基于MVC模式&#xff0c;但都是从UI页面开始设计&#xff0c;然后根据输入的城市名称&#xff0c;将其传入到model层&#xff0c;进行相对应的处理。 对于controler层&#xff0c;需要通过一些协议完成一些输入的反馈&#xff0c;例如输…

PostgreSQL技术内幕22:vacuum full 和 vacuum

文章目录 0.简介1.概念及使用方式2.工作原理2.1 主要功能2.2 清理流程2.3 防止事务id环绕说明 3.使用建议 0.简介 在之前介绍MVCC文章中介绍过常见的MVCC实现的两种方式&#xff0c;一种是将旧数据放到回滚段&#xff0c;一种是直接生成一条新数据&#xff08;对于删除是不删除…

【面试】程序员 简历

一、简历整体结构 完整简历包含基本信息、教育背景、求职意向、工作经历、职业技能、项目经历、个人优势和个人荣誉八个部分。编写时&#xff0c;前几部分在保证真实的基础上可适当美化&#xff1b;个人优势和荣誉描述要突出难点亮点且避免夸张&#xff0c;可写入如马拉松参赛、…

WebGIS在应急灾害中对村庄、风景区、机场的影响范围应用-以日喀则市定日县地震为例

目录 前言 一、关于影响范围 1、震中距离5公里 2、震中20公里范围 3、20到80公里范围 二、空间查询知识 1、相关数据介绍 2、空间数据查询 三、前后端数据查询以及web可视化实现 1、后台API实现 2、WebGIS前端实现 四、Web成果展示 1、空间位置分析 2、包含风景区…

【UE5 C++课程系列笔记】27——多线程基础——ControlFlow插件的基本使用

目录 步骤 一、搭建基本同步框架 二、添加委托 三、添加蓝图互动框架 四、修改为异步框架 完整代码 通过一个游戏初始化流程的示例来介绍“ControlFlows”的基本使用。 步骤 一、搭建基本同步框架 1. 勾选“ControlFlows”插件 2. 新建一个空白C类&#xff0c;这里…

<C++> XlsxWriter写EXCEL

XlsxWriter XlsxWriter是一个用于创建和写入Excel 2007及以上版本&#xff08;.xlsx文件格式&#xff09;的C库。以下是对XlsxWriter的详细介绍&#xff1a; 主要功能 文本、数字和公式写入&#xff1a;可以向多个工作表中写入文本、数字和公式。格式设置&#xff1a;支持丰…

linux 设置mysql 外网访问

1、修改 MySQL 配置文件 找到并编辑配置文件&#xff1a;在Linux系统中&#xff0c;MySQL的配置文件通常是/etc/mysql/my.cnf&#xff0c;使用命令sudo vim /etc/mysql/my.cnf打开文件。 注释或修改 bindaddress&#xff1a;找到bindaddress 127.0.0.1&#xff0c;将其注释掉…

JavaEE之定时器及自我实现

在生活当中&#xff0c;有很多事情&#xff0c;我们不是立马就去做&#xff0c;而是在规定了时间之后&#xff0c;在到该时间时&#xff0c;再去执行&#xff0c;比如&#xff1a;闹钟、定时关机等等&#xff0c;在程序的世界中&#xff0c;有些代码也不是立刻执行&#xff0c;…

国产3D CAD将逐步取代国外软件

在工业软件的关键领域&#xff0c;计算机辅助设计&#xff08;CAD&#xff09;软件对于制造业的重要性不言而喻。近年来&#xff0c;国产 CAD 的发展态势迅猛&#xff0c;展现出巨大的潜力与机遇&#xff0c;正逐步改变着 CAD 市场长期由国外软件主导的格局。 国产CAD发展现状 …

【HarmonyOS Next NAPI 深度探索1】Node.js 和 CC++ 原生扩展简介

【HarmonyOS Next NAPI 深度探索1】Node.js 和 CC 原生扩展简介 如果你用过 Node.js&#xff0c;应该知道它强大的地方在于能处理各种场景&#xff0c;速度还很快。但你有没有想过&#xff0c;Node.js 的速度秘密是什么&#xff1f;今天我们来聊聊其中一个幕后英雄——原生扩展…

new[]创建对象数组会怎样?

当你使用 new[] 操作符来创建一个对象数组时&#xff0c;构造函数会被调用与数组大小相等的次数。每个数组元素都会通过构造函数进行初始化。 以下是一个例子&#xff1a; #include <iostream> class MyClass { public:MyClass() {std::cout << "MyClass con…

linux:文件的创建/删除/复制/移动/查看/查找/权限/类型/压缩/打包

关于文件的关键词 创建 touch 删除 rm 复制 cp 权限 chmod 移动 mv 查看内容 cat(全部); head(前10行); tail(末尾10行); more,less 查找 find 压缩 gzip ; bzip 打包 tar 编辑 sed 创建文件 格式&#xff1a; touch 文件名 删除文件 复制文件 移动文件 查看文…

数据结构C语言描述11(图文结合)--二叉搜索树(BST树)的实现(数据采用KV存储形式进行封装)

前言 这个专栏将会用纯C实现常用的数据结构和简单的算法&#xff1b;有C基础即可跟着学习&#xff0c;代码均可运行&#xff1b;准备考研的也可跟着写&#xff0c;个人感觉&#xff0c;如果时间充裕&#xff0c;手写一遍比看书、刷题管用很多&#xff0c;这也是本人采用纯C语言…

Chrome_60.0.3112.113_x64 单文件版 下载

单文件&#xff0c;免安装&#xff0c;直接用~ Google Chrome, 免費下載. Google Chrome 60.0.3112.113: Chrome 是 Google 開發的網路瀏覽器。它的特點是速度快,功能多。 下载地址: https://blog.s3.sh.cn/thread-150-1-1.htmlhttps://blog.s3.sh.cn/thread-150-1-1.html

概率论与数理统计总复习

复习课本&#xff1a;中科大使用的教辅《概率论和数理统计》缪柏其、张伟平版本 目录 0.部分积分公式 1.容斥原理 2.条件概率 3.全概率公式 4.贝叶斯公式 5.独立性 6.伯努利分布&#xff08;两点分布&#xff09; 7.二项分布 8.帕斯卡分布&#xff08;负二项分布&am…

xml简介

目录 基本语法特点及应用场景一个简单示例 xml&#xff08;全称eXtensible Markup Language&#xff09;是一种用于存储和传输数据的标记语言&#xff0c;跨平台并且跨语言&#xff0c;xml内容较多&#xff0c;这篇文章会介绍一些基础的内容。 基本语法 xml文档通常以xml声明开…

【线性代数】通俗理解特征向量与特征值

这一块在线性代数中属于重点且较难理解的内容&#xff0c;下面仅个人学习过程中的体会&#xff0c;错误之处欢迎指出&#xff0c;有更简洁易懂的理解方式也欢迎留言学习。 文章目录 概念计算几何直观理解意义PS.适用 概念 矩阵本身就是一个线性变换&#xff0c;对一个空间中的…

Conmi的正确答案——Cordova使用“src-cordova/config.xml”编辑“Android平台”的“uses-permission”

Cordova版本&#xff1a;12.0.0 (cordova-lib12.0.1) 1、配置例程&#xff1a; <platform name"android"><config-file target"AndroidManifest.xml" parent"/manifest"><uses-permission android:name"android.permission…

React 元素渲染

React 元素渲染 React 是一个用于构建用户界面的 JavaScript 库&#xff0c;它允许开发人员创建大型应用程序&#xff0c;这些应用程序可以随着时间的推移而高效地更新和渲染。React 的核心概念之一是元素渲染&#xff0c;它描述了如何将 JavaScript 对象转换为 DOM&#xff0…