[Solved] MakeValid not working for a single model object


As stated in the linked post MakeValid is a database function, which means that it can be executed only during querying the database.

It is 1-to-1 similar to the PostGIS usage of ST_MakeValid which cannot be executed outside of a table query (cannot exist autonomously).

When you create the np object, and then you try to do:

np.polygon = MakeValid(np.polygon)

You are essentially trying to apply a database function to an instance of the ‘MyModel’ class which isn’t supposed to work! (as it does not)


What you can do:

  1. You can create a query to update a specific table row:

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

    Note: The object with id=np.id‘s polygon, will be updated in the
    database permanently with that method.

  2. You can utilize the GEOSGeometry.buffer():

    Using polygon.buffer(0) can tidy up most of the polygon irregularities (it can even solve some types of “bowtie”/self-intersecting polygons)

    np.polygon.valid          # False
    np.polygon.buffer(0)      # Make valid with buffer(0)
    np.polygon.valid          # True
    
  3. Finally, you can use Shapely and create a shapely polygon for your calculations which you can make valid with the same method as above (both Shapely’s buffer and GeoDjango’s buffer use GEOS library):

    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
    

7

solved MakeValid not working for a single model object