import math
import doctest
# ========================================================
# ========================================================
# === ANGLE
# ========================================================
# ========================================================
[docs]class Angle:
""" Class to convert angles for astronomy
Angle formats are:
* deg = degrees. e.g.
* rad = radian. e.g.
:Usage:
First, instanciate an object from the class:
::
angle = Angle()
Second, assign a date in any angle format:
::
angle.angle("-0d3m28.56s")
Third, get the converted angle:
::
rad = angle.rad()
deg = angle.deg()
arcmin = angle.arcmin()
arcsec = angle.arcsec()
dms = angle.dms()
uspzad = angle.sexagesimal(sexagesimal_format)
:Informations:
::
help(Angle)
Angle().infos("doctest")
Angle().infos("doc_methods")
"""
# ========================================================
# === attributs
# ========================================================
# --- multiplicators for units
_r2d = 180.0/math.pi
_d2r = 1./_r2d
_r2h = _r2d/15.0
_h2r = 1./_r2h
_r2m = _r2d*60.0
_m2r = 1./_r2m
_r2s = _r2d*3600.0
_s2r = 1./_r2s
_r2mh = _r2m/15.0
_mh2r = 1./_r2mh
_r2sh = _r2s/15.0
_sh2r = 1./_r2sh
# --- correspondances between units and multiplicator ->r
_u2r = {}
_u2r["R"] = 1
_u2r["D"] = _d2r
_u2r["M"] = _m2r
_u2r["S"] = _s2r
_u2r["H"] = _h2r
_u2r["MH"] = _mh2r
_u2r["SH"] = _sh2r
# ========================================================
# === internal methods
# ========================================================
def _init(self,angle=""):
""" Initialize internal attributes.
:param angle: angle is an angle in any supported format (cf. help(Angle))
:type angle: str
:Usage:
::
objangle = Angle()
objangle._init()
"""
self._init_angle = angle
self._init_angleformat = []
self._computed_rad = 0
self._angle_redefined()
self._computed_sexagesimal_format = "D.3"
self._rad = 0
def _angle_redefined(self):
""" Initialize internal attributes when a radian angle is just defined or redefined.
"""
self._computed_deg = 0
self._computed_arcmin = 0
self._computed_arcsec = 0
self._computed_sexagesimal = 0
self._deg = 0
self._arcmin = 0
self._arcsec = 0
self._sexagesimal = 0
self._cos_rad_modulo = math.nan
self._sin_rad_modulo = math.nan
def _is_number(self,s):
""" Return True if the string is a number else return False.
:param s: a value to test
:type s: str
:Usage:
>>> objangle = Angle()
>>> objangle._is_number("3e5")
True
>>> objangle._is_number("3a5")
False
"""
try:
float(s)
return True
except ValueError:
pass
try:
import unicodedata
unicodedata.numeric(s)
return True
except (TypeError, ValueError):
pass
return False
def _angle_compare(self, angle, operator):
""" Comparaison of angles for various operators.
:param angle: An angle in any supported format (cf. help(Angle))
:type angle: Angle()
:param operator: Operator such as == != > >= < <=
:type operator: string
:returns: The logic result of the comparison.
:rtype: bool
:Example:
>>> objangle1 = Angle()
>>> objangle2 = Angle()
>>> objangle1.angle(12.345) ; objangle2.angle("56d28m") ; objangle1._angle_compare(objangle2,">")
12.345
'56d28m'
False
.. note:: Does not account for the modulo.
"""
if isinstance(angle, Angle) == False:
angle = Angle(angle)
if self._computed_rad == 0:
self.rad()
if angle._computed_rad == 0:
angle.rad()
res = False
if (self._computed_rad == 1) and (angle._computed_rad == 1):
toeval = str(self._rad)+" "+operator+" "+str(angle._rad)
res = eval(toeval)
return res
# ========================================================
# === angle methods
# ========================================================
[docs] def angle_angle2rad(self,angle):
""" Compute radian from any angle format
:param angle: angle is an angle in any supported format (cf. help(Angle))
:type angle: str
:Usage:
>>> objangle = Angle()
>>> objangle.angle_angle2rad("-57d45m34s")
([('-57', 'D'), ('45', 'M'), ('34', 'S')], -1.0080924796783026)
First integer is used to check the recognized input date format:
0 = Error, format not known
:Related topics:
Prefer using objangle.angle() followed by objangle.rad()
"""
str_angle = str(angle).upper()
#print("str_angle = "+str_angle)
cars = "+-.0123456789"
# --- eliminate leading characters before the first numeric cheracter
k = 0
for car in str_angle:
if (car in cars):
break
k += 1
if (k==0):
# problem, no valid numeric value found.
pass
str_angle = str_angle[k:]
# ---
# "-0 45 ' 34 sec"
# angle_numb = [ "-0", "45", "34" ]
# angle_numb = [ " ", " ' ", " sec" ]
ind_numb = -1
ind_unit = -1
angle_numbs = []
angle_units = []
knumb = 0
kunit = 0
for car in str_angle:
if (car in cars) or (car=='E' and knumb>0):
# --- numeric case for value
if (knumb==0):
ind_numb += 1
angle_numbs.append('')
angle_numbs[ind_numb] += car
knumb += 1
kunit = 0
else:
# --- alpha case for units
if (kunit==0):
ind_unit += 1
angle_units.append('')
if ( (car!=" ") and (car!=":") ):
if (car=="'"):
car = "M"
if (car=='"'):
car = "S"
angle_units[ind_unit] += car
kunit += 1
knumb = 0
# --- reformat units
#print("angle_numbs={}".format(angle_numbs))
#print("angle_units={}".format(angle_units))
n_numb = len(angle_numbs)
n_unit = len(angle_units)
tmps = [];
for angle_unit in angle_units:
if angle_unit is '':
angle_unit = ' '
tmps.append(angle_unit)
angle_units = tmps.copy()
# --- simplify units
angle_fnumbs = []
angle_funits = []
if (n_unit==0) and (n_numb==0):
angle_fnumbs.append("0")
angle_funits.append("R")
elif (n_unit==0):
angle_fnumbs.append(angle_numbs[0])
angle_funits.append("D")
elif (n_unit==1):
angle_fnumbs.append(angle_numbs[0])
u1 = angle_units[0]
if (u1[0]=="R"):
angle_funits.append("R")
elif (u1[0]=="M"):
angle_funits.append("M")
if (n_numb==2):
angle_funits.append("S")
angle_fnumbs.append(angle_numbs[1])
elif (u1[0]=="S"):
angle_funits.append("S")
elif (u1[0]=="H"):
angle_funits.append("H")
if (n_numb==2):
angle_funits.append("MH")
angle_fnumbs.append(angle_numbs[1])
else:
angle_funits.append("D")
if (n_numb==2):
angle_funits.append("M")
angle_fnumbs.append(angle_numbs[1])
elif (n_numb==2):
# cases DM or MS HM
angle_fnumbs.append(angle_numbs[0])
angle_fnumbs.append(angle_numbs[1])
u1 = angle_units[0]
u2 = angle_units[1]
if (u1[0]=="M"):
angle_funits.append("M")
angle_funits.append("S")
elif (u1[0]=="H" and u2[0]=="S"):
angle_funits.append("H")
angle_funits.append("SH")
elif (u1[0]=="H"):
angle_funits.append("H")
angle_funits.append("MH")
else:
angle_funits.append("D")
angle_funits.append("M")
elif (n_numb==3):
# cases DMS or HMS
angle_fnumbs.append(angle_numbs[0])
angle_fnumbs.append(angle_numbs[1])
angle_fnumbs.append(angle_numbs[2])
u1 = angle_units[0]
if (u1[0]=="H"):
angle_funits.append("H")
angle_funits.append("MH")
angle_funits.append("SH")
else:
angle_funits.append("D")
angle_funits.append("M")
angle_funits.append("S")
# --- compute the angle
if (angle_fnumbs=="."):
angle_fnumbs="0."
#print(angle_fnumbs)
#print(angle_funits)
init_angleformat = list ( zip (angle_fnumbs, angle_funits) )
sign = 1
k=0
rad = 0
for init_angle in init_angleformat:
numb = init_angle[0]
unit = init_angle[1]
if (k==0) and ('-' in numb):
sign = -1
fnumb = math.fabs(float(numb))
mult = self._u2r[unit]
rad += fnumb*mult
rad *= sign
self._rad = rad
self._rad_modulo_2pi = math.fmod(rad,2*math.pi)
if (self._rad_modulo_2pi<0):
self._rad_modulo_2pi += (2*math.pi)
return init_angleformat, rad
[docs] def angle_rad2deg(self,rad):
""" Compute a angle in degrees from a angle in radian
:param rad: rad is an angle in radian.
:type rad: float
:Usage:
>>> objangle = Angle()
>>> objangle.angle_rad2deg(1)
(0, 57.29577951308232)
First integer is an error code. 0 = no problem.
:Related topics:
Prefer using objangle.angle() followed by objangle.deg()
"""
error = 0
res = rad * self._r2d
return error, res
[docs] def angle_rad2sexagesimal(self,rad, sexagesimal_format):
""" Compute a sexagesimal format string from radian
:param rad: rad is an angle in radian
:type rad: float
:param sexagesimal_format: The uspzad format (see details below)
:type sexagesimal_format: str
Sexagesimal format:
* u (unit) = h,H,d,D (default=D). Capital mean module [0:360[, lower case means module [-180:180[
* s (separator) = " ",:,"" (default="" means letters hms or dms)
* p (plus/minus) = +,"" (default="")
* z (zeros) = 0,"" (default="")
* a (angle_limits) = "",90, (+/-limit if unit D,H, default="" means 360)
* d (sec_digits) = "",".1",".2",... (default="")
Style 1:
* To Display a R.A.: "H0.2" => 23h07m42.49s
* To Display a Decl.: "d+090.1" => +00d34m22.6s
* To Display a H.A.: "h0.2" => -08h43m16.05s
Style 2:
* To Display a R.A.: "H 0.2" => 23 07 42.49
* To Display a Decl.: "d +090.1" => -00 34 22.6
* To Display a H.A.: "h 0.2" => -08 43 16.05
Style 3:
* To Display a R.A.: "H:0.2" => 23:07:42.49
* To Display a Decl.: "d:+090.1" => -00:34:22.6
* To Display a H.A.: "h:0.2" => -08:43:16.05
:Example:
>>> objangle = Angle()
>>> objangle.angle_rad2sexagesimal(-0.01,"d:-090.1")
(0, '-00:34:22.6')
First integer is used to check the recognized input date format:
0 = Error, format not known
:Related topics:
Prefer using objangle.angle() followed by objangle.sexagesimal()
"""
symbols = str(sexagesimal_format)
digits = ""
unit=0; # 0=deg 1=hours
separator=0; # 0=hdms 1=space 2=:
modulo=0; # 0=360 1=180
sign=0; # 0=[0:modulo] 1=[-modulo/2:modulo/2]
zeros=0; # 0=spaces 1=leading zeros
k=0
for car in symbols:
if (car=='D'):
unit=0
modulo=0
if (car=='d'):
unit=0
modulo=1
if (car=='H'):
unit=1
modulo=0
if (car=='h'):
unit=1
modulo=1
if (car==' '):
separator=1
if (car=='_'):
separator=1
if (car==':'):
separator=2
if (car=='+'):
sign=1
if (self._is_number(car)) or car=='.':
digits = symbols[k:]
break
k += 1
# int unit=0; // 0=deg 1=hours
# int modulo=0; // 0=360 1=180
# int separator=0; // 0=hdms 1=space 2=:
# int sign=0; // 0=[0:modulo] 1=[-modulo/2:modulo/2]
# === trailing format (digits)
angle_limit = 360
nb_decimalsec = 2
ld = len(digits)
if (ld>0):
# e.g. digits = "090.3"
car = digits[0]
if car=='0':
zeros=1
digits = digits[1:]
# now digits = "90.3" and zeros=1
kd = digits.find(".")
if kd==-1:
if (self._is_number(digits)==True):
angle_limit = int(digits)
else:
if (self._is_number(digits[0:kd])==True):
angle_limit = int(digits[0:kd])
if (self._is_number(digits[kd+1:])==True):
nb_decimalsec = int(digits[kd+1:])
# now digits_angle_limit = "90", digits_nb_decimal="3"
#print("ld="+str(ld))
#print("symbols="+symbols)
#print("digits="+digits)
#print("unit="+str(unit))
#print("modulo="+str(modulo))
#print("separator="+str(separator))
#print("sign="+str(sign))
#print("zeros="+str(zeros))
#print("angle_limit="+str(angle_limit))
#print("nb_decimal="+str(nb_decimalsec))
error, deg = self.angle_rad2deg(rad)
# --- all angle in [0:360[
deg = math.fmod(deg, 360)
if (deg<0):
deg = math.fmod(deg+360, 360)
#print("deg 1 ="+str(deg))
# --- case modulo [-180:180[
if modulo==1:
if deg>180:
deg-=360
#print("deg 2 ="+str(deg))
# --- limit angle
if deg>angle_limit:
deg = angle_limit
elif deg<-angle_limit:
deg = -angle_limit
#print("deg 3 ="+str(deg))
# --- sign of the input angle
s = 1
if deg<0:
s = -1
deg = -deg
# --- case hour/deg
if (unit==1):
angle = deg/15
angle_limit = angle_limit/15
else:
angle = deg
#print("angle 1 ="+str(angle))
# --- compute the trheee components of xx mm ss
r = angle
xx = int(math.floor(r))
mm = 0
ss = 0
r = (r-xx)*60
mm = int(math.floor(r))
ss = (r-mm)*60
#print("xx ="+str(xx))
#print("mm ="+str(mm))
#print("ss ="+str(ss))
# === Compute the result
result = ""
# --- sign
if sign==1 and s>=0:
result += "+"
elif s<0:
result += "-"
# --- xx
n = 1+int(math.log10(angle_limit))
if zeros==0:
fstring = "{:d}"
else:
fstring = "{:0"+str(n)+"d}"
result += fstring.format(xx)
# --- separator xx mm
if separator==1:
result += " "
elif separator==2:
result += ":"
else:
if unit==0:
result += "d"
else:
result += "h"
# --- mm
if zeros==0:
fstring = "{:d}"
else:
fstring = "{:02d}"
result += fstring.format(mm)
# --- separator mm ss
if separator==1:
result += " "
elif separator==2:
result += ":"
else:
result += "m"
# --- ss
if zeros==0:
fstring = "{:."+str(nb_decimalsec)+"f}"
else:
if nb_decimalsec==0:
fstring = "{:0"+str(nb_decimalsec+2)+".0f}"
else:
fstring = "{:0"+str(nb_decimalsec+3)+"."+str(nb_decimalsec)+"f}"
#print("fstring="+fstring)
result += fstring.format(ss)
# --- separator ss
if separator==0:
result += "s"
# -- end
return 0, result
# ========================================================
# === get/set methods
# ========================================================
[docs] def angle(self, angle=""):
""" Set the input angle in any format
:param angle: angle is an angle in any supported format (cf. help(Angle))
:type angle: str
:Example:
>>> objangle = Angle()
>>> objangle.angle("23d 27m")
'23d 27m'
:Related topics:
After using objangle.angle() get conversions with methods as objangle.deg()
or objdate.rad().
"""
if angle != "":
if (angle != self._init_angle):
self._init(angle)
return self._init_angle
[docs] def rad(self):
""" Get the angle in radian
:Example:
>>> objangle = Angle()
>>> objangle.angle("-23 d 56'")
"-23 d 56'"
>>> objangle.rad()
-0.4177154676439762
:Related topics:
Before use objdate.angle() to set the input angle.
"""
if (self._computed_rad == 0):
init_angleformat, rad = self.angle_angle2rad(self._init_angle)
self._init_angleformat = init_angleformat
self._computed_rad = 1
self._rad = rad
return self._rad
[docs] def deg(self):
""" Get the angle in degrees
:Example:
>>> objangle = Angle()
>>> objangle.angle("-23 d 56'")
"-23 d 56'"
>>> objangle.deg()
-23.933333333333334
:Related topics:
Before use objdate.angle() to set the input angle.
"""
if (self._computed_deg == 0):
if (self._computed_rad == 0):
self.rad()
if (len(self._init_angleformat) > 0):
error, deg = self.angle_rad2deg(self._rad)
if error==0:
self._computed_deg = 1
self._deg = deg
return self._deg
return -1
return self._deg
[docs] def arcmin(self):
""" Get the angle in arcmin
:Example:
>>> objangle = Angle()
>>> objangle.angle("-23 d 56'")
"-23 d 56'"
>>> objangle.arcmin()
-1436.0
:Related topics:
Before use objdate.angle() to set the input angle.
"""
if (self._computed_arcmin == 0):
if (self._computed_rad == 0):
self.rad()
if (len(self._init_angleformat) > 0):
error, deg = self.angle_rad2deg(self._rad)
arcmin = deg*60
if error==0:
self._computed_arcmin = 1
self._arcmin = arcmin
return self._arcmin
return -1
return self._arcmin
[docs] def arcsec(self):
""" Get the angle in arcsec
:Example:
>>> objangle = Angle()
>>> objangle.angle("-23 d 56'")
"-23 d 56'"
>>> objangle.arcsec()
-86160.0
:Related topics:
Before use objdate.angle() to set the input angle.
"""
if (self._computed_arcsec == 0):
if (self._computed_rad == 0):
self.rad()
if (len(self._init_angleformat) > 0):
error, deg = self.angle_rad2deg(self._rad)
arcsec = deg*3600
if error==0:
self._computed_arcsec = 1
self._arcsec = arcsec
return self._arcsec
return -1
return self._arcsec
[docs] def sexagesimal(self,sexagesimal_format):
""" Get the angle in sexagesimal
:param rad: rad is an angle in radian
:type rad: float
:param sexagesimal_format: The uspzad format (see details below)
:type sexagesimal_format: str
Sexagesimal format:
* u (unit) = h,H,d,D (default=D). Capital mean module [0:360[, lower case means module [-180:180[
* s (separator) = " ",:,"" (default="" means letters hms or dms)
* p (plus/minus) = +,"" (default="")
* z (zeros) = 0,"" (default="")
* a (angle_limits) = "",90, (+/-limit if unit D,H, default="" means 360)
* d (sec_digits) = "",".1",".2",... (default="")
Style 1:
* To Display a R.A.: "H0.2" => 23h07m42.49s
* To Display a Decl.: "d+090.1" => +00d34m22.6s
* To Display a H.A.: "h0.2" => -08h43m16.05s
Style 2:
* To Display a R.A.: "H 0.2" => 23 07 42.49
* To Display a Decl.: "d +090.1" => -00 34 22.6
* To Display a H.A.: "h 0.2" => -08 43 16.05
Style 3:
* To Display a R.A.: "H:0.2" => 23:07:42.49
* To Display a Decl.: "d:+090.1" => -00:34:22.6
* To Display a H.A.: "h:0.2" => -08:43:16.05
:Example:
>>> objangle = Angle()
>>> objangle.angle(-0.57)
-0.57
>>> objangle.sexagesimal("d:-090.1")
'-00:34:12.0'
:Related topics:
Before use objdate.angle() to set the input angle.
"""
if (self._computed_sexagesimal == 0) or (sexagesimal_format != self._computed_sexagesimal_format):
if (self._computed_rad == 0):
self.rad()
if (len(self._init_angleformat) > 0):
error, sexagesimal = self.angle_rad2sexagesimal(self._rad, sexagesimal_format)
if error==0:
self._computed_sexagesimal = 1
self._sexagesimal = sexagesimal
self._computed_sexagesimal_format = sexagesimal_format
return self._sexagesimal
return -1
return self._sexagesimal
# ========================================================
# === debug methods
# ========================================================
[docs] def infos(self, action) -> None:
""" To get informations about this class
:param action: A command to run a debug action (see examples).
:type action: string
:Example:
Angle().infos("doctest")
Angle().infos("doc_methods")
Angle().infos("internal_attributes")
Angle().infos("public_methods")
"""
if (action == "doc_methods"):
publics = [x for x in dir(self) if x[0]!="_"]
for public in publics:
varname = "{}".format(public)
if (callable(getattr(self,varname))==True):
print("\n{:=^40}".format(" method "+varname+" "))
t = "Angle()."+varname+".__doc__"
tt =eval(t)
print(tt)
if (action == "doctest"):
if __name__ == "__main__":
print("\n{:~^40}".format("doctest"))
#doctest.testmod(verbose=True, extraglobs={'objangle': Angle()})
doctest.testmod(verbose=True)
if (action == "internal_attributes"):
internals = [x for x in dir(self) if x[0]=="_" and x[1]!="_"]
for internal in internals:
varname = "{}".format(internal)
#if (hasattr(self,varname)==True):
if (callable(getattr(self,varname))==False):
print(varname + "=" + str(getattr(self,varname)))
if (action == "public_methods"):
publics = [x for x in dir(self) if x[0]!="_"]
for public in publics:
varname = "{}".format(public)
if (callable(getattr(self,varname))==True):
print(varname)
# ========================================================
# === special methods
# ========================================================
def __init__(self, angle=""):
""" Object initialization where angle is the input in any format.
:param angle : An angle in any supported format (cf. help(Angle))
:type angle : string
"""
self._init(angle)
[docs] def __add__(self, angle):
""" Add an angle to an angle.
:param angle : An angle in any supported format (cf. help(Angle))
:type angle : Angle()
:returns: The result of the addition
:rtype: Angle()
:Example:
>>> objangle1 = Angle()
>>> objangle2 = Angle()
>>> objangle1.angle(12.345) ; objangle2.angle("56d28m") ; objangle = objangle1 + objangle2 ; objangle.sexagesimal("D")
12.345
'56d28m'
'68d48m42.00s'
"""
if isinstance(angle, Angle) == False:
angle = Angle(angle)
res = Angle()
if self._computed_rad == 0:
self.rad()
if angle._computed_rad == 0:
angle.rad()
if (self._computed_rad == 1) and (angle._computed_rad == 1):
rad = self._rad + angle._rad
deg = rad * self._r2d
res = Angle(deg)
return res
[docs] def __radd__(self, angle):
""" Right addition an angle to an angle.
"""
return self + angle
[docs] def __iadd__(self, angle):
""" Add an angle to an angle.
"""
return self + angle
[docs] def __sub__(self, angle):
""" Subtract an angle to an angle.
:param angle : An angle in any supported format (cf. help(Angle))
:type angle : Angle()
:returns: The result of the subtraction
:rtype: Angle()
:Example:
>>> objangle1 = Angle()
>>> objangle2 = Angle()
>>> objangle1.angle(12.345) ; objangle2.angle("56d28m") ; objangle = objangle1 - objangle2 ; objangle.sexagesimal("D")
12.345
'56d28m'
'315d52m42.00s'
"""
if isinstance(angle, Angle) == False:
angle = Angle(angle)
res = Angle()
if self._computed_rad == 0:
self.rad()
if angle._computed_rad == 0:
angle.rad()
if (self._computed_rad == 1) and (angle._computed_rad == 1):
rad = self._rad - angle._rad
deg = rad * self._r2d
res = Angle(deg)
return res
[docs] def __rsub__(self, angle):
""" Right subtraction only an angle to an angle.
"""
if isinstance(angle, Angle) == True:
return self - angle
else:
return angle
[docs] def __isub__(self, angle):
""" Subtract an angle to an angle.
:param angle : An angle in any supported format (cf. help(Angle))
:type angle : Angle()
:returns: The result of the subtraction
:rtype: Angle()
:Example:
>>> objangle1 = Angle()
>>> objangle2 = Angle()
>>> objangle1.angle(12.345) ; objangle2.angle("56d28m") ; objangle1 -= objangle2 ; objangle1.sexagesimal("D")
12.345
'56d28m'
'315d52m42.00s'
"""
return self - angle
[docs] def __eq__(self, angle):
""" Comparaison of angles. Return True if angles are defined and equals.
:param angle : An angle in any supported format (cf. help(Angle))
:type angle : Angle()
:returns: The logic result of the comparison.
:rtype: bool
:Example:
>>> objangle1 = Angle()
>>> objangle2 = Angle()
>>> objangle1.angle(12.345) ; objangle2.angle("56d28m") ; objangle1 == objangle2
12.345
'56d28m'
False
.. note:: Does not account for the modulo.
"""
return self._angle_compare(angle, "==")
[docs] def __ne__(self, angle):
""" Comparaison of angles. Return True if angles are defined and not equals.
:param angle : An angle in any supported format (cf. help(Angle))
:type angle : Angle()
:returns: The logic result of the comparison.
:rtype: bool
:Example:
>>> objangle1 = Angle()
>>> objangle2 = Angle()
>>> objangle1.angle(12.345) ; objangle2.angle("56d28m") ; objangle1 != objangle2
12.345
'56d28m'
True
.. note:: Does not account for the modulo.
"""
return self._angle_compare(angle, "!=")
[docs] def __gt__(self, angle):
""" Comparaison of angles. Return True if self > angle
:param angle : An angle in any supported format (cf. help(Angle))
:type angle : Angle()
:returns: The logic result of the comparison.
:rtype: bool
:Example:
>>> objangle1 = Angle()
>>> objangle2 = Angle()
>>> objangle1.angle(12.345) ; objangle2.angle("56d28m") ; objangle1 > objangle2
12.345
'56d28m'
False
.. note:: Does not account for the modulo.
"""
return self._angle_compare(angle,">")
[docs] def __ge__(self, angle):
""" Comparaison of angles. Return True if self >= angle
:param angle : An angle in any supported format (cf. help(Angle))
:type angle : Angle()
:returns: The logic result of the comparison.
:rtype: bool
:Example:
>>> objangle1 = Angle()
>>> objangle2 = Angle()
>>> objangle1.angle(12.345) ; objangle2.angle("56d28m") ; objangle1 >= objangle2
12.345
'56d28m'
False
.. note:: Does not account for the modulo.
"""
return self._angle_compare(angle,">=")
[docs] def __lt__(self, angle):
""" Comparaison of angles. Return True if self < angle
:param angle : An angle in any supported format (cf. help(Angle))
:type angle : Angle()
:returns: The logic result of the comparison.
:rtype: bool
:Example:
>>> objangle1 = Angle()
>>> objangle2 = Angle()
>>> objangle1.angle(12.345) ; objangle2.angle("56d28m") ; objangle1 < objangle2
12.345
'56d28m'
True
.. note:: Does not account for the modulo.
"""
return self._angle_compare(angle,"<")
[docs] def __le__(self, angle):
""" Comparaison of angles. Return True if self <= angle
:param angle : An angle in any supported format (cf. help(Angle))
:type angle : Angle()
:returns: The logic result of the comparison.
:rtype: bool
:Example:
>>> objangle1 = Angle()
>>> objangle2 = Angle()
>>> objangle1.angle(12.345) ; objangle2.angle("56d28m") ; objangle1 <= objangle2
12.345
'56d28m'
True
.. note:: Does not account for the modulo.
"""
return self._angle_compare(angle,"<=")
[docs] def __mod__(self, angle):
""" Modulo of an angle by another angle. Return an angle
:param angle : An angle in any supported format (cf. help(Angle))
:type angle : Angle()
:returns: An angle
:rtype: Angle()
:Example:
>>> objangle1 = Angle()
>>> objangle2 = Angle()
>>> objangle1.angle(30.56) ; objangle2.angle(2.34) ; (objangle1 % objangle2).deg()
30.56
2.34
0.14000000000000412
"""
if isinstance(angle, Angle) == False:
angle = Angle(angle)
if self._computed_deg == 0:
self.deg()
if angle._computed_deg == 0:
angle.deg()
anglemod = Angle()
if (self._computed_deg == 1) and (angle._computed_deg == 1):
deg = math.fmod(self._deg, angle._deg)
if (deg<0):
deg += angle._deg
anglemod.angle(deg)
return anglemod
[docs] def __mul__(self, multiplier):
""" multiplication of an angle by a float or int. Return an angle
:param multiplier: A real number
:type multiplier: float
:returns: An angle
:rtype: Angle()
:Example:
>>> objangle = Angle()
>>> objangle.angle(30.43) ; (objangle*2).deg()
30.43
60.86000000000001
"""
if isinstance(multiplier, (int, float)) == False:
raise TypeError
return ""
if self._computed_deg == 0:
self.deg()
anglemult = Angle()
if (self._computed_deg == 1):
deg = self._deg * multiplier
anglemult.angle(deg)
return anglemult
[docs] def __rmul__(self, multiplier):
""" Right multiplication of an angle by a float or int.
"""
return self * multiplier
[docs] def __truediv__(self, divisor):
""" division of an angle by a float or int. Return an angle
:param divisor: A real number
:type divisor: float
:returns: An angle
:rtype: Angle()
:Example:
>>> objangle = Angle()
>>> objangle.angle(30.43) ; (objangle/2).deg()
30.43
15.215000000000002
"""
if isinstance(divisor, (int, float)) == False:
raise TypeError
return ""
if (divisor==0):
raise ZeroDivisionError
if self._computed_deg == 0:
self.deg()
anglediv = Angle()
if (self._computed_deg == 1):
deg = self._deg / divisor
anglediv.angle(deg)
return anglediv
# ========================================================
# ========================================================
# ========================================================