Added OffDbRasterField, changed orthophoto type from RasterField to OffDbRasterField

pull/66/head
Piero Toffanin 2016-12-12 10:32:17 -05:00
rodzic dcdf69feb9
commit 5c54aca9c1
4 zmienionych plików z 89 dodań i 40 usunięć

Wyświetl plik

@ -4,7 +4,6 @@ import shutil
import zipfile
from django.contrib.auth.models import User
from django.contrib.gis.db import models as gismodels
from django.contrib.gis.gdal import GDALRaster
from django.contrib.postgres import fields
from django.core.exceptions import ValidationError
@ -18,6 +17,7 @@ from guardian.models import UserObjectPermissionBase
from guardian.shortcuts import get_perms_for_model, assign_perm
from app import pending_actions
from app.postgis import OffDbRasterField
from nodeodm import status_codes
from nodeodm.exceptions import ProcessingException
from nodeodm.models import ProcessingNode
@ -139,7 +139,7 @@ class Task(models.Model):
ground_control_points = models.FileField(null=True, blank=True, upload_to=gcp_directory_path, help_text="Optional Ground Control Points file to use for processing")
# georeferenced_model
orthophoto = gismodels.RasterField(null=True, blank=True, srid=4326, help_text="Orthophoto created by OpenDroneMap")
orthophoto = OffDbRasterField(null=True, blank=True, srid=4326, help_text="Orthophoto created by OpenDroneMap")
# textured_model
# mission
created_at = models.DateTimeField(default=timezone.now, help_text="Creation date")

Wyświetl plik

@ -7,11 +7,14 @@ from django.contrib.gis.db.backends.postgis.pgraster import (
STRUCT_SIZE,
pack)
from django.contrib.gis.db.backends.postgis.pgraster import chunk, unpack
from django.contrib.gis.db.models.fields import RasterField
from django.contrib.gis.db.models.fields import RasterField, BaseSpatialField
from django.contrib.gis.gdal import GDALException
from django.contrib.gis.gdal import GDALRaster
from django.forms import ValidationError
from django.utils.translation import ugettext_lazy as _
class OutOfDbRasterField(RasterField):
class OffDbRasterField(RasterField):
"""
Out-of-db Raster field for GeoDjango -- evaluates into GDALRaster objects.
"""
@ -19,14 +22,42 @@ class OutOfDbRasterField(RasterField):
description = _("Out-of-db Raster Field")
def from_db_value(self, value, expression, connection, context):
return connection.ops.parse_raster(value)
return from_pgraster(value, True)
def get_db_prep_save(self, value, connection):
"""
Prepare the value for saving in the database.
"""
if not value:
return None
else:
return to_pgraster(value, True)
def get_db_prep_value(self, value, connection, prepared=False):
self._check_connection(connection)
# Prepare raster for writing to database.
if not prepared:
value = connection.ops.deconstruct_raster(value)
return super(OutOfDbRasterField, self).get_db_prep_value(value, connection, prepared)
value = to_pgraster(value, True)
# Call RasterField's base class get_db_prep_value
return BaseSpatialField.get_db_prep_value(self, value, connection, prepared)
def get_raster_prep_value(self, value, is_candidate):
"""
Return a GDALRaster if conversion is successful, otherwise return None.
"""
if isinstance(value, GDALRaster):
return value
elif is_candidate:
try:
return GDALRaster(value)
except GDALException:
pass
elif isinstance(value, (dict, str)):
try:
return GDALRaster(value)
except GDALException:
raise ValueError("Couldn't create spatial object from lookup value '%s'." % value)
class POSTGIS_BANDTYPES(object):
@ -35,7 +66,7 @@ class POSTGIS_BANDTYPES(object):
BANDTYPE_FLAG_ISNODATA = 1 << 5
def from_pgraster(data):
def from_pgraster(data, offdb = False):
"""
Convert a PostGIS HEX String into a dictionary.
"""
@ -111,16 +142,18 @@ def from_pgraster(data):
if len(set(pixeltypes)) != 1:
raise ValidationError("Band pixeltypes are not all equal.")
return {
'srid': int(header[9]),
'width': header[10], 'height': header[11],
'datatype': pixeltypes[0],
'origin': (header[5], header[6]),
'scale': (header[3], header[4]),
'skew': (header[7], header[8]),
'bands': bands,
}
if offdb and len(bands) > 0:
return bands[0]['path']
else:
return {
'srid': int(header[9]),
'width': header[10], 'height': header[11],
'datatype': pixeltypes[0],
'origin': (header[5], header[6]),
'scale': (header[3], header[4]),
'skew': (header[7], header[8]),
'bands': bands,
}
def to_pgraster(rast, offdb = False):

Wyświetl plik

@ -1,22 +0,0 @@
from django.contrib.gis.gdal import GDALRaster
from .classes import BootTestCase
from app.fields import from_pgraster, to_pgraster
import os
class TestApi(BootTestCase):
def setUp(self):
pass
def tearDown(self):
pass
def test_pgraster_functions(self):
# Make sure conversion from PostGIS <---> GDALRaster works
# for out-of-db
raster = GDALRaster(os.path.join("app", "fixtures", "orthophoto.tif"))
self.assertTrue(raster.srid == 32615)
self.assertTrue(raster.width == 212)
#hexwkb =

Wyświetl plik

@ -0,0 +1,38 @@
from django.contrib.gis.gdal import GDALRaster
from .classes import BootTestCase
from app.postgis import from_pgraster, to_pgraster
import os
class TestApi(BootTestCase):
def setUp(self):
pass
def tearDown(self):
pass
def test_pgraster_functions(self):
# Make sure conversion from PostGIS <---> GDALRaster works
# for out-of-db
raster = GDALRaster(os.path.join("app", "fixtures", "orthophoto.tif"))
self.assertTrue(raster.srid == 32615)
self.assertTrue(raster.width == 212)
# Classic
hexwkb = to_pgraster(raster)
deserialized_raster = GDALRaster(from_pgraster(hexwkb))
self.assertTrue(len(deserialized_raster.bands) == 4)
self.assertTrue(deserialized_raster.srid == raster.srid)
self.assertTrue(deserialized_raster.width == raster.width)
self.assertTrue(deserialized_raster.height == raster.height)
# Off-db
hexwkb = to_pgraster(raster, True)
deserialized_raster = GDALRaster(from_pgraster(hexwkb, True))
self.assertTrue(deserialized_raster.name == raster.name)
self.assertTrue(deserialized_raster.srid == raster.srid)
self.assertTrue(deserialized_raster.width == raster.width)
self.assertTrue(deserialized_raster.height == raster.height)