python_arango_ogm.utils.math_util

  1from dataclasses import dataclass, asdict
  2from enum import Enum
  3from typing import Sequence
  4from .f_range import frange
  5
  6NORMAL_RANGE = frange(0.0, 1.0, upper_inclusive=True)
  7
  8def safe_float(obj) -> bool:
  9  if isinstance(obj, float):
 10    return obj
 11
 12  try:
 13    f = float(obj)
 14  except ValueError as x:
 15    f = 0
 16
 17  return f
 18
 19def clamp(x: float, minval=0.0, maxval=1.0):
 20  return max(min(x, maxval), minval)
 21
 22def clamp_sequence(seq: Sequence, minval=0.0, maxval=1.0):
 23  return [clamp(x, minval, maxval) for x in seq]
 24
 25
 26LerpType = Enum('LerpType', 'Linear Cube RootCube RootSquare Square')
 27
 28def lerp(pct, min, max, lerp_type: LerpType = LerpType.Linear):
 29  if max <= min:
 30    raise ValueError(f"Maximum should be greater than minimum Max:{max}, Min:{min}")
 31
 32  if pct not in NORMAL_RANGE:
 33    raise ValueError(f"Percentage should be between 0.0 and 1.0:  Is {pct}")
 34
 35  return min + pct * (max - min)
 36
 37def delerp(val, min, max, lerp_type: LerpType = LerpType.Linear):
 38  if mag <= min:
 39    raise ValueError(f"Maximum should be greater than minimum Max:{max}, Min:{min}")
 40
 41  if val < min or val > max:
 42    raise ValueError(f"Value should be between minimum and maximum:  Min:{min} <= Value:{val} <= Max:{max}")
 43
 44  return val - min / max - min
 45
 46@dataclass  # (frozen=True)
 47class Vector2d():
 48  """ Attributes for graph """
 49  x: float = 0.0
 50  y: float = 0.0
 51
 52  def __init__(self, obj1=0, obj2=None):
 53    if isinstance(obj1, tuple):
 54      self.x, self.y = obj1
 55    elif isinstance(obj1, Vector2d):
 56      self.x, self.y = other.x, other.y
 57    elif obj1 is not None and obj2 is not None:
 58      self.x, self.y = obj1, obj2
 59
 60  def to_dict(self):
 61    return asdict(self)
 62
 63  def __neg__(self):
 64    return Vector2d(-self.x, -self.y)
 65
 66  def __add__(self, other):
 67    return Vector2d(self.x + other.x, self.y + other.y)
 68
 69  def __sub__(self, other):
 70    return self.__add__(-other)
 71
 72  def __mul__(self, other):
 73    return Vector2d(self.x * other.x, self.y * other.y)
 74
 75  def __truediv__(self, other):
 76    return self.__mul__(-other)
 77
 78  def __iter__(self):
 79    self.iterstate = None
 80    return self
 81
 82  def __next__(self):
 83    state = self.iterstate  # getattr(self, 'state', -1)
 84    result = None
 85    if state == None:
 86      result = self.x
 87      self.iterstate = 'x'
 88    elif state == 'x':
 89      result = self.y
 90      self.iterstate = 'y'
 91    else:
 92      raise StopIteration('No more items (x & y only)')
 93    return result
 94
 95@dataclass
 96class Vector3d(Vector2d):
 97  z: float = 0.0
 98
 99@dataclass
