Ticket #11433: 3d_fix_v1.diff

File 3d_fix_v1.diff, 9.9 KB (added by jbronn, 5 years ago)

First draft of 3D fix. More tests are needed.

  • django/contrib/gis/geos/geometry.py

     
    375375        """
    376376        # A possible faster, all-python, implementation:
    377377        #  str(self.wkb).encode('hex')
    378         return wkb_w.write_hex(self)
     378        if self.hasz:
     379            return wkb_w3d.write_hex(self)
     380        else:
     381            return wkb_w.write_hex(self)
    379382
    380383    @property
    381384    def json(self):
     
    392395    @property
    393396    def wkb(self):
    394397        "Returns the WKB of the Geometry as a buffer."
    395         return wkb_w.write(self)
     398        if self.hasz:
     399            return wkb_w3d.write(self)
     400        else:
     401            return wkb_w.write(self)
    396402
    397403    @property
    398404    def kml(self):
     
    617623                }
    618624
    619625# Similarly, import the GEOS I/O instances here to avoid conflicts.
    620 from django.contrib.gis.geos.io import wkt_r, wkt_w, wkb_r, wkb_w
     626from django.contrib.gis.geos.io import wkt_r, wkt_w, wkb_r, wkb_w, wkb_w3d
    621627
    622628# If supported, import the PreparedGeometry class.
    623629if GEOS_PREPARE:
  • django/contrib/gis/geos/prototypes/geom.py

     
    6262
    6363### ctypes prototypes ###
    6464
    65 # Deprecated creation routines from WKB, HEX, WKT
     65# Deprecated creation and output routines from WKB, HEX, WKT
    6666from_hex = bin_constructor(lgeos.GEOSGeomFromHEX_buf)
    6767from_wkb = bin_constructor(lgeos.GEOSGeomFromWKB_buf)
    6868from_wkt = geom_output(lgeos.GEOSGeomFromWKT, [c_char_p])
    6969
    70 # Output routines
    7170to_hex = bin_output(lgeos.GEOSGeomToHEX_buf)
    7271to_wkb = bin_output(lgeos.GEOSGeomToWKB_buf)
    7372to_wkt = string_from_geom(lgeos.GEOSGeomToWKT)
    7473
    75 # The GEOS geometry type, typeid, num_coordites and number of geometries
     74# The GEOS geometry type, typeid, num_coordinates and number of geometries
    7675geos_normalize = int_from_geom(lgeos.GEOSNormalize)
    7776geos_type = string_from_geom(lgeos.GEOSGeomType)
    7877geos_typeid = int_from_geom(lgeos.GEOSGeomTypeId)
  • django/contrib/gis/geos/io.py

     
    1414    "Base class for GEOS I/O objects."
    1515    def __init__(self):
    1616        # Getting the pointer with the constructor.
    17         self.ptr = self.constructor()
     17        self.ptr = self._constructor()
    1818
    1919    def __del__(self):
    2020        # Cleaning up with the appropriate destructor.
    21         if self._ptr: self.destructor(self._ptr)
     21        if self._ptr: self._destructor(self._ptr)
    2222
    2323### WKT Reading and Writing objects ###
    2424
    2525# Non-public class for internal use because its `read` method returns
    2626# _pointers_ instead of a GEOSGeometry object.
    2727class _WKTReader(IOBase):
    28     constructor = capi.wkt_reader_create
    29     destructor = capi.wkt_reader_destroy
     28    _constructor = capi.wkt_reader_create
     29    _destructor = capi.wkt_reader_destroy
    3030    ptr_type = capi.WKT_READ_PTR
    3131
    3232    def read(self, wkt):
     
    3939        return GEOSGeometry(super(WKTReader, self).read(wkt))
    4040
    4141class WKTWriter(IOBase):
    42     constructor = capi.wkt_writer_create
    43     destructor = capi.wkt_writer_destroy
     42    _constructor = capi.wkt_writer_create
     43    _destructor = capi.wkt_writer_destroy
    4444    ptr_type = capi.WKT_WRITE_PTR
    4545
    4646    def write(self, geom):
     
    5151
    5252# Non-public class for the same reason as _WKTReader above.
    5353class _WKBReader(IOBase):
    54     constructor = capi.wkb_reader_create
    55     destructor = capi.wkb_reader_destroy
     54    _constructor = capi.wkb_reader_create
     55    _destructor = capi.wkb_reader_destroy
    5656    ptr_type = capi.WKB_READ_PTR
    5757
    5858    def read(self, wkb):
     
    7171        return GEOSGeometry(super(WKBReader, self).read(wkb))
    7272
    7373class WKBWriter(IOBase):
    74     constructor = capi.wkb_writer_create
    75     destructor = capi.wkb_writer_destroy
     74    _constructor = capi.wkb_writer_create
     75    _destructor = capi.wkb_writer_destroy
    7676    ptr_type = capi.WKB_WRITE_PTR
    7777
    7878    def write(self, geom):
     
    121121wkt_w = WKTWriter()
    122122wkb_r = _WKBReader()
    123123wkb_w = WKBWriter()
     124wkb_w3d = WKBWriter()
     125wkb_w3d.outdim = 3
  • django/contrib/gis/utils/layermapping.py

     
    493493        # Transforming the geometry with our Coordinate Transformation object,
    494494        # but only if the class variable `transform` is set w/a CoordTransform
    495495        # object.
    496         if self.transform: g.transform(self.transform)
     496        if self.transform:
     497            # Have to get the coordinate dimension of the original geometry
     498            # and set the transformed geometry's dimension with it afterwards.
     499            # This is because of a GDAL bug (in versions prior to 1.7) which
     500            # automatically converts non-point 2D geometries to 3D if they're:
     501            # transformed.  See: http://trac.osgeo.org/gdal/changeset/17792
     502            orig_dim = g.coord_dim
     503            g.transform(self.transform)
     504            if g.coord_dim != orig_dim:
     505                g.coord_dim = orig_dim
    497506       
    498507        # Returning the WKT of the geometry.
    499508        return g.wkt
     
    506515            # Getting the target spatial reference system
    507516            target_srs = SpatialRefSys.objects.get(srid=self.geo_col.srid).srs
    508517
    509             # Creating the CoordTransform object
     518            # Creating the CoordTransform object -- which is much faster than
     519            # transforming w/a SpatialReferencce object.
    510520            return CoordTransform(self.source_srs, target_srs)
    511521        except Exception, msg:
    512522            raise LayerMapError('Could not translate between the data source and model geometry: %s' % msg)
  • django/contrib/gis/tests/geo3d/views.py

     
     1# Create your views here.
  • django/contrib/gis/tests/geo3d/tests.py

     
     1import unittest
     2from django.test import TestCase
     3
     4from models import City3D
     5
     6class Geo3DTest(TestCase):
     7    def test01_3D(self):
     8        "Test the creation of 3D models."
     9        City3D.objects.create(name='Pueblo', point='POINT(5 23 17)')
     10        cty = City3D.objects.get(name='Pueblo')
     11        self.assertEqual(17.0, cty.point.z)
     12
     13def suite():
     14    s = unittest.TestSuite()
     15    s.addTest(unittest.makeSuite(Geo3DTest))
     16    return s
  • django/contrib/gis/tests/geo3d/models.py

     
     1from django.contrib.gis.db import models
     2
     3class City3D(models.Model):
     4    name = models.CharField(max_length=30)
     5    point = models.PointField(dim=3)
     6    objects = models.GeoManager()
     7
     8    def __unicode__(self):
     9        return self.name
  • django/contrib/gis/tests/__init__.py

     
    2121    s.addTest(geos_tests.suite())
    2222
    2323    # Tests that require use of a spatial database (e.g., creation of models)
    24     test_apps = ['geoapp', 'relatedapp']
     24    test_apps = ['geoapp', 'relatedapp', 'geo3d']
    2525
    2626    # Tests that do not require setting up and tearing down a spatial database.
    2727    test_suite_names = [
  • django/contrib/gis/gdal/prototypes/geom.py

     
    8383get_area = double_output(lgdal.OGR_G_GetArea, [c_void_p])
    8484get_centroid = void_output(lgdal.OGR_G_Centroid, [c_void_p, c_void_p])
    8585get_dims = int_output(lgdal.OGR_G_GetDimension, [c_void_p])
    86 get_coord_dims = int_output(lgdal.OGR_G_GetCoordinateDimension, [c_void_p])
     86get_coord_dim = int_output(lgdal.OGR_G_GetCoordinateDimension, [c_void_p])
     87set_coord_dim = void_output(lgdal.OGR_G_SetCoordinateDimension, [c_void_p, c_int], errcheck=False)
    8788
    8889get_geom_count = int_output(lgdal.OGR_G_GetGeometryCount, [c_void_p])
    8990get_geom_name = const_string_output(lgdal.OGR_G_GetGeometryName, [c_void_p])
  • django/contrib/gis/gdal/geometries.py

     
    179179        "Returns 0 for points, 1 for lines, and 2 for surfaces."
    180180        return capi.get_dims(self.ptr)
    181181
    182     @property
    183     def coord_dim(self):
     182    def _get_coord_dim(self):
    184183        "Returns the coordinate dimension of the Geometry."
    185         return capi.get_coord_dims(self.ptr)
     184        return capi.get_coord_dim(self.ptr)
    186185
     186    def _set_coord_dim(self, dim):
     187        "Sets the coordinate dimension of this Geometry."
     188        if not dim in (2, 3):
     189            raise ValueError('Geometry dimension must be either 2 or 3')
     190        capi.set_coord_dim(self.ptr, dim)
     191
     192    coord_dim = property(_get_coord_dim, _set_coord_dim)
     193
    187194    @property
    188195    def geom_count(self):
    189196        "The number of elements in this Geometry."
Back to Top