########################################################################
# #
# Copyright (C) 2018, Marius Hürzeler #
# #
# This file is part of PyVerm. #
# #
# PyVerm is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# PyVerm is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with Foobar. If not, see <http://www.gnu.org/licenses/>. #
# #
########################################################################
"""
_classes module defines all the classes
"""
from decimal import *
import collections
import math
from . import _functions
from . import _utils
from . import settings
getcontext().prec = settings.DEFAULT_DECIMAL_PRECISION
Point = collections.namedtuple("Point", ["y", "x", "z"])
[docs]class Station:
def __init__(self, standpoint, orientation):
standpoint = _utils.input_point(standpoint)
orientation = _utils.input_angle(orientation)
self.standpoint = standpoint
self._orientation = orientation
@property
def orientation(self):
return _utils.output_angle(self._orientation)
@orientation.setter
def orientation(self, orientation):
orientation = _utils.input_angle(orientation)
self._orientation = orientation
[docs] def survey(self, observation):
"""Returns the Point, which was surveyed with the given observation.
:param observation:
:type observation: pyverm.ObservationPolar
:return: :class:`Point <Point>` object
:rtype: pyverm.Point
"""
y, x = _functions.cartesian(observation.reduced_distance,
observation.reduced_horizontal_angle + self.orientation)
y += self.standpoint[0]
x += self.standpoint[1]
return Point(y, x, 0)
[docs] def stakeout(self, point):
"""Return the observation values, which are needed to stakeout the given point.
:param point: point to stakeout
:type point: tuple or pyverm.Point
:return: :class:`ObservationPolar <ObservationPolar>` object
:rtype: pyverm.ObservationPolar
"""
point = _utils.input_point(point)
dist, azi = _functions.polar(point, origin=self.standpoint)
hz = azi - self.orientation
if point[2] is not None and self.standpoint[2] is not None:
delta_h = self.standpoint[2] - point[2]
zenith = _utils.output_angle(math.atan(delta_h/dist)+(math.pi/2))
observation = ObservationPolar(reduced_distance=dist, reduced_horizontal_angle=hz, reduced_zenith_angle=zenith)
else:
observation = ObservationPolar(reduced_distance=dist, reduced_horizontal_angle=hz)
return observation
def __repr__(self):
return "<Station at ({:.5f}, {:.5f}, {:.5f}) with orientation {:.5f}>".format(self.standpoint[0], self.standpoint[1],self.standpoint[2], self.orientation)
[docs]class ObservationPolar:
[docs] def __init__(self, **kwargs):
"""Represent a polar observation with all associated values as simple and usable as possible.
Despite all attributes are optional, depending on the function certain attributes must be present.
.. todo::
* Document the reduction of the raw values
* implement the reduction of the distance
* add unittest for this class
:param reduced_targetpoint: (optional) Point which was measured with this observation
:type reduced_targetpoint: tuple or pyverm.Point
:param reduced_horizontal_angle: (optional) horizontal angle in gon with all corrections
:type reduced_horizontal_angle: float or decimal
:param reduced_zenith_angle: (optional) zenith angle in gon with all corrections
:type reduced_zenith_angle: float or decimal
:param reduced_distance: (optional) distance in meters with all corrections
:type reduced_distance: float or decimal
:param raw_horizontal_angle: (optional) horizontal angle in gon
:type raw_horizontal_angle: float or decimal
:param raw_horizontal_angle_2: (optional) horizontal angle in gon in second direction
:type raw_horizontal_angle_2: float or decimal
:param raw_zenith_angle: (optional) zenith angle in gon
:type raw_zenith_angle: float or decimal
:param raw_zenith_angle_2: (optional) zenith angle in gon in second direction
:type raw_zenith_angle_2: float or decimal
:param raw_distance: (optional) distance in meters **not yet implemented**
:type raw_distance: float or decimal
:param raw_distance_2: (optional) distance in meters in second direction **not yet implemented**
:type raw_distance_2: float or decimal
"""
# reduced values
self.reduced_targetpoint = kwargs.setdefault("reduced_targetpoint", None)
self._reduced_hz = _utils.input_angle(kwargs.setdefault("reduced_horizontal_angle", None))
self._reduced_v = _utils.input_angle(kwargs.setdefault("reduced_zenith_angle", None))
self._reduced_distance = _utils.input_decimal(kwargs.setdefault("reduced_distance", None))
# raw values
self._raw_hz_1 = _utils.input_angle(kwargs.setdefault("raw_horizontal_angle", None))
self._raw_hz_2 = _utils.input_angle(kwargs.setdefault("raw_horizontal_angle_2", None))
self._raw_v_1 = _utils.input_angle(kwargs.setdefault("raw_zenith_angle", None))
self._raw_v_2 = _utils.input_angle(kwargs.setdefault("raw_zenith_angle_2", None))
self._raw_distance_1 = _utils.input_decimal(kwargs.setdefault("raw_distance", None))
self._raw_distance_2 = _utils.input_decimal(kwargs.setdefault("raw_distance_2", None))
@property
def reduced_horizontal_angle(self):
"""
Return reduced_horizontal_angle or if None and raw in two direction present, return calculated reduced angle
:return:
"""
if self._reduced_hz is None:
# average from to directions
if self._raw_hz_2 is not None and self._raw_hz_1 is not None:
if self._raw_hz_2 > self._raw_hz_1:
temp = -1
else:
temp = +1
reduced = ((self._raw_hz_1 + (
self._raw_hz_2 + Decimal(math.pi * temp)))) / Decimal(2)
elif self._raw_hz_1 is not None:
reduced = self._raw_hz_1
else:
raise NotImplemented("there is no zenith angle")
output = reduced
else:
output = self._reduced_hz
return _utils.output_angle(output)
@reduced_horizontal_angle.setter
def reduced_horizontal_angle(self, reduced_horizontal_angle):
self._reduced_hz = _utils.input_angle(reduced_horizontal_angle)
@property
def reduced_zenith_angle(self):
"""
Return reduced_zenith_angle or if None and raw in two direction present, return calculated reduced angle
:return:
"""
if self._reduced_v is None:
# average from to directions
if self._raw_v_2 is not None and self._raw_v_1 is not None:
reduced = ((self._raw_v_1 - self._raw_v_2) + math.pi * 2) / 2
elif self._raw_v_1 is not None:
reduced = self._raw_v_1
else:
raise NotImplemented("there is no zenith angle")
output = reduced
else:
output = self._reduced_v
return _utils.output_angle(output)
@reduced_zenith_angle.setter
def reduced_zenith_angle(self, reduced_zenith_angle):
self._reduced_v = _utils.input_angle(reduced_zenith_angle)
@property
def reduced_distance(self):
if self._reduced_distance is None:
raise NotImplemented("reduction of raw distance is not implemented")
else:
return self._reduced_distance
@reduced_distance.setter
def reduced_distance(self, reduced_distance):
self._reduced_distance = reduced_distance
def __repr__(self):
return "<Polar Observation with Hz {:.5f} and Dist {:.5f}>".format(self.reduced_horizontal_angle, self.reduced_distance)
class Orthogonal:
def __init__(self, point_a, point_b, *, mesured_distande=None):
pass
class Line:
def __init__(self, startpoint, endpoint):
startpoint = _utils.input_point(startpoint)
endpoint = _utils.input_point(endpoint)
self.startpoint = startpoint
self.endpoint = endpoint
class Circle:
def __init__(self, center, radius):
center = _utils.input_point(center)
radius = _utils.input_decimal(radius)
self.center = center
self.radius = radius