geometry.py

changeset 14
d383f319f35b
parent 13
12d4ddc4bfd8
child 15
45b3aeb25003
equal deleted inserted replaced
13:12d4ddc4bfd8 14:d383f319f35b
316 ''' 316 '''
317 return Matrix3x3([ 317 return Matrix3x3([
318 sum(self[i, k] * other[k, j] for k in range(3)) 318 sum(self[i, k] * other[k, j] for k in range(3))
319 for i, j in matrix_indices() 319 for i, j in matrix_indices()
320 ]) 320 ])
321 def __add__(self, other):
322 return Matrix3x3([
323 a + b
324 for a, b in zip(self.values, other.values)
325 ])
326 def __mul__(self, scalar):
327 return Matrix3x3([
328 x * scalar
329 for x in self.values
330 ])
321 331
322 def complete_matrix(matrix, anchor): 332 def complete_matrix(matrix, anchor):
323 ''' 333 '''
324 Combines a 3×3 matrix and an anchor vertex into a full 4×4 334 Combines a 3×3 matrix and an anchor vertex into a full 4×4
325 transformation matrix. 335 transformation matrix.
347 z = transformation_matrix[8] * vertex.x \ 357 z = transformation_matrix[8] * vertex.x \
348 + transformation_matrix[9] * vertex.y \ 358 + transformation_matrix[9] * vertex.y \
349 + transformation_matrix[10] * vertex.z \ 359 + transformation_matrix[10] * vertex.z \
350 + transformation_matrix[11], 360 + transformation_matrix[11],
351 ) 361 )
362
363 def transform_to_xy(polygon):
364 '''
365 Transforms the provided polygon into the XY plane. The polygon is
366 assumed to be planar.
367
368 Implementation is based on this StackOverflow answer:
369 https://math.stackexchange.com/a/476311
370 '''
371 v1, v2, v3 = polygon.vertices[:3]
372 a, b = v3 - v2, v1 - v2
373 normal = cross_product(a, b).normalized()
374 v = cross_product(normal, Vector(0, 0, 1))
375 cosine = dot_product(normal, Vector(0, 0, 1))
376 v_matrix = Matrix3x3([
377 0, -v.z, v.y,
378 v.z, 0, -v.x,
379 -v.y, v.x, 0,
380 ])
381 try:
382 rotation_matrix = Matrix3x3()
383 rotation_matrix += v_matrix
384 rotation_matrix += (v_matrix @ v_matrix) * (1 / (1 + cosine))
385 except ZeroDivisionError:
386 rotation_matrix = Matrix3x3()
387 full_matrix = complete_matrix(rotation_matrix, Vertex(0, 0, 0))
388 return Polygon([
389 transform(vertex = vertex, transformation_matrix = full_matrix)
390 for vertex in polygon.vertices
391 ])
392
393 def vector_angle(vec_1, vec_2, normalized = False):
394 from math import acos, pi as π
395 cosine = dot_product(vec_1, vec_2)
396 try:
397 cosine /= vec_1.length() * vec_2.length()
398 except ZeroDivisionError:
399 return 0
400 angle = acos(cosine)
401 if normalized and angle > π / 2:
402 angle = π - angle
403 return angle
404
405 def split_quadrilateral(polygon):
406 assert(len(polygon.vertices) == 4)
407 vertices = IndexRing(polygon.vertices)
408 for i in (0, 1):
409 a, b = vertices[0 + i], vertices[1 + i]
410 c, d = vertices[2 + i], vertices[3 + i]
411 yield Polygon([a, b, c]), Polygon([b, c, d])
412
413 def triangle_plane_normal(polygon):
414 assert(len(polygon.vertices) == 3)
415 a, b, c = polygon.vertices[:3]
416 return cross_product(b - a, b - c)

mercurial