-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathspring.py
More file actions
60 lines (46 loc) · 2.25 KB
/
spring.py
File metadata and controls
60 lines (46 loc) · 2.25 KB
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
55
56
57
58
59
60
# This code borrowed from:
# https://github.com/nrsyed/utilities/blob/master/spring/spring.py
# Najam Syed https://github.com/nrsyed
import math
import numpy as np
def spring(start, end, nodes, width, lead1, lead2):
"""!
Return a list of points corresponding to a spring.
@param r1 (array-like) The (x, y) coordinates of the first endpoint.
@param r2 (array-like) The (x, y) coordinates of the second endpoint.
@param nodes (int) The number of spring "nodes" or coils.
@param width (int or float) The diameter of the spring.
@param lead1 (int) The starting flat piece of the spring.
@param lead2 (int) The ending flat piece of the spring.
@return An array of x coordinates and an array of y coordinates, and the start and end points
"""
# Check that nodes is at least 1.
nodes = max(int(nodes), 1)
# Convert to numpy array to account for inputs of different types/shapes.
start, end = np.array(start).reshape((2,)), np.array(end).reshape((2,))
# If both points are coincident, return the x and y coords of one of them.
if (start == end).all():
return start[0], start[1]
# Calculate length of spring (distance between endpoints).
length = np.linalg.norm(np.subtract(end, start))
# Calculate unit vectors tangent (u_t) and normal (u_t) to spring.
u_t = np.subtract(end, start) / length
u_n = np.array([[0, -1], [1, 0]]).dot(u_t)
# Add some magic here
p1 = start + lead1*u_t
p2 = end - lead2*u_t
length -= (lead1+lead2)
# Initialize array of x (row 0) and y (row 1) coords of the nodes+2 points.
spring_coords = np.zeros((2, nodes + 2))
spring_coords[:,0], spring_coords[:,-1] = p1, p2
# Check that length is not greater than the total length the spring
# can extend (otherwise, math domain error will result), and compute the
# normal distance from the centerline of the spring.
normal_dist = math.sqrt(max(0, width**2 - (length**2 / nodes**2))) / 2
# Compute the coordinates of each point (each node).
for i in range(1, nodes + 1):
spring_coords[:,i] = (
p1
+ ((length * (2 * i - 1) * u_t) / (2 * nodes))
+ (normal_dist * (-1)**i * u_n))
return spring_coords[0,:], spring_coords[1,:], p1, p2