Tue, 28 May 2019 19:10:52 +0300
fix LDRAW_ORG parsing
7 | 1 | def degree_rep(angle): |
2 | from math import degrees | |
22 | 3 | return '%.2f°' % degrees(angle) |
7 | 4 | |
5 | def position_vector(vertex): | |
6 | assert isinstance(vertex, Vertex) | |
7 | return Vector(*vertex.coordinates) | |
8 | ||
9 | def angle_magnitude_key(angle): | |
10 | ''' | |
11 | Returns how great an angle is. | |
12 | ''' | |
13 | from math import pi as π | |
14 | normalized_angle = abs(angle) % (2 * π) | |
15 | if normalized_angle > π: | |
16 | normalized_angle = (2 * π) - normalized_angle | |
17 | return normalized_angle | |
18 | ||
0 | 19 | class Vertex: |
20 | def __init__(self, x, y, z): | |
5 | 21 | if not all(is_real(coordinate) for coordinate in (x, y, z)): |
22 | raise ValueError(str.format('Bad vertex coordinates: {!r}', | |
23 | (x, y, z), | |
24 | )) | |
0 | 25 | self.x, self.y, self.z = x, y, z |
26 | def __repr__(self): | |
27 | return str.format('Vertex({!r}, {!r}, {!r})', self.x, self.y, self.z) | |
28 | def distance_to(self, other): | |
29 | # can't use hypot because of 3 arguments | |
30 | from math import sqrt | |
31 | return sqrt( | |
32 | (self.x - other.x) ** 2 + | |
33 | (self.y - other.y) ** 2 + | |
34 | (self.z - other.z) ** 2 | |
35 | ) | |
3
1dc58f44d556
Can now write dat files, added direct color handling
Santeri Piippo
parents:
1
diff
changeset
|
36 | @property |
1dc58f44d556
Can now write dat files, added direct color handling
Santeri Piippo
parents:
1
diff
changeset
|
37 | def coordinates(self): |
1dc58f44d556
Can now write dat files, added direct color handling
Santeri Piippo
parents:
1
diff
changeset
|
38 | return self.x, self.y, self.z |
5 | 39 | def __add__(self, other): |
7 | 40 | assert not (type(self) == type(other) == Vertex) |
41 | if type(self) == Vector and type(other) == Vector: | |
42 | result_type = Vector | |
43 | else: | |
44 | result_type = Vertex | |
45 | return result_type(self.x + other.x, self.y + other.y, self.z + other.z) | |
46 | def __radd__(self, other): | |
47 | return self + other | |
5 | 48 | def __neg__(self): |
6
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
49 | return type(self)(-self.x, -self.y, -self.z) |
5 | 50 | def __sub__(self, other): |
7 | 51 | result = self + (-position_vector(other)) |
52 | if isinstance(other, Vertex): | |
53 | return Vector(*result.coordinates) | |
54 | else: | |
55 | return result | |
5 | 56 | def __mul__(self, scalar): |
7 | 57 | assert is_real(scalar) |
6
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
58 | return type(self)(self.x * scalar, self.y * scalar, self.z * scalar) |
5 | 59 | def __rmul__(self, other): |
60 | return self * other | |
61 | def __truediv__(self, scalar): | |
7 | 62 | assert is_real(scalar) |
6
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
63 | return type(self)(self.x / scalar, self.y / scalar, self.z / scalar) |
5 | 64 | def __floordiv__(self, scalar): |
7 | 65 | assert is_real(scalar) |
6
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
66 | return type(self)(self.x // scalar, self.y // scalar, self.z // scalar) |
5 | 67 | def __matmul__(self, transformation_matrix): |
68 | return transform(self, transformation_matrix) | |
69 | def __eq__(self, other): | |
38
66c9591b733d
added proper handling of syntax errors
Teemu Piippo <teemu@hecknology.net>
parents:
31
diff
changeset
|
70 | return self.is_close(other, threshold = 1.0e-10) |
13 | 71 | def __ne__(self, other): |
72 | return not self.__eq__(other) | |
5 | 73 | def __lt__(self, other): |
74 | return self.coordinates < other.coordinates | |
75 | def __hash__(self): | |
76 | return hash(self.coordinates) | |
38
66c9591b733d
added proper handling of syntax errors
Teemu Piippo <teemu@hecknology.net>
parents:
31
diff
changeset
|
77 | def is_close(self, other, *, threshold = 1.0e-05): |
66c9591b733d
added proper handling of syntax errors
Teemu Piippo <teemu@hecknology.net>
parents:
31
diff
changeset
|
78 | return self.distance_to(other) < threshold |
66c9591b733d
added proper handling of syntax errors
Teemu Piippo <teemu@hecknology.net>
parents:
31
diff
changeset
|
79 | #return all( |
66c9591b733d
added proper handling of syntax errors
Teemu Piippo <teemu@hecknology.net>
parents:
31
diff
changeset
|
80 | # abs(a - b) < threshold |
66c9591b733d
added proper handling of syntax errors
Teemu Piippo <teemu@hecknology.net>
parents:
31
diff
changeset
|
81 | # for a, b in zip(self.coordinates, other.coordinates) |
66c9591b733d
added proper handling of syntax errors
Teemu Piippo <teemu@hecknology.net>
parents:
31
diff
changeset
|
82 | #) |
0 | 83 | |
84 | class LineSegment: | |
85 | def __init__(self, v1, v2): | |
86 | self.v1, self.v2 = v1, v2 | |
87 | def __repr__(self): | |
88 | return str.format('LineSegment({!r}, {!r})', self.v1, self.v2) | |
3
1dc58f44d556
Can now write dat files, added direct color handling
Santeri Piippo
parents:
1
diff
changeset
|
89 | @property |
7 | 90 | def length(self): |
91 | return self.v1.distance_to(self.v2) | |
92 | @property | |
3
1dc58f44d556
Can now write dat files, added direct color handling
Santeri Piippo
parents:
1
diff
changeset
|
93 | def vertices(self): |
1dc58f44d556
Can now write dat files, added direct color handling
Santeri Piippo
parents:
1
diff
changeset
|
94 | return self.v1, self.v2 |
6
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
95 | def __len__(self): |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
96 | return 2 |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
97 | def __getitem__(self, index): |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
98 | return self.vertices[index] |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
99 | |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
100 | class IndexRing: |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
101 | def __init__(self, container): |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
102 | self.container = container |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
103 | def __getitem__(self, index): |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
104 | return self.container[index % len(self.container)] |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
105 | |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
106 | class Vector(Vertex): |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
107 | def __init__(self, x, y, z): |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
108 | super().__init__(x, y, z) |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
109 | def __repr__(self): |
7 | 110 | return str.format('Vector({!r}, {!r}, {!r})', self.x, self.y, self.z) |
6
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
111 | def length(self): |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
112 | from math import sqrt |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
113 | return sqrt(self.x ** 2 + self.y ** 2 + self.z ** 2) |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
114 | def normalized(self): |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
115 | length = self.length() |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
116 | if length > 0: |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
117 | return Vector(self.x / length, self.y / length, self.z / length) |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
118 | else: |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
119 | return Vector(0, 0, 0) |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
120 | |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
121 | def dot_product(v1, v2): |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
122 | ''' Returns the dot product v1 · v2. ''' |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
123 | return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
124 | |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
125 | def cross_product(v1, v2): |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
126 | ''' Returns the cross product v1 × v2. ''' |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
127 | return Vector( |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
128 | x = v1.y * v2.z - v1.z * v2.y, |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
129 | y = v1.z * v2.x - v1.x * v2.z, |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
130 | z = v1.x * v2.y - v1.y * v2.x, |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
131 | ) |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
132 | |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
133 | def unit_normal(a, b, c): |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
134 | x = Matrix3x3([ |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
135 | 1, a.y, a.z, |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
136 | 1, b.y, b.z, |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
137 | 1, c.y, c.z, |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
138 | ]).determinant() |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
139 | y = Matrix3x3([ |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
140 | a.x, 1, a.z, |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
141 | b.x, 1, b.z, |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
142 | c.x, 1, c.z, |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
143 | ]).determinant() |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
144 | z = Matrix3x3([ |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
145 | a.x, a.y, 1, |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
146 | b.x, b.y, 1, |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
147 | c.x, c.y, 1, |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
148 | ]).determinant() |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
149 | return Vector(x, y, z).normalized() |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
150 | |
13 | 151 | class NoIntersection(Exception): |
152 | pass | |
153 | ||
6
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
154 | def pairs(iterable, *, count = 2): |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
155 | ''' |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
156 | Iterates the given iterable and returns tuples containing `count` |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
157 | sequential values in the iterable. |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
158 | |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
159 | Formally, for a vector A with indices 0…n and pair count k, this |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
160 | function yields: |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
161 | (A₀, A₁, …, Aₖ), |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
162 | (A₁, A₂, …, Aₖ₊₁), |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
163 | …, |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
164 | (Aₙ₋₂, Aₙ₋₁, …, Aₖ₋₂), |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
165 | (Aₙ₋₁, A₀, …, Aₖ₋₁). |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
166 | ''' |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
167 | iterable_count = len(iterable) |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
168 | for index in range(iterable_count): |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
169 | yield tuple( |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
170 | iterable[(index + offset) % iterable_count] |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
171 | for offset in range(count) |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
172 | ) |
0 | 173 | |
1 | 174 | class Polygon: |
175 | def __init__(self, vertices): | |
176 | self.vertices = vertices | |
177 | def __repr__(self): | |
178 | return str.format('Polygon({!r})', self.vertices) | |
6
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
179 | def area(self): |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
180 | total = Vector(0, 0, 0) |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
181 | for v1, v2 in pairs(self.vertices): |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
182 | total += cross_product(v1, v2) |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
183 | return dot_product(total, unit_normal(self.vertices[0], self.vertices[1], self.vertices[2])) |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
184 | def centroid(self): |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
185 | ... |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
186 | raise NotImplementedError |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
187 | def __getitem__(self, index): |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
188 | return self.vertices[index % len(self.vertices)] |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
189 | def __len__(self): |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
190 | return len(self.vertices) |
7 | 191 | @property |
192 | def perimeter_lines(self): | |
193 | for v1, v2 in pairs(self.vertices): | |
194 | yield LineSegment(v1, v2) | |
195 | @property | |
12 | 196 | def angles(self): |
197 | from math import acos | |
7 | 198 | for v1, v2, v3 in pairs(self.vertices, count = 3): |
199 | vec1 = (position_vector(v3) - position_vector(v2)).normalized() | |
200 | vec2 = (position_vector(v1) - position_vector(v2)).normalized() | |
201 | cosine = dot_product(vec1, vec2) / vec1.length() / vec2.length() | |
12 | 202 | yield acos(cosine) |
203 | @property | |
204 | def smallest_angle(self): | |
205 | return min( | |
206 | angle_magnitude_key(angle) | |
207 | for angle in self.angles) | |
7 | 208 | @property |
209 | def hairline_ratio(self): | |
210 | lengths = [line.length for line in self.perimeter_lines] | |
211 | return max(lengths) / min(lengths) | |
1 | 212 | |
0 | 213 | def is_real(number): |
214 | return isinstance(number, int) or isinstance(number, float) | |
215 | ||
9
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
216 | def matrix_indices(): |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
217 | ''' |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
218 | Yields index pairs for matrix iteration |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
219 | ''' |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
220 | from itertools import product |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
221 | yield from product(range(3), range(3)) |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
222 | |
6
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
223 | class Matrix3x3: |
0 | 224 | ''' |
225 | A 3×3 matrix forming the top-left portion of a full 4×4 transformation | |
226 | matrix. | |
227 | ''' | |
9
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
228 | class Row: |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
229 | def __init__(self, matrix_ref, i1, i2, i3): |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
230 | self.matrix_ref = matrix_ref |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
231 | self.matrix_indices = i1, i2, i3 |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
232 | def __getitem__(self, row_index): |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
233 | return self.matrix_ref[self.matrix_indices[row_index]] |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
234 | def __setitem__(self, row_index, value): |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
235 | self.matrix_ref[self.matrix_indices[row_index]] = value |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
236 | def __init__(self, values = None): |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
237 | if values is not None: |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
238 | assert(all(is_real(x) for x in values)) |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
239 | assert len(values) == 9 |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
240 | self.values = values |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
241 | else: |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
242 | self.values = [1, 0, 0, 0, 1, 0, 0, 0, 1] |
0 | 243 | def __repr__(self): |
9
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
244 | if self != Matrix3x3(): |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
245 | return str.format('Matrix3x3({!r})', self.values) |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
246 | else: |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
247 | return 'Matrix3x3()' |
0 | 248 | def __getitem__(self, index): |
9
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
249 | if isinstance(index, tuple): |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
250 | assert all(k in [0, 1, 2] for k in index) |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
251 | return self.values[index[0] * 3 + index[1]] |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
252 | else: |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
253 | return Matrix3x3.Row(self, index * 3, index * 3 + 1, index * 3 + 2) |
6
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
254 | def determinant(self): |
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
255 | return sum([ |
9
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
256 | +(self[0, 0] * self[1, 1] * self[2, 2]), |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
257 | +(self[0, 1] * self[1, 2] * self[2, 0]), |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
258 | +(self[0, 2] * self[1, 0] * self[2, 1]), |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
259 | -(self[0, 2] * self[1, 1] * self[2, 0]), |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
260 | -(self[0, 1] * self[1, 0] * self[2, 2]), |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
261 | -(self[0, 0] * self[1, 2] * self[2, 1]), |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
262 | ]) |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
263 | def scaling_vector(self): |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
264 | ''' |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
265 | Extracts scaling factors from this transformation matrix. |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
266 | ''' |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
267 | from math import sqrt |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
268 | return Vector( |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
269 | x = sqrt(self[0, 0] ** 2 + self[1, 0] ** 2 + self[2, 0] ** 2), |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
270 | y = sqrt(self[0, 1] ** 2 + self[1, 1] ** 2 + self[2, 1] ** 2), |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
271 | z = sqrt(self[0, 2] ** 2 + self[1, 2] ** 2 + self[2, 2] ** 2), |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
272 | ) |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
273 | def rotation_component(self): |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
274 | ''' |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
275 | Extracts rotation from this matrix. |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
276 | ''' |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
277 | return self.split()[0] |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
278 | def split(self): |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
279 | ''' |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
280 | Extracts the rotation matrix and scaling vector. |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
281 | ''' |
24 | 282 | vec = self.scaling_vector() |
9
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
283 | return Matrix3x3([ |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
284 | self[i, j] / vec.coordinates[j] |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
285 | for i, j in matrix_indices() |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
286 | ]), vec |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
287 | def contains_scaling(self): |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
288 | ''' |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
289 | Returns whether this matrix contains scaling factors. |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
290 | ''' |
24 | 291 | vec = self.scaling_vector() |
9
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
292 | return abs((vec.x * vec.y * vec.z) - 1) >= 1e-10 |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
293 | def contains_rotation(self): |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
294 | ''' |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
295 | Returns whether this matrix contains rotation factors. |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
296 | ''' |
24 | 297 | return self.rotation_component() != Matrix3x3() |
9
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
298 | def __eq__(self, other): |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
299 | ''' |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
300 | Returns whether two matrices are equivalent. |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
301 | ''' |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
302 | return all( |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
303 | abs(self[(i, j)] - other[(i, j)]) < 1e-10 |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
304 | for i, j in matrix_indices() |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
305 | ) |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
306 | def __matmul__(self, other): |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
307 | ''' |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
308 | Computes the matrix multiplication self × other. |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
309 | ''' |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
310 | return Matrix3x3([ |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
311 | sum(self[i, k] * other[k, j] for k in range(3)) |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
312 | for i, j in matrix_indices() |
6
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
5
diff
changeset
|
313 | ]) |
14
d383f319f35b
transform_to_xy implemented and concave test online
Santeri Piippo
parents:
13
diff
changeset
|
314 | def __add__(self, other): |
d383f319f35b
transform_to_xy implemented and concave test online
Santeri Piippo
parents:
13
diff
changeset
|
315 | return Matrix3x3([ |
d383f319f35b
transform_to_xy implemented and concave test online
Santeri Piippo
parents:
13
diff
changeset
|
316 | a + b |
d383f319f35b
transform_to_xy implemented and concave test online
Santeri Piippo
parents:
13
diff
changeset
|
317 | for a, b in zip(self.values, other.values) |
d383f319f35b
transform_to_xy implemented and concave test online
Santeri Piippo
parents:
13
diff
changeset
|
318 | ]) |
d383f319f35b
transform_to_xy implemented and concave test online
Santeri Piippo
parents:
13
diff
changeset
|
319 | def __mul__(self, scalar): |
d383f319f35b
transform_to_xy implemented and concave test online
Santeri Piippo
parents:
13
diff
changeset
|
320 | return Matrix3x3([ |
d383f319f35b
transform_to_xy implemented and concave test online
Santeri Piippo
parents:
13
diff
changeset
|
321 | x * scalar |
d383f319f35b
transform_to_xy implemented and concave test online
Santeri Piippo
parents:
13
diff
changeset
|
322 | for x in self.values |
d383f319f35b
transform_to_xy implemented and concave test online
Santeri Piippo
parents:
13
diff
changeset
|
323 | ]) |
0 | 324 | |
325 | def complete_matrix(matrix, anchor): | |
326 | ''' | |
327 | Combines a 3×3 matrix and an anchor vertex into a full 4×4 | |
328 | transformation matrix. | |
329 | ''' | |
330 | return [ | |
9
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
331 | matrix[0, 0], matrix[0, 1], matrix[0, 2], anchor.x, |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
332 | matrix[1, 0], matrix[1, 1], matrix[1, 2], anchor.y, |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
333 | matrix[2, 0], matrix[2, 1], matrix[2, 2], anchor.z, |
0 | 334 | 0, 0, 0, 1, |
335 | ] | |
336 | ||
337 | def transform(vertex, transformation_matrix): | |
338 | ''' | |
339 | Transforms a vertex by a 4×4 transformation matrix. | |
340 | ''' | |
9
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
341 | return Vertex( |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
342 | x = transformation_matrix[0] * vertex.x \ |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
343 | + transformation_matrix[1] * vertex.y \ |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
344 | + transformation_matrix[2] * vertex.z \ |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
345 | + transformation_matrix[3], |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
346 | y = transformation_matrix[4] * vertex.x \ |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
347 | + transformation_matrix[5] * vertex.y \ |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
348 | + transformation_matrix[6] * vertex.z \ |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
349 | + transformation_matrix[7], |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
350 | z = transformation_matrix[8] * vertex.x \ |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
351 | + transformation_matrix[9] * vertex.y \ |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
352 | + transformation_matrix[10] * vertex.z \ |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
353 | + transformation_matrix[11], |
fea8e9ae6f29
Added matrix code, moved library paths to ldcheck.cfg.
Santeri Piippo
parents:
7
diff
changeset
|
354 | ) |
14
d383f319f35b
transform_to_xy implemented and concave test online
Santeri Piippo
parents:
13
diff
changeset
|
355 | |
d383f319f35b
transform_to_xy implemented and concave test online
Santeri Piippo
parents:
13
diff
changeset
|
356 | def transform_to_xy(polygon): |
d383f319f35b
transform_to_xy implemented and concave test online
Santeri Piippo
parents:
13
diff
changeset
|
357 | ''' |
d383f319f35b
transform_to_xy implemented and concave test online
Santeri Piippo
parents:
13
diff
changeset
|
358 | Transforms the provided polygon into the XY plane. The polygon is |
d383f319f35b
transform_to_xy implemented and concave test online
Santeri Piippo
parents:
13
diff
changeset
|
359 | assumed to be planar. |
d383f319f35b
transform_to_xy implemented and concave test online
Santeri Piippo
parents:
13
diff
changeset
|
360 | |
d383f319f35b
transform_to_xy implemented and concave test online
Santeri Piippo
parents:
13
diff
changeset
|
361 | Implementation is based on this StackOverflow answer: |
d383f319f35b
transform_to_xy implemented and concave test online
Santeri Piippo
parents:
13
diff
changeset
|
362 | https://math.stackexchange.com/a/476311 |
d383f319f35b
transform_to_xy implemented and concave test online
Santeri Piippo
parents:
13
diff
changeset
|
363 | ''' |
d383f319f35b
transform_to_xy implemented and concave test online
Santeri Piippo
parents:
13
diff
changeset
|
364 | v1, v2, v3 = polygon.vertices[:3] |
d383f319f35b
transform_to_xy implemented and concave test online
Santeri Piippo
parents:
13
diff
changeset
|
365 | a, b = v3 - v2, v1 - v2 |
d383f319f35b
transform_to_xy implemented and concave test online
Santeri Piippo
parents:
13
diff
changeset
|
366 | normal = cross_product(a, b).normalized() |
d383f319f35b
transform_to_xy implemented and concave test online
Santeri Piippo
parents:
13
diff
changeset
|
367 | v_matrix = Matrix3x3([ |
15 | 368 | 0, 0, -normal.x, |
369 | 0, 0, -normal.y, | |
370 | normal.x, normal.y, 0, | |
14
d383f319f35b
transform_to_xy implemented and concave test online
Santeri Piippo
parents:
13
diff
changeset
|
371 | ]) |
d383f319f35b
transform_to_xy implemented and concave test online
Santeri Piippo
parents:
13
diff
changeset
|
372 | try: |
d383f319f35b
transform_to_xy implemented and concave test online
Santeri Piippo
parents:
13
diff
changeset
|
373 | rotation_matrix = Matrix3x3() |
d383f319f35b
transform_to_xy implemented and concave test online
Santeri Piippo
parents:
13
diff
changeset
|
374 | rotation_matrix += v_matrix |
15 | 375 | rotation_matrix += (v_matrix @ v_matrix) * (1 / (1 + normal.z)) |
14
d383f319f35b
transform_to_xy implemented and concave test online
Santeri Piippo
parents:
13
diff
changeset
|
376 | except ZeroDivisionError: |
d383f319f35b
transform_to_xy implemented and concave test online
Santeri Piippo
parents:
13
diff
changeset
|
377 | rotation_matrix = Matrix3x3() |
d383f319f35b
transform_to_xy implemented and concave test online
Santeri Piippo
parents:
13
diff
changeset
|
378 | full_matrix = complete_matrix(rotation_matrix, Vertex(0, 0, 0)) |
d383f319f35b
transform_to_xy implemented and concave test online
Santeri Piippo
parents:
13
diff
changeset
|
379 | return Polygon([ |
d383f319f35b
transform_to_xy implemented and concave test online
Santeri Piippo
parents:
13
diff
changeset
|
380 | transform(vertex = vertex, transformation_matrix = full_matrix) |
d383f319f35b
transform_to_xy implemented and concave test online
Santeri Piippo
parents:
13
diff
changeset
|
381 | for vertex in polygon.vertices |
d383f319f35b
transform_to_xy implemented and concave test online
Santeri Piippo
parents:
13
diff
changeset
|
382 | ]) |
d383f319f35b
transform_to_xy implemented and concave test online
Santeri Piippo
parents:
13
diff
changeset
|
383 | |
d383f319f35b
transform_to_xy implemented and concave test online
Santeri Piippo
parents:
13
diff
changeset
|
384 | def vector_angle(vec_1, vec_2, normalized = False): |
d383f319f35b
transform_to_xy implemented and concave test online
Santeri Piippo
parents:
13
diff
changeset
|
385 | from math import acos, pi as π |
d383f319f35b
transform_to_xy implemented and concave test online
Santeri Piippo
parents:
13
diff
changeset
|
386 | cosine = dot_product(vec_1, vec_2) |
d383f319f35b
transform_to_xy implemented and concave test online
Santeri Piippo
parents:
13
diff
changeset
|
387 | try: |
d383f319f35b
transform_to_xy implemented and concave test online
Santeri Piippo
parents:
13
diff
changeset
|
388 | cosine /= vec_1.length() * vec_2.length() |
d383f319f35b
transform_to_xy implemented and concave test online
Santeri Piippo
parents:
13
diff
changeset
|
389 | except ZeroDivisionError: |
d383f319f35b
transform_to_xy implemented and concave test online
Santeri Piippo
parents:
13
diff
changeset
|
390 | return 0 |
31 | 391 | # Fix the cosine, it can go outside bounds due to rounding errors, |
392 | # e.g. 1.0000000000000002, which then causes a math domain error. | |
393 | cosine = min(max(-1, cosine), 1) | |
14
d383f319f35b
transform_to_xy implemented and concave test online
Santeri Piippo
parents:
13
diff
changeset
|
394 | angle = acos(cosine) |
d383f319f35b
transform_to_xy implemented and concave test online
Santeri Piippo
parents:
13
diff
changeset
|
395 | if normalized and angle > π / 2: |
d383f319f35b
transform_to_xy implemented and concave test online
Santeri Piippo
parents:
13
diff
changeset
|
396 | angle = π - angle |
d383f319f35b
transform_to_xy implemented and concave test online
Santeri Piippo
parents:
13
diff
changeset
|
397 | return angle |
d383f319f35b
transform_to_xy implemented and concave test online
Santeri Piippo
parents:
13
diff
changeset
|
398 | |
d383f319f35b
transform_to_xy implemented and concave test online
Santeri Piippo
parents:
13
diff
changeset
|
399 | def split_quadrilateral(polygon): |
d383f319f35b
transform_to_xy implemented and concave test online
Santeri Piippo
parents:
13
diff
changeset
|
400 | assert(len(polygon.vertices) == 4) |
d383f319f35b
transform_to_xy implemented and concave test online
Santeri Piippo
parents:
13
diff
changeset
|
401 | vertices = IndexRing(polygon.vertices) |
d383f319f35b
transform_to_xy implemented and concave test online
Santeri Piippo
parents:
13
diff
changeset
|
402 | for i in (0, 1): |
d383f319f35b
transform_to_xy implemented and concave test online
Santeri Piippo
parents:
13
diff
changeset
|
403 | a, b = vertices[0 + i], vertices[1 + i] |
d383f319f35b
transform_to_xy implemented and concave test online
Santeri Piippo
parents:
13
diff
changeset
|
404 | c, d = vertices[2 + i], vertices[3 + i] |
d383f319f35b
transform_to_xy implemented and concave test online
Santeri Piippo
parents:
13
diff
changeset
|
405 | yield Polygon([a, b, c]), Polygon([b, c, d]) |
d383f319f35b
transform_to_xy implemented and concave test online
Santeri Piippo
parents:
13
diff
changeset
|
406 | |
d383f319f35b
transform_to_xy implemented and concave test online
Santeri Piippo
parents:
13
diff
changeset
|
407 | def triangle_plane_normal(polygon): |
d383f319f35b
transform_to_xy implemented and concave test online
Santeri Piippo
parents:
13
diff
changeset
|
408 | assert(len(polygon.vertices) == 3) |
d383f319f35b
transform_to_xy implemented and concave test online
Santeri Piippo
parents:
13
diff
changeset
|
409 | a, b, c = polygon.vertices[:3] |
d383f319f35b
transform_to_xy implemented and concave test online
Santeri Piippo
parents:
13
diff
changeset
|
410 | return cross_product(b - a, b - c) |
28 | 411 | |
412 | def line_intersection_xy(line_1, line_2): | |
413 | ''' | |
414 | Computes 2D line intersection. Can return a point outside the given | |
415 | segments. Z is ignored. | |
416 | ''' | |
417 | a, b = line_1.vertices | |
418 | c, d = line_2.vertices | |
419 | denominator = (a.x - b.x) * (c.y - d.y) - (a.y - b.y) * (c.x - d.x) | |
420 | x = (c.x - d.x) * (a.x * b.y - a.y * b.x) | |
421 | x -= (a.x - b.x) * (c.x * d.y - c.y * d.x) | |
422 | y = (c.y - d.y) * (a.x * b.y - a.y * b.x) | |
423 | y -= (a.y - b.y) * (c.x * d.y - c.y * d.x) | |
424 | try: | |
425 | x /= denominator | |
426 | y /= denominator | |
427 | except ZeroDivisionError: | |
428 | return None | |
429 | else: | |
430 | return Vertex(x, y, 0) | |
431 | ||
432 | def line_segment_intersection_xy(line_1, line_2): | |
433 | ''' | |
434 | Computes 2D line intersection. Only returns a result if it falls | |
435 | inside the line segments. Z is ignored. | |
436 | ''' | |
437 | from math import inf | |
438 | intersection = line_intersection_xy(line_1, line_2) | |
439 | if intersection: | |
440 | a, b = line_1.vertices | |
441 | c, d = line_2.vertices | |
442 | try: | |
30
0d9ca37901ed
added test for collinearity, fixed bowtie test
Santeri Piippo
parents:
28
diff
changeset
|
443 | t1 = (intersection.x - a.x) / (b.x - a.x) |
28 | 444 | except ZeroDivisionError: |
30
0d9ca37901ed
added test for collinearity, fixed bowtie test
Santeri Piippo
parents:
28
diff
changeset
|
445 | t1 = inf |
0d9ca37901ed
added test for collinearity, fixed bowtie test
Santeri Piippo
parents:
28
diff
changeset
|
446 | try: |
0d9ca37901ed
added test for collinearity, fixed bowtie test
Santeri Piippo
parents:
28
diff
changeset
|
447 | t2 = (intersection.x - c.x) / (d.x - c.x) |
0d9ca37901ed
added test for collinearity, fixed bowtie test
Santeri Piippo
parents:
28
diff
changeset
|
448 | except ZeroDivisionError: |
0d9ca37901ed
added test for collinearity, fixed bowtie test
Santeri Piippo
parents:
28
diff
changeset
|
449 | t2 = inf |
28 | 450 | try: |
30
0d9ca37901ed
added test for collinearity, fixed bowtie test
Santeri Piippo
parents:
28
diff
changeset
|
451 | u1 = (intersection.y - a.y) / (b.y - a.y) |
28 | 452 | except ZeroDivisionError: |
30
0d9ca37901ed
added test for collinearity, fixed bowtie test
Santeri Piippo
parents:
28
diff
changeset
|
453 | u1 = inf |
0d9ca37901ed
added test for collinearity, fixed bowtie test
Santeri Piippo
parents:
28
diff
changeset
|
454 | try: |
0d9ca37901ed
added test for collinearity, fixed bowtie test
Santeri Piippo
parents:
28
diff
changeset
|
455 | u2 = (intersection.y - c.y) / (d.y - c.y) |
0d9ca37901ed
added test for collinearity, fixed bowtie test
Santeri Piippo
parents:
28
diff
changeset
|
456 | except ZeroDivisionError: |
0d9ca37901ed
added test for collinearity, fixed bowtie test
Santeri Piippo
parents:
28
diff
changeset
|
457 | u2 = inf |
0d9ca37901ed
added test for collinearity, fixed bowtie test
Santeri Piippo
parents:
28
diff
changeset
|
458 | if (0 < t1 < 1 and 0 < t2 < 1) or (0 < u1 < 1 and 0 < u2 < 1): |
28 | 459 | return intersection |
460 | else: | |
461 | return None | |
462 | else: | |
463 | return None |