sylva.geo.coords¶
Shifting, rotating and recentring are methods of
PointCloud: translate, rotate and recentre.
sylva.geo.coords ¶
Coordinate systems: shifts, rotations, reprojection and transform files.
Shifting and rotating are methods of ~sylva.PointCloud
(~sylva.PointCloud.translate, ~sylva.PointCloud.rotate,
~sylva.PointCloud.recentre); this module builds their matrices,
reprojects between coordinate reference systems and applies registration
results to whole surveys.
A CRS is given as an EPSG code ("EPSG:7855", 7855, a compound
"EPSG:7855+5711"), a PROJ string ("+proj=utm +zone=55 +south
+ellps=GRS80") or WKT (as found in LAS files, ESRI .prj files or
exported by GIS). EPSG definitions are built in (the EPSG registry's
horizontal CRSs with codes up to 65535) and reprojection runs in the Rust
core without PROJ or GDAL.
How exact a reprojection is depends on the datums involved:
| Transformation | Example | Result |
|---|---|---|
| Same datum, other projection | MGA zone 55 to GDA2020 latitude/longitude; UTM to WGS 84 | exact (float rounding) |
| Datums tied to WGS 84 by zero parameters | GDA94, NAD83, ETRS89, NZGD2000 to WGS 84 | exact under that convention |
Helmert (towgs84) datum change |
OSGB36 to WGS 84 | exact to the published parameters; heights change |
| Datums without parameters between them | GDA2020 to WGS 84 or GDA94 | approximate: not applied (null transformation) |
| Grid-based datum change | NAD27; NTv2 grids | refused (grids are not available) |
| Vertical datum change | AHD to ellipsoidal heights | approximate: heights not changed |
Approximate transformations issue an ApproximateTransformationWarning
naming what was not applied; transformation reports it beforehand.
ApproximateTransformationWarning ¶
Bases: UserWarning
A reprojection could not apply part of the transformation (a datum shift without known parameters, or a change of vertical datum).
CRS
dataclass
¶
What Sylva understands of a coordinate reference system.
Attributes:
| Name | Type | Description |
|---|---|---|
name |
str
|
Name from the definition ( |
label |
str
|
|
epsg |
int | None
|
EPSG code of the horizontal part, or None. |
vertical_epsg |
int | None
|
EPSG code of the vertical part, or None. |
proj4 |
str
|
PROJ string the coordinates are transformed with. |
wkt |
str | None
|
WKT written to LAS files, or None (PROJ strings have none). |
datum |
str | None
|
Datum identity used to decide whether two CRSs share a datum. |
geographic |
bool | None
|
True when x and y are longitude and latitude in degrees. |
Transformation
dataclass
¶
How reproject gets from one CRS to another.
Attributes:
| Name | Type | Description |
|---|---|---|
kind |
str
|
|
exact |
bool
|
True when the result is exact to float rounding (and to the published parameters of a Helmert change). |
changes_z |
bool
|
True when heights change (Helmert datum changes, which treat z as ellipsoidal height). |
note |
str
|
Explanation; says what is not applied when |
translation_matrix ¶
translation_matrix(dx: float, dy: float, dz: float = 0.0) -> np.ndarray
A 4x4 translation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dx
|
float
|
Offset (m). |
required |
dy
|
float
|
Offset (m). |
required |
dz
|
float
|
Offset (m). |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If an offset is not finite. |
rotation_matrix ¶
rotation_matrix(angle_deg: float, axis: str | Iterable[float] = 'z', about: Iterable[float] | None = None) -> np.ndarray
A 4x4 rotation about an axis through a point.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
angle_deg
|
float
|
Angle in degrees, right-handed (counter-clockwise looking down the axis towards the origin). Multiples of 90 degrees are exact. |
required |
axis
|
str | Iterable[float]
|
|
'z'
|
about
|
Iterable[float] | None
|
A point on the axis; the origin if None. |
None
|
Returns:
| Type | Description |
|---|---|
ndarray
|
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If the angle, axis or centre is not finite, or the axis is zero or an unknown name. |
crs_info ¶
crs_info(crs) -> CRS
Parse a CRS.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
crs
|
EPSG code ( |
required |
Returns:
| Type | Description |
|---|---|
CRS
|
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If the definition is not recognised, the EPSG code is not in the built-in tables, or WKT without an EPSG code uses a projection Sylva cannot convert. |
same_crs ¶
same_crs(a, b) -> bool
Whether two CRS definitions describe the same system.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
a
|
CRS definitions, as for |
required | |
b
|
CRS definitions, as for |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True for equal definitions, for the same EPSG code(s) written
differently ( |
transformation ¶
transformation(src_crs, dst_crs) -> Transformation
Describe the transformation between two CRSs without applying it.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
src_crs
|
CRS definitions, as for |
required | |
dst_crs
|
CRS definitions, as for |
required |
Returns:
| Type | Description |
|---|---|
Transformation
|
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If a CRS cannot be parsed or the transformation needs a datum grid. |
reproject ¶
reproject(data, dst_crs, src_crs=None)
Transform coordinates into another coordinate reference system.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
A |
required | |
dst_crs
|
Target CRS: EPSG code, PROJ string or WKT (see |
required | |
src_crs
|
CRS of |
None
|
Returns:
| Type | Description |
|---|---|
PointCloud or ndarray
|
Same type as |
Raises:
| Type | Description |
|---|---|
ValueError
|
If there is no source CRS, a CRS cannot be parsed, the transformation needs a datum grid, or an array has the wrong shape. |
TypeError
|
For a |
Warns:
| Type | Description |
|---|---|
ApproximateTransformationWarning
|
When part of the transformation cannot be applied (a datum change without known parameters, or a vertical datum change). |
Notes
Uses proj4rs (a Rust port of PROJ.4) with the EPSG registry's PROJ.4
definitions. Transformations that PROJ carries out with grids (NTv2,
NADCON, geoid models) are not available; the GDA94 to GDA2020 Helmert
can be applied by giving GDA2020 as a PROJ string with its towgs84
parameters (see the coordinates guide).
Examples:
>>> cloud = sylva.read("plot.laz") # crs from the LAS header
>>> lonlat = sylva.geo.coords.reproject(cloud, "EPSG:7844")
apply_transforms ¶
apply_transforms(scans, transforms, out: str | Path | None = None, merge: bool = False) -> list[PointCloud] | PointCloud
Put scans into one frame with their registration matrices.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
scans
|
Point cloud paths or |
required | |
transforms
|
One of
|
required | |
out
|
str | Path | None
|
Where to write: a directory for one file per scan (named after the
scan, keeping its format, |
None
|
merge
|
bool
|
Return (and write) one cloud with a |
False
|
Returns:
| Type | Description |
|---|---|
list of PointCloud or PointCloud
|
The transformed scans in input order, or the merged cloud. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If a scan has no matching transform, a name matches several, the numbers of scans and positional transforms differ, or a matrix is not 4x4. |
OSError
|
If a file cannot be read or written. |
Notes
A scan is matched to a named transform by its mapping key, or by its
path: the file stem or any parent folder that equals a transform name or
starts with it followed by a non-alphanumeric character. So
ScanPos001.rxp, ScanPos001_2cm.laz and
ScanPos001/scans/240101_1200.rxp all get ScanPos001, and
ScanPos0011 does not. Unnamed clouds need positional transforms.
Examples:
>>> clouds = sylva.geo.coords.apply_transforms("scans/", "plot_coreg/transforms.json",
... out="plot.laz", merge=True)