STIntersect表示每个点都与每个区域相交-需要确认

如何解决STIntersect表示每个点都与每个区域相交-需要确认

我正在为一个工业集团实施车辆安全计划。该小组提供了3k +个地理区域,覆盖了属于该小组成员的站点。提供的文件是shapefile。我的同事将其提取并转换为4326,然后将其上传到新数据库中。我使用IsValidDetailed()检查了区域。 7个无效,但在对它们运行MakeValid()时会纠正。仅使用自动,地理表SaferTogether就创建了空间索引。

我最初使用以下工具进行测试。这将在每个区域的每个点上运行,一个多小时后,我得到了结果。

INSERT INTO @Intersects (LogId,ogr_fid,NodeId)
SELECT p.LogId,s.ogr_fid,p.NodeId
FROM LogPos p,[gis]..safertogether as s
WHERE p.MyPoint.STIntersects(s.geog4326) = 1
and AssembledTime between @PeriodStart and @PeriodEnd

我现在正在测试27个对数点的单程旅行,我注意到我有81162个结果,这大致匹配27个点x 3k +区域。我不认为每个区域都覆盖每个点。下面的代码是对一趟日志的测试。效率不高。

UPDATE #Logs
SET IsIntersect = 0

SET @Message = 'Detecting Log intersects with Zone ' + CONVERT(VARCHAR(10),@GeographyId) + ':' + @GeographyName
EXEC usp_Log @ProcessName,@Message,@SessionName,@LogInfo,@Section

UPDATE #Logs
SET IsIntersect = 1
WHERE @Geography.STIntersects(MyPoint) = 1

SELECT @rc = COUNT(1)
FROM #Logs WHERE IsIntersect = 1

SET @Message = 'Trip ' + CONVERT(VARCHAR(10),@TripLogId) + ' intersecting points with ' + CONVERT(VARCHAR(10),@GeographyId) + ':' + @GeographyName + ': ' + CONVERT(varchar(10),@rc)
EXEC usp_Log @ProcessName,@LogDebug,@Section

