Geo Interface

Intended Usage

The intended usage of the ezdxf.addons.geo module is as tool to work with geospatial data in conjunction with dedicated geospatial applications and libraries and the module can not and should not replicate their functionality.

The only reimplemented feature is the most common WSG84 EPSG:3395 World Mercator projection, for everything else use the dedicated packages like:

  • pyproj - Cartographic projections and coordinate transformations library.

  • Shapely - Manipulation and analysis of geometric objects in the Cartesian plane.

  • PyShp - The Python Shapefile Library (PyShp) reads and writes ESRI Shapefiles in pure Python.

  • GeoJSON - GeoJSON interface for Python.

  • GDAL - Tools for programming and manipulating the GDAL Geospatial Data Abstraction Library.

  • Fiona - Fiona is GDAL’s neat and nimble vector API for Python programmers.

  • QGIS - A free and open source geographic information system.

  • and many more …

This module provides support for the __geo_interface__: https://gist.github.com/sgillies/2217756

Which is also supported by Shapely, for supported types see the GeoJSON Standard and examples in Appendix-A.

See also

Tutorial for the Geo Add-on for loading GPX data into DXF files with an existing geo location reference and exporting DXF entities as GeoJSON data.

Proxy From Mapping

The GeoProxy represents a __geo_interface__ mapping, create a new proxy by GeoProxy.parse() from an external __geo_interface__ mapping. GeoProxy.to_dxf_entities() returns new DXF entities from this mapping. Returns “Point” as Point entity, “LineString” as LWPolyline entity and “Polygon” as Hatch entity or as separated LWPolyline entities (or both) and new in v0.16.6 as MPolygon. Supports “MultiPoint”, “MultiLineString”, “MultiPolygon”, “GeometryCollection”, “Feature” and “FeatureCollection”. Add new DXF entities to a layout by the Layout.add_entity() method.

Proxy From DXF Entity

The proxy() function or the constructor GeoProxy.from_dxf_entities() creates a new GeoProxy object from a single DXF entity or from an iterable of DXF entities, entities without a corresponding representation will be approximated.

Supported DXF entities are:

  • POINT as “Point”

  • LINE as “LineString”

  • LWPOLYLINE as “LineString” if open and “Polygon” if closed

  • POLYLINE as “LineString” if open and “Polygon” if closed, supports only 2D and 3D polylines, POLYMESH and POLYFACE are not supported

  • SOLID, TRACE, 3DFACE as “Polygon”

  • CIRCLE, ARC, ELLIPSE and SPLINE by approximation as “LineString” if open and “Polygon” if closed

  • HATCH and MPOLYGON as “Polygon”, holes are supported

Warning

This module does no extensive validity checks for “Polygon” objects and because DXF has different requirements for HATCH boundary paths than the GeoJSON Standard, it is possible to create invalid “Polygon” objects. It is recommended to check critical objects by a sophisticated geometry library like Shapely.

Module Functions

ezdxf.addons.geo.proxy(entity: DXFGraphic | Iterable[DXFGraphic], distance: float = MAX_FLATTENING_DISTANCE, force_line_string: bool = False) GeoProxy

Returns a GeoProxy object.

Parameters:
  • entity – a single DXF entity or iterable of DXF entities

  • distance – maximum flattening distance for curve approximations

  • force_line_string – by default this function returns Polygon objects for closed geometries like CIRCLE, SOLID, closed POLYLINE and so on, by setting argument force_line_string to True, this entities will be returned as LineString objects.

ezdxf.addons.geo.dxf_entities(geo_mapping: MutableMapping[str, Any], polygon=PolygonConversion.HATCH, dxfattribs=None, *, post_process: Callable[[DXFGraphic, MutableMapping[str, Any]], None] | None = None) Iterator[DXFGraphic]

Returns __geo_interface__ mappings as DXF entities.

The enum polygon determines the method to convert polygons, use PolygonConversion.HATCH for Hatch entity, PolygonConversion.POLYLINE for LWPolyline or PolygonConversion.HATCH_AND_POLYLINE for both. Option PolygonConversion.POLYLINE returns for the exterior path and each hole a separated LWPolyline entity. The Hatch entity supports holes, but has no explicit borderline.

Yields Hatch always before LWPolyline entities.

