1. ========
    
  2. GEOS API
    
  3. ========
    
  4. 
    
  5. .. module:: django.contrib.gis.geos
    
  6.     :synopsis: GeoDjango's high-level interface to the GEOS library.
    
  7. 
    
  8. Background
    
  9. ==========
    
  10. 
    
  11. What is GEOS?
    
  12. -------------
    
  13. 
    
  14. `GEOS`__ stands for **Geometry Engine - Open Source**,
    
  15. and is a C++ library, ported from the  `Java Topology Suite`__.  GEOS
    
  16. implements the OpenGIS `Simple Features for SQL`__ spatial predicate functions
    
  17. and spatial operators. GEOS, now an OSGeo project, was initially developed and
    
  18. maintained by `Refractions Research`__ of Victoria, Canada.
    
  19. 
    
  20. __ https://libgeos.org/
    
  21. __ https://sourceforge.net/projects/jts-topo-suite/
    
  22. __ https://www.ogc.org/standards/sfs
    
  23. __ http://www.refractions.net/
    
  24. 
    
  25. Features
    
  26. --------
    
  27. 
    
  28. GeoDjango implements a high-level Python wrapper for the GEOS library, its
    
  29. features include:
    
  30. 
    
  31. * A BSD-licensed interface to the GEOS geometry routines, implemented purely
    
  32.   in Python using ``ctypes``.
    
  33. * Loosely-coupled to GeoDjango.  For example, :class:`GEOSGeometry` objects
    
  34.   may be used outside of a Django project/application.  In other words,
    
  35.   no need to have :envvar:`DJANGO_SETTINGS_MODULE` set or use a database, etc.
    
  36. * Mutability: :class:`GEOSGeometry` objects may be modified.
    
  37. * Cross-platform and tested; compatible with Windows, Linux, Solaris, and
    
  38.   macOS platforms.
    
  39. 
    
  40. .. _geos-tutorial:
    
  41. 
    
  42. Tutorial
    
  43. ========
    
  44. 
    
  45. This section contains a brief introduction and tutorial to using
    
  46. :class:`GEOSGeometry` objects.
    
  47. 
    
  48. Creating a Geometry
    
  49. -------------------
    
  50. 
    
  51. :class:`GEOSGeometry` objects may be created in a few ways.  The first is
    
  52. to simply instantiate the object on some spatial input -- the following
    
  53. are examples of creating the same geometry from WKT, HEX, WKB, and GeoJSON::
    
  54. 
    
  55.     >>> from django.contrib.gis.geos import GEOSGeometry
    
  56.     >>> pnt = GEOSGeometry('POINT(5 23)') # WKT
    
  57.     >>> pnt = GEOSGeometry('010100000000000000000014400000000000003740') # HEX
    
  58.     >>> pnt = GEOSGeometry(memoryview(b'\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x14@\x00\x00\x00\x00\x00\x007@')) # WKB
    
  59.     >>> pnt = GEOSGeometry('{ "type": "Point", "coordinates": [ 5.000000, 23.000000 ] }') # GeoJSON
    
  60. 
    
  61. Another option is to use the constructor for the specific geometry type
    
  62. that you wish to create.  For example, a :class:`Point` object may be
    
  63. created by passing in the X and Y coordinates into its constructor::
    
  64. 
    
  65.     >>> from django.contrib.gis.geos import Point
    
  66.     >>> pnt = Point(5, 23)
    
  67. 
    
  68. All these constructors take the keyword argument ``srid``. For example::
    
  69. 
    
  70.     >>> from django.contrib.gis.geos import GEOSGeometry, LineString, Point
    
  71.     >>> print(GEOSGeometry('POINT (0 0)', srid=4326))
    
  72.     SRID=4326;POINT (0 0)
    
  73.     >>> print(LineString((0, 0), (1, 1), srid=4326))
    
  74.     SRID=4326;LINESTRING (0 0, 1 1)
    
  75.     >>> print(Point(0, 0, srid=32140))
    
  76.     SRID=32140;POINT (0 0)
    
  77. 
    
  78. Finally, there is the :func:`fromfile` factory method which returns a
    
  79. :class:`GEOSGeometry` object from a file::
    
  80. 
    
  81.     >>> from django.contrib.gis.geos import fromfile
    
  82.     >>> pnt = fromfile('/path/to/pnt.wkt')
    
  83.     >>> pnt = fromfile(open('/path/to/pnt.wkt'))
    
  84. 
    
  85. .. _geos-exceptions-in-logfile:
    
  86. 
    
  87. .. admonition:: My logs are filled with GEOS-related errors
    
  88. 
    
  89.     You find many ``TypeError`` or ``AttributeError`` exceptions filling your
    
  90.     web server's log files. This generally means that you are creating GEOS
    
  91.     objects at the top level of some of your Python modules. Then, due to a race
    
  92.     condition in the garbage collector, your module is garbage collected before
    
  93.     the GEOS object. To prevent this, create :class:`GEOSGeometry` objects
    
  94.     inside the local scope of your functions/methods.
    
  95. 
    
  96. Geometries are Pythonic
    
  97. -----------------------
    
  98. :class:`GEOSGeometry` objects are 'Pythonic', in other words components may
    
  99. be accessed, modified, and iterated over using standard Python conventions.
    
  100. For example, you can iterate over the coordinates in a :class:`Point`::
    
  101. 
    
  102.     >>> pnt = Point(5, 23)
    
  103.     >>> [coord for coord in pnt]
    
  104.     [5.0, 23.0]
    
  105. 
    
  106. With any geometry object, the :attr:`GEOSGeometry.coords` property
    
  107. may be used to get the geometry coordinates as a Python tuple::
    
  108. 
    
  109.     >>> pnt.coords
    
  110.     (5.0, 23.0)
    
  111. 
    
  112. You can get/set geometry components using standard Python indexing
    
  113. techniques.  However, what is returned depends on the geometry type
    
  114. of the object.  For example, indexing on a :class:`LineString`
    
  115. returns a coordinate tuple::
    
  116. 
    
  117.     >>> from django.contrib.gis.geos import LineString
    
  118.     >>> line = LineString((0, 0), (0, 50), (50, 50), (50, 0), (0, 0))
    
  119.     >>> line[0]
    
  120.     (0.0, 0.0)
    
  121.     >>> line[-2]
    
  122.     (50.0, 0.0)
    
  123. 
    
  124. Whereas indexing on a :class:`Polygon` will return the ring
    
  125. (a :class:`LinearRing` object) corresponding to the index::
    
  126. 
    
  127.     >>> from django.contrib.gis.geos import Polygon
    
  128.     >>> poly = Polygon( ((0.0, 0.0), (0.0, 50.0), (50.0, 50.0), (50.0, 0.0), (0.0, 0.0)) )
    
  129.     >>> poly[0]
    
  130.     <LinearRing object at 0x1044395b0>
    
  131.     >>> poly[0][-2] # second-to-last coordinate of external ring
    
  132.     (50.0, 0.0)
    
  133. 
    
  134. In addition, coordinates/components of the geometry may added or modified,
    
  135. just like a Python list::
    
  136. 
    
  137.     >>> line[0] = (1.0, 1.0)
    
  138.     >>> line.pop()
    
  139.     (0.0, 0.0)
    
  140.     >>> line.append((1.0, 1.0))
    
  141.     >>> line.coords
    
  142.     ((1.0, 1.0), (0.0, 50.0), (50.0, 50.0), (50.0, 0.0), (1.0, 1.0))
    
  143. 
    
  144. Geometries support set-like operators::
    
  145. 
    
  146.     >>> from django.contrib.gis.geos import LineString
    
  147.     >>> ls1 = LineString((0, 0), (2, 2))
    
  148.     >>> ls2 = LineString((1, 1), (3, 3))
    
  149.     >>> print(ls1 | ls2)  # equivalent to `ls1.union(ls2)`
    
  150.     MULTILINESTRING ((0 0, 1 1), (1 1, 2 2), (2 2, 3 3))
    
  151.     >>> print(ls1 & ls2)  # equivalent to `ls1.intersection(ls2)`
    
  152.     LINESTRING (1 1, 2 2)
    
  153.     >>> print(ls1 - ls2)  # equivalent to `ls1.difference(ls2)`
    
  154.     LINESTRING(0 0, 1 1)
    
  155.     >>> print(ls1 ^ ls2)  # equivalent to `ls1.sym_difference(ls2)`
    
  156.     MULTILINESTRING ((0 0, 1 1), (2 2, 3 3))
    
  157. 
    
  158. .. admonition:: Equality operator doesn't check spatial equality
    
  159. 
    
  160.     The :class:`~GEOSGeometry` equality operator uses
    
  161.     :meth:`~GEOSGeometry.equals_exact`, not :meth:`~GEOSGeometry.equals`, i.e.
    
  162.     it requires the compared geometries to have the same coordinates in the
    
  163.     same positions with the same SRIDs::
    
  164. 
    
  165.         >>> from django.contrib.gis.geos import LineString
    
  166.         >>> ls1 = LineString((0, 0), (1, 1))
    
  167.         >>> ls2 = LineString((1, 1), (0, 0))
    
  168.         >>> ls3 = LineString((1, 1), (0, 0), srid=4326)
    
  169.         >>> ls1.equals(ls2)
    
  170.         True
    
  171.         >>> ls1 == ls2
    
  172.         False
    
  173.         >>> ls3 == ls2  # different SRIDs
    
  174.         False
    
  175. 
    
  176. Geometry Objects
    
  177. ================
    
  178. 
    
  179. ``GEOSGeometry``
    
  180. ----------------
    
  181. 
    
  182. .. class:: GEOSGeometry(geo_input, srid=None)
    
  183. 
    
  184.     :param geo_input: Geometry input value (string or buffer)
    
  185.     :param srid: spatial reference identifier
    
  186.     :type srid: int
    
  187. 
    
  188. This is the base class for all GEOS geometry objects.  It initializes on the
    
  189. given ``geo_input`` argument, and then assumes the proper geometry subclass
    
  190. (e.g., ``GEOSGeometry('POINT(1 1)')`` will create a :class:`Point` object).
    
  191. 
    
  192. The ``srid`` parameter, if given, is set as the SRID of the created geometry if
    
  193. ``geo_input`` doesn't have an SRID. If different SRIDs are provided through the
    
  194. ``geo_input`` and ``srid`` parameters, ``ValueError`` is raised::
    
  195. 
    
  196.     >>> from django.contrib.gis.geos import GEOSGeometry
    
  197.     >>> GEOSGeometry('POINT EMPTY', srid=4326).ewkt
    
  198.     'SRID=4326;POINT EMPTY'
    
  199.     >>> GEOSGeometry('SRID=4326;POINT EMPTY', srid=4326).ewkt
    
  200.     'SRID=4326;POINT EMPTY'
    
  201.     >>> GEOSGeometry('SRID=1;POINT EMPTY', srid=4326)
    
  202.     Traceback (most recent call last):
    
  203.     ...
    
  204.     ValueError: Input geometry already has SRID: 1.
    
  205. 
    
  206. The following input formats, along with their corresponding Python types,
    
  207. are accepted:
    
  208. 
    
  209. =======================  ==========
    
  210. Format                   Input Type
    
  211. =======================  ==========
    
  212. WKT / EWKT               ``str``
    
  213. HEX / HEXEWKB            ``str``
    
  214. WKB / EWKB               ``buffer``
    
  215. :rfc:`GeoJSON <7946>`    ``str``
    
  216. =======================  ==========
    
  217. 
    
  218. For the GeoJSON format, the SRID is set based on the ``crs`` member. If ``crs``
    
  219. isn't provided, the SRID defaults to 4326.
    
  220. 
    
  221. .. classmethod:: GEOSGeometry.from_gml(gml_string)
    
  222. 
    
  223.     Constructs a :class:`GEOSGeometry` from the given GML string.
    
  224. 
    
  225. Properties
    
  226. ~~~~~~~~~~
    
  227. 
    
  228. .. attribute:: GEOSGeometry.coords
    
  229. 
    
  230.     Returns the coordinates of the geometry as a tuple.
    
  231. 
    
  232. .. attribute:: GEOSGeometry.dims
    
  233. 
    
  234.     Returns the dimension of the geometry:
    
  235. 
    
  236.     * ``0`` for :class:`Point`\s and :class:`MultiPoint`\s
    
  237.     * ``1`` for :class:`LineString`\s and :class:`MultiLineString`\s
    
  238.     * ``2`` for :class:`Polygon`\s and :class:`MultiPolygon`\s
    
  239.     * ``-1`` for empty :class:`GeometryCollection`\s
    
  240.     * the maximum dimension of its elements for non-empty
    
  241.       :class:`GeometryCollection`\s
    
  242. 
    
  243. .. attribute:: GEOSGeometry.empty
    
  244. 
    
  245.     Returns whether or not the set of points in the geometry is empty.
    
  246. 
    
  247. .. attribute:: GEOSGeometry.geom_type
    
  248. 
    
  249.     Returns a string corresponding to the type of geometry.  For example::
    
  250. 
    
  251.         >>> pnt = GEOSGeometry('POINT(5 23)')
    
  252.         >>> pnt.geom_type
    
  253.         'Point'
    
  254. 
    
  255. .. attribute:: GEOSGeometry.geom_typeid
    
  256. 
    
  257.     Returns the GEOS geometry type identification number.  The following table
    
  258.     shows the value for each geometry type:
    
  259. 
    
  260.     ===========================  ========
    
  261.     Geometry                     ID
    
  262.     ===========================  ========
    
  263.     :class:`Point`               0
    
  264.     :class:`LineString`          1
    
  265.     :class:`LinearRing`          2
    
  266.     :class:`Polygon`             3
    
  267.     :class:`MultiPoint`          4
    
  268.     :class:`MultiLineString`     5
    
  269.     :class:`MultiPolygon`        6
    
  270.     :class:`GeometryCollection`  7
    
  271.     ===========================  ========
    
  272. 
    
  273. .. attribute:: GEOSGeometry.num_coords
    
  274. 
    
  275.     Returns the number of coordinates in the geometry.
    
  276. 
    
  277. .. attribute:: GEOSGeometry.num_geom
    
  278. 
    
  279.     Returns the number of geometries in this geometry.  In other words, will
    
  280.     return 1 on anything but geometry collections.
    
  281. 
    
  282. .. attribute:: GEOSGeometry.hasz
    
  283. 
    
  284.     Returns a boolean indicating whether the geometry is three-dimensional.
    
  285. 
    
  286. .. attribute:: GEOSGeometry.ring
    
  287. 
    
  288.     Returns a boolean indicating whether the geometry is a ``LinearRing``.
    
  289. 
    
  290. .. attribute:: GEOSGeometry.simple
    
  291. 
    
  292.     Returns a boolean indicating whether the geometry is 'simple'. A geometry
    
  293.     is simple if and only if it does not intersect itself (except at boundary
    
  294.     points).  For example, a :class:`LineString` object is not simple if it
    
  295.     intersects itself. Thus, :class:`LinearRing` and :class:`Polygon` objects
    
  296.     are always simple because they do cannot intersect themselves, by
    
  297.     definition.
    
  298. 
    
  299. .. attribute:: GEOSGeometry.valid
    
  300. 
    
  301.     Returns a boolean indicating whether the geometry is valid.
    
  302. 
    
  303. .. attribute:: GEOSGeometry.valid_reason
    
  304. 
    
  305.     Returns a string describing the reason why a geometry is invalid.
    
  306. 
    
  307. .. attribute:: GEOSGeometry.srid
    
  308. 
    
  309.     Property that may be used to retrieve or set the SRID associated with the
    
  310.     geometry.  For example::
    
  311. 
    
  312.         >>> pnt = Point(5, 23)
    
  313.         >>> print(pnt.srid)
    
  314.         None
    
  315.         >>> pnt.srid = 4326
    
  316.         >>> pnt.srid
    
  317.         4326
    
  318. 
    
  319. Output Properties
    
  320. ~~~~~~~~~~~~~~~~~
    
  321. 
    
  322. The properties in this section export the :class:`GEOSGeometry` object into
    
  323. a different.  This output may be in the form of a string, buffer, or even
    
  324. another object.
    
  325. 
    
  326. .. attribute:: GEOSGeometry.ewkt
    
  327. 
    
  328.     Returns the "extended" Well-Known Text of the geometry.  This representation
    
  329.     is specific to PostGIS and is a superset of the OGC WKT standard. [#fnogc]_
    
  330.     Essentially the SRID is prepended to the WKT representation, for example
    
  331.     ``SRID=4326;POINT(5 23)``.
    
  332. 
    
  333.     .. note::
    
  334. 
    
  335.         The output from this property does not include the 3dm, 3dz, and 4d
    
  336.         information that PostGIS supports in its EWKT representations.
    
  337. 
    
  338. .. attribute:: GEOSGeometry.hex
    
  339. 
    
  340.     Returns the WKB of this Geometry in hexadecimal form.  Please note
    
  341.     that the SRID value is not included in this representation
    
  342.     because it is not a part of the OGC specification (use the
    
  343.     :attr:`GEOSGeometry.hexewkb` property instead).
    
  344. 
    
  345. .. attribute:: GEOSGeometry.hexewkb
    
  346. 
    
  347.     Returns the EWKB of this Geometry in hexadecimal form.  This is an
    
  348.     extension of the WKB specification that includes the SRID value
    
  349.     that are a part of this geometry.
    
  350. 
    
  351. .. attribute:: GEOSGeometry.json
    
  352. 
    
  353.     Returns the GeoJSON representation of the geometry. Note that the result is
    
  354.     not a complete GeoJSON structure but only the ``geometry`` key content of a
    
  355.     GeoJSON structure. See also :doc:`/ref/contrib/gis/serializers`.
    
  356. 
    
  357. .. attribute:: GEOSGeometry.geojson
    
  358. 
    
  359.     Alias for :attr:`GEOSGeometry.json`.
    
  360. 
    
  361. .. attribute:: GEOSGeometry.kml
    
  362. 
    
  363.     Returns a `KML`__ (Keyhole Markup Language) representation of the
    
  364.     geometry.  This should only be used for geometries with an SRID of
    
  365.     4326 (WGS84), but this restriction is not enforced.
    
  366. 
    
  367. .. attribute:: GEOSGeometry.ogr
    
  368. 
    
  369.     Returns an :class:`~django.contrib.gis.gdal.OGRGeometry` object
    
  370.     corresponding to the GEOS geometry.
    
  371. 
    
  372. .. _wkb:
    
  373. 
    
  374. .. attribute:: GEOSGeometry.wkb
    
  375. 
    
  376.     Returns the WKB (Well-Known Binary) representation of this Geometry
    
  377.     as a Python buffer.  SRID value is not included, use the
    
  378.     :attr:`GEOSGeometry.ewkb` property instead.
    
  379. 
    
  380. .. _ewkb:
    
  381. 
    
  382. .. attribute:: GEOSGeometry.ewkb
    
  383. 
    
  384.     Return the EWKB representation of this Geometry as a Python buffer.
    
  385.     This is an extension of the WKB specification that includes any SRID
    
  386.     value that are a part of this geometry.
    
  387. 
    
  388. .. attribute:: GEOSGeometry.wkt
    
  389. 
    
  390.     Returns the Well-Known Text of the geometry (an OGC standard).
    
  391. 
    
  392. __ https://developers.google.com/kml/documentation/
    
  393. 
    
  394. Spatial Predicate Methods
    
  395. ~~~~~~~~~~~~~~~~~~~~~~~~~
    
  396. 
    
  397. All of the following spatial predicate methods take another
    
  398. :class:`GEOSGeometry` instance (``other``) as a parameter, and
    
  399. return a boolean.
    
  400. 
    
  401. .. method:: GEOSGeometry.contains(other)
    
  402. 
    
  403.     Returns ``True`` if :meth:`other.within(this) <GEOSGeometry.within>` returns
    
  404.     ``True``.
    
  405. 
    
  406. .. method:: GEOSGeometry.covers(other)
    
  407. 
    
  408.     Returns ``True`` if this geometry covers the specified geometry.
    
  409. 
    
  410.     The ``covers`` predicate has the following equivalent definitions:
    
  411. 
    
  412.     * Every point of the other geometry is a point of this geometry.
    
  413.     * The `DE-9IM`_ Intersection Matrix for the two geometries is
    
  414.       ``T*****FF*``, ``*T****FF*``, ``***T**FF*``, or ``****T*FF*``.
    
  415. 
    
  416.     If either geometry is empty, returns ``False``.
    
  417. 
    
  418.     This predicate is similar to :meth:`GEOSGeometry.contains`, but is more
    
  419.     inclusive (i.e. returns ``True`` for more cases). In particular, unlike
    
  420.     :meth:`~GEOSGeometry.contains` it does not distinguish between points in the
    
  421.     boundary and in the interior of geometries. For most situations,
    
  422.     ``covers()`` should be preferred to :meth:`~GEOSGeometry.contains`. As an
    
  423.     added benefit, ``covers()`` is more amenable to optimization and hence
    
  424.     should outperform :meth:`~GEOSGeometry.contains`.
    
  425. 
    
  426.     .. _DE-9IM: https://en.wikipedia.org/wiki/DE-9IM
    
  427. 
    
  428. .. method:: GEOSGeometry.crosses(other)
    
  429. 
    
  430.     Returns ``True`` if the DE-9IM intersection matrix for the two Geometries
    
  431.     is ``T*T******`` (for a point and a curve,a point and an area or a line
    
  432.     and an area) ``0********`` (for two curves).
    
  433. 
    
  434. .. method:: GEOSGeometry.disjoint(other)
    
  435. 
    
  436.     Returns ``True`` if the DE-9IM intersection matrix for the two geometries
    
  437.     is ``FF*FF****``.
    
  438. 
    
  439. .. method:: GEOSGeometry.equals(other)
    
  440. 
    
  441.     Returns ``True`` if the DE-9IM intersection matrix for the two geometries
    
  442.     is ``T*F**FFF*``.
    
  443. 
    
  444. .. method:: GEOSGeometry.equals_exact(other, tolerance=0)
    
  445. 
    
  446.     Returns true if the two geometries are exactly equal, up to a
    
  447.     specified tolerance.  The ``tolerance`` value should be a floating
    
  448.     point number representing the error tolerance in the comparison, e.g.,
    
  449.     ``poly1.equals_exact(poly2, 0.001)`` will compare equality to within
    
  450.     one thousandth of a unit.
    
  451. 
    
  452. .. method:: GEOSGeometry.intersects(other)
    
  453. 
    
  454.     Returns ``True`` if :meth:`GEOSGeometry.disjoint` is ``False``.
    
  455. 
    
  456. .. method:: GEOSGeometry.overlaps(other)
    
  457. 
    
  458.     Returns true if the DE-9IM intersection matrix for the two geometries
    
  459.     is ``T*T***T**`` (for two points or two surfaces) ``1*T***T**``
    
  460.     (for two curves).
    
  461. 
    
  462. .. method:: GEOSGeometry.relate_pattern(other, pattern)
    
  463. 
    
  464.     Returns ``True`` if the elements in the DE-9IM intersection matrix
    
  465.     for this geometry and the other matches the given ``pattern`` --
    
  466.     a string of nine characters from the alphabet: {``T``, ``F``, ``*``, ``0``}.
    
  467. 
    
  468. .. method:: GEOSGeometry.touches(other)
    
  469. 
    
  470.     Returns ``True`` if the DE-9IM intersection matrix for the two geometries
    
  471.     is ``FT*******``, ``F**T*****`` or ``F***T****``.
    
  472. 
    
  473. .. method:: GEOSGeometry.within(other)
    
  474. 
    
  475.     Returns ``True`` if the DE-9IM intersection matrix for the two geometries
    
  476.     is ``T*F**F***``.
    
  477. 
    
  478. Topological Methods
    
  479. ~~~~~~~~~~~~~~~~~~~
    
  480. 
    
  481. .. method:: GEOSGeometry.buffer(width, quadsegs=8)
    
  482. 
    
  483.     Returns a :class:`GEOSGeometry` that represents all points whose distance
    
  484.     from this geometry is less than or equal to the given ``width``. The
    
  485.     optional ``quadsegs`` keyword sets the number of segments used to
    
  486.     approximate a quarter circle (defaults is 8).
    
  487. 
    
  488. .. method:: GEOSGeometry.buffer_with_style(width, quadsegs=8, end_cap_style=1, join_style=1, mitre_limit=5.0)
    
  489. 
    
  490.     Same as :meth:`buffer`, but allows customizing the style of the buffer.
    
  491. 
    
  492.     * ``end_cap_style`` can be round (``1``), flat (``2``), or square (``3``).
    
  493.     * ``join_style`` can be round (``1``), mitre (``2``), or bevel (``3``).
    
  494.     * Mitre ratio limit (``mitre_limit``) only affects mitered join style.
    
  495. 
    
  496. .. method:: GEOSGeometry.difference(other)
    
  497. 
    
  498.     Returns a :class:`GEOSGeometry` representing the points making up this
    
  499.     geometry that do not make up other.
    
  500. 
    
  501. .. method:: GEOSGeometry.interpolate(distance)
    
  502. .. method:: GEOSGeometry.interpolate_normalized(distance)
    
  503. 
    
  504.     Given a distance (float), returns the point (or closest point) within the
    
  505.     geometry (:class:`LineString` or :class:`MultiLineString`) at that distance.
    
  506.     The normalized version takes the distance as a float between 0 (origin) and
    
  507.     1 (endpoint).
    
  508. 
    
  509.     Reverse of :meth:`GEOSGeometry.project`.
    
  510. 
    
  511. .. method:: GEOSGeometry.intersection(other)
    
  512. 
    
  513.     Returns a :class:`GEOSGeometry` representing the points shared by this
    
  514.     geometry and other.
    
  515. 
    
  516. .. method:: GEOSGeometry.project(point)
    
  517. .. method:: GEOSGeometry.project_normalized(point)
    
  518. 
    
  519.     Returns the distance (float) from the origin of the geometry
    
  520.     (:class:`LineString` or :class:`MultiLineString`) to the point projected on
    
  521.     the geometry (that is to a point of the line the closest to the given
    
  522.     point). The normalized version returns the distance as a float between 0
    
  523.     (origin) and 1 (endpoint).
    
  524. 
    
  525.     Reverse of :meth:`GEOSGeometry.interpolate`.
    
  526. 
    
  527. .. method:: GEOSGeometry.relate(other)
    
  528. 
    
  529.     Returns the DE-9IM intersection matrix (a string) representing the
    
  530.     topological relationship between this geometry and the other.
    
  531. 
    
  532. .. method:: GEOSGeometry.simplify(tolerance=0.0, preserve_topology=False)
    
  533. 
    
  534.     Returns a new :class:`GEOSGeometry`, simplified to the specified tolerance
    
  535.     using the Douglas-Peucker algorithm. A higher tolerance value implies
    
  536.     fewer points in the output. If no tolerance is provided, it defaults to 0.
    
  537. 
    
  538.     By default, this function does not preserve topology. For example,
    
  539.     :class:`Polygon` objects can be split, be collapsed into lines, or
    
  540.     disappear. :class:`Polygon` holes can be created or disappear, and lines may
    
  541.     cross. By specifying ``preserve_topology=True``, the result will have the
    
  542.     same dimension and number of components as the input; this is significantly
    
  543.     slower, however.
    
  544. 
    
  545. .. method:: GEOSGeometry.sym_difference(other)
    
  546. 
    
  547.     Returns a :class:`GEOSGeometry` combining the points in this geometry
    
  548.     not in other, and the points in other not in this geometry.
    
  549. 
    
  550. .. method:: GEOSGeometry.union(other)
    
  551. 
    
  552.     Returns a :class:`GEOSGeometry` representing all the points in this
    
  553.     geometry and the other.
    
  554. 
    
  555. Topological Properties
    
  556. ~~~~~~~~~~~~~~~~~~~~~~
    
  557. 
    
  558. .. attribute:: GEOSGeometry.boundary
    
  559. 
    
  560.     Returns the boundary as a newly allocated Geometry object.
    
  561. 
    
  562. .. attribute:: GEOSGeometry.centroid
    
  563. 
    
  564.     Returns a :class:`Point` object representing the geometric center of
    
  565.     the geometry.  The point is not guaranteed to be on the interior
    
  566.     of the geometry.
    
  567. 
    
  568. .. attribute:: GEOSGeometry.convex_hull
    
  569. 
    
  570.     Returns the smallest :class:`Polygon` that contains all the points in
    
  571.     the geometry.
    
  572. 
    
  573. .. attribute:: GEOSGeometry.envelope
    
  574. 
    
  575.     Returns a :class:`Polygon` that represents the bounding envelope of
    
  576.     this geometry. Note that it can also return a :class:`Point` if the input
    
  577.     geometry is a point.
    
  578. 
    
  579. .. attribute:: GEOSGeometry.point_on_surface
    
  580. 
    
  581.     Computes and returns a :class:`Point` guaranteed to be on the interior
    
  582.     of this geometry.
    
  583. 
    
  584. .. attribute:: GEOSGeometry.unary_union
    
  585. 
    
  586.     Computes the union of all the elements of this geometry.
    
  587. 
    
  588.     The result obeys the following contract:
    
  589. 
    
  590.     * Unioning a set of :class:`LineString`\s has the effect of fully noding and
    
  591.       dissolving the linework.
    
  592. 
    
  593.     * Unioning a set of :class:`Polygon`\s will always return a :class:`Polygon`
    
  594.       or :class:`MultiPolygon` geometry (unlike :meth:`GEOSGeometry.union`,
    
  595.       which may return geometries of lower dimension if a topology collapse
    
  596.       occurs).
    
  597. 
    
  598. Other Properties & Methods
    
  599. ~~~~~~~~~~~~~~~~~~~~~~~~~~
    
  600. 
    
  601. .. attribute:: GEOSGeometry.area
    
  602. 
    
  603.     This property returns the area of the Geometry.
    
  604. 
    
  605. .. attribute:: GEOSGeometry.extent
    
  606. 
    
  607.     This property returns the extent of this geometry as a 4-tuple,
    
  608.     consisting of ``(xmin, ymin, xmax, ymax)``.
    
  609. 
    
  610. .. method:: GEOSGeometry.clone()
    
  611. 
    
  612.     This method returns a :class:`GEOSGeometry` that is a clone of the original.
    
  613. 
    
  614. .. method:: GEOSGeometry.distance(geom)
    
  615. 
    
  616.     Returns the distance between the closest points on this geometry and the
    
  617.     given ``geom`` (another :class:`GEOSGeometry` object).
    
  618. 
    
  619.     .. note::
    
  620. 
    
  621.         GEOS distance calculations are  linear -- in other words, GEOS does not
    
  622.         perform a spherical calculation even if the SRID specifies a geographic
    
  623.         coordinate system.
    
  624. 
    
  625. .. attribute:: GEOSGeometry.length
    
  626. 
    
  627.     Returns the length of this geometry (e.g., 0 for a :class:`Point`,
    
  628.     the length of a :class:`LineString`, or the circumference of
    
  629.     a :class:`Polygon`).
    
  630. 
    
  631. .. attribute:: GEOSGeometry.prepared
    
  632. 
    
  633.     Returns a GEOS ``PreparedGeometry`` for the contents of this geometry.
    
  634.     ``PreparedGeometry`` objects are optimized for the contains, intersects,
    
  635.     covers, crosses, disjoint, overlaps, touches and within operations. Refer to
    
  636.     the :ref:`prepared-geometries` documentation for more information.
    
  637. 
    
  638. .. attribute:: GEOSGeometry.srs
    
  639. 
    
  640.     Returns a :class:`~django.contrib.gis.gdal.SpatialReference` object
    
  641.     corresponding to the SRID of the geometry or ``None``.
    
  642. 
    
  643. .. method:: GEOSGeometry.transform(ct, clone=False)
    
  644. 
    
  645.     Transforms the geometry according to the given coordinate transformation
    
  646.     parameter (``ct``), which may be an integer SRID, spatial reference WKT
    
  647.     string, a PROJ string, a :class:`~django.contrib.gis.gdal.SpatialReference`
    
  648.     object, or a :class:`~django.contrib.gis.gdal.CoordTransform` object. By
    
  649.     default, the geometry is transformed in-place and nothing is returned.
    
  650.     However if the ``clone`` keyword is set, then the geometry is not modified
    
  651.     and a transformed clone of the geometry is returned instead.
    
  652. 
    
  653.     .. note::
    
  654. 
    
  655.         Raises :class:`~django.contrib.gis.geos.GEOSException` if GDAL is not
    
  656.         available or if the geometry's SRID is ``None`` or less than 0. It
    
  657.         doesn't impose any constraints on the geometry's SRID if called with a
    
  658.         :class:`~django.contrib.gis.gdal.CoordTransform` object.
    
  659. 
    
  660. .. method:: GEOSGeometry.make_valid()
    
  661. 
    
  662.     .. versionadded:: 4.1
    
  663. 
    
  664.     Returns a valid :class:`GEOSGeometry` equivalent, trying not to lose any of
    
  665.     the input vertices. If the geometry is already valid, it is returned
    
  666.     untouched. This is similar to the
    
  667.     :class:`~django.contrib.gis.db.models.functions.MakeValid` database
    
  668.     function. Requires GEOS 3.8.
    
  669. 
    
  670. .. method:: GEOSGeometry.normalize(clone=False)
    
  671. 
    
  672.     Converts this geometry to canonical form. If the ``clone`` keyword is set,
    
  673.     then the geometry is not modified and a normalized clone of the geometry is
    
  674.     returned instead::
    
  675. 
    
  676.         >>> g = MultiPoint(Point(0, 0), Point(2, 2), Point(1, 1))
    
  677.         >>> print(g)
    
  678.         MULTIPOINT (0 0, 2 2, 1 1)
    
  679.         >>> g.normalize()
    
  680.         >>> print(g)
    
  681.         MULTIPOINT (2 2, 1 1, 0 0)
    
  682. 
    
  683.     .. versionchanged:: 4.1
    
  684. 
    
  685.         The ``clone`` argument was added.
    
  686. 
    
  687. ``Point``
    
  688. ---------
    
  689. 
    
  690. .. class:: Point(x=None, y=None, z=None, srid=None)
    
  691. 
    
  692.     ``Point`` objects are instantiated using arguments that represent the
    
  693.     component coordinates of the point or with a single sequence coordinates.
    
  694.     For example, the following are equivalent::
    
  695. 
    
  696.         >>> pnt = Point(5, 23)
    
  697.         >>> pnt = Point([5, 23])
    
  698. 
    
  699.     Empty ``Point`` objects may be instantiated by passing no arguments or an
    
  700.     empty sequence. The following are equivalent::
    
  701. 
    
  702.         >>> pnt = Point()
    
  703.         >>> pnt = Point([])
    
  704. 
    
  705. ``LineString``
    
  706. --------------
    
  707. 
    
  708. .. class:: LineString(*args, **kwargs)
    
  709. 
    
  710.     ``LineString`` objects are instantiated using arguments that are either a
    
  711.     sequence of coordinates or :class:`Point` objects. For example, the
    
  712.     following are equivalent::
    
  713. 
    
  714.         >>> ls = LineString((0, 0), (1, 1))
    
  715.         >>> ls = LineString(Point(0, 0), Point(1, 1))
    
  716. 
    
  717.     In addition, ``LineString`` objects may also be created by passing in a
    
  718.     single sequence of coordinate or :class:`Point` objects::
    
  719. 
    
  720.         >>> ls = LineString( ((0, 0), (1, 1)) )
    
  721.         >>> ls = LineString( [Point(0, 0), Point(1, 1)] )
    
  722. 
    
  723.     Empty ``LineString`` objects may be instantiated by passing no arguments
    
  724.     or an empty sequence. The following are equivalent::
    
  725. 
    
  726.         >>> ls = LineString()
    
  727.         >>> ls = LineString([])
    
  728. 
    
  729.     .. attribute:: closed
    
  730. 
    
  731.         Returns whether or not this ``LineString`` is closed.
    
  732. 
    
  733. ``LinearRing``
    
  734. --------------
    
  735. 
    
  736. .. class:: LinearRing(*args, **kwargs)
    
  737. 
    
  738.     ``LinearRing`` objects are constructed in the exact same way as
    
  739.     :class:`LineString` objects, however the coordinates must be *closed*, in
    
  740.     other words, the first coordinates must be the same as the last
    
  741.     coordinates. For example::
    
  742. 
    
  743.         >>> ls = LinearRing((0, 0), (0, 1), (1, 1), (0, 0))
    
  744. 
    
  745.     Notice that ``(0, 0)`` is the first and last coordinate -- if they were not
    
  746.     equal, an error would be raised.
    
  747. 
    
  748.     .. attribute:: is_counterclockwise
    
  749. 
    
  750.         Returns whether this ``LinearRing`` is counterclockwise.
    
  751. 
    
  752. ``Polygon``
    
  753. -----------
    
  754. 
    
  755. .. class:: Polygon(*args, **kwargs)
    
  756. 
    
  757.     ``Polygon`` objects may be instantiated by passing in parameters that
    
  758.     represent the rings of the polygon.  The parameters must either be
    
  759.     :class:`LinearRing` instances, or a sequence that may be used to construct a
    
  760.     :class:`LinearRing`::
    
  761. 
    
  762.         >>> ext_coords = ((0, 0), (0, 1), (1, 1), (1, 0), (0, 0))
    
  763.         >>> int_coords = ((0.4, 0.4), (0.4, 0.6), (0.6, 0.6), (0.6, 0.4), (0.4, 0.4))
    
  764.         >>> poly = Polygon(ext_coords, int_coords)
    
  765.         >>> poly = Polygon(LinearRing(ext_coords), LinearRing(int_coords))
    
  766. 
    
  767.     .. classmethod:: from_bbox(bbox)
    
  768. 
    
  769.         Returns a polygon object from the given bounding-box, a 4-tuple
    
  770.         comprising ``(xmin, ymin, xmax, ymax)``.
    
  771. 
    
  772.     .. attribute:: num_interior_rings
    
  773. 
    
  774.         Returns the number of interior rings in this geometry.
    
  775. 
    
  776. .. admonition:: Comparing Polygons
    
  777. 
    
  778.     Note that it is possible to compare ``Polygon`` objects directly with ``<``
    
  779.     or ``>``, but as the comparison is made through Polygon's
    
  780.     :class:`LineString`, it does not mean much (but is consistent and quick).
    
  781.     You can always force the comparison with the :attr:`~GEOSGeometry.area`
    
  782.     property::
    
  783. 
    
  784.         >>> if poly_1.area > poly_2.area:
    
  785.         >>>     pass
    
  786. 
    
  787. .. _geos-geometry-collections:
    
  788. 
    
  789. Geometry Collections
    
  790. ====================
    
  791. 
    
  792. ``MultiPoint``
    
  793. --------------
    
  794. 
    
  795. .. class:: MultiPoint(*args, **kwargs)
    
  796. 
    
  797.     ``MultiPoint`` objects may be instantiated by passing in :class:`Point`
    
  798.     objects as arguments, or a single sequence of :class:`Point` objects::
    
  799. 
    
  800.         >>> mp = MultiPoint(Point(0, 0), Point(1, 1))
    
  801.         >>> mp = MultiPoint( (Point(0, 0), Point(1, 1)) )
    
  802. 
    
  803. ``MultiLineString``
    
  804. -------------------
    
  805. 
    
  806. .. class:: MultiLineString(*args, **kwargs)
    
  807. 
    
  808.     ``MultiLineString`` objects may be instantiated by passing in
    
  809.     :class:`LineString` objects as arguments, or a single sequence of
    
  810.     :class:`LineString` objects::
    
  811. 
    
  812.         >>> ls1 = LineString((0, 0), (1, 1))
    
  813.         >>> ls2 = LineString((2, 2), (3, 3))
    
  814.         >>> mls = MultiLineString(ls1, ls2)
    
  815.         >>> mls = MultiLineString([ls1, ls2])
    
  816. 
    
  817.     .. attribute:: merged
    
  818. 
    
  819.         Returns a :class:`LineString` representing the line merge of
    
  820.         all the components in this ``MultiLineString``.
    
  821. 
    
  822.     .. attribute:: closed
    
  823. 
    
  824.         Returns ``True`` if and only if all elements are closed.
    
  825. 
    
  826. ``MultiPolygon``
    
  827. ----------------
    
  828. 
    
  829. .. class:: MultiPolygon(*args, **kwargs)
    
  830. 
    
  831.     ``MultiPolygon`` objects may be instantiated by passing :class:`Polygon`
    
  832.     objects as arguments, or a single sequence of :class:`Polygon` objects::
    
  833. 
    
  834.         >>> p1 = Polygon( ((0, 0), (0, 1), (1, 1), (0, 0)) )
    
  835.         >>> p2 = Polygon( ((1, 1), (1, 2), (2, 2), (1, 1)) )
    
  836.         >>> mp = MultiPolygon(p1, p2)
    
  837.         >>> mp = MultiPolygon([p1, p2])
    
  838. 
    
  839. ``GeometryCollection``
    
  840. ----------------------
    
  841. 
    
  842. .. class:: GeometryCollection(*args, **kwargs)
    
  843. 
    
  844.     ``GeometryCollection`` objects may be instantiated by passing in other
    
  845.     :class:`GEOSGeometry` as arguments, or a single sequence of
    
  846.     :class:`GEOSGeometry` objects::
    
  847. 
    
  848.         >>> poly = Polygon( ((0, 0), (0, 1), (1, 1), (0, 0)) )
    
  849.         >>> gc = GeometryCollection(Point(0, 0), MultiPoint(Point(0, 0), Point(1, 1)), poly)
    
  850.         >>> gc = GeometryCollection((Point(0, 0), MultiPoint(Point(0, 0), Point(1, 1)), poly))
    
  851. 
    
  852. .. _prepared-geometries:
    
  853. 
    
  854. Prepared Geometries
    
  855. ===================
    
  856. 
    
  857. In order to obtain a prepared geometry, access the
    
  858. :attr:`GEOSGeometry.prepared` property.  Once you have a
    
  859. ``PreparedGeometry`` instance its spatial predicate methods, listed below,
    
  860. may be used with other ``GEOSGeometry`` objects.  An operation with a prepared
    
  861. geometry can be orders of magnitude faster -- the more complex the geometry
    
  862. that is prepared, the larger the speedup in the operation.  For more information,
    
  863. please consult the `GEOS wiki page on prepared geometries <https://trac.osgeo.org/geos/wiki/PreparedGeometry>`_.
    
  864. 
    
  865. For example::
    
  866. 
    
  867.     >>> from django.contrib.gis.geos import Point, Polygon
    
  868.     >>> poly = Polygon.from_bbox((0, 0, 5, 5))
    
  869.     >>> prep_poly = poly.prepared
    
  870.     >>> prep_poly.contains(Point(2.5, 2.5))
    
  871.     True
    
  872. 
    
  873. ``PreparedGeometry``
    
  874. --------------------
    
  875. 
    
  876. .. class:: PreparedGeometry
    
  877. 
    
  878.     All methods on ``PreparedGeometry`` take an ``other`` argument, which
    
  879.     must be a :class:`GEOSGeometry` instance.
    
  880. 
    
  881.     .. method:: contains(other)
    
  882. 
    
  883.     .. method:: contains_properly(other)
    
  884. 
    
  885.     .. method:: covers(other)
    
  886. 
    
  887.     .. method:: crosses(other)
    
  888. 
    
  889.     .. method:: disjoint(other)
    
  890. 
    
  891.     .. method:: intersects(other)
    
  892. 
    
  893.     .. method:: overlaps(other)
    
  894. 
    
  895.     .. method:: touches(other)
    
  896. 
    
  897.     .. method:: within(other)
    
  898. 
    
  899. Geometry Factories
    
  900. ==================
    
  901. 
    
  902. .. function:: fromfile(file_h)
    
  903. 
    
  904.     :param file_h: input file that contains spatial data
    
  905.     :type file_h: a Python ``file`` object or a string path to the file
    
  906.     :rtype: a :class:`GEOSGeometry` corresponding to the spatial data in the file
    
  907. 
    
  908.     Example::
    
  909. 
    
  910.         >>> from django.contrib.gis.geos import fromfile
    
  911.         >>> g = fromfile('/home/bob/geom.wkt')
    
  912. 
    
  913. .. function:: fromstr(string, srid=None)
    
  914. 
    
  915.     :param string: string that contains spatial data
    
  916.     :type string: str
    
  917.     :param srid: spatial reference identifier
    
  918.     :type srid: int
    
  919.     :rtype: a :class:`GEOSGeometry` corresponding to the spatial data in the string
    
  920. 
    
  921.     ``fromstr(string, srid)`` is equivalent to
    
  922.     :class:`GEOSGeometry(string, srid) <GEOSGeometry>`.
    
  923. 
    
  924.     Example::
    
  925. 
    
  926.         >>> from django.contrib.gis.geos import fromstr
    
  927.         >>> pnt = fromstr('POINT(-90.5 29.5)', srid=4326)
    
  928. 
    
  929. I/O Objects
    
  930. ===========
    
  931. 
    
  932. Reader Objects
    
  933. --------------
    
  934. 
    
  935. The reader I/O classes return a :class:`GEOSGeometry` instance from the WKB
    
  936. and/or WKT input given to their ``read(geom)`` method.
    
  937. 
    
  938. .. class:: WKBReader
    
  939. 
    
  940.     Example::
    
  941. 
    
  942.         >>> from django.contrib.gis.geos import WKBReader
    
  943.         >>> wkb_r = WKBReader()
    
  944.         >>> wkb_r.read('0101000000000000000000F03F000000000000F03F')
    
  945.         <Point object at 0x103a88910>
    
  946. 
    
  947. .. class:: WKTReader
    
  948. 
    
  949.     Example::
    
  950. 
    
  951.         >>> from django.contrib.gis.geos import WKTReader
    
  952.         >>> wkt_r = WKTReader()
    
  953.         >>> wkt_r.read('POINT(1 1)')
    
  954.         <Point object at 0x103a88b50>
    
  955. 
    
  956. Writer Objects
    
  957. --------------
    
  958. 
    
  959. All writer objects have a ``write(geom)`` method that returns either the
    
  960. WKB or WKT of the given geometry.  In addition, :class:`WKBWriter` objects
    
  961. also have properties that may be used to change the byte order, and or
    
  962. include the SRID value (in other words, EWKB).
    
  963. 
    
  964. .. class:: WKBWriter(dim=2)
    
  965. 
    
  966.     ``WKBWriter`` provides the most control over its output.  By default it
    
  967.     returns OGC-compliant WKB when its ``write`` method is called.  However,
    
  968.     it has properties that allow for the creation of EWKB, a superset of the
    
  969.     WKB standard that includes additional information. See the
    
  970.     :attr:`WKBWriter.outdim` documentation for more details about the ``dim``
    
  971.     argument.
    
  972. 
    
  973.     .. method:: WKBWriter.write(geom)
    
  974. 
    
  975.     Returns the WKB of the given geometry as a Python ``buffer`` object.
    
  976.     Example::
    
  977. 
    
  978.         >>> from django.contrib.gis.geos import Point, WKBWriter
    
  979.         >>> pnt = Point(1, 1)
    
  980.         >>> wkb_w = WKBWriter()
    
  981.         >>> wkb_w.write(pnt)
    
  982.         <read-only buffer for 0x103a898f0, size -1, offset 0 at 0x103a89930>
    
  983. 
    
  984.     .. method:: WKBWriter.write_hex(geom)
    
  985. 
    
  986.     Returns WKB of the geometry in hexadecimal.  Example::
    
  987. 
    
  988.         >>> from django.contrib.gis.geos import Point, WKBWriter
    
  989.         >>> pnt = Point(1, 1)
    
  990.         >>> wkb_w = WKBWriter()
    
  991.         >>> wkb_w.write_hex(pnt)
    
  992.         '0101000000000000000000F03F000000000000F03F'
    
  993. 
    
  994.     .. attribute:: WKBWriter.byteorder
    
  995. 
    
  996.     This property may be set to change the byte-order of the geometry
    
  997.     representation.
    
  998. 
    
  999.     =============== =================================================
    
  1000.     Byteorder Value Description
    
  1001.     =============== =================================================
    
  1002.     0               Big Endian (e.g., compatible with RISC systems)
    
  1003.     1               Little Endian (e.g., compatible with x86 systems)
    
  1004.     =============== =================================================
    
  1005. 
    
  1006.     Example::
    
  1007. 
    
  1008.         >>> from django.contrib.gis.geos import Point, WKBWriter
    
  1009.         >>> wkb_w = WKBWriter()
    
  1010.         >>> pnt = Point(1, 1)
    
  1011.         >>> wkb_w.write_hex(pnt)
    
  1012.         '0101000000000000000000F03F000000000000F03F'
    
  1013.         >>> wkb_w.byteorder = 0
    
  1014.         '00000000013FF00000000000003FF0000000000000'
    
  1015. 
    
  1016.     .. attribute:: WKBWriter.outdim
    
  1017. 
    
  1018.     This property may be set to change the output dimension of the geometry
    
  1019.     representation.  In other words, if you have a 3D geometry then set to 3
    
  1020.     so that the Z value is included in the WKB.
    
  1021. 
    
  1022.     ============ ===========================
    
  1023.     Outdim Value Description
    
  1024.     ============ ===========================
    
  1025.     2            The default, output 2D WKB.
    
  1026.     3            Output 3D WKB.
    
  1027.     ============ ===========================
    
  1028. 
    
  1029.     Example::
    
  1030. 
    
  1031.         >>> from django.contrib.gis.geos import Point, WKBWriter
    
  1032.         >>> wkb_w = WKBWriter()
    
  1033.         >>> wkb_w.outdim
    
  1034.         2
    
  1035.         >>> pnt = Point(1, 1, 1)
    
  1036.         >>> wkb_w.write_hex(pnt) # By default, no Z value included:
    
  1037.         '0101000000000000000000F03F000000000000F03F'
    
  1038.         >>> wkb_w.outdim = 3 # Tell writer to include Z values
    
  1039.         >>> wkb_w.write_hex(pnt)
    
  1040.         '0101000080000000000000F03F000000000000F03F000000000000F03F'
    
  1041. 
    
  1042.     .. attribute:: WKBWriter.srid
    
  1043. 
    
  1044.     Set this property with a boolean to indicate whether the SRID of the
    
  1045.     geometry should be included with the WKB representation.  Example::
    
  1046. 
    
  1047.         >>> from django.contrib.gis.geos import Point, WKBWriter
    
  1048.         >>> wkb_w = WKBWriter()
    
  1049.         >>> pnt = Point(1, 1, srid=4326)
    
  1050.         >>> wkb_w.write_hex(pnt) # By default, no SRID included:
    
  1051.         '0101000000000000000000F03F000000000000F03F'
    
  1052.         >>> wkb_w.srid = True # Tell writer to include SRID
    
  1053.         >>> wkb_w.write_hex(pnt)
    
  1054.         '0101000020E6100000000000000000F03F000000000000F03F'
    
  1055. 
    
  1056. .. class:: WKTWriter(dim=2, trim=False, precision=None)
    
  1057. 
    
  1058.     This class allows outputting the WKT representation of a geometry. See the
    
  1059.     :attr:`WKBWriter.outdim`, :attr:`trim`, and :attr:`precision` attributes for
    
  1060.     details about the constructor arguments.
    
  1061. 
    
  1062.     .. method:: WKTWriter.write(geom)
    
  1063. 
    
  1064.     Returns the WKT of the given geometry. Example::
    
  1065. 
    
  1066.         >>> from django.contrib.gis.geos import Point, WKTWriter
    
  1067.         >>> pnt = Point(1, 1)
    
  1068.         >>> wkt_w = WKTWriter()
    
  1069.         >>> wkt_w.write(pnt)
    
  1070.         'POINT (1.0000000000000000 1.0000000000000000)'
    
  1071. 
    
  1072.     .. attribute:: WKTWriter.outdim
    
  1073. 
    
  1074.         See :attr:`WKBWriter.outdim`.
    
  1075. 
    
  1076.     .. attribute:: WKTWriter.trim
    
  1077. 
    
  1078.     This property is used to enable or disable trimming of
    
  1079.     unnecessary decimals.
    
  1080. 
    
  1081.         >>> from django.contrib.gis.geos import Point, WKTWriter
    
  1082.         >>> pnt = Point(1, 1)
    
  1083.         >>> wkt_w = WKTWriter()
    
  1084.         >>> wkt_w.trim
    
  1085.         False
    
  1086.         >>> wkt_w.write(pnt)
    
  1087.         'POINT (1.0000000000000000 1.0000000000000000)'
    
  1088.         >>> wkt_w.trim = True
    
  1089.         >>> wkt_w.write(pnt)
    
  1090.         'POINT (1 1)'
    
  1091. 
    
  1092.     .. attribute:: WKTWriter.precision
    
  1093. 
    
  1094.     This property controls the rounding precision of coordinates;
    
  1095.     if set to ``None`` rounding is disabled.
    
  1096. 
    
  1097.         >>> from django.contrib.gis.geos import Point, WKTWriter
    
  1098.         >>> pnt = Point(1.44, 1.66)
    
  1099.         >>> wkt_w = WKTWriter()
    
  1100.         >>> print(wkt_w.precision)
    
  1101.         None
    
  1102.         >>> wkt_w.write(pnt)
    
  1103.         'POINT (1.4399999999999999 1.6599999999999999)'
    
  1104.         >>> wkt_w.precision = 0
    
  1105.         >>> wkt_w.write(pnt)
    
  1106.         'POINT (1 2)'
    
  1107.         >>> wkt_w.precision = 1
    
  1108.         >>> wkt_w.write(pnt)
    
  1109.         'POINT (1.4 1.7)'
    
  1110. 
    
  1111. .. rubric:: Footnotes
    
  1112. .. [#fnogc] *See* `PostGIS EWKB, EWKT and Canonical Forms <https://postgis.net/docs/using_postgis_dbmanagement.html#EWKB_EWKT>`_, PostGIS documentation at Ch. 4.1.2.
    
  1113. 
    
  1114. Settings
    
  1115. ========
    
  1116. 
    
  1117. .. setting:: GEOS_LIBRARY_PATH
    
  1118. 
    
  1119. ``GEOS_LIBRARY_PATH``
    
  1120. ---------------------
    
  1121. 
    
  1122. A string specifying the location of the GEOS C library.  Typically,
    
  1123. this setting is only used if the GEOS C library is in a non-standard
    
  1124. location (e.g., ``/home/bob/lib/libgeos_c.so``).
    
  1125. 
    
  1126. .. note::
    
  1127. 
    
  1128.     The setting must be the *full* path to the **C** shared library; in
    
  1129.     other words you want to use ``libgeos_c.so``, not ``libgeos.so``.
    
  1130. 
    
  1131. Exceptions
    
  1132. ==========
    
  1133. 
    
  1134. .. exception:: GEOSException
    
  1135. 
    
  1136.     The base GEOS exception, indicates a GEOS-related error.