pysurveytools 0.1.0__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.
- pysurveytools-0.1.0/LICENSE +21 -0
- pysurveytools-0.1.0/PKG-INFO +45 -0
- pysurveytools-0.1.0/README.md +21 -0
- pysurveytools-0.1.0/pyproject.toml +34 -0
- pysurveytools-0.1.0/setup.cfg +4 -0
- pysurveytools-0.1.0/setup.py +32 -0
- pysurveytools-0.1.0/src/pysurveytools.egg-info/PKG-INFO +45 -0
- pysurveytools-0.1.0/src/pysurveytools.egg-info/SOURCES.txt +22 -0
- pysurveytools-0.1.0/src/pysurveytools.egg-info/dependency_links.txt +1 -0
- pysurveytools-0.1.0/src/pysurveytools.egg-info/entry_points.txt +2 -0
- pysurveytools-0.1.0/src/pysurveytools.egg-info/requires.txt +4 -0
- pysurveytools-0.1.0/src/pysurveytools.egg-info/top_level.txt +1 -0
- pysurveytools-0.1.0/src/surveytools/__init__.py +13 -0
- pysurveytools-0.1.0/src/surveytools/angle.py +92 -0
- pysurveytools-0.1.0/src/surveytools/coordinate.py +47 -0
- pysurveytools-0.1.0/src/surveytools/full_angle_measurement.py +20 -0
- pysurveytools-0.1.0/src/surveytools/instrument_station.py +18 -0
- pysurveytools-0.1.0/src/surveytools/measurement.py +34 -0
- pysurveytools-0.1.0/src/surveytools/measurement_target.py +36 -0
- pysurveytools-0.1.0/src/surveytools/surveytools.py +10 -0
- pysurveytools-0.1.0/tests/test_angle.py +126 -0
- pysurveytools-0.1.0/tests/test_coordinate.py +66 -0
- pysurveytools-0.1.0/tests/test_measurement.py +72 -0
- pysurveytools-0.1.0/tests/test_measurement_target.py +66 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Stefan Printz
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pysurveytools
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Geodetic classes for managing and calculating (Angle, Coordinate, Measurement, …)
|
|
5
|
+
Home-page: https://gitlab-ce.hs-bochum.de/fachbereich-geodaesie/pypi/pysurveytools
|
|
6
|
+
Author: Stefan Printz
|
|
7
|
+
Author-email: Stefan Printz <stefan.printz@hs-bochum.de>
|
|
8
|
+
License: MIT
|
|
9
|
+
Project-URL: Homepage, https://gitlab-ce.hs-bochum.de/fachbereich-geodaesie/pypi/pysurveytools
|
|
10
|
+
Project-URL: Issue Tracker, https://gitlab-ce.hs-bochum.de/fachbereich-geodaesie/pypi/pysurveytools/-/issues
|
|
11
|
+
Project-URL: Source, https://gitlab-ce.hs-bochum.de/fachbereich-geodaesie/pypi/pysurveytools.git
|
|
12
|
+
Keywords: geodesy,surveying,coordinates,angles,measurement
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
License-File: LICENSE
|
|
18
|
+
Requires-Dist: numpy>=1.20
|
|
19
|
+
Provides-Extra: test
|
|
20
|
+
Requires-Dist: pytest>=7.0; extra == "test"
|
|
21
|
+
Dynamic: author
|
|
22
|
+
Dynamic: home-page
|
|
23
|
+
Dynamic: license-file
|
|
24
|
+
|
|
25
|
+
# pySurveytools
|
|
26
|
+
|
|
27
|
+
**Geodetic classes for managing and calculating**
|
|
28
|
+
|
|
29
|
+
## Overview
|
|
30
|
+
|
|
31
|
+
`surveytools` is a Python library providing essential geodetic classes and utilities to support surveying calculations and coordinate management. It offers robust implementations for angles, coordinates, measurements, and other related geospatial operations, enabling precise and efficient geodetic data processing.
|
|
32
|
+
|
|
33
|
+
## Features
|
|
34
|
+
|
|
35
|
+
- Angle representation and conversion
|
|
36
|
+
- Coordinate handling in multiple formats
|
|
37
|
+
- Measurement encapsulation with metadata
|
|
38
|
+
- Easy integration with surveying instruments and software
|
|
39
|
+
|
|
40
|
+
## Installation
|
|
41
|
+
|
|
42
|
+
You can install `surveytools` via pip:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
pip install pysurveytools
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# pySurveytools
|
|
2
|
+
|
|
3
|
+
**Geodetic classes for managing and calculating**
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
`surveytools` is a Python library providing essential geodetic classes and utilities to support surveying calculations and coordinate management. It offers robust implementations for angles, coordinates, measurements, and other related geospatial operations, enabling precise and efficient geodetic data processing.
|
|
8
|
+
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
- Angle representation and conversion
|
|
12
|
+
- Coordinate handling in multiple formats
|
|
13
|
+
- Measurement encapsulation with metadata
|
|
14
|
+
- Easy integration with surveying instruments and software
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
You can install `surveytools` via pip:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
pip install pysurveytools
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=42", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "pysurveytools"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Geodetic classes for managing and calculating (Angle, Coordinate, Measurement, …)"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
authors = [
|
|
11
|
+
{ name = "Stefan Printz", email = "stefan.printz@hs-bochum.de" }
|
|
12
|
+
]
|
|
13
|
+
license = { text = "MIT" }
|
|
14
|
+
urls = {"Homepage" = "https://gitlab-ce.hs-bochum.de/fachbereich-geodaesie/pypi/pysurveytools", "Issue Tracker" = "https://gitlab-ce.hs-bochum.de/fachbereich-geodaesie/pypi/pysurveytools/-/issues", "Source" = "https://gitlab-ce.hs-bochum.de/fachbereich-geodaesie/pypi/pysurveytools.git"}
|
|
15
|
+
keywords = ["geodesy", "surveying", "coordinates", "angles", "measurement"]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Programming Language :: Python :: 3",
|
|
18
|
+
"License :: OSI Approved :: MIT License",
|
|
19
|
+
"Operating System :: OS Independent"
|
|
20
|
+
]
|
|
21
|
+
dependencies = [
|
|
22
|
+
"numpy >= 1.20"
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
[project.optional-dependencies]
|
|
26
|
+
test = [
|
|
27
|
+
"pytest >= 7.0"
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
[tool.setuptools.packages.find]
|
|
31
|
+
where = ["src"]
|
|
32
|
+
|
|
33
|
+
[project.scripts]
|
|
34
|
+
surveytools-cli = "surveytools.surveytools:main"
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
import setuptools
|
|
3
|
+
|
|
4
|
+
if __name__ == "__main__":
|
|
5
|
+
setuptools.setup(
|
|
6
|
+
name="pysurveytools",
|
|
7
|
+
version="0.1.0",
|
|
8
|
+
author="Stefan Printz",
|
|
9
|
+
author_email="stefan.printz@hs-bochum.de",
|
|
10
|
+
description="Geodetic classes for managing and calculating (Angle, Coordinate, Measurement, …)",
|
|
11
|
+
long_description=open("README.md", encoding="utf-8").read(),
|
|
12
|
+
long_description_content_type="text/markdown",
|
|
13
|
+
url="https://gitlab-ce.hs-bochum.de/fachbereich-geodaesie/pypi/pysurveytools",
|
|
14
|
+
packages=setuptools.find_packages(where="src"),
|
|
15
|
+
package_dir={"": "src"},
|
|
16
|
+
install_requires=[
|
|
17
|
+
"numpy>=1.20",
|
|
18
|
+
],
|
|
19
|
+
extras_require={
|
|
20
|
+
"test": ["pytest>=7.0"],
|
|
21
|
+
},
|
|
22
|
+
classifiers=[
|
|
23
|
+
"Programming Language :: Python :: 3",
|
|
24
|
+
"License :: OSI Approved :: MIT License",
|
|
25
|
+
"Operating System :: OS Independent",
|
|
26
|
+
],
|
|
27
|
+
entry_points={
|
|
28
|
+
"console_scripts": [
|
|
29
|
+
"surveytools-cli=surveytools.surveytools:main",
|
|
30
|
+
],
|
|
31
|
+
},
|
|
32
|
+
)
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pysurveytools
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Geodetic classes for managing and calculating (Angle, Coordinate, Measurement, …)
|
|
5
|
+
Home-page: https://gitlab-ce.hs-bochum.de/fachbereich-geodaesie/pypi/pysurveytools
|
|
6
|
+
Author: Stefan Printz
|
|
7
|
+
Author-email: Stefan Printz <stefan.printz@hs-bochum.de>
|
|
8
|
+
License: MIT
|
|
9
|
+
Project-URL: Homepage, https://gitlab-ce.hs-bochum.de/fachbereich-geodaesie/pypi/pysurveytools
|
|
10
|
+
Project-URL: Issue Tracker, https://gitlab-ce.hs-bochum.de/fachbereich-geodaesie/pypi/pysurveytools/-/issues
|
|
11
|
+
Project-URL: Source, https://gitlab-ce.hs-bochum.de/fachbereich-geodaesie/pypi/pysurveytools.git
|
|
12
|
+
Keywords: geodesy,surveying,coordinates,angles,measurement
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
License-File: LICENSE
|
|
18
|
+
Requires-Dist: numpy>=1.20
|
|
19
|
+
Provides-Extra: test
|
|
20
|
+
Requires-Dist: pytest>=7.0; extra == "test"
|
|
21
|
+
Dynamic: author
|
|
22
|
+
Dynamic: home-page
|
|
23
|
+
Dynamic: license-file
|
|
24
|
+
|
|
25
|
+
# pySurveytools
|
|
26
|
+
|
|
27
|
+
**Geodetic classes for managing and calculating**
|
|
28
|
+
|
|
29
|
+
## Overview
|
|
30
|
+
|
|
31
|
+
`surveytools` is a Python library providing essential geodetic classes and utilities to support surveying calculations and coordinate management. It offers robust implementations for angles, coordinates, measurements, and other related geospatial operations, enabling precise and efficient geodetic data processing.
|
|
32
|
+
|
|
33
|
+
## Features
|
|
34
|
+
|
|
35
|
+
- Angle representation and conversion
|
|
36
|
+
- Coordinate handling in multiple formats
|
|
37
|
+
- Measurement encapsulation with metadata
|
|
38
|
+
- Easy integration with surveying instruments and software
|
|
39
|
+
|
|
40
|
+
## Installation
|
|
41
|
+
|
|
42
|
+
You can install `surveytools` via pip:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
pip install pysurveytools
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
setup.py
|
|
5
|
+
src/pysurveytools.egg-info/PKG-INFO
|
|
6
|
+
src/pysurveytools.egg-info/SOURCES.txt
|
|
7
|
+
src/pysurveytools.egg-info/dependency_links.txt
|
|
8
|
+
src/pysurveytools.egg-info/entry_points.txt
|
|
9
|
+
src/pysurveytools.egg-info/requires.txt
|
|
10
|
+
src/pysurveytools.egg-info/top_level.txt
|
|
11
|
+
src/surveytools/__init__.py
|
|
12
|
+
src/surveytools/angle.py
|
|
13
|
+
src/surveytools/coordinate.py
|
|
14
|
+
src/surveytools/full_angle_measurement.py
|
|
15
|
+
src/surveytools/instrument_station.py
|
|
16
|
+
src/surveytools/measurement.py
|
|
17
|
+
src/surveytools/measurement_target.py
|
|
18
|
+
src/surveytools/surveytools.py
|
|
19
|
+
tests/test_angle.py
|
|
20
|
+
tests/test_coordinate.py
|
|
21
|
+
tests/test_measurement.py
|
|
22
|
+
tests/test_measurement_target.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
surveytools
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# src/surveytools/__init__.py
|
|
2
|
+
from .surveytools import SWVersion
|
|
3
|
+
from .coordinate import Coordinate
|
|
4
|
+
from .angle import Angle, RHO
|
|
5
|
+
from .measurement import Measurement
|
|
6
|
+
from .measurement_target import MeasurementTarget
|
|
7
|
+
from .full_angle_measurement import FullAngleMeasurement
|
|
8
|
+
|
|
9
|
+
__all__ = [
|
|
10
|
+
"Angle", "RHO",
|
|
11
|
+
"Coordinate", "Measurement",
|
|
12
|
+
"SWVersion", "FullAngleMeasurement", "MeasurementTarget"
|
|
13
|
+
]
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import math
|
|
2
|
+
from functools import total_ordering
|
|
3
|
+
|
|
4
|
+
RHO = 200 / math.pi
|
|
5
|
+
|
|
6
|
+
@total_ordering
|
|
7
|
+
class Angle(object):
|
|
8
|
+
|
|
9
|
+
def __init__(self, rad: int = 0):
|
|
10
|
+
self.value_rad = rad
|
|
11
|
+
|
|
12
|
+
@staticmethod
|
|
13
|
+
def from_gon(gon_value):
|
|
14
|
+
r = Angle()
|
|
15
|
+
r.set_gon(gon_value)
|
|
16
|
+
return r
|
|
17
|
+
|
|
18
|
+
@staticmethod
|
|
19
|
+
def from_rad(rad_value):
|
|
20
|
+
r = Angle(rad_value)
|
|
21
|
+
return r
|
|
22
|
+
|
|
23
|
+
def set_gon(self, gon):
|
|
24
|
+
self.value_rad = gon / RHO
|
|
25
|
+
return
|
|
26
|
+
|
|
27
|
+
def get_gon(self):
|
|
28
|
+
return self.value_rad * RHO
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def __abs__(self):
|
|
32
|
+
r = Angle()
|
|
33
|
+
r.value_rad = abs(self.value_rad)
|
|
34
|
+
return r
|
|
35
|
+
|
|
36
|
+
def __add__(self, o):
|
|
37
|
+
if isinstance(o, Angle):
|
|
38
|
+
r = Angle()
|
|
39
|
+
r.value_rad = self.value_rad + o.value_rad
|
|
40
|
+
return r
|
|
41
|
+
else:
|
|
42
|
+
raise TypeError("unsupported operand type(s) for +: 'Angle' and '" + str(type(o).__name__) + "'")
|
|
43
|
+
|
|
44
|
+
def __sub__(self, o):
|
|
45
|
+
if isinstance(o, Angle):
|
|
46
|
+
r = Angle()
|
|
47
|
+
r.value_rad = self.value_rad - o.value_rad
|
|
48
|
+
return r
|
|
49
|
+
else:
|
|
50
|
+
raise TypeError("unsupported operand type(s) for -: 'Angle' and '" + type(o).__name__ + "'")
|
|
51
|
+
|
|
52
|
+
def __truediv__(self, o):
|
|
53
|
+
if isinstance(o, (int, float)):
|
|
54
|
+
r = Angle()
|
|
55
|
+
r.value_rad = self.value_rad / o
|
|
56
|
+
else:
|
|
57
|
+
raise TypeError("unsupported operand type(s) for /: 'Angle' and '" + type(o).__name__ + "'")
|
|
58
|
+
return r
|
|
59
|
+
|
|
60
|
+
def __eq__(self, other):
|
|
61
|
+
if not isinstance(other, Angle):
|
|
62
|
+
return NotImplemented
|
|
63
|
+
return self.value_rad == other.value_rad
|
|
64
|
+
|
|
65
|
+
def __lt__(self, other):
|
|
66
|
+
if not isinstance(other, Angle):
|
|
67
|
+
return NotImplemented
|
|
68
|
+
return self.value_rad < other.value_rad
|
|
69
|
+
|
|
70
|
+
def __str__(self):
|
|
71
|
+
return '{0:.7} gon'.format(self.get_gon())
|
|
72
|
+
|
|
73
|
+
def normalise(self):
|
|
74
|
+
self.value_rad %= 2 * math.pi
|
|
75
|
+
return self
|
|
76
|
+
|
|
77
|
+
def add_half_circle(self):
|
|
78
|
+
r = Angle()
|
|
79
|
+
r.value_rad = self.value_rad + math.pi
|
|
80
|
+
r.normalise()
|
|
81
|
+
return r
|
|
82
|
+
|
|
83
|
+
def supplementary_angle(self):
|
|
84
|
+
r = Angle()
|
|
85
|
+
r.value_rad = 2 * math.pi - self.value_rad
|
|
86
|
+
return r
|
|
87
|
+
|
|
88
|
+
def sin(self):
|
|
89
|
+
return math.sin(self.value_rad)
|
|
90
|
+
|
|
91
|
+
def cos(self):
|
|
92
|
+
return math.cos(self.value_rad)
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import math
|
|
2
|
+
|
|
3
|
+
from surveytools.angle import Angle
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Coordinate(object):
|
|
7
|
+
|
|
8
|
+
def __init__(self, pkt_nr : str, x: float, y: float, z: float):
|
|
9
|
+
self.value_rad = None
|
|
10
|
+
self.pkt_nr = pkt_nr
|
|
11
|
+
self.x = x
|
|
12
|
+
self.y = y
|
|
13
|
+
self.z = z
|
|
14
|
+
|
|
15
|
+
def __add__(self, o):
|
|
16
|
+
if isinstance(o, Coordinate):
|
|
17
|
+
return Coordinate(self.pkt_nr, self.x + o.x, self.y + o.y, self.z + o.z)
|
|
18
|
+
else:
|
|
19
|
+
raise TypeError("unsupported operand type(s) for +: 'Coordinate' and '" + type(o).__name__ + "'")
|
|
20
|
+
|
|
21
|
+
def __sub__(self, o):
|
|
22
|
+
if isinstance(o, Coordinate):
|
|
23
|
+
return Coordinate(self.pkt_nr, self.x - o.x, self.y - o.y, self.z - o.z)
|
|
24
|
+
else:
|
|
25
|
+
raise TypeError("unsupported operand type(s) for -: 'Coordinate' and '" + type(o).__name__ + "'")
|
|
26
|
+
|
|
27
|
+
def direction_to(self, o):
|
|
28
|
+
dc = o - self
|
|
29
|
+
theta_rad = math.atan2(dc.x, dc.y)
|
|
30
|
+
return Angle.from_rad(theta_rad)
|
|
31
|
+
|
|
32
|
+
def distance_to(self, o):
|
|
33
|
+
dc = o - self
|
|
34
|
+
return math.sqrt(dc.x * dc.x + dc.y * dc.y + dc.z * dc.z)
|
|
35
|
+
|
|
36
|
+
def get_array(self):
|
|
37
|
+
return [self.y, self.x, self.z]
|
|
38
|
+
|
|
39
|
+
def get_homogene_array(self):
|
|
40
|
+
return [self.y, self.x, self.z, 1]
|
|
41
|
+
|
|
42
|
+
def get_normalized_vector(self):
|
|
43
|
+
norm = math.sqrt(self.x * self.x + self.y * self.y + self.z * self.z)
|
|
44
|
+
return [self.x / norm, self.y / norm, self.z / norm]
|
|
45
|
+
|
|
46
|
+
def __str__(self):
|
|
47
|
+
return f"[Pkt: {self.pkt_nr}, x: {self.x:.4f}, y: {self.y:.4f}, z: {self.z:.4f}]"
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
from surveytools.angle import Angle
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class FullAngleMeasurement(object):
|
|
5
|
+
|
|
6
|
+
def __init__(self):
|
|
7
|
+
self.hz: Angle = Angle()
|
|
8
|
+
self.v: Angle = Angle()
|
|
9
|
+
self.angle_accuracy: Angle = Angle()
|
|
10
|
+
self.angle_time: int = 0
|
|
11
|
+
self.cross_incline: Angle = Angle()
|
|
12
|
+
self.length_incline: Angle = Angle()
|
|
13
|
+
self.accuracy_incline: Angle = Angle()
|
|
14
|
+
self.incline_time: int = 0
|
|
15
|
+
self.face_def: int = 0
|
|
16
|
+
|
|
17
|
+
def __str__(self):
|
|
18
|
+
return "[hz: " + str(self.hz) + ", v: " + str(self.v) + " , angle_accuracy: " + str(self.angle_accuracy) + \
|
|
19
|
+
", angle_time: " + str(self.angle_time) + ", cross_incline: " + str(self.cross_incline) +\
|
|
20
|
+
", length_incline: " + str(self.length_incline) + ", accuracy_incline: " + str(self.accuracy_incline) + "]"
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from typing import List
|
|
2
|
+
|
|
3
|
+
from surveytools import MeasurementTarget, Measurement, Angle
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class InstrumentStation:
|
|
7
|
+
|
|
8
|
+
def __init__(self, station_name: str):
|
|
9
|
+
self.station_name = station_name
|
|
10
|
+
self.targets : dict[str, MeasurementTarget] = dict()
|
|
11
|
+
self.orientation : Angle = Angle.from_rad(0)
|
|
12
|
+
|
|
13
|
+
def add_measurement_target(self, target : MeasurementTarget):
|
|
14
|
+
self.targets[target.target_number] = target
|
|
15
|
+
|
|
16
|
+
def evaluation(self) -> List[Measurement]:
|
|
17
|
+
return [x.evaluation(self.orientation) for x in self.targets.values()]
|
|
18
|
+
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
from surveytools.coordinate import Coordinate
|
|
2
|
+
from surveytools.angle import Angle
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class Measurement(object):
|
|
6
|
+
|
|
7
|
+
def __init__(self, target : str, direction: Angle, zenith: Angle, sd : float, atmospheric_data, measure_time):
|
|
8
|
+
self.target_number = target
|
|
9
|
+
self.direction = direction
|
|
10
|
+
self.zenith = zenith
|
|
11
|
+
self.slope_distances = sd
|
|
12
|
+
self.atmospheric_data = atmospheric_data
|
|
13
|
+
self.measure_time = measure_time
|
|
14
|
+
|
|
15
|
+
def __str__(self):
|
|
16
|
+
return "[target: " + str(self.target_number) + ", direction: " + str(self.direction) + " , zenith: " \
|
|
17
|
+
+ str(self.zenith) + ", slope_distances: " + str(self.slope_distances) + ", atmospheric_data: "\
|
|
18
|
+
+ str(self.atmospheric_data) + ", Measure Time: " + str(self.measure_time) + "]"
|
|
19
|
+
|
|
20
|
+
def get_horizontal_distances(self):
|
|
21
|
+
return self.slope_distances * self.zenith.sin()
|
|
22
|
+
|
|
23
|
+
def get_delta_height(self):
|
|
24
|
+
return self.slope_distances * self.zenith.cos()
|
|
25
|
+
|
|
26
|
+
def get_local_coordinate(self):
|
|
27
|
+
hd = self.get_horizontal_distances()
|
|
28
|
+
y = hd * self.direction.sin()
|
|
29
|
+
x = hd * self.direction.cos()
|
|
30
|
+
z = self.get_delta_height()
|
|
31
|
+
return Coordinate(self.target_number, x, y, z)
|
|
32
|
+
|
|
33
|
+
def get_arra(self):
|
|
34
|
+
return [self.target_number, self.direction.get_gon(), self.zenith.get_gon(), self.slope_distances ]
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
from surveytools.angle import Angle
|
|
2
|
+
from surveytools.measurement import Measurement
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class MeasurementTarget(object):
|
|
6
|
+
def __init__(self, target: str, direction: Angle, zenith: Angle, distance: float):
|
|
7
|
+
self.target_number = target
|
|
8
|
+
self.direction = direction
|
|
9
|
+
self.distance = distance
|
|
10
|
+
self.zenith = zenith
|
|
11
|
+
self.face1 = []
|
|
12
|
+
self.face2 = []
|
|
13
|
+
|
|
14
|
+
def evaluation(self, zero_direction: Angle = Angle.from_rad(0)) -> Measurement:
|
|
15
|
+
return Measurement(self.target_number, self.direction_evaluation(zero_direction), self.zenith_evaluation(), self.distance_evaluation(), self.face1[0].atmospheric_data, self.face1[0].measure_time)
|
|
16
|
+
|
|
17
|
+
def direction_evaluation(self, zero_direction : Angle) -> Angle:
|
|
18
|
+
sum_r = Angle()
|
|
19
|
+
for i in range(len(self.face1)):
|
|
20
|
+
sum_r += ((self.face1[i].direction + self.face2[i].direction.add_half_circle())/2.0 - zero_direction).normalise()
|
|
21
|
+
return sum_r/len(self.face1)
|
|
22
|
+
|
|
23
|
+
def zenith_evaluation(self) -> Angle:
|
|
24
|
+
sum_z = Angle()
|
|
25
|
+
for i in range(len(self.face1)):
|
|
26
|
+
sum_z += (((self.face1[i].zenith - self.face2[i].zenith).normalise()) / 2.0)
|
|
27
|
+
return sum_z / len(self.face1)
|
|
28
|
+
|
|
29
|
+
def distance_evaluation(self) -> float:
|
|
30
|
+
sum_d = 0
|
|
31
|
+
for i in range(len(self.face1)):
|
|
32
|
+
sum_d += (self.face1[i].slope_distances + self.face2[i].slope_distances) / 2.0
|
|
33
|
+
return sum_d / len(self.face1)
|
|
34
|
+
|
|
35
|
+
def __str__(self):
|
|
36
|
+
return "Target: " + str(self.target_number) + " hz: " + str(self.direction) + " vz: " + str(self.zenith) + " s: " + str(self.distance)
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
|
|
2
|
+
class SWVersion(object):
|
|
3
|
+
|
|
4
|
+
def __init__(self, release: int, version: int, sub_version: int):
|
|
5
|
+
self.release = release
|
|
6
|
+
self.version = version
|
|
7
|
+
self.sub_version = sub_version
|
|
8
|
+
|
|
9
|
+
def __str__(self):
|
|
10
|
+
return "Version {0:02d}.{1:02d}.{2:02d}".format(self.release, self.version, self.sub_version)
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import math
|
|
2
|
+
import pytest
|
|
3
|
+
from surveytools import RHO, Angle
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
@pytest.mark.parametrize("gon", [0, 50, 200])
|
|
7
|
+
def test_from_and_to_gon(gon):
|
|
8
|
+
a = Angle.from_gon(gon)
|
|
9
|
+
assert pytest.approx(a.get_gon(), rel=1e-9) == gon
|
|
10
|
+
|
|
11
|
+
def test_conversion_rad_gon():
|
|
12
|
+
rad = math.pi
|
|
13
|
+
a = Angle.from_rad(rad)
|
|
14
|
+
assert pytest.approx(a.get_gon(), rel=1e-9) == rad * RHO
|
|
15
|
+
|
|
16
|
+
def test_normalise_wraps():
|
|
17
|
+
a = Angle.from_rad(3 * math.pi)
|
|
18
|
+
a.normalise()
|
|
19
|
+
assert pytest.approx(a.value_rad, rel=1e-9) == math.pi
|
|
20
|
+
|
|
21
|
+
@pytest.mark.parametrize("a_gon,b_gon,expected", [
|
|
22
|
+
(100, 100, True),
|
|
23
|
+
( 50,100, False),
|
|
24
|
+
])
|
|
25
|
+
def test_eq(a_gon, b_gon, expected):
|
|
26
|
+
a = Angle.from_gon(a_gon)
|
|
27
|
+
b = Angle.from_gon(b_gon)
|
|
28
|
+
assert (a == b) is expected
|
|
29
|
+
assert (a != b) is (not expected)
|
|
30
|
+
|
|
31
|
+
@pytest.mark.parametrize("a_rad,b_rad,expected", [
|
|
32
|
+
(1.0, 2.0, True),
|
|
33
|
+
(2.0, 1.0, False),
|
|
34
|
+
( math.pi, math.pi, False),
|
|
35
|
+
])
|
|
36
|
+
def test_lt(a_rad, b_rad, expected):
|
|
37
|
+
a = Angle.from_rad(a_rad)
|
|
38
|
+
b = Angle.from_rad(b_rad)
|
|
39
|
+
assert (a < b) is expected
|
|
40
|
+
assert (b > a) is expected # test __gt__
|
|
41
|
+
|
|
42
|
+
@pytest.mark.parametrize("a_rad,b_rad,expected", [
|
|
43
|
+
(1.0, 1.0, True),
|
|
44
|
+
(1.0, 2.0, True),
|
|
45
|
+
(2.0, 1.0, False),
|
|
46
|
+
])
|
|
47
|
+
def test_le(a_rad, b_rad, expected):
|
|
48
|
+
a = Angle.from_rad(a_rad)
|
|
49
|
+
b = Angle.from_rad(b_rad)
|
|
50
|
+
assert (a <= b) is expected
|
|
51
|
+
assert (b >= a) is expected # test __ge__
|
|
52
|
+
|
|
53
|
+
def test_sin_cos():
|
|
54
|
+
# sin und cos für 30° (π/6)
|
|
55
|
+
a = Angle.from_rad(math.pi / 6)
|
|
56
|
+
assert pytest.approx(a.sin(), rel=1e-9) == 0.5
|
|
57
|
+
assert pytest.approx(a.cos(), rel=1e-9) == math.sqrt(3) / 2
|
|
58
|
+
|
|
59
|
+
def test_supplementary_angle():
|
|
60
|
+
# 2π – π/2 = 3π/2
|
|
61
|
+
a = Angle.from_rad(math.pi / 2)
|
|
62
|
+
sup = a.supplementary_angle()
|
|
63
|
+
assert pytest.approx(sup.value_rad, rel=1e-9) == 2 * math.pi - math.pi / 2
|
|
64
|
+
|
|
65
|
+
def test_add_half():
|
|
66
|
+
a = Angle.from_rad(1.0)
|
|
67
|
+
half = a.add_half_circle()
|
|
68
|
+
# prüfe reinen Wert
|
|
69
|
+
assert pytest.approx(half.value_rad, rel=1e-9) == 1.0 + math.pi
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def test_add_and_subtract_angles():
|
|
73
|
+
a = Angle.from_rad(1.5)
|
|
74
|
+
b = Angle.from_rad(2.5)
|
|
75
|
+
c = a + b
|
|
76
|
+
d = b - a
|
|
77
|
+
|
|
78
|
+
assert pytest.approx(c.value_rad, rel=1e-9) == 4.0
|
|
79
|
+
assert pytest.approx(d.value_rad, rel=1e-9) == 1.0
|
|
80
|
+
|
|
81
|
+
def test_division_by_scalar():
|
|
82
|
+
a = Angle.from_rad(2.0)
|
|
83
|
+
half = a / 2
|
|
84
|
+
assert pytest.approx(half.value_rad, rel=1e-9) == 1.0
|
|
85
|
+
|
|
86
|
+
def test_arithmetic_type_errors():
|
|
87
|
+
a = Angle.from_gon(50)
|
|
88
|
+
with pytest.raises(TypeError):
|
|
89
|
+
_ = a + 5
|
|
90
|
+
with pytest.raises(TypeError):
|
|
91
|
+
_ = a - "string"
|
|
92
|
+
with pytest.raises(TypeError):
|
|
93
|
+
_ = a / Angle.from_rad(1.0)
|
|
94
|
+
|
|
95
|
+
@pytest.mark.parametrize("rad, expected", [
|
|
96
|
+
( 1.0, 1.0),
|
|
97
|
+
(-1.0, 1.0),
|
|
98
|
+
( 3*math.pi, 3*math.pi), # Betrag vor Normalisierung
|
|
99
|
+
(-3*math.pi, 3*math.pi),
|
|
100
|
+
])
|
|
101
|
+
def test_abs_without_normalise(rad, expected):
|
|
102
|
+
"""
|
|
103
|
+
abs() soll den ungeklärten Betrag liefern,
|
|
104
|
+
also abs(value_rad), ohne automatisch zu normieren.
|
|
105
|
+
"""
|
|
106
|
+
a = Angle.from_rad(rad)
|
|
107
|
+
b = abs(a)
|
|
108
|
+
assert pytest.approx(b.value_rad, rel=1e-9) == expected
|
|
109
|
+
|
|
110
|
+
def test_abs_and_normalise_chain():
|
|
111
|
+
"""
|
|
112
|
+
Wenn man danach normalisiert, verhält es sich erwartbar:
|
|
113
|
+
"""
|
|
114
|
+
a = Angle.from_rad(-1.0)
|
|
115
|
+
b = abs(a)
|
|
116
|
+
b.normalise()
|
|
117
|
+
# -1rad → Betrag 1rad → normalize bleibt 1rad
|
|
118
|
+
assert pytest.approx(b.value_rad, rel=1e-9) == 1.0
|
|
119
|
+
|
|
120
|
+
def test_abs_type_error():
|
|
121
|
+
"""
|
|
122
|
+
abs() auf Nicht-Angle-Objekt ist nicht relevant – Python ruft nur __abs__ auf Angle-Instanzen.
|
|
123
|
+
"""
|
|
124
|
+
with pytest.raises(TypeError):
|
|
125
|
+
# falls jemand fälschlich versucht, abs mit einem anderen Typ zu tricksen
|
|
126
|
+
_ = Angle.from_rad(1.0).__abs__("invalid")
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# tests/test_coordinate.py
|
|
2
|
+
|
|
3
|
+
import math
|
|
4
|
+
import pytest
|
|
5
|
+
from surveytools import Angle, Coordinate
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def test_add_and_subtract_coordinates():
|
|
9
|
+
a = Coordinate("A", 1.0, 2.0, 3.0)
|
|
10
|
+
b = Coordinate("B", 4.0, 5.0, 6.0)
|
|
11
|
+
# Addition
|
|
12
|
+
c = a + b
|
|
13
|
+
assert isinstance(c, Coordinate)
|
|
14
|
+
assert c.pkt_nr == "A"
|
|
15
|
+
assert c.x == pytest.approx(5.0)
|
|
16
|
+
assert c.y == pytest.approx(7.0)
|
|
17
|
+
assert c.z == pytest.approx(9.0)
|
|
18
|
+
# Subtraktion
|
|
19
|
+
d = b - a
|
|
20
|
+
assert isinstance(d, Coordinate)
|
|
21
|
+
assert d.pkt_nr == "B"
|
|
22
|
+
assert d.x == pytest.approx(3.0)
|
|
23
|
+
assert d.y == pytest.approx(3.0)
|
|
24
|
+
assert d.z == pytest.approx(3.0)
|
|
25
|
+
# Falsche Operanden-Typen werfen TypeError
|
|
26
|
+
with pytest.raises(TypeError):
|
|
27
|
+
_ = a + 123
|
|
28
|
+
with pytest.raises(TypeError):
|
|
29
|
+
_ = b - "foo"
|
|
30
|
+
|
|
31
|
+
def test_direction_to_and_distance_to():
|
|
32
|
+
origin = Coordinate("O", 0.0, 0.0, 0.0)
|
|
33
|
+
# Punkt auf der X-Achse
|
|
34
|
+
p1 = Coordinate("P1", 1.0, 0.0, 0.0)
|
|
35
|
+
ang = origin.direction_to(p1)
|
|
36
|
+
# math.atan2(dc.x, dc.y) für dc=(1,0,0) ergibt π/2
|
|
37
|
+
assert isinstance(ang, Angle)
|
|
38
|
+
assert ang.value_rad == pytest.approx(math.pi/2)
|
|
39
|
+
# Abstand sollte 1.0 sein
|
|
40
|
+
assert origin.distance_to(p1) == pytest.approx(1.0)
|
|
41
|
+
# 3–4–12–Triangle: sqrt(9+16+144) = 13
|
|
42
|
+
p2 = Coordinate("P2", 3.0, 4.0, 12.0)
|
|
43
|
+
assert origin.distance_to(p2) == pytest.approx(13.0)
|
|
44
|
+
|
|
45
|
+
def test_array_methods_and_normalized_vector():
|
|
46
|
+
p = Coordinate("P", 1.1, 2.2, 3.3)
|
|
47
|
+
# get_array gibt [y, x, z]
|
|
48
|
+
assert p.get_array() == [2.2, 1.1, 3.3]
|
|
49
|
+
# homogene Koordinaten
|
|
50
|
+
assert p.get_homogene_array() == [2.2, 1.1, 3.3, 1]
|
|
51
|
+
# Normalisierter Vektor
|
|
52
|
+
norm = math.sqrt(1.1**2 + 2.2**2 + 3.3**2)
|
|
53
|
+
vec = p.get_normalized_vector()
|
|
54
|
+
assert vec[0] == pytest.approx(1.1 / norm)
|
|
55
|
+
assert vec[1] == pytest.approx(2.2 / norm)
|
|
56
|
+
assert vec[2] == pytest.approx(3.3 / norm)
|
|
57
|
+
|
|
58
|
+
def test_str_representation():
|
|
59
|
+
# Die __str__-Methode solltePkt-Nummer und gerundete Werte anzeigen
|
|
60
|
+
p = Coordinate("X1", 1.23456, 2.34567, 3.45678)
|
|
61
|
+
s = str(p)
|
|
62
|
+
assert s.startswith("[Pkt: X1")
|
|
63
|
+
# Je nach implementiertem Format auf 4 Dezimalstellen gerundet
|
|
64
|
+
assert "x: 1.2346" in s
|
|
65
|
+
assert "y: 2.3457" in s
|
|
66
|
+
assert "z: 3.4568" in s
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# tests/test_measurement.py
|
|
2
|
+
|
|
3
|
+
import math
|
|
4
|
+
import pytest
|
|
5
|
+
from surveytools import Angle, Coordinate, Measurement
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def test_init_and_attributes():
|
|
9
|
+
atm = {"pressure": 1013.25, "temp": 20.0}
|
|
10
|
+
mt = "2025-05-26T12:00:00"
|
|
11
|
+
m = Measurement(42, Angle.from_gon(100), Angle.from_rad(math.pi / 4), 123.45, atm, mt)
|
|
12
|
+
|
|
13
|
+
# Attribute wurden korrekt gesetzt
|
|
14
|
+
assert m.target_number == 42
|
|
15
|
+
assert m.direction.get_gon() == pytest.approx(100) # Gauge aus Gon :contentReference[oaicite:0]{index=0}
|
|
16
|
+
assert m.zenith.value_rad == pytest.approx(
|
|
17
|
+
math.pi / 4) # Radiant direkt aus from_rad :contentReference[oaicite:1]{index=1}
|
|
18
|
+
assert m.slope_distances == pytest.approx(123.45)
|
|
19
|
+
assert m.atmospheric_data is atm
|
|
20
|
+
assert m.measure_time == mt
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def test_get_horizontal_distances():
|
|
24
|
+
# hd = slope_distances * sin(zenith)
|
|
25
|
+
zen = Angle.from_rad(math.pi / 6)
|
|
26
|
+
m = Measurement(0, Angle.from_rad(0), zen, 10.0, None, None)
|
|
27
|
+
expected = 10.0 * math.sin(math.pi / 6)
|
|
28
|
+
assert m.get_horizontal_distances() == pytest.approx(
|
|
29
|
+
expected) # get_horizontal_distances :contentReference[oaicite:2]{index=2}
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def test_get_delta_height():
|
|
33
|
+
# dh = slope_distances * cos(zenith)
|
|
34
|
+
zen = Angle.from_rad(math.pi / 3)
|
|
35
|
+
m = Measurement(0, Angle.from_rad(0), zen, 20.0, None, None)
|
|
36
|
+
expected = 20.0 * math.cos(math.pi / 3)
|
|
37
|
+
assert m.get_delta_height() == pytest.approx(expected) # get_delta_height :contentReference[oaicite:3]{index=3}
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def test_get_local_coordinate():
|
|
41
|
+
# hd = sd * sin(zenith) = 5 * 1 = 5
|
|
42
|
+
# direction = 45° → x = hd*cos(45°), y = hd*sin(45°), z = sd*cos(zenith) = 0
|
|
43
|
+
dir_ang = Angle.from_rad(math.pi / 4)
|
|
44
|
+
zen = Angle.from_rad(math.pi / 2)
|
|
45
|
+
m = Measurement(7, dir_ang, zen, 5.0, None, None)
|
|
46
|
+
coord = m.get_local_coordinate()
|
|
47
|
+
|
|
48
|
+
assert isinstance(coord, Coordinate)
|
|
49
|
+
assert coord.pkt_nr == 7
|
|
50
|
+
assert coord.x == pytest.approx(
|
|
51
|
+
5.0 * math.cos(math.pi / 4)) # get_local_coordinate :contentReference[oaicite:4]{index=4}
|
|
52
|
+
assert coord.y == pytest.approx(5.0 * math.sin(math.pi / 4))
|
|
53
|
+
assert coord.z == pytest.approx(5.0 * math.cos(math.pi / 2))
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def test_get_arra_and_str():
|
|
57
|
+
# get_arra liefert [target_number, direction_gon, zenith_gon, slope_distances]
|
|
58
|
+
dir_ang = Angle.from_gon(150)
|
|
59
|
+
zen = Angle.from_gon(75)
|
|
60
|
+
m = Measurement(8, dir_ang, zen, 12.3, "ATM_DATA", "TIME_STAMP")
|
|
61
|
+
arr = m.get_arra()
|
|
62
|
+
assert arr == [8, pytest.approx(dir_ang.get_gon()), pytest.approx(zen.get_gon()),
|
|
63
|
+
pytest.approx(12.3)] # get_arra :contentReference[oaicite:5]{index=5}
|
|
64
|
+
|
|
65
|
+
# __str__ enthält alle Informationen
|
|
66
|
+
s = str(m)
|
|
67
|
+
assert "target: 8" in s
|
|
68
|
+
assert "direction:" in s and "gon" in s
|
|
69
|
+
assert "zenith:" in s and "gon" in s
|
|
70
|
+
assert "slope_distances: 12.3" in s
|
|
71
|
+
assert "atmospheric_data: ATM_DATA" in s
|
|
72
|
+
assert "Measure Time: TIME_STAMP" in s # __str__ :contentReference[oaicite:6]{index=6}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
|
|
3
|
+
from surveytools import MeasurementTarget, Measurement, Angle
|
|
4
|
+
|
|
5
|
+
# 1. Erstelle jeweils zwei Measurement-Instanzen für face1
|
|
6
|
+
m1_f1 = Measurement(
|
|
7
|
+
target=1,
|
|
8
|
+
direction=Angle.from_gon(172.1609), # Horizontalwinkel in Gon
|
|
9
|
+
zenith=Angle.from_gon(97.1722), # Zenitwinkel in Gon
|
|
10
|
+
sd=12.287, # Schrägentfernung
|
|
11
|
+
atmospheric_data={"pressure": 1013.25},
|
|
12
|
+
measure_time="2025-05-26T10:00:00"
|
|
13
|
+
)
|
|
14
|
+
m2_f1 = Measurement(
|
|
15
|
+
target=1,
|
|
16
|
+
direction=Angle.from_gon(172.1659),
|
|
17
|
+
zenith=Angle.from_gon(97.1682),
|
|
18
|
+
sd=12.29,
|
|
19
|
+
atmospheric_data={"pressure": 1013.25},
|
|
20
|
+
measure_time="2025-05-26T10:01:00"
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
# 2. Erstelle jeweils zwei Measurement-Instanzen für face2
|
|
24
|
+
m1_f2 = Measurement(
|
|
25
|
+
target=1,
|
|
26
|
+
direction=Angle.from_gon(372.1589),
|
|
27
|
+
zenith=Angle.from_gon(302.8283),
|
|
28
|
+
sd=12.292,
|
|
29
|
+
atmospheric_data={"pressure": 1013.25},
|
|
30
|
+
measure_time="2025-05-26T10:02:00"
|
|
31
|
+
)
|
|
32
|
+
m2_f2 = Measurement(
|
|
33
|
+
target=1,
|
|
34
|
+
direction=Angle.from_gon(372.1589),
|
|
35
|
+
zenith=Angle.from_gon(302.8322),
|
|
36
|
+
sd=12.285,
|
|
37
|
+
atmospheric_data={"pressure": 1013.25},
|
|
38
|
+
measure_time="2025-05-26T10:03:00"
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
# 3. Instanziiere das MeasurementTarget
|
|
42
|
+
target = MeasurementTarget(
|
|
43
|
+
target=1,
|
|
44
|
+
direction=Angle.from_gon(172), # Referenzrichtung
|
|
45
|
+
zenith=Angle.from_gon(97), # Referenzzenit
|
|
46
|
+
distance=12.3 # Referenzentfernung
|
|
47
|
+
) # face1 und face2 sind zunächst leere Listen
|
|
48
|
+
|
|
49
|
+
# 4. Fülle face1 und face2
|
|
50
|
+
target.face1.extend([m1_f1, m2_f1])
|
|
51
|
+
target.face2.extend([m1_f2, m2_f2])
|
|
52
|
+
|
|
53
|
+
# 5. Optional: Auswertung durchführen
|
|
54
|
+
result = target.evaluation(zero_direction=Angle.from_rad(0))
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def test_measurement_target_evaluation_practical():
|
|
58
|
+
# 4) Auswertung prüfen
|
|
59
|
+
# Direction: (172.1609 + 172.1659 + (372.1589-200)*2) / 4 ≈ 172.1612 gon
|
|
60
|
+
assert result.direction.get_gon() == pytest.approx(172.1612, abs=1e-4)
|
|
61
|
+
|
|
62
|
+
# Zenith: (97.1722 + 97.1682 + (400-302.8283) + (400-302.8322)) / 4 ≈ 97.1700 gon
|
|
63
|
+
assert result.zenith.get_gon() == pytest.approx(97.1700, abs=1e-4)
|
|
64
|
+
|
|
65
|
+
# Slope distance: (12.287 + 12.290 + 12.292 + 12.285) / 4 ≈ 12.2885
|
|
66
|
+
assert result.slope_distances == pytest.approx(12.2885, abs=1e-4)
|