/usr/include/simbody/SimTKcommon/internal/PolygonalMesh.h is in libsimbody-dev 3.5.4+dfsg-1ubuntu2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
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 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 | #ifndef SimTK_SimTKCOMMON_POLYGONAL_MESH_H_
#define SimTK_SimTKCOMMON_POLYGONAL_MESH_H_
/* -------------------------------------------------------------------------- *
* Simbody(tm): SimTKcommon *
* -------------------------------------------------------------------------- *
* This is part of the SimTK biosimulation toolkit originating from *
* Simbios, the NIH National Center for Physics-Based Simulation of *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org/home/simbody. *
* *
* Portions copyright (c) 2008-14 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: Michael Sherman *
* *
* Licensed under the Apache License, Version 2.0 (the "License"); you may *
* not use this file except in compliance with the License. You may obtain a *
* copy of the License at http://www.apache.org/licenses/LICENSE-2.0. *
* *
* Unless required by applicable law or agreed to in writing, software *
* distributed under the License is distributed on an "AS IS" BASIS, *
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
* See the License for the specific language governing permissions and *
* limitations under the License. *
* -------------------------------------------------------------------------- */
#include "SimTKcommon/Simmatrix.h"
#include "SimTKcommon/internal/PrivateImplementation.h"
namespace SimTK {
class PolygonalMesh;
class PolygonalMeshImpl;
// We only want the template instantiation to occur once. This symbol is defined
// in the SimTKcommon compilation unit that defines the PolygonalMesh class but
// should not be defined any other time.
#ifndef SimTK_SIMTKCOMMON_DEFINING_POLYGONALMESH
extern template class PIMPLHandle<PolygonalMesh, PolygonalMeshImpl, true>;
#endif
/** This class provides a description of a mesh made of polygonal faces (not
limited to triangles). Its primary purpose is for loading geometry from files,
which can then be used for visualization or collision detection. For example,
the following lines load a mesh from a Wavefront OBJ file, then create a
DecorativeMesh from it.
@code
PolygonalMesh mesh;
mesh.loadObjFile("teapot.obj");
DecorativeMesh decoration(mesh);
@endcode
You can also read a polygon mesh from a VTK PolyData (.vtp) file, or an STL
file (.stl) that is in ascii or binary format. You can also build meshes
programmatically, and some static methods are provided here for generating some
common shapes. If you don't know what kind of file you have, you can attempt to
read it with the loadFile() method which will examine the file extension to
determine the expected format.
The mesh has its own local frame and vertex locations are given in that
frame. You can scale and transform the vertices relative to that frame
(changing the values stored in the mesh) but more commonly the mesh will be
placed on a body relative to that body's frame, meaning you can re-use the
same mesh in various places.
We expect this to be a large object so give it shared (reference) semantics;
that is, the copy constructor and copy assignment default to shallow copies
(both handles will refer to the same data). If you want to make a deep
(non-shared) copy of a PolygonalMesh, use the copyAssign() method provided by
the PIMPLHandle base class. **/
class SimTK_SimTKCOMMON_EXPORT PolygonalMesh
: public PIMPLHandle<PolygonalMesh, PolygonalMeshImpl, true> {
public:
/** Create an empty %PolygonalMesh, with no vertices or faces. **/
PolygonalMesh() {}
/** Create a sphere-shaped mesh, with roughly uniform mesh elements.
@param[in] radius
The radius of the underlying sphere. Vertices of the mesh will be on
the sphere, with mesh elements somewhat inside.
@param[in] resolution
Control for how dense a mesh to produce. Resolution 0 will produce an
octahedron (8 triangular faces). Resolution 1 (the default) gives
32 faces, resolution 2 gives 128. In general for resolution n there
will be 2*4^(n+1) faces.
@return A %PolygonalMesh representing a sphere of the specified radius. **/
static PolygonalMesh createSphereMesh(Real radius,
int resolution = 1);
/** Create a brick-shaped mesh. A brick is a rectangular solid (a box)
centered at and aligned with the mesh local frame. Note that its size is
given with \e half dimensions. By default you will just get two mesh faces
along the longest edge of the brick, with all other edges roughly the same
size. You can control the mesh density with the \a resolution parameter.
@param[in] halfDims
The half-dimensions of the brick. The extreme vertices are at
-halfDims and +halfDims, so the brick is centered around the mesh
local frame.
@param[in] resolution
Control for how dense a mesh to produce. For this shape, \a resolution
is interpreted as the number of extra vertices to insert in the
\e longest edge of the brick. Extra vertices are inserted into the
shorter edges if needed to keep the edge lengths approximately
uniform for every mesh face. \a resolution=0 gives only
vertices at the corners; the default is 1 meaning that the longest
edge is split once.
@return A %PolygonalMesh representing a brick of the requested size.
<h3>Controlling the mesh density:</h3>
If you want a brick mesh where all the edges in the mesh are roughly the
same length, say \c wantEdgeLength, set \a resolution like this:
@code
Real wantEdgeLength = ...;
Vec3 halfDims = ...;
int resolution = (int)(max(halfDims)/wantEdgeLength + 0.5);
@endcode
If you want a brick mesh where all the edges are roughly the same length
as the shortest edge of the brick, just set
<code>wantEdgeLength=min(halfDims)</code> in the above calculation. **/
static PolygonalMesh createBrickMesh(const Vec3& halfDims,
int resolution = 1);
/** Create a cylinder-shaped mesh, with the long axis in a given
direction. By default you'll get a 12 sided polygon as the base and
elements of roughly similar dimension along the edges. You can control the
mesh density with the \a resolution parameter.
@param[in] axis
The central axis direction of the cylinder, in the mesh local frame.
This can be provided using the constants XAxis, YAxis, or ZAxis, or
you can provide a unit vector in any direction.
@param[in] radius
The cylinder radius.
@param[in] halfLength
Half the length of the cylinder along its axis. The bases are at
-halfLength and +halfLength along the \a axis, so the cylinder is
centered around the mesh local frame origin.
@param[in] resolution
Control for how dense a mesh to produce (see below for details).
@return A %PolygonalMesh representing a cylinder of the requested dimensions
and orientation.
<h3>Controlling the mesh density:</h3>
At resolution 0 the base is a hexagon with six triangular faces, and the
tube is meshed with quad faces that are about as long
as the diameter of the base. Resolution 1 (the default) makes the base
a 12-sided polygon and introduces an intermediate 12-sided polygon of
have the diameter. There will be triangles in the center still, but
quad faces between the polygons. The length of the tube faces will be
reduced to match. Higher resolutions refine the mesh similarly. **/
static PolygonalMesh createCylinderMesh(const UnitVec3& axis,
Real radius,
Real halfLength,
int resolution=1);
/** Restore this %PolygonalMesh to its default-constructed state, meaning
that it will contain no vertices or faces after this call. **/
void clear();
/** Get the number of faces in the mesh. **/
int getNumFaces() const;
/** Get the number of vertices in the mesh. **/
int getNumVertices() const;
/** Get the position of a vertex in the mesh.
@param[in] vertex The index of the vertex (as returned by addVertex()).
@return The position of the specified vertex, measured and expressed in
the mesh local frame. **/
const Vec3& getVertexPosition(int vertex) const;
/** Get the number of vertices that make up a particular face.
@param[in] face The index of the face (as returned by addFace()). **/
int getNumVerticesForFace(int face) const;
/** Get the index of one of the vertices of a face.
@param[in] face The index of the face (as returned by addFace()).
@param[in] vertex The index of the vertex within the face (from 0, 1, or 2
for a triangular face, etc.) These are ordered the same
way as when the face was defined.
@return The index of the specified vertex. **/
int getFaceVertex(int face, int vertex) const;
/** Add a vertex to the mesh.
@param[in] position The position of the vertex to add, measured and
expressed in the mesh local frame.
@return The index of the newly added vertex. **/
int addVertex(const Vec3& position);
/** Add a face to the mesh. Note that the ordering of the vertices defines
the outward normal for the face; they must be counterclockwise around the
desired normal.
@param[in] vertices Indices of the vertices which make up the new face,
in counterclockwise order with respect to the face
normal.
@return The index of the newly added face. **/
int addFace(const Array_<int>& vertices);
/** Scale a mesh by multiplying every vertex by a fixed value. Note that
this permanently modifies the vertex locations within the mesh. Since the
vertices are measured in the mesh local frame, scaling will appear to
occur around the mesh origin (that is, the origin will remain where it
was while everything else changes.
@param[in] scale The scale factor. Can be any value except zero.
@return A reference to this now-scaled mesh object. **/
PolygonalMesh& scaleMesh(Real scale);
/** %Transform a mesh by applying the given Transform to every vertex,
leaving the mesh permanently changed. This has the effect of replacing the
mesh local frame M with a new frame A.
@param[in] X_AM The transform giving the pose of the mesh local frame in
the new frame A. Every vertex v_M becomes v_A=X_AM*v_M.
@return A reference to this now-transformed mesh object. **/
PolygonalMesh& transformMesh(const Transform& X_AM);
/** Attempt to interpret the given file as a mesh file, with the format
determined from the file name extension. If we recognize the extension
we'll call one of the specialized methods below; see the descriptions for
more information. Ignoring case, we recognize:
- <tt>.obj </tt>: Wavefront OBJ file
- <tt>.stl </tt>: 3D Systems Stereolithography file (ascii or binary)
- <tt>.stla</tt>: ascii-only stl extension
- <tt>.vtp </tt>: VTK PolyData file (we can only read the ascii version)
@param[in] pathname The name of a mesh file with a recognized extension.
**/
void loadFile(const String& pathname);
/** Load a Wavefront OBJ (.obj) file, adding the vertices and faces it
contains to this mesh, and ignoring anything else in the file. The suffix
for these files is typically ".obj" but we don't check here.
@param[in] pathname The name of a .obj file. **/
void loadObjFile(const String& pathname);
/** Alternate signature for Wavefront OBJ format that takes an already-open
istream rather than a pathname. This is useful for testing since it
can be supplied by a stringstream rather than a file.
@param[in,out] file An input stream from which to load the file
contents. **/
void loadObjFile(std::istream& file);
/** Load a VTK PolyData (.vtp) file, adding the vertices and faces it
contains to this mesh and ignoring anything else in the file. The suffix
for these files is typically ".vtp" but we don't check here.
@param[in] pathname The name of a .vtp file. **/
void loadVtpFile(const String& pathname);
/** Load an STL file, adding the vertices and faces it contains to this
mesh and ignoring anything else in the file. The file may be in ascii or
binary format. If the suffix is ".stla" then it can only be ascii.
Otherwise, including ".stl" or anything else, we'll examine the contents to
determine which format is used. STL files include many repeated vertices;
we will collapse any that coincide to within a small tolerance so that there
is some hope of getting a connected surface.
@param[in] pathname The name of a .stl or .stla file. **/
void loadStlFile(const String& pathname);
private:
explicit PolygonalMesh(PolygonalMeshImpl* impl) : HandleBase(impl) {}
void initializeHandleIfEmpty();
};
} // namespace SimTK
#endif // SimTK_SimTKCOMMON_POLYGONAL_MESH_H_
|