PolygonConversion.MPOLYGON support was added in v0.16.6, which is like a Hatch entity with additional borderlines, but the MPOLYGON entity is not a core DXF entity and DXF viewers, applications and libraries my not support this entity. The DXF attribute color defines the borderline color and fill_color the color of the solid filling.

The returned DXF entities can be added to a layout by the Layout.add_entity() method.

Parameters:
  • geo_mapping__geo__interface__ mapping as dict or a Python object with a __geo__interface__ property

  • polygon – see PolygonConversion

  • dxfattribs – dict with additional DXF attributes

  • post_process – post process function of type PostProcessFunc that get the created DXF entity and the geo mapping as input, see reference implementation assign_layers()

ezdxf.addons.geo.gfilter(entities: Iterable[DXFGraphic]) Iterator[DXFGraphic]

Filter DXF entities from iterable entities, which are incompatible to the __geo_reference__ interface.

GeoProxy Class

class ezdxf.addons.geo.GeoProxy(geo_mapping: MutableMapping[str, Any], places: int = 6)

Stores the __geo_interface__ mapping in a parsed and compiled form.

Stores coordinates as Vec3 objects and represents “Polygon” always as tuple (exterior, holes) even without holes.

The GeoJSON specification recommends 6 decimal places for latitude and longitude which equates to roughly 10cm of precision. You may need slightly more for certain applications, 9 decimal places would be sufficient for professional survey-grade GPS coordinates.

Parameters:
  • geo_mapping – parsed and compiled __geo_interface__ mapping

  • places – decimal places to round for __geo_interface__ export

__geo_interface__

Returns the __geo_interface__ compatible mapping as dict.

geotype

Property returns the top level entity type or None.

classmethod parse(geo_mapping: MutableMapping[str, Any]) Self

Parse and compile a __geo_interface__ mapping as dict or a Python object with a __geo_interface__ property, does some basic syntax checks, converts all coordinates into Vec3 objects, represents “Polygon” always as tuple (exterior, holes) even without holes.

classmethod from_dxf_entities(entity: DXFGraphic | Iterable[DXFGraphic], distance: float = MAX_FLATTENING_DISTANCE, force_line_string: bool = False) GeoProxy

Constructor from a single DXF entity or an iterable of DXF entities.

Parameters:
  • entity – DXF entity or entities

  • distance – maximum flattening distance for curve approximations

  • force_line_string – by default this function returns Polygon objects for closed geometries like CIRCLE, SOLID, closed POLYLINE and so on, by setting argument force_line_string to True, this entities will be returned as LineString objects.

to_dxf_entities(polygon=PolygonConversion.HATCH, dxfattribs=None, *, post_process: Callable[[DXFGraphic, MutableMapping[str, Any]], None] | None = None) Iterator[DXFGraphic]

Returns stored __geo_interface__ mappings as DXF entities.

The polygon argument determines the method to convert polygons, use 1 for Hatch entity, 2 for LWPolyline or 3 for both. Option 2 returns for the exterior path and each hole a separated LWPolyline entity. The Hatch entity supports holes, but has no explicit borderline.

Yields Hatch always before LWPolyline entities.

MPolygon support was added in v0.16.6, which is like a Hatch entity with additional borderlines, but the MPOLYGON entity is not a core DXF entity and DXF viewers, applications and libraries my not support this entity. The DXF attribute color defines the borderline color and fill_color the color of the solid filling.

The returned DXF entities can be added to a layout by the Layout.add_entity() method.

Parameters:
  • polygon – see PolygonConversion

  • dxfattribs – dict with additional DXF attributes

  • post_process – post process function of type PostProcesFunc that get the created DXF entity and the geo mapping as input, see reference implementation assign_layers()

copy() GeoProxy

Returns a deep copy.

__iter__() Iterator[MutableMapping[str, Any]]

Iterate over all geometry entities.

Yields only “Point”, “LineString”, “Polygon”, “MultiPoint”, “MultiLineString” and “MultiPolygon” objects, returns the content of “GeometryCollection”, “FeatureCollection” and “Feature” as geometry objects (“Point”, …).

wcs_to_crs(crs: Matrix44) None