100class Rect2d():
101  origin: Vector2d
102  size: Vector2d
103
104  def __init__(self, a=None, b=None, c=None, d=None):
105    if None not in [a, b, c, d]:
106      self.origin = Vector2d(a, b)
107      self.size = Vector2d(c, d)
108    else:
109      if isinstance(a, Vector2d):
110        self.origin = a
111      elif isinstance(a, tuple):
112        self.origin = Vector2d(a)
113
114      if isinstance(b, Vector2d):
115        self.size = b
116      elif isinstance(a, tuple):
117        self.size = Vector2d(b)
118
119  @property
120  def right(self):
121    return self.origin.x + self.size.x
122
123  @property
124  def bottom(self):
125    return self.origin.y + self.size.y
126
127  def __iter__(self):
128    self.iterstate = 0
129    self.iteritems = [self.origin.x, self.origin.y, self.size.x, self.size.y]
130    return self
131
132  def __next__(self):
133    state = self.iterstate  # getattr(self, 'state', -1)
134    if state > len(self.iteritems) - 1:
135      raise StopIteration('No more items (x,y,w,h) only')
136
137    self.iterstate += 1
138    return self.iteritems[state]
139
140  def __add__(self, other):
141    result = None
142    if isinstance(other, Rect2d):
143      result = Rect2d(self.origin + other.origin, self.size + other.size)
144    elif isinstance(other, Vector2d):
145      result = Rect2d(self.origin + other, self.size + other)
146    return result
147
148  def __sub__(self, other):
149    return self.__add__(other)
150
151  def __mul__(self, other):
152    result = None
153    if isinstance(other, Rect2d):
154      result = Rect2d(self.origin * other.origin, self.size * other.size)
155    elif isinstance(other, Vector2d):
156      result = Rect2d(self.origin * other, self.size * other)
157    return result
158
159  def __truediv__(self, other):
160    return self.__mul__(-other)
161
162  def __neg__(self):
163    return Rect2d(-self.origin, -self.size)
NORMAL_RANGE = <python_arango_ogm.utils.f_range.frange object>
def safe_float(obj) -> bool:
 9def safe_float(obj) -> bool:
10  if isinstance(obj, float):
11    return obj
12
13  try:
14    f = float(obj)
15  except ValueError as x:
16    f = 0
17
18  return f
def clamp(x: float, minval=0.0, maxval=1.0):
20def clamp(x: float, minval=0.0, maxval=1.0):
21  return max(min(x, maxval), minval)
def clamp_sequence(seq: Sequence, minval=0.0, maxval=1.0):
23def clamp_sequence(seq: Sequence, minval=0.0, maxval=1.0):
24  return [clamp(x, minval, maxval) for x in seq]
class LerpType(enum.Enum):

Create a collection of name/value pairs.

Example enumeration:

>>> class Color(Enum):
...     RED = 1
...     BLUE = 2
...     GREEN = 3

Access them by:

  • attribute access:

    >>> Color.RED
    <Color.RED: 1>
    
  • value lookup:

    >>> Color(1)
    <Color.RED: 1>
    
  • name lookup:

    >>> Color['RED']
    <Color.RED: 1>
    

Enumerations can be iterated over, and know how many members they have:

>>> len(Color)
3
>>> list(Color)
[<Color.RED: 1>, <Color.BLUE: 2>, <Color.GREEN: 3>]

Methods can be added to enumerations, and members can have their own attributes -- see the documentation for details.

Linear = <LerpType.Linear: 1>
Cube = <LerpType.Cube: 2>
RootCube = <LerpType.RootCube: 3>
RootSquare = <LerpType.RootSquare: 4>
Square = <LerpType.Square: 5>
Inherited Members
enum.Enum
name
value
def lerp( pct, min, max, lerp_type: LerpType = <LerpType.Linear: 1>):
29def lerp(pct, min, max, lerp_type: LerpType = LerpType.Linear):
30  if max <= min:
31    raise ValueError(f"Maximum should be greater than minimum Max:{max}, Min:{min}")
32
33  if pct not in NORMAL_RANGE:
34    raise ValueError(f"Percentage should be between 0.0 and 1.0:  Is {pct}")
35
36  return min + pct * (max - min)
def delerp( val, min, max, lerp_type: LerpType = <LerpType.Linear: 1>):
38def delerp(val, min, max, lerp_type: LerpType = LerpType.Linear):
39  if mag <= min:
40    raise ValueError(f"Maximum should be greater than minimum Max:{max}, Min:{min}")
41
42  if val < min or val > max:
43    raise ValueError(f"Value should be between minimum and maximum:  Min:{min} <= Value:{val} <= Max:{max}")
44
45  return val - min / max - min
@dataclass
class Vector2d:
47@dataclass  # (frozen=True)
48class Vector2d():
49  """ Attributes for graph """
50  x: float = 0.0
51  y: float = 0.0
52
53  def __init__(self, obj1=0, obj2=None):
54    if isinstance(obj1, tuple):
55      self.x, self.y = obj1
56    elif isinstance(obj1, Vector2d):
57      self.x, self.y = other.x, other.y
58    elif obj1 is not None and obj2 is not None:
59      self.x, self.y = obj1, obj2
60
61  def to_dict(self):
62    return asdict(self)
63
64  def __neg__(self):
65    return Vector2d(-self.x, -self.y)
66
67  def __add__(self, other):
68    return Vector2d(self.x + other.x, self.y + other.y)
69
70  def __sub__(self, other):
71    return self.__add__(-other)
72
73  def __mul__(self, other):
74    return Vector2d(self.x * other.x, self.y * other.y)
75
76  def __truediv__(self, other):
77    return self.__mul__(-other)
78
79  def __iter__(self):
80    self.iterstate = None
81    return self
82
83  def __next__(self):
84    state = self.iterstate  # getattr(self, 'state', -1)
85    result = None
86    if state == None:
87      result = self.x
88      self.iterstate = 'x'
89    elif state == 'x':
90      result = self.y
91      self.iterstate = 'y'
92    else:
93      raise StopIteration('No more items (x & y only)')
94    return result

