基于PostGIS的曲线拐点计算

news2024/11/30 2:41:47

在这篇博文中,我将介绍一种查找曲线拐点的方法。 一个简单的理解方式:将曲线想象成我们正在行驶的道路,我们想要找到我们停止右转并开始左转或反之的点,如下所示:

我们将展示解决方案的草图和 PostGIS 中的实际实施。 我认为这是一个很好的展示在数据库中实现 GIS 算法的有用技术的简单示例。

在这里插入图片描述

推荐:用 NSDT设计器 快速搭建可编程3D场景。

1、解决方案的草图

这个问题可以用非常标准的二维计算几何资源来解决。 特别是,使用叉积作为检测点位于给定直线左侧还是右侧的方法在这里很有用。 以下伪代码基于行列式:

function isLeft(Point a, Point b, Point c){ 
	return ((b.X - a.X)*(c.Y - a.Y) - (b.Y - a.Y)*(c.X - a.X)) > 0; 
}

总的来说,我反对实现你自己的计算几何代码:数学公式的直接翻译通常会遇到舍入错误、极端情况和明显的低效率问题。 你最好使用优秀的计算几何库之一,例如:GEOS,它最初是作为 JTS 的一个移植,或 CGAL。 无论如何你都可能在使用它们,因为它们位于许多 GIS 软件堆栈的底部。 这适用于任何非平凡的数学(线性代数、优化……)。 记住:浮点数不是实数。

在这种情况下,我更关心实用性而不是纯粹的效率,使用 SQLs 数字类型以牺牲速度为代价提供任意精度的算术,防止了我们在双精度时会遇到的一些舍入错误,节省了 我们自己实施快速健壮的谓词。

2、PostGIS 实现

长期以来,我一直认为 Postgres/PostGIS 是地理空间分析的最佳工作台(证明我错了)。 在许多用例中,能够直接在存储数据的地方执行分析是无与伦比的。 必须编写 SQL 脚本对于某些用户来说可能是一种倒退,但在数据工作流的可重现性和可追溯性方面很有用。

在这种特殊情况下,我们假设我们的输入是一个包含 LineString 几何特征的表格,每个几何特征都有其唯一标识符。 当然,在任何计算之前,都会对几何图形进行适当的索引和有效性测试。 在开发过程中,通过感兴趣的区域将计算限制在数据的子集内,以缩短测试结果和参数的迭代过程也很有用。

解决方案的草图是:

  • 简化几何结构以避免噪声(误报)。 ST_Simplify 或 ST_SimplifyPreserveTopology 就足够了。
  • 分解点,跟踪原始几何图形,这可以使用 generate_series 和 ST_DumpPoints 轻松完成。
  • 我们需要 3 个点来计算 isLeft:2 个来定义段,1个是要测试的点。 因此,对于沿 LineString 的每个点,我们得到该点本身和前 2 个点的 X、Y 坐标。 我们将检查当前点相对于前两个点定义的线段的位置。 这也意味着当检测到转折点时,将是该段的最后一个点,即:前一个点。 我发现通过 Posgres 窗口函数这个计算出奇的简单。
  • 使用以上几点来计算 isLeft 的度量。
  • 选择此度量更改的点。

像往常一样,良好的代码实践通常也适用于数据库。 特别是,CTE 可用于阐明查询,就像在任何编程语言中命名变量或函数一样:以实现重用,同时通过提供描述性名称来增强可读性。 任何在该语言中通常被认为是正常的令人眼花缭乱的 SQL 查询都没有任何借口。

查看草图解决方案并与以下实现进行对比以了解我的意思:

