14
14
from django .contrib .gis .geos .error import GEOSException , GEOSIndexError
15
15
from django .contrib .gis .geos .libgeos import GEOM_PTR
16
16
from django .contrib .gis .geos .mutable_list import ListMixin
17
+ from django .contrib .gis .geos .prepared import PreparedGeometry
8000
17
18
from django .contrib .gis .geos .prototypes .io import (
18
19
ewkb_w , wkb_r , wkb_w , wkt_r , wkt_w ,
19
20
)
@@ -27,8 +28,10 @@ class GEOSGeometry(GEOSBase, ListMixin):
27
28
# Raise GEOSIndexError instead of plain IndexError
28
29
# (see ticket #4740 and GEOSIndexError docstring)
29
30
_IndexError = GEOSIndexError
31
+ _GEOS_CLASSES = None
30
32
31
33
ptr_type = GEOM_PTR
34
+ has_cs = False # Only Point, LineString, LinearRing have coordinate sequences
32
35
33
36
def __init__ (self , geo_input , srid = None ):
34
37
"""
@@ -92,7 +95,24 @@ def _post_init(self, srid):
92
95
self .srid = srid
93
96
94
97
# Setting the class type (e.g., Point, Polygon, etc.)
95
- self .__class__ = GEOS_CLASSES [self .geom_typeid ]
98
+ if GEOSGeometry ._GEOS_CLASSES is None :
99
+ # Lazy-loaded variable to avoid import conflicts with GEOSGeometry.
100
+ from .linestring import LineString , LinearRing
8000
101
+ from .point import Point
102
+ from .polygon import Polygon
103
+ from .collections import (
104
+ GeometryCollection , MultiPoint , MultiLineString , MultiPolygon )
105
+ GEOSGeometry ._GEOS_CLASSES = {
106
+ 0 : Point ,
107
+ 1 : LineString ,
108
+ 2 : LinearRing ,
109
+ 3 : Polygon ,
110
+ 4 : MultiPoint ,
111
+ 5 : MultiLineString ,
112
+ 6 : MultiPolygon ,
113
+ 7 : GeometryCollection ,
114
+ }
115
+ self .__class__ = GEOSGeometry ._GEOS_CLASSES [self .geom_typeid ]
96
116
97
117
# Setting the coordinate sequence for the geometry (will be None on
98
118
# geometries that do not have coordinate sequences)
@@ -185,15 +205,6 @@ def __xor__(self, other):
185
205
return self .sym_difference (other )
186
206
187
207
# #### Coordinate Sequence Routines ####
188
- @property
189
- def has_cs (self ):
190
- "Returns True if this Geometry has a coordinate sequence, False if not."
191
- # Only these geometries are allowed to have coordinate sequences.
192
- if isinstance (self , (Point , LineString , LinearRing )):
193
- return True
194
- else :
195
- return False
196
-
197
208
def _set_cs (self ):
198
209
"Sets the coordinate sequence for this Geometry."
199
210
if self .has_cs :
@@ -560,16 +571,6 @@ def envelope(self):
560
571
"Return the envelope for this geometry (a polygon)."
561
572
return self ._topology (capi .geos_envelope (self .ptr ))
562
573
563
- def interpolate (self , distance ):
564
- if not isinstance (self , (LineString , MultiLineString )):
565
- raise TypeError ('interpolate only works on LineString and MultiLineString geometries' )
566
- return self ._topology (capi .geos_interpolate (self .ptr , distance ))
567
-
568
- def interpolate_normalized (self , distance ):
569
- if not isinstance (self , (LineString , MultiLineString )):
570
- raise TypeError ('interpolate only works on LineString and MultiLineString geometries' )
571
- return self ._topology (capi .geos_interpolate_normalized (self .ptr , distance ))
572
-
573
574
def intersection (self , other ):
574
575
"Returns a Geometry representing the points shared by this Geometry and other."
575
576
return self ._topology (capi .geos_intersection (self .ptr , other .ptr ))
@@ -579,20 +580,6 @@ def point_on_surface(self):
579
580
"Computes an interior point of this Geometry."
580
581
return self ._topology (capi .geos_pointonsurface (self .ptr ))
581
582
582
- def project (self , point ):
583
- if not isinstance (point , Point ):
584
- raise TypeError ('locate_point argument must be a Point' )
585
- if not isinstance (self , (LineString , MultiLineString )):
586
- raise TypeError ('locate_point only works on LineString and MultiLineString geometries' )
587
- return capi .geos_project (self .ptr , point .ptr )
588
-
589
- def project_normalized (self , point ):
590
- if not isinstance (point , Point ):
591
- raise TypeError ('locate_point argument must be a Point' )
592
- if not isinstance (self , (LineString , MultiLineString )):
593
- raise TypeError ('locate_point only works on LineString and MultiLineString geometries' )
594
- return capi .geos_project_normalized (self .ptr , point .ptr )
595
-
596
583
def relate (self , other ):
597
584
"Returns the DE-9IM intersection matrix for this Geometry and the other."
598
585
return capi .geos_relate (self .ptr , other .ptr ).decode ()
@@ -647,6 +634,7 @@ def extent(self):
647
634
Returns the extent of this geometry as a 4-tuple, consisting of
648
635
(xmin, ymin, xmax, ymax).
649
636
"""
637
+ from .point import Point
650
638
env = self .envelope
651
639
if isinstance (env , Point ):
652
640
xmin , ymin = env .tuple
@@ -668,21 +656,25 @@ def clone(self):
668
656
"Clones this Geometry."
669
657
return GEOSGeometry (capi .geom_clone (self .ptr ), srid = self .srid )
670
658
671
- # Class mapping dictionary. Has to be at the end to avoid import
672
- # conflicts with GEOSGeometry.
673
- from django .contrib .gis .geos .linestring import LineString , LinearRing # isort:skip
674
- from django .contrib .gis .geos .point import Point # isort:skip
675
- from django .contrib .gis .geos .polygon import Polygon # isort:skip
676
- from django .contrib .gis .geos .collections import ( # isort:skip
677
- GeometryCollection , MultiPoint , MultiLineString , MultiPolygon )
678
- from django .contrib .gis .geos .prepared import PreparedGeometry # isort:skip
679
- GEOS_CLASSES = {
680
- 0 : Point ,
681
- 1 : LineString ,
682
- 2 : LinearRing ,
683
- 3 : Polygon ,
684
- 4 : MultiPoint ,
685
- 5 : MultiLineString ,
686
- 6 : MultiPolygon ,
687
- 7 : GeometryCollection ,
688
- }
659
+
660
+ class ProjectInterpolateMixin (object ):
661
+ """
662
+ Used for LineString and MultiLineString.
663
+ """
664
+ def interpolate (self , distance ):
665
+ return self ._topology (capi .geos_interpolate (self .ptr , distance ))
666
+
667
+ def interpolate_normalized (self , distance ):
668
+ return self ._topology (capi .geos_interpolate_normalized (self .ptr , distance ))
669
+
670
+ def project (self , point ):
671
+ from .point import Point
672
+ if not isinstance (point , Point ):
673
+ raise TypeError ('locate_point argument must be a Point' )
674
+ return capi .geos_project (self .ptr , point .ptr )
675
+
676
+ def project_normalized (self , point ):
677
+ from .point import Point
678
+ if not isinstance (point , Point ):
679
+ raise TypeError ('locate_point argument must be a Point' )
680
+ return capi .geos_project_normalized (self .ptr , point .ptr )
0 commit comments