-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathutil.py
54 lines (39 loc) · 1.8 KB
/
util.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
import numpy as np
def zig_zag_encode(arr):
"""
Input can be number or numpy array
https://gist.github.com/mfuerstenau/ba870a29e16536fdbaba
(i >> bitlength-1) ^ (i << 1)
So I right shift 15 because these arrays are int16
Note: since I'm only right-shifting 15 places, this will fail for values >
int16
"""
return np.bitwise_xor(np.right_shift(arr, 15), np.left_shift(arr, 1))
def is_ccw(positions, indices):
"""For each triangle, determine if in counter-clockwise winding order
Implements algorithm from here:
https://stackoverflow.com/a/1165943
NOTE: this algorithm is reversed if the origin is the top left (i.e. as in a
PNG), rather than the standard origin of the bottom left.
Args:
positions: numpy array of shape (-1, 3) defining positions. Each row is a single coordinate
indices: numpy array either flat or of shape (-1, 3) defining triangles
Returns:
1d numpy array where each value represents a single triangle formed by a
triple within `indices`. The value is `True` if the triangle is
counter-clockwise or `False` if clockwise.
"""
# Make sure indices
indices = indices.reshape(-1, 3)
# Perform coordinate lookup in positions using indices
# `coords` is then an array of shape (-1, 3, 3) where each block of (i, 3,
# 3) represents all the coordinates of a single triangle
coords = positions[indices]
# x2 - x1 for every edge of every triangle
x2x1 = np.roll(coords[:, :, 0], -1, axis=1) - coords[:, :, 0]
# y2 + y1 for every edge of every triangle
y2y1 = np.roll(coords[:, :, 1], -1, axis=1) + coords[:, :, 1]
# Sum edge weights for each triangle
axissum = (x2x1 * y2y1).sum(axis=1)
# Values <0 represent counter-clockwise triangles
return axissum < 0