Commit cdaa580a authored by jlaura's avatar jlaura Committed by GitHub
Browse files

Valid geom trigger in the db (#325)

* Trigger to do geometry validation

* Working geomvalidator with tests
parent 50fce548
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -193,7 +193,7 @@ class Images(BaseMixin, Base):
    name = Column(String)
    path = Column(String)
    serial = Column(String, unique=True)
    active = Column(Boolean)
    active = Column(Boolean, default=True)
    _footprint_latlon = Column("footprint_latlon", Geometry('MultiPolygon', srid=srid, dimension=2, spatial_index=True))
    footprint_bodyfixed = Column(Geometry('MULTIPOLYGON', dimension=2))
    #footprint_bodyfixed = Column(Geometry('POLYGON',dimension=3))
@@ -330,7 +330,7 @@ class Measures(BaseMixin, Base):
        self._measuretype = v

if Session:
    from autocnet.io.db.triggers import valid_point_function, valid_point_trigger
    from autocnet.io.db.triggers import valid_point_function, valid_point_trigger, valid_geom_function, valid_geom_trigger
    # Create the database
    if not database_exists(engine.url):
        create_database(engine.url, template='template_postgis')  # This is a hardcode to the local template
@@ -339,6 +339,8 @@ if Session:
        # based on the point count.
        event.listen(Base.metadata, 'before_create', valid_point_function)
        event.listen(Measures.__table__, 'after_create', valid_point_trigger)
        event.listen(Base.metadata, 'before_create', valid_geom_function)
        event.listen(Images.__table__, 'after_create', valid_geom_trigger)

    Base.metadata.bind = engine
    # If the table does not exist, this will create it. This is used in case a
+17 −1
Original line number Diff line number Diff line
@@ -5,7 +5,7 @@ import numpy as np
import pandas as pd
import pytest
import sqlalchemy
from shapely.geometry import Polygon, Point
from shapely.geometry import MultiPolygon, Polygon, Point
from unittest.mock import MagicMock, patch

from autocnet.io.db import model
@@ -168,3 +168,19 @@ def test_jigsaw_append(mockFunc, session, measure_data, point_data, image_data):
    resp = session.query(model.Measures).filter(model.Measures.id == 1).first()
    assert resp.liner == 0.1
    assert resp.sampler == 0.1

def test_broken_bad_geom(session):
    # An irreperablly damaged poly
    geom = MultiPolygon([Polygon([(0,0), (1,1), (1,2), (1,1), (0,0)])])
    i = model.Images.create(session, footprint_latlon=geom,
                                      serial = 'serial')
    resp = session.query(model.Images).filter(model.Images.id==i.id).one()
    assert resp.active == False
    
def test_fix_bad_geom(session):
    geom = MultiPolygon([Polygon([(0,0), (0,1), (1,1), (0,1), (1,1), (1,0), (0,0) ])])
    i = model.Images.create(session, footprint_latlon=geom,
                                     serial = 'serial' )
    resp = session.query(model.Images).filter(model.Images.id==i.id).one()
    assert resp.active == True
    assert resp.footprint_latlon == MultiPolygon([Polygon([(0,0), (0,1), (1,1), (1,0), (0,0) ])])
+25 −0
Original line number Diff line number Diff line
from sqlalchemy.schema import DDL

valid_geom_function = DDL("""
CREATE OR REPLACE FUNCTION validate_geom()
  RETURNS trigger AS
$BODY$
  BEGIN
      NEW.footprint_latlon = ST_MAKEVALID(NEW.footprint_latlon);
      RETURN NEW;
    EXCEPTION WHEN OTHERS THEN
      NEW.active = false;
      RETURN NEW;
END;
$BODY$

LANGUAGE plpgsql VOLATILE -- Says the function is implemented in the plpgsql language; VOLATILE says the function has side effects.
COST 100; -- Estimated execution cost of the function.
""")

valid_geom_trigger = DDL("""
CREATE TRIGGER image_inserted
  BEFORE INSERT OR UPDATE
  ON images
  FOR EACH ROW
EXECUTE PROCEDURE validate_geom();
""")

valid_point_function = DDL("""
CREATE OR REPLACE FUNCTION validate_points()
  RETURNS trigger AS