add support for reading binary STL files
This commit is contained in:
@ -21,7 +21,7 @@ Syntax
|
||||
*single* args = x y z
|
||||
x,y,z = coordinates of a single particle (distance units)
|
||||
*mesh* args = STL-file
|
||||
STL-file = file with triangle mesh in ASCII STL format
|
||||
STL-file = file with triangle mesh in STL format
|
||||
*random* args = N seed region-ID
|
||||
N = number of particles to create
|
||||
seed = random # seed (positive integer)
|
||||
@ -136,18 +136,20 @@ positions.
|
||||
:align: right
|
||||
:target: _images/marble_race.jpg
|
||||
|
||||
For the *mesh* style, a file with a triangle mesh in `ASCII STL format
|
||||
<https://en.wikipedia.org/wiki/STL_(file_format)#ASCII_STL>`_ is read
|
||||
and one or more particles are placed into the area of each triangle.
|
||||
Binary STL files (e.g. as frequently offered for 3d-printing) can be
|
||||
converted to ASCII with the :ref:`stl_bin2txt tool <stlconvert>`. The
|
||||
use of the *units box* option is required. There are two algorithms for
|
||||
placing atoms available: *bisect* and *qrand*. They can be selected via
|
||||
the *meshmode* option; *bisect* is the default. If the atom style allows
|
||||
to set a per-atom radius this radius is set to the average
|
||||
distance of the triangle vertices from its center times the value of the
|
||||
*radscale* keyword (default: 1.0). If the atom style supports it, the
|
||||
atoms created from the mesh are assigned a new molecule ID.
|
||||
For the *mesh* style, a file with a triangle mesh in `STL format
|
||||
<https://en.wikipedia.org/wiki/STL_(file_format)>`_ is read and one or
|
||||
more particles are placed into the area of each triangle. The reader
|
||||
supports both ASCII and binary files conforming to the format on the
|
||||
Wikipedia page. Binary STL files (e.g. as frequently offered for
|
||||
3d-printing) also be first converted to ASCII for editing with the
|
||||
:ref:`stl_bin2txt tool <stlconvert>`. The use of the *units box* option
|
||||
is required. There are two algorithms for placing atoms available:
|
||||
*bisect* and *qrand*. They can be selected via the *meshmode* option;
|
||||
*bisect* is the default. If the atom style allows to set a per-atom
|
||||
radius this radius is set to the average distance of the triangle
|
||||
vertices from its center times the value of the *radscale* keyword
|
||||
(default: 1.0). If the atom style supports it, the atoms created from
|
||||
the mesh are assigned a new molecule ID.
|
||||
|
||||
In *bisect* mode a particle is created at the center of each triangle
|
||||
unless the average distance of the triangle vertices from its center is
|
||||
|
||||
@ -1036,9 +1036,11 @@ void CreateAtoms::add_mesh(const char *filename)
|
||||
molid = maxmol + 1;
|
||||
}
|
||||
|
||||
FILE *fp = fopen(filename, "r");
|
||||
FILE *fp = fopen(filename, "rb");
|
||||
if (fp == nullptr) error->one(FLERR, "Cannot open file {}: {}", filename, utils::getsyserror());
|
||||
|
||||
// first try reading the file in ASCII format
|
||||
|
||||
TextFileReader reader(fp, "STL mesh");
|
||||
try {
|
||||
char *line = reader.next_line();
|
||||
@ -1047,7 +1049,7 @@ void CreateAtoms::add_mesh(const char *filename)
|
||||
|
||||
line += 6;
|
||||
if (comm->me == 0)
|
||||
utils::logmesg(lmp, "Reading STL object {} from file {}\n", utils::trim(line), filename);
|
||||
utils::logmesg(lmp, "Reading STL object {} from text file {}\n", utils::trim(line), filename);
|
||||
|
||||
while ((line = reader.next_line())) {
|
||||
|
||||
@ -1092,8 +1094,50 @@ void CreateAtoms::add_mesh(const char *filename)
|
||||
}
|
||||
}
|
||||
} catch (std::exception &e) {
|
||||
|
||||
// if ASCII failed for the first line, try reading as binary
|
||||
if (utils::strmatch(e.what(), "^Invalid STL mesh file format")) {
|
||||
char title[80];
|
||||
float triangle[12];
|
||||
uint32_t ntri;
|
||||
uint16_t attr;
|
||||
size_t count;
|
||||
|
||||
rewind(fp);
|
||||
count = fread(title, sizeof(char), 80, fp);
|
||||
title[79] = '\0';
|
||||
count = fread(&ntri, sizeof(ntri), 1, fp);
|
||||
if (count <= 0) {
|
||||
error->all(FLERR, "Error reading STL file {}: {}", filename, utils::getsyserror());
|
||||
} else {
|
||||
if (comm->me == 0)
|
||||
utils::logmesg(lmp, "Reading STL object {} from binary file {}\n", utils::trim(title),
|
||||
filename);
|
||||
}
|
||||
|
||||
for (uint32_t i = 0U; i < ntri; ++i) {
|
||||
count = fread(triangle, sizeof(float), 12, fp);
|
||||
if (count != 12)
|
||||
error->all(FLERR, "Error reading STL file {}: {}", filename, utils::getsyserror());
|
||||
count = fread(&attr, sizeof(attr), 1, fp);
|
||||
|
||||
for (int j = 0; j < 3; ++j)
|
||||
for (int k = 0; k < 3; ++k) vert[j][k] = triangle[3 * j + 3 + k];
|
||||
|
||||
++ntriangle;
|
||||
if (mesh_style == BISECTION) {
|
||||
// add in center of triangle or bisecting recursively along longest edge
|
||||
// as needed to get the desired atom density/radii
|
||||
atomlocal += add_bisection(vert, molid);
|
||||
} else if (mesh_style == QUASIRANDOM) {
|
||||
// add quasi-random distribution of atoms
|
||||
atomlocal += add_quasirandom(vert, molid);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
error->all(FLERR, "Error reading triangles from file {}: {}", filename, e.what());
|
||||
}
|
||||
}
|
||||
|
||||
if (ntriangle > 0) {
|
||||
MPI_Allreduce(&atomlocal, &atomall, 1, MPI_LMP_BIGINT, MPI_SUM, world);
|
||||
|
||||
Reference in New Issue
Block a user