1. import re
    
  2. 
    
  3. from django.db import connection
    
  4. from django.test import TestCase, skipUnlessDBFeature
    
  5. from django.utils.functional import cached_property
    
  6. 
    
  7. test_srs = (
    
  8.     {
    
  9.         "srid": 4326,
    
  10.         "auth_name": ("EPSG", True),
    
  11.         "auth_srid": 4326,
    
  12.         # Only the beginning, because there are differences depending on installed libs
    
  13.         "srtext": 'GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84"',
    
  14.         # +ellps=WGS84 has been removed in the 4326 proj string in proj-4.8
    
  15.         "proj_re": (
    
  16.             r"\+proj=longlat (\+ellps=WGS84 )?(\+datum=WGS84 |\+towgs84=0,0,0,0,0,0,0 )"
    
  17.             r"\+no_defs ?"
    
  18.         ),
    
  19.         "spheroid": "WGS 84",
    
  20.         "name": "WGS 84",
    
  21.         "geographic": True,
    
  22.         "projected": False,
    
  23.         "spatialite": True,
    
  24.         # From proj's "cs2cs -le" and Wikipedia (semi-minor only)
    
  25.         "ellipsoid": (6378137.0, 6356752.3, 298.257223563),
    
  26.         "eprec": (1, 1, 9),
    
  27.         "wkt": re.sub(
    
  28.             r"[\s+]",
    
  29.             "",
    
  30.             """
    
  31.         GEOGCS["WGS 84",
    
  32.     DATUM["WGS_1984",
    
  33.         SPHEROID["WGS 84",6378137,298.257223563,
    
  34.             AUTHORITY["EPSG","7030"]],
    
  35.         AUTHORITY["EPSG","6326"]],
    
  36.     PRIMEM["Greenwich",0,
    
  37.         AUTHORITY["EPSG","8901"]],
    
  38.     UNIT["degree",0.01745329251994328,
    
  39.         AUTHORITY["EPSG","9122"]],
    
  40.     AUTHORITY["EPSG","4326"]]
    
  41.     """,
    
  42.         ),
    
  43.     },
    
  44.     {
    
  45.         "srid": 32140,
    
  46.         "auth_name": ("EPSG", False),
    
  47.         "auth_srid": 32140,
    
  48.         "srtext": (
    
  49.             'PROJCS["NAD83 / Texas South Central",GEOGCS["NAD83",'
    
  50.             'DATUM["North_American_Datum_1983",SPHEROID["GRS 1980"'
    
  51.         ),
    
  52.         "proj_re": (
    
  53.             r"\+proj=lcc (\+lat_1=30.28333333333333? |\+lat_2=28.38333333333333? "
    
  54.             r"|\+lat_0=27.83333333333333? |"
    
  55.             r"\+lon_0=-99 ){4}\+x_0=600000 \+y_0=4000000 (\+ellps=GRS80 )?"
    
  56.             r"(\+datum=NAD83 |\+towgs84=0,0,0,0,0,0,0 )?\+units=m \+no_defs ?"
    
  57.         ),
    
  58.         "spheroid": "GRS 1980",
    
  59.         "name": "NAD83 / Texas South Central",
    
  60.         "geographic": False,
    
  61.         "projected": True,
    
  62.         "spatialite": False,
    
  63.         # From proj's "cs2cs -le" and Wikipedia (semi-minor only)
    
  64.         "ellipsoid": (6378137.0, 6356752.31414, 298.257222101),
    
  65.         "eprec": (1, 5, 10),
    
  66.     },
    
  67. )
    
  68. 
    
  69. 
    
  70. @skipUnlessDBFeature("has_spatialrefsys_table")
    
  71. class SpatialRefSysTest(TestCase):
    
  72.     @cached_property
    
  73.     def SpatialRefSys(self):
    
  74.         return connection.ops.connection.ops.spatial_ref_sys()
    
  75. 
    
  76.     def test_get_units(self):
    
  77.         epsg_4326 = next(f for f in test_srs if f["srid"] == 4326)
    
  78.         unit, unit_name = self.SpatialRefSys().get_units(epsg_4326["wkt"])
    
  79.         self.assertEqual(unit_name, "degree")
    
  80.         self.assertAlmostEqual(unit, 0.01745329251994328)
    
  81. 
    
  82.     def test_retrieve(self):
    
  83.         """
    
  84.         Test retrieval of SpatialRefSys model objects.
    
  85.         """
    
  86.         for sd in test_srs:
    
  87.             srs = self.SpatialRefSys.objects.get(srid=sd["srid"])
    
  88.             self.assertEqual(sd["srid"], srs.srid)
    
  89. 
    
  90.             # Some of the authority names are borked on Oracle, e.g., SRID=32140.
    
  91.             #  also, Oracle Spatial seems to add extraneous info to fields, hence the
    
  92.             #  the testing with the 'startswith' flag.
    
  93.             auth_name, oracle_flag = sd["auth_name"]
    
  94.             # Compare case-insensitively because srs.auth_name is lowercase
    
  95.             # ("epsg") on Spatialite.
    
  96.             if not connection.ops.oracle or oracle_flag:
    
  97.                 self.assertIs(srs.auth_name.upper().startswith(auth_name), True)
    
  98. 
    
  99.             self.assertEqual(sd["auth_srid"], srs.auth_srid)
    
  100. 
    
  101.             # No PROJ and different srtext on Oracle.
    
  102.             if not connection.ops.oracle:
    
  103.                 self.assertTrue(srs.wkt.startswith(sd["srtext"]))
    
  104.                 self.assertRegex(srs.proj4text, sd["proj_re"])
    
  105. 
    
  106.     def test_osr(self):
    
  107.         """
    
  108.         Test getting OSR objects from SpatialRefSys model objects.
    
  109.         """
    
  110.         for sd in test_srs:
    
  111.             sr = self.SpatialRefSys.objects.get(srid=sd["srid"])
    
  112.             self.assertTrue(sr.spheroid.startswith(sd["spheroid"]))
    
  113.             self.assertEqual(sd["geographic"], sr.geographic)
    
  114.             self.assertEqual(sd["projected"], sr.projected)
    
  115.             self.assertIs(sr.name.startswith(sd["name"]), True)
    
  116.             # Testing the SpatialReference object directly.
    
  117.             if not connection.ops.oracle:
    
  118.                 srs = sr.srs
    
  119.                 self.assertRegex(srs.proj, sd["proj_re"])
    
  120.                 self.assertTrue(srs.wkt.startswith(sd["srtext"]))
    
  121. 
    
  122.     def test_ellipsoid(self):
    
  123.         """
    
  124.         Test the ellipsoid property.
    
  125.         """
    
  126.         for sd in test_srs:
    
  127.             # Getting the ellipsoid and precision parameters.
    
  128.             ellps1 = sd["ellipsoid"]
    
  129.             prec = sd["eprec"]
    
  130. 
    
  131.             # Getting our spatial reference and its ellipsoid
    
  132.             srs = self.SpatialRefSys.objects.get(srid=sd["srid"])
    
  133.             ellps2 = srs.ellipsoid
    
  134. 
    
  135.             for i in range(3):
    
  136.                 self.assertAlmostEqual(ellps1[i], ellps2[i], prec[i])
    
  137. 
    
  138.     @skipUnlessDBFeature("supports_add_srs_entry")
    
  139.     def test_add_entry(self):
    
  140.         """
    
  141.         Test adding a new entry in the SpatialRefSys model using the
    
  142.         add_srs_entry utility.
    
  143.         """
    
  144.         from django.contrib.gis.utils import add_srs_entry
    
  145. 
    
  146.         add_srs_entry(3857)
    
  147.         self.assertTrue(self.SpatialRefSys.objects.filter(srid=3857).exists())
    
  148.         srs = self.SpatialRefSys.objects.get(srid=3857)
    
  149.         self.assertTrue(
    
  150.             self.SpatialRefSys.get_spheroid(srs.wkt).startswith("SPHEROID[")
    
  151.         )