Transform all coordinates recursive from WCS coordinates into Coordinate Reference System (CRS) by transformation matrix crs inplace.

The CRS is defined by the GeoData entity, get the GeoData entity from the modelspace by method get_geodata(). The CRS transformation matrix can be acquired form the GeoData object by get_crs_transformation() method:

doc = ezdxf.readfile('file.dxf')
msp = doc.modelspace()
geodata = msp.get_geodata()
if geodata:
    matrix, axis_ordering = geodata.get_crs_transformation()

If axis_ordering is False the CRS is not compatible with the __geo_interface__ or GeoJSON (see chapter 3.1.1).

Parameters:

crs – transformation matrix of type Matrix44

crs_to_wcs(crs: Matrix44) None

Transform all coordinates recursive from CRS into WCS coordinates by transformation matrix crs inplace, see also GeoProxy.wcs_to_crs().

Parameters:

crs – transformation matrix of type Matrix44

globe_to_map(func: Callable[[Vec3], Vec3] | None = None) None

Transform all coordinates recursive from globe representation in longitude and latitude in decimal degrees into 2D map representation in meters.

Default is WGS84 EPSG:4326 (GPS) to WGS84 EPSG:3395 World Mercator function wgs84_4326_to_3395().

Use the pyproj package to write a custom projection function as needed.

Parameters:

func – custom transformation function, which takes one Vec3 object as argument and returns the result as a Vec3 object.

map_to_globe(func: Callable[[Vec3], Vec3] | None = None) None

Transform all coordinates recursive from 2D map representation in meters into globe representation as longitude and latitude in decimal degrees.

Default is WGS84 EPSG:3395 World Mercator to WGS84 EPSG:4326 GPS function wgs84_3395_to_4326().

Use the pyproj package to write a custom projection function as needed.

Parameters:

func – custom transformation function, which takes one Vec3 object as argument and returns the result as a Vec3 object.

apply(func: Callable[[Vec3], Vec3]) None

Apply the transformation function func recursive to all coordinates.

Parameters:

func – transformation function as Callable[[Vec3], Vec3]

filter(func: Callable[[GeoProxy], bool]) None

Removes all mappings for which func() returns False. The function only has to handle Point, LineString and Polygon entities, other entities like MultiPolygon are divided into separate entities also any collection.

Helper Functions

ezdxf.addons.geo.wgs84_4326_to_3395(location: Vec3) Vec3

Transform WGS84 EPSG:4326 location given as latitude and longitude in decimal degrees as used by GPS into World Mercator cartesian 2D coordinates in meters EPSG:3395.

Parameters:

locationVec3 object, x-attribute represents the longitude value (East-West) in decimal degrees and the y-attribute represents the latitude value (North-South) in decimal degrees.

ezdxf.addons.geo.wgs84_3395_to_4326(location: Vec3, tol: float = 1e-6) Vec3

Transform WGS84 World Mercator EPSG:3395 location given as cartesian 2D coordinates x, y in meters into WGS84 decimal degrees as longitude and latitude EPSG:4326 as used by GPS.

Parameters:
  • locationVec3 object, z-axis is ignored

  • tol – accuracy for latitude calculation

ezdxf.addons.geo.dms2dd(d: float, m: float = 0, s: float = 0) float

Convert degree, minutes, seconds into decimal degrees.

ezdxf.addons.geo.dd2dms(dd: float) tuple[float, float, float]

Convert decimal degrees into degree, minutes, seconds.

ezdxf.addons.geo.assign_layers(entity: DXFGraphic, mapping: MutableMapping[str, Any]) None

Reference implementation for a post_process() function.

See also

dxf_entities()

def assign_layers(entity: DXFGraphic, mapping: GeoMapping) -> None:
    properties = mapping.get("properties)
    if properties is None:
        return
    layer = properties.get("layer")
    if layer:
        entity.dxf.layer = layer

Types

class ezdxf.addons.geo.PolygonConversion(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)

Polygon conversion types as IntEnum.

HATCH
POLYLINE
HATCH_AND_POLYLINE
MPOLYGON
ezdxf.addons.geo.GeoMapping

alias of MutableMapping[str, Any]

ezdxf.addons.geo.PostProcessFunc

alias of Callable[[DXFGraphic, MutableMapping[str, Any]], None]