WITH 
  -- Optional: area of interest.
  aoi AS (
    SELECT ST_SetSRID(
          ST_MakeBox2D(
            ST_Point(467399,4671999),
            ST_Point(470200,4674000))
          ,25831) 
        AS geom
  ),
  -- Simplify geometries to avoid excessive noise. Tolerance is empiric and depends on application
  simplified AS (
    SELECT oid as contour_id, ST_Simplify(input_contours.geom, 0.2) AS geom 
    FROM input_contours, aoi
    WHERE input_contours.geom && aoi.geom
  ), 
  -- Explode points generating index and keeping track of original curve
  points AS (
    SELECT contour_id,
        generate_series(1, st_numpoints(geom)) AS npoint,
        (ST_DumpPoints(geom)).geom AS geom
    FROM simplified
  ), 
  -- Get the numeric values for X an Y of the current point 
  coords AS (
    SELECT *, st_x(geom)::numeric AS cx, st_y(geom)::numeric AS cy
    FROM points    
    ORDER BY contour_id, npoint
  ),
  -- Add the values of the 2 previous points inside the same linestring
  -- LAG and PARTITION BY do all the work here.
  segments AS (
    SELECT *, 
      LAG(geom, 1)        over (PARTITION BY contour_id) AS prev_geom, 
      LAG(cx::numeric, 2) over (PARTITION BY contour_id) AS ax, 
      LAG(cy::numeric, 2) over (PARTITION BY contour_id) AS ay, 
      LAG(cx::numeric, 1) over (PARTITION BY contour_id) AS bx, 
      LAG(cy::numeric, 1) over (PARTITION BY contour_id) AS by
    FROM coords
    ORDER BY contour_id, npoint
  ),
  det AS (
    SELECT *, 
      (((bx-ax)*(cy-ay)) - ((by-ay)*(cx-ax))) AS det -- cross product in 2d
    FROM segments
  ),
  -- Uses the SIGN multipliaction as a proxy for XOR (change in convexity) 
  convexity AS (
    SELECT *, 
      SIGN(det) * SIGN(lag(det, 1) OVER (PARTITION BY contour_id))
AS change
    FROM det
  )
SELECT contour_id, npoint, prev_geom AS geom
FROM convexity
WHERE change = -1
ORDER BY contour_id, npoint

以下是示例区域的结果:
在这里插入图片描述


原文链接:PostGIS曲线拐点计算 — BimAnt

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

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

相关文章

AR VR 到底哪种技术可以改变未来?

随着科技的不断进步,虚拟现实(VR)和增强现实(AR)技术已经成为了当今科技领域的热门话题。VR和AR的出现,为人们带来了前所未有的体验和感受,也为各行各业的发展提供了新的机遇。但是,…

MySQL学习---14、变量、定义条件和处理程序

1、变量 在MySQL数据库的存储过程和函数中,可以使用变量来存储查询或计算的中间结果数据,或者输出最终的结果数据。 在MySQL数据库中,变量分为:1、系统变量2、用户自定义变量1、系统变量 1.1.1 系统变量分类 1、变量由系统定义…

SpringCloud使用SkyWalking实现分布式链路追踪2以及Prometheus全方位监控告警系统

文章目录 一、SkyWalking链路追踪使用Elasticsearch数据库1、SkyWalking连接Elasticsearch数据库2、SkyWalking自定义链路追踪3、SkyWalking的调用日志 二、SkyWalking链路追踪的告警功能1、SkyWalking的告警规则2、SkyWalking自定义告警规则3、SkyWalking实现网络钩子Webhooks…

基于springboot+vue的校园任务订单配送管理系统

随着我国教育制度的改革的发展,各大高校的学生数量也在不断的增加。当前大学生的生活和消费习惯等导致他们更喜欢通过网络来获取自己想要的商品和服务,这也是导致当前校园配送盛行的主要原因。为了能够让更多的学生享受到校园配送的服务,我们…

记录一次华三交换机配置IP地址和SNMP服务的过程

一、华三交换机配置IP地址 1、将交换机的console口连接到台式机,然后通过XShell连接到COM口 2、进入华三交换机的系统配置界面 命令:system-view 示例:system-view 3、创建vlan。输入vlan vlan-id命令创建一个VLAN。其中,vlan…

FreeRTOS_移植和配置

目录 1. 什么是FreeRTOS? 2. FreeRTOS 特点 3. FreeRTOS 移植 3.1 验证程序 1. 什么是FreeRTOS? 我们先看 FreeRTOS 的名字,可以分成两部分:Free 和 RTOS,Free 就是免费的、自由的、不受约束的意思,RTO…

016-fty_crkme3

运行程序 check错误 查壳 有UPX壳,ESP定律脱壳 载入OD分析 搜索字符串 向上找,找到段首 开始分析算法 搜先判断输入是否为空 再下面开始判断输入的字符除了 “-” 是不是满足0-9 如果满足的话,要再判断长度,0x9 到 0xB&#x…

【计算机组成原理】第一章 计算系统概论

系列文章目录 第一章 计算系统概论 第二章 运算方法和运算器 第三章 多层次的存储器 第四章 指令系统 第五章 中央处理器 第六章 总线系统 第七章 外围设备 文章目录 系列文章目录前言第一章 计算机系统概论1.1 计算机的分类1.2 计算机发展简史1.2.1 计算机的五代变化1.2.2 半…

19 KVM管理虚拟机-虚拟机生命周期管理命令

