compass-lib 0.0.4__tar.gz → 0.0.6__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {compass_lib-0.0.4 → compass_lib-0.0.6}/PKG-INFO +1 -2
- {compass_lib-0.0.4 → compass_lib-0.0.6}/compass_lib/__init__.py +1 -1
- {compass_lib-0.0.4 → compass_lib-0.0.6}/compass_lib/geojson.py +161 -85
- {compass_lib-0.0.4 → compass_lib-0.0.6}/compass_lib/project/parser.py +3 -2
- {compass_lib-0.0.4 → compass_lib-0.0.6}/pyproject.toml +3 -11
- {compass_lib-0.0.4 → compass_lib-0.0.6}/LICENSE +0 -0
- {compass_lib-0.0.4 → compass_lib-0.0.6}/README.md +0 -0
- {compass_lib-0.0.4 → compass_lib-0.0.6}/compass_lib/commands/__init__.py +0 -0
- {compass_lib-0.0.4 → compass_lib-0.0.6}/compass_lib/commands/convert.py +0 -0
- {compass_lib-0.0.4 → compass_lib-0.0.6}/compass_lib/commands/encrypt.py +0 -0
- {compass_lib-0.0.4 → compass_lib-0.0.6}/compass_lib/commands/geojson.py +0 -0
- {compass_lib-0.0.4 → compass_lib-0.0.6}/compass_lib/commands/main.py +0 -0
- {compass_lib-0.0.4 → compass_lib-0.0.6}/compass_lib/constants.py +0 -0
- {compass_lib-0.0.4 → compass_lib-0.0.6}/compass_lib/enums.py +0 -0
- {compass_lib-0.0.4 → compass_lib-0.0.6}/compass_lib/errors.py +0 -0
- {compass_lib-0.0.4 → compass_lib-0.0.6}/compass_lib/geo_utils.py +0 -0
- {compass_lib-0.0.4 → compass_lib-0.0.6}/compass_lib/interface.py +0 -0
- {compass_lib-0.0.4 → compass_lib-0.0.6}/compass_lib/io.py +0 -0
- {compass_lib-0.0.4 → compass_lib-0.0.6}/compass_lib/models.py +0 -0
- {compass_lib-0.0.4 → compass_lib-0.0.6}/compass_lib/plot/__init__.py +0 -0
- {compass_lib-0.0.4 → compass_lib-0.0.6}/compass_lib/plot/models.py +0 -0
- {compass_lib-0.0.4 → compass_lib-0.0.6}/compass_lib/plot/parser.py +0 -0
- {compass_lib-0.0.4 → compass_lib-0.0.6}/compass_lib/project/__init__.py +0 -0
- {compass_lib-0.0.4 → compass_lib-0.0.6}/compass_lib/project/format.py +0 -0
- {compass_lib-0.0.4 → compass_lib-0.0.6}/compass_lib/project/models.py +0 -0
- {compass_lib-0.0.4 → compass_lib-0.0.6}/compass_lib/solver/__init__.py +0 -0
- {compass_lib-0.0.4 → compass_lib-0.0.6}/compass_lib/solver/ariane.py +0 -0
- {compass_lib-0.0.4 → compass_lib-0.0.6}/compass_lib/solver/base.py +0 -0
- {compass_lib-0.0.4 → compass_lib-0.0.6}/compass_lib/solver/lse.py +0 -0
- {compass_lib-0.0.4 → compass_lib-0.0.6}/compass_lib/solver/models.py +0 -0
- {compass_lib-0.0.4 → compass_lib-0.0.6}/compass_lib/solver/noop.py +0 -0
- {compass_lib-0.0.4 → compass_lib-0.0.6}/compass_lib/solver/proportional.py +0 -0
- {compass_lib-0.0.4 → compass_lib-0.0.6}/compass_lib/solver/sparse.py +0 -0
- {compass_lib-0.0.4 → compass_lib-0.0.6}/compass_lib/survey/__init__.py +0 -0
- {compass_lib-0.0.4 → compass_lib-0.0.6}/compass_lib/survey/format.py +0 -0
- {compass_lib-0.0.4 → compass_lib-0.0.6}/compass_lib/survey/models.py +0 -0
- {compass_lib-0.0.4 → compass_lib-0.0.6}/compass_lib/survey/parser.py +0 -0
- {compass_lib-0.0.4 → compass_lib-0.0.6}/compass_lib/validation.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: compass_lib
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.6
|
|
4
4
|
Summary: Compass Parser Library.
|
|
5
5
|
Keywords: cave,survey,karst
|
|
6
6
|
Author-email: Jonathan Dekhtiar <jonathan@dekhtiar.com>
|
|
@@ -35,7 +35,6 @@ Requires-Dist: python-dotenv>=1.0.0,<2.0.0 ; extra == "test"
|
|
|
35
35
|
Requires-Dist: deepdiff>=7.0,<9.0 ; extra == "test"
|
|
36
36
|
Requires-Dist: pytest>=8.0.0,<10.0.0 ; extra == "test"
|
|
37
37
|
Requires-Dist: pytest-cov>=5.0.0,<8.0.0 ; extra == "test"
|
|
38
|
-
Requires-Dist: pytest-dotenv>=0.5.0,<1.0.0 ; extra == "test"
|
|
39
38
|
Requires-Dist: pytest-env>=1.1.3,<2.0.0 ; extra == "test"
|
|
40
39
|
Requires-Dist: pytest-runner>=6.0.0,<7.0.0 ; extra == "test"
|
|
41
40
|
Requires-Dist: pytest-ordering>=0.6,<1.0.0 ; extra == "test"
|
|
@@ -33,10 +33,10 @@ from __future__ import annotations
|
|
|
33
33
|
import datetime
|
|
34
34
|
import logging
|
|
35
35
|
import math
|
|
36
|
+
import uuid
|
|
36
37
|
from collections import deque
|
|
37
38
|
from dataclasses import dataclass
|
|
38
39
|
from dataclasses import field
|
|
39
|
-
from dataclasses import replace
|
|
40
40
|
from typing import TYPE_CHECKING
|
|
41
41
|
from typing import Any
|
|
42
42
|
|
|
@@ -54,6 +54,7 @@ from shapely.ops import unary_union
|
|
|
54
54
|
from compass_lib.constants import FEET_TO_METERS
|
|
55
55
|
from compass_lib.constants import GEOJSON_COORDINATE_PRECISION
|
|
56
56
|
from compass_lib.constants import JSON_ENCODING
|
|
57
|
+
from compass_lib.constants import METERS_TO_FEET
|
|
57
58
|
from compass_lib.enums import Datum
|
|
58
59
|
from compass_lib.geo_utils import GeoLocation
|
|
59
60
|
from compass_lib.geo_utils import get_declination
|
|
@@ -153,7 +154,7 @@ class MisclosureLeg:
|
|
|
153
154
|
the position computed by the arriving (typically longer) path; the
|
|
154
155
|
``existing`` is the position already set by the first path to
|
|
155
156
|
reach the station. The longest path is considered the "true"
|
|
156
|
-
segment; closure error is ghost
|
|
157
|
+
segment; closure error is ghost - existing.
|
|
157
158
|
"""
|
|
158
159
|
|
|
159
160
|
existing: Station # Station already computed by another anchor's BFS
|
|
@@ -212,7 +213,6 @@ def length_to_meters(length_ft: float) -> float:
|
|
|
212
213
|
_transformer_cache: dict[str, Transformer] = {}
|
|
213
214
|
|
|
214
215
|
|
|
215
|
-
|
|
216
216
|
def _get_transformer(zone: int, northern: bool, datum: Datum) -> Transformer:
|
|
217
217
|
"""Get or create a cached transformer from UTM to WGS84.
|
|
218
218
|
|
|
@@ -488,9 +488,7 @@ def _compute_file_scopes(project: CompassMakFile) -> dict[str, int]:
|
|
|
488
488
|
for fd in project.file_directives:
|
|
489
489
|
# Explicit linking = at least one link station WITHOUT coordinates.
|
|
490
490
|
# Link stations with coordinates are just anchors (fixed points).
|
|
491
|
-
has_explicit_linking = any(
|
|
492
|
-
ls.location is None for ls in fd.link_stations
|
|
493
|
-
)
|
|
491
|
+
has_explicit_linking = any(ls.location is None for ls in fd.link_stations)
|
|
494
492
|
if has_explicit_linking:
|
|
495
493
|
current_scope += 1
|
|
496
494
|
file_scopes[fd.file] = current_scope
|
|
@@ -559,12 +557,8 @@ def build_station_graph(
|
|
|
559
557
|
|
|
560
558
|
all_shots.append((shot, file_dir.file, survey_name, survey))
|
|
561
559
|
|
|
562
|
-
from_name = _scope_name(
|
|
563
|
-
|
|
564
|
-
)
|
|
565
|
-
to_name = _scope_name(
|
|
566
|
-
shot.to_station_name, scope_id, link_names
|
|
567
|
-
)
|
|
560
|
+
from_name = _scope_name(shot.from_station_name, scope_id, link_names)
|
|
561
|
+
to_name = _scope_name(shot.to_station_name, scope_id, link_names)
|
|
568
562
|
|
|
569
563
|
# Skip self-loops (from == to). These are data errors
|
|
570
564
|
# that create impossible solver constraints.
|
|
@@ -587,12 +581,18 @@ def build_station_graph(
|
|
|
587
581
|
# Pre-scoped names are stored in the tuple so BFS
|
|
588
582
|
# does not need to re-scope per shot.
|
|
589
583
|
adjacency[from_name].append(
|
|
590
|
-
(
|
|
591
|
-
|
|
584
|
+
(
|
|
585
|
+
shot,
|
|
586
|
+
file_dir.file,
|
|
587
|
+
survey_name,
|
|
588
|
+
survey,
|
|
589
|
+
False,
|
|
590
|
+
from_name,
|
|
591
|
+
to_name,
|
|
592
|
+
)
|
|
592
593
|
)
|
|
593
594
|
adjacency[to_name].append(
|
|
594
|
-
(shot, file_dir.file, survey_name, survey, True,
|
|
595
|
-
from_name, to_name)
|
|
595
|
+
(shot, file_dir.file, survey_name, survey, True, from_name, to_name)
|
|
596
596
|
)
|
|
597
597
|
|
|
598
598
|
return adjacency, all_shots
|
|
@@ -803,9 +803,7 @@ def propagate_coordinates(
|
|
|
803
803
|
primary_station.origin = primary_name
|
|
804
804
|
result.stations = {primary_name: primary_station}
|
|
805
805
|
result.anchors = {primary_name}
|
|
806
|
-
_secondary_anchors = {
|
|
807
|
-
k: v for k, v in anchors.items() if k != primary_name
|
|
808
|
-
}
|
|
806
|
+
_secondary_anchors = {k: v for k, v in anchors.items() if k != primary_name}
|
|
809
807
|
else:
|
|
810
808
|
# Multi-origin BFS: seed from all anchors
|
|
811
809
|
result.stations = dict(anchors)
|
|
@@ -854,8 +852,15 @@ def propagate_coordinates(
|
|
|
854
852
|
if not current_station:
|
|
855
853
|
continue
|
|
856
854
|
|
|
857
|
-
for (
|
|
858
|
-
|
|
855
|
+
for (
|
|
856
|
+
shot,
|
|
857
|
+
file_name,
|
|
858
|
+
survey_name,
|
|
859
|
+
survey,
|
|
860
|
+
is_reverse,
|
|
861
|
+
from_name,
|
|
862
|
+
to_name,
|
|
863
|
+
) in adjacency.get(current_name, []):
|
|
859
864
|
# Multi-origin: forward only. Single-origin: both.
|
|
860
865
|
if is_reverse and not detect_same_origin_loops:
|
|
861
866
|
continue
|
|
@@ -912,7 +917,10 @@ def propagate_coordinates(
|
|
|
912
917
|
# the frontsight; for reverse edges it uses the backsight
|
|
913
918
|
# (or frontsight + 180° when no backsight is available).
|
|
914
919
|
shot_delta = compute_shot_delta(
|
|
915
|
-
shot,
|
|
920
|
+
shot,
|
|
921
|
+
is_reverse,
|
|
922
|
+
declination,
|
|
923
|
+
convergence,
|
|
916
924
|
)
|
|
917
925
|
de, dn, dz = shot_delta
|
|
918
926
|
|
|
@@ -933,8 +941,7 @@ def propagate_coordinates(
|
|
|
933
941
|
new_station.survey = survey_name
|
|
934
942
|
new_station.origin = current_station.origin
|
|
935
943
|
new_station.path_distance = (
|
|
936
|
-
current_station.path_distance
|
|
937
|
-
+ length_to_meters(shot.length or 0.0)
|
|
944
|
+
current_station.path_distance + length_to_meters(shot.length or 0.0)
|
|
938
945
|
)
|
|
939
946
|
result.stations[target_name] = new_station
|
|
940
947
|
|
|
@@ -1106,8 +1113,7 @@ def propagate_coordinates(
|
|
|
1106
1113
|
),
|
|
1107
1114
|
)
|
|
1108
1115
|
logger.info(
|
|
1109
|
-
"Closure at anchor '%s': %.3f m "
|
|
1110
|
-
"(path distance: %.1f m)",
|
|
1116
|
+
"Closure at anchor '%s': %.3f m (path distance: %.1f m)",
|
|
1111
1117
|
sec_known.name,
|
|
1112
1118
|
gap,
|
|
1113
1119
|
bfs_station.path_distance,
|
|
@@ -1152,8 +1158,15 @@ def propagate_coordinates(
|
|
|
1152
1158
|
if not current_station:
|
|
1153
1159
|
continue
|
|
1154
1160
|
|
|
1155
|
-
for (
|
|
1156
|
-
|
|
1161
|
+
for (
|
|
1162
|
+
shot,
|
|
1163
|
+
file_name,
|
|
1164
|
+
survey_name,
|
|
1165
|
+
survey,
|
|
1166
|
+
is_reverse,
|
|
1167
|
+
from_name,
|
|
1168
|
+
to_name,
|
|
1169
|
+
) in adjacency.get(current_name, []):
|
|
1157
1170
|
# Same traversal rules as main BFS
|
|
1158
1171
|
target_name = from_name if is_reverse else to_name
|
|
1159
1172
|
|
|
@@ -1175,18 +1188,24 @@ def propagate_coordinates(
|
|
|
1175
1188
|
result.datum or Datum.WGS_1984,
|
|
1176
1189
|
)
|
|
1177
1190
|
declination = calculate_survey_declination(
|
|
1178
|
-
station_wgs84,
|
|
1191
|
+
station_wgs84,
|
|
1192
|
+
survey.header.date,
|
|
1179
1193
|
)
|
|
1180
1194
|
survey_declinations[survey_key] = declination
|
|
1181
1195
|
logger.debug(
|
|
1182
1196
|
"Survey %s declination: %.2f° (date: %s)",
|
|
1183
|
-
survey_key,
|
|
1197
|
+
survey_key,
|
|
1198
|
+
declination,
|
|
1199
|
+
survey.header.date,
|
|
1184
1200
|
)
|
|
1185
1201
|
else:
|
|
1186
1202
|
declination = survey_declinations[survey_key]
|
|
1187
1203
|
|
|
1188
1204
|
shot_delta = compute_shot_delta(
|
|
1189
|
-
shot,
|
|
1205
|
+
shot,
|
|
1206
|
+
is_reverse,
|
|
1207
|
+
declination,
|
|
1208
|
+
convergence,
|
|
1190
1209
|
)
|
|
1191
1210
|
de, dn, dz = shot_delta
|
|
1192
1211
|
|
|
@@ -1287,8 +1306,15 @@ def propagate_coordinates(
|
|
|
1287
1306
|
# reverse edges to orphaned stations.
|
|
1288
1307
|
fallback_queue: deque[str] = deque()
|
|
1289
1308
|
for name in list(visited_stations):
|
|
1290
|
-
for (
|
|
1291
|
-
|
|
1309
|
+
for (
|
|
1310
|
+
_,
|
|
1311
|
+
_,
|
|
1312
|
+
_,
|
|
1313
|
+
_,
|
|
1314
|
+
is_reverse,
|
|
1315
|
+
_from_scoped,
|
|
1316
|
+
_,
|
|
1317
|
+
) in adjacency.get(name, []):
|
|
1292
1318
|
if not is_reverse:
|
|
1293
1319
|
continue
|
|
1294
1320
|
if _from_scoped in orphaned:
|
|
@@ -1301,18 +1327,21 @@ def propagate_coordinates(
|
|
|
1301
1327
|
if not current_station:
|
|
1302
1328
|
continue
|
|
1303
1329
|
|
|
1304
|
-
for (
|
|
1305
|
-
|
|
1306
|
-
|
|
1330
|
+
for (
|
|
1331
|
+
shot,
|
|
1332
|
+
file_name,
|
|
1333
|
+
survey_name,
|
|
1334
|
+
survey,
|
|
1335
|
+
is_reverse,
|
|
1336
|
+
from_name,
|
|
1337
|
+
to_name,
|
|
1338
|
+
) in adjacency.get(current_name, []):
|
|
1307
1339
|
shot_key = (min(from_name, to_name), max(from_name, to_name))
|
|
1308
1340
|
if shot_key in visited_shots:
|
|
1309
1341
|
continue
|
|
1310
1342
|
|
|
1311
1343
|
# Determine target and direction.
|
|
1312
|
-
if is_reverse
|
|
1313
|
-
target_name = from_name
|
|
1314
|
-
else:
|
|
1315
|
-
target_name = to_name
|
|
1344
|
+
target_name = from_name if is_reverse else to_name
|
|
1316
1345
|
|
|
1317
1346
|
if target_name in result.stations:
|
|
1318
1347
|
continue # Already computed
|
|
@@ -1332,14 +1361,18 @@ def propagate_coordinates(
|
|
|
1332
1361
|
result.datum or Datum.WGS_1984,
|
|
1333
1362
|
)
|
|
1334
1363
|
declination = calculate_survey_declination(
|
|
1335
|
-
station_wgs84,
|
|
1364
|
+
station_wgs84,
|
|
1365
|
+
survey.header.date,
|
|
1336
1366
|
)
|
|
1337
1367
|
survey_declinations[survey_key] = declination
|
|
1338
1368
|
else:
|
|
1339
1369
|
declination = survey_declinations[survey_key]
|
|
1340
1370
|
|
|
1341
1371
|
forward_delta = compute_shot_delta(
|
|
1342
|
-
shot,
|
|
1372
|
+
shot,
|
|
1373
|
+
is_reverse=False,
|
|
1374
|
+
declination=declination,
|
|
1375
|
+
convergence=convergence,
|
|
1343
1376
|
)
|
|
1344
1377
|
de, dn, dz = forward_delta
|
|
1345
1378
|
|
|
@@ -1368,8 +1401,7 @@ def propagate_coordinates(
|
|
|
1368
1401
|
new_station.survey = survey_name
|
|
1369
1402
|
new_station.origin = current_station.origin
|
|
1370
1403
|
new_station.path_distance = (
|
|
1371
|
-
current_station.path_distance
|
|
1372
|
-
+ length_to_meters(shot.length or 0.0)
|
|
1404
|
+
current_station.path_distance + length_to_meters(shot.length or 0.0)
|
|
1373
1405
|
)
|
|
1374
1406
|
result.stations[target_name] = new_station
|
|
1375
1407
|
visited_stations.add(target_name)
|
|
@@ -1434,7 +1466,9 @@ def compute_survey_coordinates(
|
|
|
1434
1466
|
adjacency, _ = build_station_graph(project)
|
|
1435
1467
|
anchors = find_anchor_stations(project)
|
|
1436
1468
|
result = propagate_coordinates(
|
|
1437
|
-
project,
|
|
1469
|
+
project,
|
|
1470
|
+
anchors,
|
|
1471
|
+
adjacency,
|
|
1438
1472
|
detect_same_origin_loops=(solver is not None),
|
|
1439
1473
|
)
|
|
1440
1474
|
|
|
@@ -1526,7 +1560,12 @@ def station_to_feature(
|
|
|
1526
1560
|
GeoJSON Feature with Point geometry
|
|
1527
1561
|
"""
|
|
1528
1562
|
lon, lat = _cached_utm_to_wgs84(
|
|
1529
|
-
station.easting,
|
|
1563
|
+
station.easting,
|
|
1564
|
+
station.northing,
|
|
1565
|
+
zone,
|
|
1566
|
+
northern,
|
|
1567
|
+
datum,
|
|
1568
|
+
wgs84_cache,
|
|
1530
1569
|
)
|
|
1531
1570
|
|
|
1532
1571
|
properties: dict[str, Any] = {
|
|
@@ -1568,16 +1607,22 @@ def anchor_to_feature(
|
|
|
1568
1607
|
GeoJSON Feature with Point geometry and type "anchor"
|
|
1569
1608
|
"""
|
|
1570
1609
|
lon, lat = _cached_utm_to_wgs84(
|
|
1571
|
-
station.easting,
|
|
1610
|
+
station.easting,
|
|
1611
|
+
station.northing,
|
|
1612
|
+
zone,
|
|
1613
|
+
northern,
|
|
1614
|
+
datum,
|
|
1615
|
+
wgs84_cache,
|
|
1572
1616
|
)
|
|
1573
1617
|
|
|
1618
|
+
depth_ft = round(station.elevation * METERS_TO_FEET, 2)
|
|
1619
|
+
|
|
1574
1620
|
return Feature(
|
|
1575
1621
|
geometry=Point((lon, lat, round(station.elevation, 2))),
|
|
1576
1622
|
properties={
|
|
1577
|
-
"
|
|
1578
|
-
"
|
|
1579
|
-
"
|
|
1580
|
-
"elevation_m": round(station.elevation, 2),
|
|
1623
|
+
"id": station.name,
|
|
1624
|
+
"depth": abs(depth_ft),
|
|
1625
|
+
"name": station.survey,
|
|
1581
1626
|
},
|
|
1582
1627
|
)
|
|
1583
1628
|
|
|
@@ -1602,29 +1647,24 @@ def leg_to_feature(
|
|
|
1602
1647
|
GeoJSON Feature with LineString geometry
|
|
1603
1648
|
"""
|
|
1604
1649
|
from_lon, from_lat = _cached_utm_to_wgs84(
|
|
1605
|
-
leg.from_station.easting,
|
|
1606
|
-
|
|
1650
|
+
leg.from_station.easting,
|
|
1651
|
+
leg.from_station.northing,
|
|
1652
|
+
zone,
|
|
1653
|
+
northern,
|
|
1654
|
+
datum,
|
|
1655
|
+
wgs84_cache,
|
|
1607
1656
|
)
|
|
1608
1657
|
to_lon, to_lat = _cached_utm_to_wgs84(
|
|
1609
|
-
leg.to_station.easting,
|
|
1610
|
-
|
|
1658
|
+
leg.to_station.easting,
|
|
1659
|
+
leg.to_station.northing,
|
|
1660
|
+
zone,
|
|
1661
|
+
northern,
|
|
1662
|
+
datum,
|
|
1663
|
+
wgs84_cache,
|
|
1611
1664
|
)
|
|
1612
1665
|
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
"from": leg.from_station.name,
|
|
1616
|
-
"to": leg.to_station.name,
|
|
1617
|
-
"distance_ft": leg.distance,
|
|
1618
|
-
"distance_m": round(length_to_meters(leg.distance), 2)
|
|
1619
|
-
if leg.distance
|
|
1620
|
-
else None,
|
|
1621
|
-
"azimuth": leg.azimuth,
|
|
1622
|
-
"inclination": leg.inclination,
|
|
1623
|
-
"file": leg.file,
|
|
1624
|
-
"survey": leg.survey,
|
|
1625
|
-
}
|
|
1626
|
-
if leg.from_station.origin:
|
|
1627
|
-
properties["origin"] = leg.from_station.origin
|
|
1666
|
+
depth_m = leg.to_station.elevation
|
|
1667
|
+
depth_ft = round(depth_m * METERS_TO_FEET, 2)
|
|
1628
1668
|
|
|
1629
1669
|
return Feature(
|
|
1630
1670
|
geometry=LineString(
|
|
@@ -1633,7 +1673,11 @@ def leg_to_feature(
|
|
|
1633
1673
|
(to_lon, to_lat, round(leg.to_station.elevation, 2)),
|
|
1634
1674
|
]
|
|
1635
1675
|
),
|
|
1636
|
-
properties=
|
|
1676
|
+
properties={
|
|
1677
|
+
"id": str(uuid.uuid5(uuid.NAMESPACE_OID, leg.to_station.name)),
|
|
1678
|
+
"depth": abs(depth_ft), # Compass depth is < 0
|
|
1679
|
+
"name": leg.survey,
|
|
1680
|
+
},
|
|
1637
1681
|
)
|
|
1638
1682
|
|
|
1639
1683
|
|
|
@@ -1793,16 +1837,36 @@ def passage_to_feature(
|
|
|
1793
1837
|
|
|
1794
1838
|
try:
|
|
1795
1839
|
from_left = _cached_utm_to_wgs84(
|
|
1796
|
-
from_left_e,
|
|
1840
|
+
from_left_e,
|
|
1841
|
+
from_left_n,
|
|
1842
|
+
zone,
|
|
1843
|
+
northern,
|
|
1844
|
+
datum,
|
|
1845
|
+
wgs84_cache,
|
|
1797
1846
|
)
|
|
1798
1847
|
from_right = _cached_utm_to_wgs84(
|
|
1799
|
-
from_right_e,
|
|
1848
|
+
from_right_e,
|
|
1849
|
+
from_right_n,
|
|
1850
|
+
zone,
|
|
1851
|
+
northern,
|
|
1852
|
+
datum,
|
|
1853
|
+
wgs84_cache,
|
|
1800
1854
|
)
|
|
1801
1855
|
to_left = _cached_utm_to_wgs84(
|
|
1802
|
-
to_left_e,
|
|
1856
|
+
to_left_e,
|
|
1857
|
+
to_left_n,
|
|
1858
|
+
zone,
|
|
1859
|
+
northern,
|
|
1860
|
+
datum,
|
|
1861
|
+
wgs84_cache,
|
|
1803
1862
|
)
|
|
1804
1863
|
to_right = _cached_utm_to_wgs84(
|
|
1805
|
-
to_right_e,
|
|
1864
|
+
to_right_e,
|
|
1865
|
+
to_right_n,
|
|
1866
|
+
zone,
|
|
1867
|
+
northern,
|
|
1868
|
+
datum,
|
|
1869
|
+
wgs84_cache,
|
|
1806
1870
|
)
|
|
1807
1871
|
except InvalidCoordinateError:
|
|
1808
1872
|
return None
|
|
@@ -1891,7 +1955,6 @@ def survey_to_geojson(
|
|
|
1891
1955
|
# Add station points
|
|
1892
1956
|
if include_stations:
|
|
1893
1957
|
for name, station in survey.stations.items():
|
|
1894
|
-
|
|
1895
1958
|
try:
|
|
1896
1959
|
feat = station_to_feature(station, zone, northern, datum, wgs84_cache)
|
|
1897
1960
|
if color_by_origin:
|
|
@@ -1949,12 +2012,18 @@ def survey_to_geojson(
|
|
|
1949
2012
|
for misc in survey.misclosures:
|
|
1950
2013
|
try:
|
|
1951
2014
|
ex_lon, ex_lat = utm_to_wgs84(
|
|
1952
|
-
misc.existing.easting,
|
|
1953
|
-
|
|
2015
|
+
misc.existing.easting,
|
|
2016
|
+
misc.existing.northing,
|
|
2017
|
+
zone,
|
|
2018
|
+
northern,
|
|
2019
|
+
datum,
|
|
1954
2020
|
)
|
|
1955
2021
|
gh_lon, gh_lat = utm_to_wgs84(
|
|
1956
|
-
misc.ghost.easting,
|
|
1957
|
-
|
|
2022
|
+
misc.ghost.easting,
|
|
2023
|
+
misc.ghost.northing,
|
|
2024
|
+
zone,
|
|
2025
|
+
northern,
|
|
2026
|
+
datum,
|
|
1958
2027
|
)
|
|
1959
2028
|
|
|
1960
2029
|
gap_dist = (
|
|
@@ -1991,10 +2060,12 @@ def survey_to_geojson(
|
|
|
1991
2060
|
props["closing_segment_distance_m"] = round(closing_dist, 2)
|
|
1992
2061
|
|
|
1993
2062
|
line_feat = Feature(
|
|
1994
|
-
geometry=LineString(
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
2063
|
+
geometry=LineString(
|
|
2064
|
+
[
|
|
2065
|
+
(gh_lon, gh_lat, round(misc.ghost.elevation, 2)),
|
|
2066
|
+
(ex_lon, ex_lat, round(misc.existing.elevation, 2)),
|
|
2067
|
+
]
|
|
2068
|
+
),
|
|
1998
2069
|
properties=props,
|
|
1999
2070
|
)
|
|
2000
2071
|
features.append(line_feat)
|
|
@@ -2011,7 +2082,12 @@ def survey_to_geojson(
|
|
|
2011
2082
|
if leg.excluded_from_plotting:
|
|
2012
2083
|
continue
|
|
2013
2084
|
passage = passage_to_feature(
|
|
2014
|
-
leg,
|
|
2085
|
+
leg,
|
|
2086
|
+
zone,
|
|
2087
|
+
northern,
|
|
2088
|
+
datum,
|
|
2089
|
+
station_lrud,
|
|
2090
|
+
wgs84_cache,
|
|
2015
2091
|
)
|
|
2016
2092
|
if not passage:
|
|
2017
2093
|
continue
|
|
@@ -18,6 +18,7 @@ from compass_lib.enums import FormatIdentifier
|
|
|
18
18
|
from compass_lib.errors import CompassParseException
|
|
19
19
|
from compass_lib.errors import SourceLocation
|
|
20
20
|
from compass_lib.project.models import CompassMakFile
|
|
21
|
+
from compass_lib.project.models import CompassProjectDirective
|
|
21
22
|
|
|
22
23
|
|
|
23
24
|
class CompassProjectParser:
|
|
@@ -133,7 +134,7 @@ class CompassProjectParser:
|
|
|
133
134
|
# Legacy model-returning methods (thin wrappers for backwards compat)
|
|
134
135
|
# -------------------------------------------------------------------------
|
|
135
136
|
|
|
136
|
-
def parse_file(self, path: Path) -> list[
|
|
137
|
+
def parse_file(self, path: Path) -> list[CompassProjectDirective]:
|
|
137
138
|
"""Parse a project file.
|
|
138
139
|
|
|
139
140
|
DEPRECATED: Use parse_file_to_dict() for new code.
|
|
@@ -156,7 +157,7 @@ class CompassProjectParser:
|
|
|
156
157
|
self,
|
|
157
158
|
data: str,
|
|
158
159
|
source: str = "<string>",
|
|
159
|
-
) -> list[
|
|
160
|
+
) -> list[CompassProjectDirective]:
|
|
160
161
|
"""Parse project data from a string.
|
|
161
162
|
|
|
162
163
|
DEPRECATED: Use parse_string_to_dict() for new code.
|
|
@@ -7,11 +7,9 @@ package = true
|
|
|
7
7
|
|
|
8
8
|
[dependency-groups]
|
|
9
9
|
dev = [
|
|
10
|
-
"
|
|
11
|
-
"pre-commit>=4.1,<4.6",
|
|
10
|
+
"prek>=0.3.3,<0.4",
|
|
12
11
|
"ruff>=0.14,<0.16",
|
|
13
12
|
"flit>=3.12,<4",
|
|
14
|
-
"wheel>=0.45",
|
|
15
13
|
# File encryption/decryption
|
|
16
14
|
"python-dotenv>=1.0.0,<2.0.0",
|
|
17
15
|
"cryptography>=44.0.0,<47.0.0",
|
|
@@ -76,7 +74,6 @@ test = [
|
|
|
76
74
|
"deepdiff>=7.0,<9.0",
|
|
77
75
|
"pytest>=8.0.0,<10.0.0",
|
|
78
76
|
"pytest-cov>=5.0.0,<8.0.0",
|
|
79
|
-
"pytest-dotenv>=0.5.0,<1.0.0",
|
|
80
77
|
"pytest-env>=1.1.3,<2.0.0",
|
|
81
78
|
"pytest-runner>=6.0.0,<7.0.0",
|
|
82
79
|
"pytest-ordering>=0.6,<1.0.0",
|
|
@@ -97,17 +94,12 @@ convert = "compass_lib.commands.convert:convert"
|
|
|
97
94
|
geojson = "compass_lib.commands.geojson:geojson"
|
|
98
95
|
|
|
99
96
|
[tool.pytest.ini_options]
|
|
100
|
-
env_files = [".env"]
|
|
101
97
|
testpaths = ["tests/"]
|
|
102
98
|
addopts = "-vvv --cov=compass_lib --cov-report=term-missing"
|
|
103
99
|
# addopts = "-vvv --cov=compass_lib --cov-report=term-missing --capture=no"
|
|
104
100
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
# [tool.setuptools]
|
|
108
|
-
# # If there are data files included in your packages that need to be
|
|
109
|
-
# # installed, specify them here.
|
|
110
|
-
# package-data = {"sample" = ["*.dat"]}
|
|
101
|
+
[tool.pytest_env]
|
|
102
|
+
env_files = [".env"]
|
|
111
103
|
|
|
112
104
|
[tool.isort]
|
|
113
105
|
profile = "black"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|