SQL Geography.STContains返回错误值

时间:2018-08-21 08:59:02

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

我正在创建几个地理变量,我想检查该位置内是否存在一组坐标。我使用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

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

1 个答案:

答案 0 :(得分:0)

左手规则是@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本身有快速的方法,请其他答案。