Code source de ensae_teaching_cs.special.geometry_point

"""
Defines a point in N-dimension


:githublink:`%|py|5`
"""

import math


[docs]class GeometryException(Exception): """ raises when an issue arises with class GeometryPoint :githublink:`%|py|12` """ pass
[docs]class GeometryPoint: """ one point :githublink:`%|py|19` """ __slots__ = ["_x"]
[docs] def __init__(self, *x): """ :param x: is a vector :githublink:`%|py|25` """ if isinstance(x, (tuple, list)): if len(x) == 0: raise ValueError("empty dimension") if isinstance(x[0], GeometryPoint) and len(x) == 1: self._x = x[0]._x else: self._x = tuple(x) else: raise TypeError("Unexpected type %r." % type(x))
[docs] def __eq__(self, x): """ is equal :githublink:`%|py|39` """ return self._x == x
[docs] def __neq__(self, x): """ is different :githublink:`%|py|45` """ return not self.__eq__(x)
[docs] def __len__(self): """ returns the dimension :githublink:`%|py|51` """ return len(self._x)
[docs] def __str__(self): """ converts into string :githublink:`%|py|57` """ if len(self) == 2: s = "({0},{1})".format(*self._x) return s.replace(".000000", "") format = ", ".join(["{}" for _ in self._x]) t = format.format(*self._x) s = "(%s)" % t return s.replace(".000000", "")
[docs] def __repr__(self): """ ``eval(__repr__)`` should return the same object :githublink:`%|py|70` """ return "GeometryPoint(%s)" % ", ".join(str(_) for _ in self._x)
[docs] def __iadd__(self, x): """ addition :githublink:`%|py|76` """ if len(self) != len(x): raise GeometryException("dimension problem %d != %d" % (len(self), len(x))) if len(self) == 2: self._x = (self._x[0] + x._x[0], self._x[1] + x._x[1]) else: self._x = tuple(a + b for a, b in zip(self._x, x._x)) return self
[docs] def __add__(self, x): """ addition :githublink:`%|py|89` """ if len(self) != len(x): raise GeometryException("dimension problem %d != %d" % (len(self), len(x))) if len(self) == 2: return GeometryPoint(self._x[0] + x._x[0], self._x[1] + x._x[1]) else: return GeometryPoint(a + b for a, b in zip(self._x, x._x))
[docs] def __sub__(self, x): """ substraction :githublink:`%|py|101` """ if len(self) != len(x): raise GeometryException("dimension problem %d != %d" % (len(self), len(x))) if len(self) == 2: return GeometryPoint(self._x[0] - x._x[0], self._x[1] - x._x[1]) return GeometryPoint(a - b for a, b in zip(self._x, x._x))
[docs] def __imul__(self, k): """ multiplication by a scalar :githublink:`%|py|112` """ if len(self) == 2: self._x = (self._x[0] * k, self._x[1] * k) else: self._x = tuple(_ * k for _ in self._x) return self
[docs] def __mul__(self, k): """ multiplication by a scalar :githublink:`%|py|122` """ if len(self) == 2: return GeometryPoint(self._x[0] * k, self._x[1] * k) else: return GeometryPoint(_ * k for _ in self._x)
[docs] def scalar(self, x): """ scalar product :githublink:`%|py|131` """ if len(self) != len(x): raise GeometryException("dimension problem %d != %d\n%s ? %s" % (len(self), len(x), str(self), str(x))) r = 0. for a, b in zip(self._x, x._x): r += a * b return r
[docs] def __cmp__(self, x): """ comparison :githublink:`%|py|143` """ if len(self) != len(x): raise GeometryException("dimension problem %d != %d" % (len(self), len(x))) for a, b in zip(self._x, x._x): t = -1 if a < b else (0 if a == b else 1) if t != 0: return t return 0
[docs] def __lt__(self, x): """ inferior :githublink:`%|py|156` """ return self.__cmp__(x) == -1
[docs] def product(self, x): """ vectoriel product, dimension 2 only :githublink:`%|py|162` """ if len(self) != 2: raise GeometryException( "this function only exists if len(self) == 2") return self._x[1] * x._x[0] - self._x[0] * x._x[1]
[docs] def cossin(self): """ return the cos, sin of a vector (dimension 2 only) :githublink:`%|py|172` """ n = self.norm2() if n == 0.: return 1., 0. n = n ** 0.5 p = GeometryPoint(1., 0.) cos = self.scalar(p) / n sin = self.product(p) / n return cos, sin
[docs] def norm2(self): """ return the norm :githublink:`%|py|185` """ return self.scalar(self)
[docs] def angle(self): """ return the angle :githublink:`%|py|191` """ cos, sin = self.cossin() if cos == 0: if sin == 0: return 0 elif sin > 0: return math.pi / 2 else: return -math.pi / 2 else: t = sin / cos a = math.atan(t) if cos < 0: return a - math.pi else: return a