# Coverage for src/ensae_teaching_cs/special/geometry_point.py: 63%

## 102 statements

, created at 2023-01-27 05:44 +0100

1"""

2@file

3@brief Defines a point in N-dimension

4"""

6import math

9class GeometryException(Exception):

10 """

11 raises when an issue arises with class GeometryPoint

12 """

13 pass

16class GeometryPoint:

17 """

18 one point

19 """

20 __slots__ = ["_x"]

22 def __init__(self, *x):

23 """

24 @param x is a vector

25 """

26 if isinstance(x, (tuple, list)):

27 if len(x) == 0:

28 raise ValueError("empty dimension")

29 if isinstance(x[0], GeometryPoint) and len(x) == 1:

30 self._x = x[0]._x

31 else:

32 self._x = tuple(x)

33 else:

34 raise TypeError(f"Unexpected type {type(x)!r}.")

36 def __eq__(self, x):

37 """

38 is equal

39 """

40 return self._x == x

42 def __neq__(self, x):

43 """

44 is different

45 """

46 return not self.__eq__(x)

48 def __len__(self):

49 """

50 returns the dimension

51 """

52 return len(self._x)

54 def __str__(self):

55 """

56 converts into string

57 """

58 if len(self) == 2:

59 s = "({0},{1})".format(*self._x)

60 return s.replace(".000000", "")

62 format = ", ".join(["{}" for _ in self._x])

63 t = format.format(*self._x)

64 s = f"({t})"

65 return s.replace(".000000", "")

67 def __repr__(self):

68 """

69 ``eval(__repr__)`` should return the same object

70 """

71 return f"GeometryPoint({', '.join(str(_) for _ in self._x)})"

74 """

76 """

77 if len(self) != len(x):

78 raise GeometryException(

79 f"dimension problem {len(self)} != {len(x)}")

80 if len(self) == 2:

81 self._x = (self._x[0] + x._x[0], self._x[1] + x._x[1])

82 else:

83 self._x = tuple(a + b for a, b in zip(self._x, x._x))

84 return self

87 """

89 """

90 if len(self) != len(x):

91 raise GeometryException(

92 f"dimension problem {len(self)} != {len(x)}")

93 if len(self) == 2:

94 return GeometryPoint(self._x[0] + x._x[0], self._x[1] + x._x[1])

95 else:

96 return GeometryPoint(a + b for a, b in zip(self._x, x._x))

98 def __sub__(self, x):

99 """

100 substraction

101 """

102 if len(self) != len(x):

103 raise GeometryException(

104 f"dimension problem {len(self)} != {len(x)}")

105 if len(self) == 2:

106 return GeometryPoint(self._x[0] - x._x[0], self._x[1] - x._x[1])

107 return GeometryPoint(a - b for a, b in zip(self._x, x._x))

109 def __imul__(self, k):

110 """

111 multiplication by a scalar

112 """

113 if len(self) == 2:

114 self._x = (self._x[0] * k, self._x[1] * k)

115 else:

116 self._x = tuple(_ * k for _ in self._x)

117 return self

119 def __mul__(self, k):

120 """

121 multiplication by a scalar

122 """

123 if len(self) == 2:

124 return GeometryPoint(self._x[0] * k, self._x[1] * k)

125 else:

126 return GeometryPoint(_ * k for _ in self._x)

128 def scalar(self, x):

129 """

130 scalar product

131 """

132 if len(self) != len(x):

133 raise GeometryException("dimension problem %d != %d\n%s ? %s" % (len(self), len(x),

134 str(self), str(x)))

135 r = 0.

136 for a, b in zip(self._x, x._x):

137 r += a * b

138 return r

140 def __cmp__(self, x):

141 """

142 comparison

143 """

144 if len(self) != len(x):

145 raise GeometryException(

146 f"dimension problem {len(self)} != {len(x)}")

147 for a, b in zip(self._x, x._x):

148 t = -1 if a < b else (0 if a == b else 1)

149 if t != 0:

150 return t

151 return 0

153 def __lt__(self, x):

154 """

155 inferior

156 """

157 return self.__cmp__(x) == -1

159 def product(self, x):

160 """

161 vectoriel product, dimension 2 only

162 """

163 if len(self) != 2:

164 raise GeometryException(

165 "this function only exists if len(self) == 2")

167 return self._x[1] * x._x[0] - self._x[0] * x._x[1]

169 def cossin(self):

170 """

171 return the cos, sin of a vector (dimension 2 only)

172 """

173 n = self.norm2()

174 if n == 0.:

175 return 1., 0.

176 n = n ** 0.5

177 p = GeometryPoint(1., 0.)

178 cos = self.scalar(p) / n

179 sin = self.product(p) / n

180 return cos, sin

182 def norm2(self):

183 """

184 return the norm

185 """

186 return self.scalar(self)

188 def angle(self):

189 """

190 return the angle

191 """

192 cos, sin = self.cossin()

193 if cos == 0:

194 if sin == 0:

195 return 0

196 elif sin > 0:

197 return math.pi / 2

198 else:

199 return -math.pi / 2

200 else:

201 t = sin / cos

202 a = math.atan(t)

203 if cos < 0:

204 return a - math.pi

205 else:

206 return a