文章目录 19 KVM管理虚拟机-虚拟机生命周期管理命令19.1 概述19.2 前提条件19.3 命令使用说明 19 KVM管理虚拟机-虚拟机生命周期管理命令 19.1 概述 用户可以使用virsh命令工具管理虚拟机生命周期。本节介绍生命周期相关的命令以指导用户使用。 19.2 前提条件 执行虚拟机生…

uboot symbol value ‘‘ invalid for SYS_TEXT_BASE 解决方法

环境 Win10 64位 ubuntu 20.04 虚拟机 VMware Workstation 16 Pro gcc 交叉编译工具链: ARM 官方 gcc version 11.2.1 20220111 NUC980 uboot 版本 :尝试移植到 u-boot-2019.10,官方当前 u-boot 版本为 2016.11 问题描述 升级 u-boot …

ThinkPHP6 模板引擎普通标签中,模板引擎运算符函数,循环标签,判断标签的使用,及一些特殊标签

ThinkPHP6 模板引擎普通标签中,模板引擎运算符函数,循环标签,判断标签的使用,及一些特殊标签 模板引擎支持普通标签和XML标签方式两种标签定义,分别用于不同的目的: 标签类型描述普通标签主要用于输出变量…

Linux 安装 JDK、MySQL、Tomcat(图文并茂)

所需资料 下载 1.1 软件安装方式 在Linux系统中,安装软件的方式主要有四种,这四种安装方式的特点如下: 安装方式特点二进制发布包安装软件已经针对具体平台编译打包发布,只要解压,修改配置即可rpm安装软件已经按照re…

Unity里URP项目的介绍和创建

大家好,我是阿赵,接下来会介绍一下URP的使用 一、URP的介绍 URP(Universal Render Pipeline)通用渲染管线,是Unity在2019.3版本之后推出的一种新的渲染管线。 对比起默认的渲染管线,他的使用上会产生了一些变化,包括…

RS485电路及程序设计

一、电路原理图 图中 A、B 总线接口,用于连接 485 总线。RO 是接收输出端,DI 是发送数据收入端,RE是接收使能信号(低电平有效),DE 是发送使能信号(高电平有效)。RE DE接在一起就是高…

jenkins安装配置--持续集成

目录 1.什么是持续集成 1.1持续集成 Continuous integration ,简称CI 1.2持续集成具有的特点: 1.3持续集成的作用 2.jenkins简介 2.1概述 2.2特点 3.jenkins安装 1.下载Jenkins 2.下载jdk 3.网盘安装包载 4.创建软件安装目录 5.上传jdk和Jen…

C-内存管理

内存管理 堆,栈,静态区 c程序地址空间分布规则: 栈是从高地址向低地址延伸的,后创建的变量,后入栈,那么地址就越小. 静态变量,作用域不变,声明周期发生改变.本质原因是存储位置发生改变.编译器编译的时候放到了全局数据区. #include<stdio.h> #include<stdlib.h>…

虾皮Shopee商品详情接口(item_get-根据ID取商品详情)代码封装

item_get-根据ID取商品详情接口 通过代码封装该接口可以拿到商品标题&#xff0c;商品价格&#xff0c;商品促销信息&#xff0c;商品优惠价&#xff0c;商品库存&#xff0c;sku属性&#xff0c;商品图片&#xff0c;desc图片&#xff0c;desc描述&#xff0c;sku图片&#xf…

基于阿里云服务器安装宝塔Linux面板详细流程(有图)

使用阿里云服务器安装宝塔面板教程&#xff0c;阿里云百科以ECS云服务器CentOS操作系统为例&#xff0c;安装宝塔Linux面板&#xff0c;先远程连接到云服务器&#xff0c;然后执行宝塔面板安装命令&#xff0c;系统会自动安装宝塔面板&#xff0c;安装完成后会返回面板地址、账…

JS数据分组

JS对数据进行分组_js数据分组_柳宁依的博客-CSDN博客 原理没看懂&#xff0c;增加分组显示数据部分。 <html> <head> <style> select { display: block; margin: auto; } table { border-collapse: collapse; margin: auto; } th, td { border: 1px solid b…

“裸奔”时代下,我们该如何有效应对网络攻击、数据泄露和隐私侵犯

随着互联网的普及&#xff0c;越来越多的个人信息被上传到互联网上&#xff0c;而网络攻击、数据泄露和隐私侵犯等问题也日益严重。在这个“裸奔”时代&#xff0c;如何保护我们的网络隐私成为了一项紧迫的任务。本文将介绍一些实用的技巧和工具&#xff0c;帮助我们有效应对网…