【问题标题】:MakeValid not working for a single model objectMakeValid 不适用于单个模型对象
【发布时间】:2018-01-24 07:42:22
【问题描述】:

我正在尝试使用 MakeValid 来修复(验证)我的几何字段。
我可以通过单行获取和更新来使其工作:

from django.contrib.gis.db.models.functions import MakeValid

MyModel.objects.filter(id=<id>).update(polygon=MakeValid('polygon'))

但在某些情况下,我必须更新已经在函数中实例化的单个模型对象的 polygon(这意味着我已经完成了 .filter/.get),这给了我以下错误:

// np is an object of MyModel which has a field 'polygon' which is `MultiPolygon` django model field
np.polygon = MakeValid(np.polygon)
// np.save()
TypeError: Cannot set MyModel SpatialProxy (MULTIPOLYGON) with value of type: <class 'django.contrib.gis.db.models.functions.MakeValid'>

这里,MakeValid(np.polygon) 不返回 MultiPolygon 对象。相反,它返回一个django.contrib.gis.db.models.functions.MakeValid 包装器。

我可以从MakeValid 获取几何对象吗?

【问题讨论】:

  • np.polygon 是多面体吗?我记得在某处读过 makeValid 不支持多面体
  • 是的。也有问题更新。它也适用于 MultiPolygons。第一个查询工作正常。
  • 仅供参考,这个问题是subject of a meta question

标签: python django django-views postgis geodjango


【解决方案1】:

因为stated in the linked postMakeValiddatabase function,也就是说只能在查询数据库的时候执行。

它是一对一的,类似于ST_MakeValidPostGIS 用法,不能在表查询之外执行(不能自主存在)。

当你创建np对象,然后你尝试做:

np.polygon = MakeValid(np.polygon)

您实际上是在尝试将数据库函数应用于不应工作的“MyModel”类的实例! (因为它没有)


你可以做什么:

  1. 您可以创建查询来更新特定的表行:

    np = MyModel.objects.filter(id=np.id).update(polygon=MakeValid('polygon'))
    

    注意: 带有id=np.id 多边形的对象,将在 使用该方法永久保存数据库。

  2. 您可以使用GEOSGeometry.buffer()

    使用polygon.buffer(0) 可以整理大部分多边形的不规则性(它甚至可以解决某些类型的“蝴蝶结”/自相交多边形)

    np.polygon.valid          # False
    np.polygon.buffer(0)      # Make valid with buffer(0)
    np.polygon.valid          # True
    
  3. 最后,您可以使用Shapely 并为您的计算创建一个形状多边形,您可以使用与上述相同的方法使其有效(Shapely's bufferGeoDjango's buffer 都使用GEOS 库):

    from shapely.geometry import Polygon
    
    # Initialize the polygon object with one of the following ways:
    np_polygon = Polygon([np.polygon.coords])
    # or
    np_polygon = Polygon(np.polygon.wkt)
    
    np_polygon.is_valid                 # False
    np_polygon = np_polygon.buffer(0)   # Make valid with buffer(0)
    np_polygon.is_valid                 # True
    

【讨论】:

  • 我的函数中已经有对象np。使用filter 再次获取它然后更新它会使其效率低下,对吧?
  • @ajaysingh 是的,它会有点低效,所以你需要决定使用MakeValid 函数。另一种解决方案是为模型对象创建MakeValid,而不是作为数据库函数,但这可能过于复杂。
  • 您能给我一些关于如何为模型对象创建MakeValid 的指导吗?
  • @ajaysingh 我想我找到了一些没有太多复杂性的解决方案。看看我编辑的答案!
  • 嘿,我今天才试过。这有点适合我。但它有时返回Polygon 对象,有时返回MultiPolygon 对象。有什么想法吗?还有,MakeValidbuffer(0)有什么区别吗?
猜你喜欢
  • 2018-06-19
  • 1970-01-01
  • 2019-08-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-21
相关资源
最近更新 更多