Attributes for graph

Vector2d(obj1=0, obj2=None)
53  def __init__(self, obj1=0, obj2=None):
54    if isinstance(obj1, tuple):
55      self.x, self.y = obj1
56    elif isinstance(obj1, Vector2d):
57      self.x, self.y = other.x, other.y
58    elif obj1 is not None and obj2 is not None:
59      self.x, self.y = obj1, obj2
x: float = 0.0
y: float = 0.0
def to_dict(self):
61  def to_dict(self):
62    return asdict(self)
@dataclass
class Vector3d(Vector2d):
96@dataclass
97class Vector3d(Vector2d):
98  z: float = 0.0
Vector3d(x: float = 0.0, y: float = 0.0, z: float = 0.0)
z: float = 0.0
Inherited Members
Vector2d
x
y
to_dict
@dataclass
class Rect2d:
100@dataclass
101class Rect2d():
102  origin: Vector2d
103  size: Vector2d
104
105  def __init__(self, a=None, b=None, c=None, d=None):
106    if None not in [a, b, c, d]:
107      self.origin = Vector2d(a, b)
108      self.size = Vector2d(c, d)
109    else:
110      if isinstance(a, Vector2d):
111        self.origin = a
112      elif isinstance(a, tuple):
113        self.origin = Vector2d(a)
114
115      if isinstance(b, Vector2d):
116        self.size = b
117      elif isinstance(a, tuple):
118        self.size = Vector2d(b)
119
120  @property
121  def right(self):
122    return self.origin.x + self.size.x
123
124  @property
125  def bottom(self):
126    return self.origin.y + self.size.y
127
128  def __iter__(self):
129    self.iterstate = 0
130    self.iteritems = [self.origin.x, self.origin.y, self.size.x, self.size.y]
131    return self
132
133  def __next__(self):
134    state = self.iterstate  # getattr(self, 'state', -1)
135    if state > len(self.iteritems) - 1:
136      raise StopIteration('No more items (x,y,w,h) only')
137
138    self.iterstate += 1
139    return self.iteritems[state]
140
141  def __add__(self, other):
142    result = None
143    if isinstance(other, Rect2d):
144      result = Rect2d(self.origin + other.origin, self.size + other.size)
145    elif isinstance(other, Vector2d):
146      result = Rect2d(self.origin + other, self.size + other)
147    return result
148
149  def __sub__(self, other):
150    return self.__add__(other)
151
152  def __mul__(self, other):
153    result = None
154    if isinstance(other, Rect2d):
155      result = Rect2d(self.origin * other.origin, self.size * other.size)
156    elif isinstance(other, Vector2d):
157      result = Rect2d(self.origin * other, self.size * other)
158    return result
159
160  def __truediv__(self, other):
161    return self.__mul__(-other)
162
163  def __neg__(self):
164    return Rect2d(-self.origin, -self.size)
Rect2d(a=None, b=None, c=None, d=None)
105  def __init__(self, a=None, b=None, c=None, d=None):
106    if None not in [a, b, c, d]:
107      self.origin = Vector2d(a, b)
108      self.size = Vector2d(c, d)
109    else:
110      if isinstance(a, Vector2d):
111        self.origin = a
112      elif isinstance(a, tuple):
113        self.origin = Vector2d(a)
114
115      if isinstance(b, Vector2d):
116        self.size = b
117      elif isinstance(a, tuple):
118        self.size = Vector2d(b)
origin: Vector2d
size: Vector2d
right
120  @property
121  def right(self):
122    return self.origin.x + self.size.x
bottom
124  @property
125  def bottom(self):
126    return self.origin.y + self.size.y