import os
import numpy as np
[docs]
def create_cube_mesh(file_name, centre_point, side_len, description=None, verbose=False):
"""
Creates a cube mesh in wavefront file format.
Args:
file_name (str) : Path to output file
centre_point (float, float, float): Centre of cube
side_len (float) : Side of cube
description (str) : Description added to file header
verbose (bool) : Display extra information
"""
mesh_dir = os.path.dirname(file_name)
if len(mesh_dir) > 0 and not os.path.exists(mesh_dir):
os.makedirs(mesh_dir)
if type(centre_point) is not np.ndarray:
centre_point = np.array(centre_point)
if verbose:
print("Creating cube mesh")
print(f"File: {file_name}")
print(f"Centre: {centre_point}")
print(f"Side: {side_len}")
print(f"Description: {description}")
vertex = np.array([[0.0, 0.0, 0.0],
[0.0, 0.0, 1.0],
[0.0, 1.0, 0.0],
[0.0, 1.0, 1.0],
[1.0, 0.0, 0.0],
[1.0, 0.0, 1.0],
[1.0, 1.0, 0.0],
[1.0, 1.0, 1.0]])
# Centre cube
vertex -= np.array([0.5, 0.5, 0.5])
# Scale the cube to right size
vertex *= side_len
# Position cube
vertex += centre_point
vertex *= 1e6 # The other obj files are in micrometers, so convert :(
normal_str = "vn 0.0 0.0 1.0\n" \
+ "vn 0.0 0.0 -1.0\n" \
+ "vn 0.0 1.0 0.0\n" \
+ "vn 0.0 -1.0 0.0\n" \
+ "vn 1.0 0.0 0.0\n" \
+ "vn -1.0 0.0 0.0\n"
face_str = "f 1//2 7//2 5//2\n" \
+ "f 1//2 3//2 7//2\n" \
+ "f 1//6 4//6 3//6\n" \
+ "f 1//6 2//6 4//6\n" \
+ "f 3//3 8//3 7//3\n" \
+ "f 3//3 4//3 8//3\n" \
+ "f 5//5 7//5 8//5\n" \
+ "f 5//5 8//5 6//5\n" \
+ "f 1//4 5//4 6//4\n" \
+ "f 1//4 6//4 2//4\n" \
+ "f 2//1 6//1 8//1\n" \
+ "f 2//1 8//1 4//1\n"
with open(file_name, 'wt') as f:
f.write("# Generated by create_cube_mesh.py\n")
f.write(f"# {description}\n\n")
f.write("g cube\n\n")
for row in vertex:
f.write("v %f %f %f\n" % tuple(row))
f.write(f"\n{normal_str}")
f.write(f"\n{face_str}")
def cube_cli():
import argparse
parser = argparse.ArgumentParser("Create cube mesh for Snudda")
parser.add_argument("filename", help="Filename of obj file")
parser.add_argument("side_len", help="Length of the side (units micrometers)", type=float)
parser.add_argument("--center", "-center", help="Center of cube", default="0,0,0")
parser.add_argument("--description", help="Description of cube", default=None)
args = parser.parse_args()
center = [float(x)*1e-6 for x in args.center.split(",")]
desc = args.description
if desc is None:
desc = f"Cube with side length {args.side_len} micrometers, centered at {args.center}"
print(f"Creating {args.filename} with side length {args.side_len} micrometers, centered at {args.center}")
create_cube_mesh(file_name=args.filename,
centre_point=center,
side_len=args.side_len*1e-6,
description=desc)
if __name__ == "__main__":
cube_cli()