Skip to content

Commit

Permalink
add line segment resampling
Browse files Browse the repository at this point in the history
  • Loading branch information
mikedh committed Dec 11, 2019
1 parent b39839d commit cef9193
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 1 deletion.
15 changes: 15 additions & 0 deletions tests/test_segments.py
Expand Up @@ -60,6 +60,21 @@ def test_extrude(self):
# compare area of mesh with source path
assert g.np.isclose(mesh.area, path.length * height)

def test_resample(self):
from trimesh.path.segments import length, resample
# create some random segments
seg = g.random((1000, 2, 3))
# set a maximum segment length
maxlen = 0.1
# one of the original segments should be longer than maxlen
assert (length(seg, summed=False) > maxlen).any()
# resample to be all shorter than maxlen
res = resample(seg, maxlen=maxlen)
# check lengths of the resampled result
assert (length(res, summed=False) < maxlen).all()
# make sure overall length hasn't changed
assert g.np.isclose(length(res), length(seg))


if __name__ == '__main__':
g.trimesh.util.attach_to_log()
Expand Down
97 changes: 97 additions & 0 deletions trimesh/path/segments.py
Expand Up @@ -363,3 +363,100 @@ def extrude(segments, height, double_sided=False):
faces, np.fliplr(faces)))

return vertices, faces


def length(segments, summed=True):
"""
Extrude 2D line segments into 3D triangles.
Parameters
-------------
segments : (n, 2, 2) float
2D line segments
height : float
Distance to extrude along Z
double_sided : bool
If true, return 4 triangles per segment
Returns
-------------
vertices : (n, 3) float
Vertices in space
faces : (n, 3) int
Indices of vertices forming triangles
"""
segments = np.asanyarray(segments)
norms = util.row_norm(segments[:, 0, :] - segments[:, 1, :])
if summed:
return norms.sum()
return norms


def resample(segments, maxlen):
"""
Resample line segments until no segment
is longer than maxlen.
Parameters
-------------
segments : (n, 2, 2) float
2D line segments
maxlen : float
The maximum length of a line segment
Returns
-------------
resampled : (m, 2, 3) float
Line segments where no segment is longer than maxlen
"""
maxlen = float(maxlen)
segments = np.asanyarray(segments, dtype=np.float64)

# shortcut for endpoints
pt1 = segments[:, 0]
pt2 = segments[:, 1]
# vector between endpoints
vec = pt2 - pt1
# the integer number of times a segment needs to be split
splits = np.ceil(util.row_norm(vec) / maxlen).astype(np.int64)

# save resulting segments
result = []

# loop through each count of unique splits needed
for split in np.unique(splits):
# get a mask of which segments need to be split
mask = splits == split
# the vector for each incremental length
increment = vec[mask] / split
# stack the increment vector into the shape needed
v = np.tile(increment, split + 1).reshape((-1, 3))
# apply integer multiples of the increment
v *= np.tile(np.arange(split + 1),
len(increment)).reshape((-1, 1))
# stack the origin points correctly
o = np.tile(pt1[mask], split + 1).reshape((-1, 3))
# now get each segment as an (split, 3) polyline
poly = (o + v).reshape((-1, split + 1, 3))
# get indexes to stack polyline into segments
stack = util.stack_lines(np.arange(split + 1))
# save the resulting segments
result.extend([p[stack] for p in poly])

if tol.strict:
# check to make sure every start and end point
# from the reconstructed result corresponds
for original, recon in zip(segments[mask], poly):
assert np.allclose(original[0], recon[0])
assert np.allclose(original[-1], recon[-1])

# stack into (n, 2, 3) segments
result = np.concatenate(result)

if tol.strict:
# make sure resampled segments have the same length as input
assert np.isclose(length(segments),
length(result),
atol=1e-3)

return result
2 changes: 1 addition & 1 deletion trimesh/scene/transforms.py
Expand Up @@ -147,7 +147,7 @@ def to_gltf(self, scene):
# start with base frame as first node index
result = [{'name': self.base_frame}]
# {node name : node index in gltf}
lookup = {0: self.base_frame}
lookup = {self.base_frame: 0}

# collect the nodes in order
for node in node_data.keys():
Expand Down

0 comments on commit cef9193

Please sign in to comment.