Skip to content
Snippets Groups Projects
Commit 9db0348a authored by andersct's avatar andersct
Browse files

Add asteroids for space examples

- add display for asteroid
- generate random convex asteroids by sampling normals
- add functions to fix surface triangulations
- add figure setting for space background
parent 6c38b697
No related branches found
No related tags found
No related merge requests found
import numpy as np
import plotly.graph_objects as go
import scene_elements_3d.asteroid as ast
from vis import triangulated_surface as vtrs
from vis.xyz_utils import set_space_background
def main(is_surface_normals=False):
seed = np.random.randint(1000)
print('seed: {}'.format(seed))
# seed = 0
np.random.seed(seed)
mu = np.array([
[0., 0, 0],
[2, 0, 1],
])
sigma = np.array([
[
[2., 0, 0],
[0, 1, 0],
[0, 0, 1],
],
[
[1., 0, .2],
[0, 1, 0],
[.2, 0, 1],
],
])
model = ast.generate_convex_asteroid(mu, sigma, 100)
fig = go.Figure()
fig.add_traces([vtrs.make_model_mesh(model)])
if is_surface_normals:
fig.add_traces(vtrs.make_surface_normals(
model.vertices, model.triangles))
title_str = 'Asteroid'
fig.update_layout(
title=title_str, autosize=False,
width=1200, height=600,
scene=dict(
xaxis=dict(range=[-8, 8]),
yaxis=dict(range=[-6, 6]),
zaxis=dict(range=[-6, 6]),
), showlegend=False)
set_space_background(fig)
fig.show()
if __name__ == '__main__':
main(is_surface_normals=False)
......@@ -2,9 +2,10 @@ import plotly.graph_objects as go
from rigid_body_models.shuttle import Shuttle
from vis import triangulated_surface as vtrs
from vis import triangulated_thruster_model as vttm
from vis.xyz_utils import set_space_background
def main_display_mesh(is_thrusters=True):
def main_display_mesh(is_thrusters=True, is_space_bg=True):
model = Shuttle(rho=1e6)
fig = go.Figure()
fig.add_traces([vtrs.make_model_mesh(model)])
......@@ -23,8 +24,10 @@ def main_display_mesh(is_thrusters=True):
yaxis=dict(range=[-6, 6]),
zaxis=dict(range=[-6, 6]),
), showlegend=is_thrusters)
if is_space_bg:
set_space_background(fig)
fig.show()
if __name__ == '__main__':
main_display_mesh(is_thrusters=True)
main_display_mesh(is_thrusters=True, is_space_bg=True)
......@@ -86,3 +86,4 @@ class Shuttle(trs.TriangulatedSurface):
_, _, im = trs.calculate_mass_properties(
self.vertices, self.triangles, rho)
self.im = im
self.color = 'white'
......@@ -69,3 +69,42 @@ def calculate_mass_properties(vertices, triangles, rho):
[-s[6], -s[5], s[7] + s[8]],
])
return m, center, im
def remove_unused_vertices(vertices, triangles):
"""
Remove vertices that do not form a triangle, and relabel triangle vertices
to their new indices.
:param vertices: n_points, 3 | includes all points forming triangle faces
:param triangles: n_faces, 3 | indices of vertices that form each triangle
:return: vertices, triangles
"""
used_inds = np.unique(triangles.ravel())
vertices_new = vertices[used_inds]
triangles_new = triangles.copy()
for i in range(used_inds.size):
triangles_new[triangles_new == used_inds[i]] = i
return vertices_new, triangles_new
def make_convex_shape_triangles_consistent(vertices, triangles):
"""
For a convex shape described by a triangulated surface, ensure
each triangle's normal faces outward.
:param vertices: n_points, 3 | includes all points forming triangle faces
:param triangles: n_faces, 3 | indices of vertices that form each triangle
:return: triangles: n_faces, 3 | triangles made consistent
"""
used_inds = np.unique(triangles.ravel())
center = vertices[used_inds].mean(axis=0)
triangle_centers = np.array([
vertices[triangles[i]].mean(axis=0) for i in range(len(triangles))
])
outward_vec = triangle_centers - center
triangle_normals = np.cross(
vertices[triangles[:, 1]] - vertices[triangles[:, 0]],
vertices[triangles[:, 2]] - vertices[triangles[:, 0]],
)
is_mismatch = np.einsum('ij,ij->i', outward_vec, triangle_normals) < 0
triangles[is_mismatch, :] = triangles[is_mismatch, :][:, [0, 2, 1]]
return triangles
import numpy as np
from rigid_body_models import triangulated_surface as trs
from scipy.spatial import ConvexHull
def generate_convex_asteroid(mu_list, sigma_list, n_samples_per, **kwargs):
"""
Generate asteroid from the convex hull of samples taken
from a list of normals.
:param mu_list: n, 3 | means of multivariate normals
:param sigma_list: n, 3, 3 | covariance matrix of multivariate normals
:param n_samples_per: number of samples per normal
:return:
vertices:
triangles:
"""
samples = []
for mu, sigma in zip(mu_list, sigma_list):
L = np.linalg.cholesky(sigma)
samples_i = (L.dot(np.random.randn(3, n_samples_per))).T + mu
samples.append(samples_i)
samples = np.vstack(samples) # n*n_samples_per, 3
hull = ConvexHull(samples)
triangles = hull.simplices
vertices = samples
vertices, triangles = trs.remove_unused_vertices(vertices, triangles)
triangles = trs.make_convex_shape_triangles_consistent(vertices, triangles)
asteroid = Asteroid(vertices, triangles, **kwargs)
return asteroid
class Asteroid(trs.TriangulatedSurface):
def __init__(self, vertices, triangles, rho=2000.):
super(Asteroid, self).__init__(rho, vertices, triangles)
m, center, im = trs.calculate_mass_properties(
self.vertices, self.triangles, rho)
self.m = m
self.im = im
self.center = 0 * center
self.vertices -= center
_, _, im = trs.calculate_mass_properties(
self.vertices, self.triangles, rho)
self.im = im
self.color = 'grey'
......@@ -15,10 +15,14 @@ def make_model_mesh(model, Rt=()):
Rt = Rt_3d()
xyz = Rt[:3, :3].dot(model.vertices.T).T + Rt[:3, -1]
ijk = model.triangles
try:
color = model.color
except AttributeError:
color = None
mesh = go.Mesh3d(
x=xyz[:, 0], y=xyz[:, 1], z=xyz[:, 2],
i=ijk[:, 0], j=ijk[:, 1], k=ijk[:, 2],
color='white', flatshading=True
color=color, flatshading=True
)
return mesh
......
......@@ -29,3 +29,12 @@ def make_3d_vector(root, vector, scale=1., name=''):
name=name,
)
return line_obj, arrow_head_obj
def set_space_background(fig):
"""
:param fig: plotly figure
:return:
"""
fig.update_layout(paper_bgcolor='rgb(10,10,10)')
fig.update_scenes(xaxis_visible=False, yaxis_visible=False, zaxis_visible=False)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment