【问题标题】:SQL Geography.STContains returns false valuesSQL Geography.STContains 返回错误值
【发布时间】:2018-08-21 08:59:01
【问题描述】:

我正在创建几个地理变量,并且我想检查该位置内是否存在一组坐标。我使用 STContains 来确定。对于大多数变量,这似乎是有效的,但我无法理解以下情况:

CREATE TABLE MAP_AREA (Position geography)

INSERT INTO MAP_AREA (Position)
VALUES (0xE610000002242D0000007DD0B359F519374025068195432F63C0956588635D8C36403F355EBA492063C0CB10C7BAB81D364054E3A59BC41063C0956588635D7C354096438B6CE7FF62C0DA1B7C6132A53440BE9F1A2FDDF062C0A913D044D8203440C74B378941EC62C06A4DF38E53943340C3F5285C8FEA62C0CE88D2DEE00B33401D5A643BDFEB62C0371AC05B208132404E62105839F062C0C7293A92CB8F31403F355EBA490063C02E90A0F831C630400AD7A3703D1A63C0EE5A423EE8D92F40E5D022DBF94663C0A167B3EA73752F40BE9F1A2FDD5863C070CE88D2DE402F401D5A643BDF6B63C0265305A3925A2F4025068195438B63C08F53742497FF2F404C37894160A963C003780B24286E304048E17A14AEBF63C09FCDAACFD5E63040C74B378941D063C068226C787A853140EE7C3F355EDE63C0E86A2BF6972D3240643BDF4F8DE763C004E78C28ED7D3240BC74931804FE63C0E0BE0E9C33823240068195438B1464C09D8026C286A7324083C0CAA1452A64C0EF38454772293340E5D022DBF94A64C09F3C2CD49AA6334062105839B45C64C027A089B0E13934400AD7A3703D6A64C03FC6DCB584EC3440E3A59BC4207464C0CDCCCCCCCC9C35407F6ABC74937864C02EFF21FDF6553640A4703D0AD77764C058A835CD3B0E374021B07268917164C058A835CD3BAE37406DE7FBA9F16664C04F401361C34338405EBA490C025764C003780B2428AE3840D7A3703D0A4764C0386744696F003940068195438B3464C0E8D9ACFA5C5D3940E17A14AE471564C0E0BE0E9C33823940A245B6F3FDFC63C04BC8073D9B853940F0A7C64B37E563C022FDF675E06C3940B81E85EB51D063C0B537F8C2643A3940B0726891EDBC63C0BD5296218EF538401D5A643BDFAB63C035EF384547B23840B4C876BE9F8E63C05BD3BCE3145D384017D9CEF7537B63C0772D211FF4DC3740560E2DB29D5363C00C93A9825189374077BE9F1A2F4163C07DD0B359F519374025068195432F63C001000000010000000001000000FFFFFFFF0000000003)

DECLARE @position GEOGRAPHY
SET @position = GEOGRAPHY::Point(70,70,4326)

SELECT MAP.POSITION.STContains(@position)
FROM MAP_AREA MAP

在这种情况下,无论位置如何,我都会得到正值。地理包括除了地理之外的所有世界吗?有没有人遇到过类似的情况?

【问题讨论】:

  • 我从这段代码中得到一个零(诚然是 2014 年而不是 2016 年,但如果它在版本之间发生如此明显的变化,那将是令人惊讶的)。
  • @Damien_The_Unbeliever 你是对的,我更新了这个问题。问题是,架构以某种方式包含了除我的地理以外的所有单词..
  • 是的,现在您已将其切换到我在阅读标题时所预期的问题。在赤道周围画一条线。我是封闭半球还是半球?当您在地球表面上绘制多边形时,内部或外部没有“自然”。所以 SQL Server 使用left-hand rule。颠倒您访问多边形中点的顺序。如果您已经拥有geography,还有一个ReorientObject 函数
  • 如果您在结果集中包含Position,您可能很容易看到这一点——假设您使用的是SSMS。它包括一个可视化工具,以便您可以查看 SQL Server 如何处理您的形状。
  • @Damien_The_Unbeliever 这就是答案!感谢您的及时回复。 ReorientObject 解决了我的问题。

标签: sql-server sql-server-2016 sqlgeography


【解决方案1】:

@Damien_The_Unbeliever 正确指出,左手规则是问题的根源。奇怪的是,GeoJSON 标准遵循似乎相反的右手法则。希望这些人在某个时候保持一致。

由于我无法控制数据进入的循环顺序,我别无选择,只能在每次将地理数据存储到 db 之前进行此检查。这是我编写的一个 python 函数,用于检查给定的多边形(在 WKT 中,但您可以为二进制自定义它),如果它不是左手规则,则将其反转并返回反转的多边形以进行进一步的操作。它使用 sql server 但不执行任何数据库写入。

def ensureProperPolygon(shapewkt):
    # resolve inverted polygon issues if any

    s1 = f"select geography::Parse('{shapewkt}').STArea() - geography::Parse('{shapewkt}').ReorientObject().STArea()"
    testarea = dbconnection.makeQuery(s1,output='oneValue')
    if testarea > 0:
        cf.logmessage("Inverting the polygon to comply with left hand rule")
        s2 = f"select geography::Parse('{shapewkt}').ReorientObject().STAsText()"
        newshape = dbconnection.makeQuery(s2,output='oneValue')
        return newshape
    else:
        return shapewkt

注意:dbconnection.makeQuery() 只是我的程序处理数据库操作的一站式功能;你可以在最后用engine.execute()左右替换它。

它的作用是计算给定多边形的面积及其倒转双胞胎的面积,并得到它们的差值。错误的面积将大致等于地球的面积(减去您的实际面积)并且会更大。所以如果 diff 是正数,那么原来的形状是错误的,必须颠倒过来。

这确实需要使用数据库服务器;在我的用例中,我有足够的余地这样做。在 python 本身中有一种方法可以做到这一点,现在我不想进入地理空间库、技术等,所以使用它。如果在 python 本身中有一种快速的方法,请邀请其他答案。

【讨论】:

    猜你喜欢
    • 2018-09-02
    • 1970-01-01
    • 2011-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-31
    • 2019-02-03
    相关资源
    最近更新 更多