SET @Message = 'Save intersects with ' + CONVERT(VARCHAR(10),@Section

INSERT INTO @Intersects (LogId,NodeId,ogr_fid)
SELECT 
    LogId,@GeographyId
FROM #Logs
WHERE IsIntersect = 1

我在这里寻找的是一种可视化区域与点的方法,这样我就可以知道它们是否损坏。我不知道如何比较内置空间结果标签中的字段。

解决方法

问题可能出在shapefile(平面图)数据到SQL Server地理(球形)模型的转换中。这些很容易做错,并且会倒置(互补的)多边形,即描述所有地球区域的多边形预期的形状

也看到了一些类似的情况,例如Google BigQuery,它使用了类似球形定向多边形的语义:

您可以通过计算多边形的面积来检查多边形是否被正确地提取到数据库中-对于倒置的多边形,多边形将是巨大的(5e14 m ^ 2的量级),而正确提取的多边形应该得到合理的结果。

SQL Server具有ReorientObject()方法,该方法可反转多边形的方向。不过要小心,因为方向与有效性会相互作用-因此最好在ReorientObject()之前使用MakeValid()。当然,最好的办法就是修复摄取方法。

或者,您可以使用使用平面地图语义的SQL Server Geometry(而不是Geography)类型。处理平面数据存在一些问题,但是假设您不交叉反子午线,并且对哪种投影适合哪种计算有基本的了解,通常应该没事。

或切换到使用球形模式但可以正确解释和转换平面数据的数据库。例如。 BigQuery理解GeoJson几何是平面的,并且在将其转换为内部球形Geography模型时会忽略它们的方向,因此,如果将Geometry加载为GeoJson字段,则永远不会出现此问题。

,

下面是我使用的最终脚本,以防万一需要帮助的人。

@Shapes是一个表变量。它被插入物填充,然后被游标循环。

每个光标循环@Shape都经过有效性测试。如果无效,则运行MakeValid()。然后测试它是否是MULTIPOLYGON。如果是这样,它将被分解为@SubShapes。如果是单个形状,则将该形状分配给第一个@SubShape。

每个@SubShape都经过验证和面积测试。如果需要,将运行MakeValid()ReorientObject()

运行完@Shape的所有@SubShapes之后,如果@Shape是MULTIPOLYGON,则将其放回原处。这是通过字符串连接和对WellKnownText的操作来完成的。这是我最不满意的一点。感觉就像是地理API的空白。

所有@Shapes处理完毕后,它们会写回到真实表中

usp_Log_Error是一个内部日志记录过程。随时将其注释掉

SET NOCOUNT ON

DECLARE @ProcessName varchar(50) = 'ST_Geography_Validation'
DECLARE @SessionName varchar(50) = 'ST_GV_' + CONVERT(VARCHAR(19),GETDATE(),126)
DECLARE @Message varchar(1000)

DECLARE @Id int 
DECLARE @Name varchar(254) 
DECLARE @Shape geography
DECLARE @ValidationDetail varchar(200)
DECLARE @ShapeCount int

DECLARE @SubValidationDetail varchar(200)
DECLARE @SubShape geography
Declare @Area float
DECLARE @AreaStr varchar(20)

DECLARE @i int

DECLARE @IsMulti int = 0
DECLARE @MultiWKT varchar(MAX)
DECLARE @SingleWKT varchar(MAX)

DECLARE @Shapes TABLE
(
    Id int,Name varchar(254),Shape geography
)

INSERT INTO @Shapes (Id,Name,Shape)
SELECT
    ogr_fid,name,geog4326
FROM safertogether2


DECLARE @SubShapes TABLE
(
    SubId int PRIMARY KEY,SubShape geography,Processed bit default 0
)

DECLARE _c CURSOR FOR
    SELECT 
        s.Id,s.name,s.Shape,'',''
    FROM @Shapes s

    OPEN _c  
        FETCH NEXT FROM _c INTO @Id,@Name,@Shape,@IsMulti,@MultiWKT,@SingleWKT

        WHILE @@FETCH_STATUS = 0  
        BEGIN

            DELETE FROM @SubShapes

            SET @ValidationDetail = @Shape.IsValidDetailed() -- This is for the base shape
            IF @ValidationDetail <> '24400: Valid'
            BEGIN
                SET @Shape = @Shape.MakeValid()
            END

            SET @ShapeCount = @Shape.STNumGeometries()
            IF @ShapeCount > 1
            BEGIN
                RAISERROR('%i:%s: is MULTIPOLYGON. Break into subshapes.',1,@Id,@Name) WITH NOWAIT
                SET @IsMulti = 2
                INSERT INTO @SubShapes(SubId,SubShape)
                SELECT 
                    smg.Id,smg.Geog 
                FROM [dbo].uf_SplitMultiGeography(@Shape) smg
            END
            ELSE IF @ShapeCount = 1
            BEGIN 
                RAISERROR('%i:%s: is SINGLE. Insert Shape whole as Id 1.',@Name) WITH NOWAIT
                SET @IsMulti = 1
                INSERT INTO @SubShapes(SubId,SubShape) 
                VALUES (1,@Shape)
            END
            ELSE
            BEGIN 
                RAISERROR('%i:%s: is NONE.',@Name) WITH NOWAIT
                SET @IsMulti = 0
            END

            SET @i = 1
            WHILE @i <= @ShapeCount
            BEGIN
                SELECT @SubShape = s.SubShape
                FROM @SubShapes s
                WHERE SubId = @i

                SET @SubValidationDetail = @SubShape.IsValidDetailed()
                RAISERROR('%i:%s:%i: .IsValidDetailed(): %s',@i,@SubValidationDetail) WITH NOWAIT

                IF @SubValidationDetail <> '24400: Valid'
                BEGIN
                    RAISERROR('%i:%s:%i: .MakeValid()',@i) WITH NOWAIT
                    SET @SubShape = @SubShape.MakeValid() -- This is for the subshape
                END

                BEGIN TRY
                    SET @Area = @SubShape.STArea()
                END TRY
                BEGIN CATCH
                    SET @Message = 'While getting the Area of a subshape'
                    EXEC usp_Log_Error @ProcessName,@SessionName,@Message
                END CATCH
            
                SET @AreaStr = LTRIM(STR(@Area,20,5))
                RAISERROR('%i:%s:%i: .STArea(): Pre: %s',@AreaStr) WITH NOWAIT
                IF @Area > 510000000000000
                BEGIN
                    RAISERROR('%i:%s:%i: .ReorientObject()',@i) WITH NOWAIT
                    SET @SubShape = @SubShape.ReorientObject()
                    SET @Area = @SubShape.STArea()
                    SET @AreaStr = LTRIM(STR(@Area,5))
                    RAISERROR('%i:%s:%i: .STArea(): Post: %s',@AreaStr) WITH NOWAIT
                END

                UPDATE @SubShapes 
                SET SubShape = @SubShape
                WHERE SubId = @Id

                IF @IsMulti = 2
                BEGIN
                    RAISERROR('%i:%s:%i: MULTIPOLYGON member.  Process WKT for recombination',@i) WITH NOWAIT
                    BEGIN TRY
                        SET @SingleWKT = @SubShape.STAsText()
                    END TRY
                    BEGIN CATCH
                        SET @Message = 'While getting the WKT of a subshape'
                        EXEC usp_Log_Error @ProcessName,@Message
                    END CATCH

                    SET @SingleWKT = REPLACE(@SingleWKT,'POLYGON','')
                    IF (@i <> @ShapeCount)
                    BEGIN
                        SET @SingleWKT = REPLACE(@SingleWKT,'))',')),')
                    END
                    SET @MultiWKT = @MultiWKT + @SingleWKT
                END
                SET @i = @i + 1
            END

        
            IF @IsMulti = 2
            BEGIN
                RAISERROR('%i:%s: Is a MULTIPOLYGON.  Recreate from updated WKT.',@i) WITH NOWAIT
                SET @MultiWKT = 'MULTIPOLYGON(' + @MultiWKT + ')'
                BEGIN TRY
                    SET @Shape = geography::STGeomFromText(@MultiWKT,4326)
                END TRY
                BEGIN CATCH
                    SET @Message = 'While creating a multipolygon'
                    EXEC usp_Log_Error @ProcessName,@Message
                END CATCH
            END
            ELSE IF @IsMulti = 1
            BEGIN
                RAISERROR('%i:%s: Is SINGLE.  Set Shape to subshape',@i) WITH NOWAIT
                SET @Shape = @SubShape
            END
            ELSE
            BEGIN
                RAISERROR('%i:%s: Is NONE.  Set Shape to none',@i) WITH NOWAIT
            END

            RAISERROR('%i:%s: Update temp table',@Name) WITH NOWAIT
            UPDATE @Shapes
            SET Shape = @Shape
            WHERE Id = @Id

            FETCH NEXT FROM _c INTO @Id,@SingleWKT
        END
    CLOSE _c
DEALLOCATE _c

select 
    st.ogr_fid,st.name,st.geog4326 as ShapePre,s.Shape as ShapePost,CASE 
        WHEN  st.geog4326.IsValidDetailed() = '24400: Valid' then st.geog4326.STArea()
        ELSE st.geog4326.MakeValid().STArea()
    END as AreaPre,CASE 
        WHEN  s.Shape.IsValidDetailed() = '24400: Valid' then s.Shape.STArea()
        ELSE s.Shape.MakeValid().STArea()
    END as AreaPost  
from safertogether2 st
join @Shapes s ON s.Id = st.ogr_fid

RAISERROR('Update back to safertogether table',1) WITH NOWAIT
UPDATE st
SET geog4326 = s.Shape
FROM @Shapes s
JOIN safertogether2 st ON s.Id = st.ogr_fid


RAISERROR('End of Script',@Name) WITH NOWAIT

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-