2.30.7.13. pycsamt.map.geometry#
Real-geometry line-layout helpers for 3-D survey maps.
Multi-line 3-D views (fence, block, depth-slice) need two things per
survey line: an along-line (“profile distance”) axis and a
line-to-line (“offset”) position. Placing lines with a synthetic
index * spacing stack ignores where the lines actually sit on the
ground, which staggers panels that should be parallel and evenly
spaced.
This module derives both from real station coordinates instead:
every station is projected onto a shared local (u, v) frame — u
along the survey’s dominant strike, v across it — so parallel
lines stay parallel and the line-to-line spacing reflects their true
geographic separation.
Pure numpy, no Plotly/Dash/pycsamt-app dependencies, so it is safe to
import from both pycsamt.map (the code-first / mapview 3-D
builder) and pycsamt.app.web (the legacy 3-D map callbacks) —
whichever data structure each caller uses (MapData stations, or
plain per-line dicts) is adapted to plain id/lat/lon/line arrays
before calling in here.
Functions
|
Local planar metres for lat/lon, equirectangular approx. |
|
Return the shared along-line unit direction for points. |
|
Shift offsets so the smallest value is zero. |
|
Cross-strike placement for one line, in metres. |
|
Fit the shared local frame used by |
|
Project every station onto a shared local (u, v) frame, metres. |
Classes
|
A survey's local along/cross-strike frame, reusable for any point. |
- pycsamt.map.geometry.equirect_xy(lat, lon)[source]
Local planar metres for lat/lon, equirectangular approx.
Centred implicitly at the mean latitude of lat.
- pycsamt.map.geometry.fit_strike(points, groups)[source]
Return the shared along-line unit direction for points.
Fits each group’s (line’s) own best-fit axis — SVD on that group’s centred points — then averages them, sign-aligned and weighted by point count. This reflects “which way each line actually runs” rather than the aggregate shape of the whole point cloud, which can pick the wrong axis when a survey’s footprint is roughly as wide (line-to-line) as it is long (along-line), e.g. a short/dense grid.
Returns
Nonewhen no direction can be fit (fewer than two points overall, or a degenerate/singular point cloud).
- pycsamt.map.geometry.survey_uv(ids, lat, lon, line)[source]
Project every station onto a shared local (u, v) frame, metres.
uis the along-strike distance,vthe cross-strike offset, both measured from the combined centroid of every station passed in. ids, lat, lon, line must be the same length and aligned (one entry per station).Returns
{}when there are fewer than two stations or no strike direction could be fit (e.g. all stations coincide).
- class pycsamt.map.geometry.SurveyFrame(mean_lat_deg, origin_xy, strike, perp)[source]
Bases:
objectA survey’s local along/cross-strike frame, reusable for any point.
survey_uv()returns only the station projections; this exposes the frame itself so an arbitrary geographic point (a borehole collar, a target) can be placed in the same local metres the 3-D map builders use.projectmirrorssurvey_uv()exactly: equirectangular metres about the survey’s mean latitude, then a shift to the station centroid and a rotation onto the fitted strike.- Parameters:
- mean_lat_deg: float
- pycsamt.map.geometry.survey_frame(lat, lon, line)[source]
Fit the shared local frame used by
survey_uv().Returns
Noneunder the same conditions assurvey_uv()(fewer than two stations, or no strike direction could be fit).
- pycsamt.map.geometry.normalize_offsets(offsets)[source]
Shift offsets so the smallest value is zero.
Returns
None(signalling “no real geometry, fall back to a synthetic layout”) when offsets is empty or any value is missing/non-finite — mixing real and synthetic placement in the same plot would look inconsistent, so it is all-or-nothing.
- pycsamt.map.geometry.resolve_offset(name, idx, real_offsets, fallback_unit, spacing)[source]
Cross-strike placement for one line, in metres.
Uses the survey’s true line-to-line spacing (scaled by spacing, e.g. a UI “line spacing” multiplier where
1.0means true spacing) when real_offsets is available, otherwise falls back to a syntheticidx * spacing * fallback_unitstack.