diff options
author | notoraptor <stevenbocco@gmail.com> | 2019-08-14 12:22:22 -0400 |
---|---|---|
committer | Philip Paquette <pcpaquette@gmail.com> | 2019-08-14 12:40:01 -0400 |
commit | 5c3bd9b3802e2001a7e77baf2911386135a03839 (patch) | |
tree | e641744650b05cddc85bc60c2d7e2d6fe2d88b47 /diplomacy/utils/equilateral_triangle.py | |
parent | 5acb4ff23be4757a49b234f93928f13c436b60c6 (diff) |
[Web] Integrated new maps on the web interface
- Fixed bug with incorrect dislodged unit on pure map
- [python] Make sure dummy powers are registered only for standard maps.
- Hardcoded supply centers into SVG files.
- Removed supply centers CSS classes.
- Update positions for units and dislodged units on all maps.
- Converted SVGs to React.
- Removed "sym" classes and hardcode related styles into symbol definitions.
- Reordered map list (standard at top, then other ones in alphabetical order)
- Displayed + button for all maps and disable it for maps without variants.
- Minified generated code when converting SVG files to React.
- [web] Added ability to hide/display map abbreviations.
Diffstat (limited to 'diplomacy/utils/equilateral_triangle.py')
-rw-r--r-- | diplomacy/utils/equilateral_triangle.py | 173 |
1 files changed, 173 insertions, 0 deletions
diff --git a/diplomacy/utils/equilateral_triangle.py b/diplomacy/utils/equilateral_triangle.py new file mode 100644 index 0000000..d31fe79 --- /dev/null +++ b/diplomacy/utils/equilateral_triangle.py @@ -0,0 +1,173 @@ +# ============================================================================== +# Copyright (C) 2019 - Philip Paquette, Steven Bocco +# +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU Affero General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# This program 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 Affero General Public License for more +# details. +# +# You should have received a copy of the GNU Affero General Public License along +# with this program. If not, see <https://www.gnu.org/licenses/>. +# ============================================================================== +# pylint: disable=anomalous-backslash-in-string +""" Helper class to compute intersection of a line (OM) with a side of an equilateral triangle, + with O the barycenter of the equilateral triangle and M a point outside the triangle. + A + / | M + / O | + C /______| B + + A = top, B = right, C = left + O = center of triangle + M = point outside of triangle +""" +class EquilateralTriangle: + """ Helper class that represent an equilateral triangle. + Used to compute intersection of a line with a side of convoy symbol, which is an equilateral triangle. + """ + __slots__ = ('x_a', 'y_a', 'x_b', 'y_b', 'x_c', 'y_c', 'x_o', 'y_o', 'height', + 'line_ab_a', 'line_ab_b', 'line_ac_a', 'line_ac_b') + + def __init__(self, x_top, y_top, x_right, y_right, x_left, y_left): + """ Constructor """ + assert y_left == y_right > y_top + assert x_left < x_top < x_right + self.x_a = x_top + self.y_a = y_top + self.x_b = x_right + self.y_b = y_right + self.x_c = x_left + self.y_c = y_left + self.height = self.y_b - self.y_a + self.x_o = self.x_a + self.y_o = self.y_a + 2 * self.height / 3 + self.line_ab_a = (self.y_b - self.y_a) / (self.x_b - self.x_a) + self.line_ab_b = self.y_b - self.x_b * self.line_ab_a + self.line_ac_a = (self.y_c - self.y_a) / (self.x_c - self.x_a) + self.line_ac_b = self.y_c - self.x_c * self.line_ac_a + + def __line_om(self, x_m, y_m): + """ Returns the slope and the intersect of the line between O and M + :return: a, b - respectively the slope and the intercept of the line OM + """ + # pylint:disable=invalid-name + a = (y_m - self.y_o) / (x_m - self.x_o) + b = y_m - a * x_m + return a, b + + def _intersection_with_ab(self, x_m, y_m): + """ Return coordinates of intersection of line (OM) with line (AB). + :param x_m: x coordinate of M + :param y_m: y coordinate of M + :return: coordinates (x, y) of intersection, or (None, None) if either + (OM) and (AB) don't intersect, or intersection point is not in segment AB. + """ + # pylint:disable=invalid-name + a, b = self.line_ab_a, self.line_ab_b + if x_m == self.x_o: + # (OM) is a vertical line + x = x_m + else: + u, v = self.__line_om(x_m, y_m) + if a == u: + # (OM) and (AB) are parallel. No intersection. + return None, None + x = (v - b) / (a - u) + y = a * x + b + if self.x_a <= x <= self.x_b and self.y_a <= y <= self.y_b: + return x, y + return None, None + + def _intersection_with_ac(self, x_m, y_m): + """ Return coordinates of intersection of line (OM) with line (AC). + :param x_m: x coordinate of M + :param y_m: y coordinate of M + :return: coordinates (x, y) of intersection, or (None, None) if either + (OM) and (AC) don't intersect, or intersection point is not in segment AC. + """ + # pylint:disable=invalid-name + a, b = self.line_ac_a, self.line_ac_b + if x_m == self.x_o: + x = x_m + else: + u, v = self.__line_om(x_m, y_m) + if a == u: + return None, None + x = (v - b) / (a - u) + y = a * x + b + if self.x_c <= x <= self.x_a and self.y_a <= y <= self.y_c: + return x, y + return None, None + + def _intersection_with_bc(self, x_m, y_m): + """ Return coordinates of intersection of line (OM) with line (BC). + NB: (BC) is an horizontal line. + :param x_m: x coordinate of M + :param y_m: y coordinate of M + :return: coordinates (x, y) of intersection, or (None, None) if either + (OM) and (BC) don't intersect, or intersection point is not in segment BC. + """ + # pylint:disable=invalid-name + y = self.y_c + if x_m == self.x_o: + x = x_m + else: + a, b = self.__line_om(x_m, y_m) + if a == 0: + return None, None + x = (y - b) / a + if self.x_c <= x <= self.x_a: + return x, y + return None, None + + def intersection(self, x_m, y_m): + """ Return coordinates of the intersection of (OM) with equilateral triangle, + with M the point with coordinates (x_m, y_m). Only the intersection with + the side of triangle near M is considered. + :param x_m: x coordinate of M + :param y_m: y coordinate of M + :return: a couple (x, y) of floating values. + """ + # pylint:disable=invalid-name + if self.x_o == x_m and self.y_o == y_m: + return x_m, y_m + + if self.x_o == x_m: + if y_m < self.y_o: + return x_m, self.y_a + # Otherwise, vertical line intersects BC + return x_m, self.y_c + + if self.y_o == y_m: + if x_m < self.x_o: + # horizontal line intersects AC + a, b = self.line_ac_a, self.line_ac_b + else: + # horizontal line intersects AB + a, b = self.line_ab_a, self.line_ab_b + x = (y_m - b) / a + return x, y_m + + # Otherwise, get nearest point in intersections with AB, AC, BC + p1_x, p1_y = self._intersection_with_ab(x_m, y_m) + p2_x, p2_y = self._intersection_with_ac(x_m, y_m) + p3_x, p3_y = self._intersection_with_bc(x_m, y_m) + distances = [] + if p1_x is not None: + distance_1 = ((p1_x - x_m) ** 2 + (p1_y - y_m) ** 2) ** 0.5 + distances.append((distance_1, p1_x, p1_y)) + if p2_x is not None: + distance_2 = ((p2_x - x_m) ** 2 + (p2_y - y_m) ** 2) ** 0.5 + distances.append((distance_2, p2_x, p2_y)) + if p3_x is not None: + distance_3 = ((p3_x - x_m) ** 2 + (p3_y - y_m) ** 2) ** 0.5 + distances.append((distance_3, p3_x, p3_y)) + + assert distances + distances.sort() + return distances[0][1:] |