This file is indexed.

/usr/include/palabos/offLattice/triangularSurfaceMesh.h is in libplb-dev 1.5~r1+repack1-2build2.

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
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
/* This file is part of the Palabos library.
 *
 * Copyright (C) 2011-2015 FlowKit Sarl
 * Route d'Oron 2
 * 1010 Lausanne, Switzerland
 * E-mail contact: contact@flowkit.com
 *
 * The most recent release of Palabos can be downloaded at 
 * <http://www.palabos.org/>
 *
 * The library Palabos is free software: you can redistribute it and/or
 * modify it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * The library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

/* Main author: Dimitrios Kontaxakis */

#ifndef TRIANGULAR_SURFACE_MESH_H
#define TRIANGULAR_SURFACE_MESH_H

#include "core/globalDefs.h"
#include "core/geometry3D.h"
#include "core/array.h"
#include "offLattice/triangleSet.h"
#include <string>
#include <vector>

namespace plb {

/// Holds one of the three edges of a triangle.
struct Edge {
    plint pv;  // Pointing Vertex.
    plint ne;  // Neighboring Edge.
};

/// Refers to a lid, i.e. a collection of triangles, constructed
///   by filling a hole in the mesh.
struct Lid {
    // Comment: if the close-holes algorithm is to be made more
    //   general one day, you will need to (1) assign the proper
    //   value to numAddedVertices, and (2) replace centerVertex
    //   by something else and change all codes which access
    //   centerVertex.
    Lid() : numAddedVertices(1) { }
    plint firstTriangle;
    plint numTriangles;
    std::vector<plint> boundaryVertices;
    plint centerVertex;
    plint numAddedVertices;
};

/// Represent a surface mesh, made up of adjacent triangles,
///   in a directed-edge format.
/** This format conveniently provides access to the surface topology
 * through triangles and vertices, but is less convenient for accessing
 * it directly through edges.
 *
 * The triangles are numbered continuously from 0 to getNumTriangles()-1,
 * and the vertices from 0 to getNumVertices()-1.
 *
 * Once the mesh is constructed, you can change the position of its
 * vertices, but you should not change its topology, which is static.
 * One exception: the method closeHoles changes the topology.
 *
 * For more information on the directed-edges format, check the paper
 * "Directed edges - A scalable representation for triangle meshes",
 * Journal of Graphics Tools (3), 1998, pp 1 - 11  
 **/
template<typename T>
class TriangularSurfaceMesh {
public:
    /// Typedefs for backward compatibility.
    typedef plb::Lid Lid;
    typedef plb::Edge Edge;
public:
    /// The ownership over the parameters vertexList, emanatingEdgeList, and
    ///   edgeList is not taken by the class TriangularSurfaceMesh, and they
    ///   are not being copied. They must be managed from outside and kept
    ///   alive up to the usage time of the TriangularSurfaceMesh instance.
    ///   The user may choose to disregard vertices at the end of vertexList,
    ///   and to only use a selected amount at the beginning: do this through
    ///   the parameter numVertices. A negative value for numVertices means:
    ///   use all vertices in vertexList.
    TriangularSurfaceMesh (
            std::vector<Array<T,3> >& vertexList_,
            std::vector<plint>& emanatingEdgeList_,
            std::vector<Edge>& edgeList_,
            plint numVertices_ = -1 );

    /// Return number of triangles on the surface (they are numbered 
    ///   continuously from 0 to getNumTriangles() -1.
    plint getNumTriangles() const {
        return numTriangles;
    }
    /// Return number of vertices on the surface (they are numbered 
    ///   continuously from 0 to getNumVertices() -1.
    plint getNumVertices() const {
        return numVertices;
    }
    /// Reset the position of a vertex to a new value;
    void replaceVertex(plint iVertex, Array<T,3> const& newPosition);

    /// Reset all vertices of a mesh to a default value.
    /** This function is used when debugging programs in which the access to the
     *  mesh is parallelized. Default values can be used to point out undefined
     *  state. In debug mode, vertices are identified to be invalid if all three
     *  coordinates are distinctly less than -1.
     */
    void resetVertices(Array<T,3> const& defaultVertex);

    /// Get one of the three vertices of a given triangle.
    ///   "localVertex" must be 0, 1 or 2.
    Array<T,3> const& getVertex(plint iTriangle, int localVertex) const;
    /// Get the coordinates of one of the vertices by providing its global index.
    Array<T,3> const& getVertex(plint iVertex) const;
    bool isValidVertex(plint iTriangle, int localVertex) const;
    bool isValidVertex(plint iVertex) const;

    /// Compute the minimum and maximum vertex positions in every direction.
    void computeBoundingBox (
            Array<T,2>& xRange,
            Array<T,2>& yRange,
            Array<T,2>& zRange ) const;

    /// Translate the surface mesh.
    void translate(Array<T,3> const& vector);
    /// Scale the surface mesh.
    void scale(T alpha);
    /// Rotate the surface mesh.
    ///   The arguments of this function are the Euler angles in radians.
    ///   The so-called "x-convention" is used, in which the rotation is
    ///   given by the three angles (phi, theta, psi), where:
    ///   1.] The first rotation is by an angle phi about the z-axis,
    ///   2.] The second rotation is by an angle theta in [0, pi] about
    ///       the new x-axis,
    ///   3.] The third rotation is by an angle psi about the new z-axis.
    void rotate(T phi, T theta, T psi);

    /// Smooth the surface mesh.
    ///   The triangular surface mesh is smoothed by using a spatial
    ///   averaging algorithm. Interior vertices are treated differently
    ///   than boundary ones. The mesh is smoothed as many times as
    ///   the integer argument "maxiter" indicates. If "isMeasureWeighted"
    ///   is true, then triangle areas and edge lengths are used in the
    ///   spatial averaging procedure. The smoothing method uses a relaxation
    ///   algorithm with a relaxation parameter 0 <= relax <= 1.
    void smooth(plint maxiter = 1, T relax = 1.0, bool isMeasureWeighted = false);

    /// Get the global vertex index of a specific vertex local to a triangle.
    plint getVertexId(plint iTriangle, plint localVertex) const;
    /// Get a list of the neighboring vertices of a given vertex.
    std::vector<plint> getNeighborVertexIds(plint iVertex) const;
    /// Get a list of the neighboring vertices of a given edge.
    std::vector<plint> getNeighborVertexIds(plint iVertex, plint jVertex) const;
    /// Get a list of the neighboring triangles of a given vertex.
    std::vector<plint> getNeighborTriangleIds(plint iVertex) const;
    /// Get a list of the adjacent triangles of a given triangle.
    ///   The adjacent triangles to a specific triangle are defined
    ///   as those that have common edges with the given triangle.
    std::vector<plint> getAdjacentTriangleIds(plint iTriangle) const;
    /// Get a list of the adjacent triangles of a given edge.
    ///   The adjacent triangles to a specific edge are defined
    ///   as those that have the specific edge common.
    std::vector<plint> getAdjacentTriangleIds(plint iVertex, plint jVertex) const;

    /// Compute the normal vector for a given triangle. If "isAreaWeighted" is false,
    ///   then the normal has length equal to one. If "isAreaWeighted" is true, then
    ///   the normal has length equal to twice the area of the triangle.
    Array<T,3> computeTriangleNormal(plint iTriangle, bool isAreaWeighted = false) const;
    Array<T,3> computeTriangleNormal(
            plint iVertex, plint jVertex, plint kVertex, bool isAreaWeighted = false) const;

    /// Compute the normal vector at a given edge. If "isAreaWeighted" is true, then
    ///   the triangle normals used in the computation are area weighted.
    Array<T,3> computeEdgeNormal(
            plint iVertex, plint jVertex, bool isAreaWeighted = false) const;
    /// Compute the normal vector at a given vertex. If "isAreaWeighted" is false, then
    ///   the vertex normal is calculated as the simple normalized sum of the individual
    ///   unit normals of the triangles which share the specific vertex. If
    ///   "isAreaWeighted" is true, then the vertex normal is calculated as the
    ///   normalized sum of the individual area weighted normals of the triangles which
    ///   share the vertex under consideration.
    Array<T,3> computeVertexNormal(plint iVertex, bool isAreaWeighted = false) const;

    /// Compute a "continuous" normal at a point "p" which belongs to the triangle
    ///   with index "iTriangle". The computed normal vector is normalized (has length
    ///   equal to one) and is continuous as its base point moves across the triangles.
    ///   The point "p" must belong to the interior or to the boundary of the triangle
    ///   with index "iTriangle". The currently implemented algorithm uses a barycentric
    ///   coordinate representation of the normal with respect to the three vertex
    ///   normals of the given triangle. If "isAreaWeighted" is true, then the vertex
    ///   normals used in the barycentric representation are area weighted.
    Array<T,3> computeContinuousNormal(
            Array<T,3> const& p, plint iTriangle, bool isAreaWeighted = false) const;

    /// Compute the area of a given triangle.
    T computeTriangleArea(plint iTriangle) const;
    T computeTriangleArea(plint iVertex, plint jVertex, plint kVertex) const;
    /// Compute the one third of the sum of the areas of the triangles that share
    ///   the specific edge.
    T computeEdgeArea(plint iVertex, plint jVertex) const;
    /// Compute the one third of the sum of the areas of all triangles that
    ///   share the given vertex.
    T computeVertexArea(plint iVertex) const;

    /// Compute the length of a given edge.
    T computeEdgeLength(plint iVertex, plint jVertex) const;

    /// Compute the dihedral angle of an edge (in radians).
    ///   By convention, if the edge is a boundary edge, the
    ///   dihedral angle returned by the function is 0.
    T computeDihedralAngle(plint iVertex, plint jVertex) const;

    /// Compute the one sixth of the sum of the heights of the
    ///   two triangles incident to the specific edge.
    T computeEdgeTileSpan(plint iVertex, plint jVertex) const;

    /// Export the surface mesh as a TriangleSet.
    TriangleSet<T> toTriangleSet(Precision precision) const;

    /// Export the surface mesh as an ASCII STL file.
    void writeAsciiSTL(std::string fname, T dx = 1.0) const;
    void writeAsciiSTL(std::string fname, T dx, Array<T,3> location) const;
    /// Export the surface mesh as an binary STL file.
    void writeBinarySTL(std::string fname, T dx = 1.0) const;
    void writeBinarySTL(std::string fname, T dx, Array<T,3> location) const;

    /// Return true if the vertex belongs to the boundary
    ///   or false if the vertex belongs to the interior
    ///   of the mesh.
    bool isBoundaryVertex(plint iVertex) const;
    /// Return true if the vertex belongs to the interior
    ///   or false if the vertex belongs to the boundary
    ///   of the mesh.
    bool isInteriorVertex(plint iVertex) const;

    /// Return true if the edge belongs to the boundary
    ///   or false if the edge belongs to the interior
    ///   of the mesh.
    bool isBoundaryEdge(plint iVertex, plint jVertex) const;
    /// Return true if the edge belongs to the interior
    ///   or false if the edge belongs to the boundary
    ///   of the mesh.
    bool isInteriorEdge(plint iVertex, plint jVertex) const;

    /// Function to compute the intersection between a triangle and a line segment
    ///   between points "point1" and "point2" (if flag = 0), or between a triangle
    ///   and a half-line starting at "point1" and containing "point2" (if flag = 1),
    ///   or between a triangle and a whole line containing both "point1" and
    ///   "point2" (if flag = 2). "intersection", "normal" and "distance" are
    ///   objects whose states are changed by this function. These states are undefined,
    ///   and cannot be used by the caller function, when the return value of this
    ///   function is not 1.
    ///   Returns 1 if an intersection is found and the intersection is inside
    ///   the triangle, 0 if there is no intersection or the intersection is
    ///   outside the triangle, and -1 is the line is parallel to the triangle
    ///   and intersects with an infinity of points.
    int pointOnTriangle (
            Array<T,3> const& point1, Array<T,3> const& point2, int flag, plint iTriangle,
            Array<T,3>& intersection, Array<T,3>& normal, T& distance ) const;

    /// The following function is a specialized version of the previous one. It simply checks
    ///   if a line segment between points "point1" and "point2" intersects a triangle. This
    ///   function is written for optimization purposes, and returns "true" if an intersection
    ///   is found and the intersection is inside the triangle, or "false" if there is no
    ///   intersection or the intersection is outside the triangle or if the line segment
    ///   belongs to the triangle and intersects with an infinity of points.
    bool segmentIntersectsTriangle (
            Array<T,3> const& point1, Array<T,3> const& point2, plint iTriangle ) const;

    /// Compute the distance between a point and a line which goes through a
    ///   given edge. Returns also a flag indicating whether the location on
    ///   the line which is closest to the point is inside the edge or not.
    void distanceToEdgeLine (
            Array<T,3> const& point, plint iTriangle, plint whichEdge,
            T& distance, bool& intersectionIsInside ) const;

    /// Compute the distance between a point and a plane which goes through a
    ///   given triangle. Returns two flags. The first indicates whether the
    ///   location on the plane which is closest to the point is inside the
    ///   triangle or not. The second indicates whether the point is "behind"
    ///   the plane, i.e. on the side which is opposed to the triangle normal.
    void distanceToTrianglePlane (
            Array<T,3> const& point, plint iTriangle,
            T& distance, bool& intersectionIsInside, bool& pointIsBehind ) const;

    /// Compute the distance between the point and a triangle. The location
    ///   on the triangle the distance to which is being computed is chosen
    ///   as follows. The point is first projected on the plane defined by
    ///   the triangle. If the obtained location is inside the triangle it is
    ///   being selected. Otherwise, it is projected on the three lines defined
    ///   by the edges, and the nearest one is picked out. If it is inside the
    ///   edge it is being selected. Otherwise, the answer consists of the
    ///   shortest distance between the point and the three vertices. Note
    ///   that none of the three cases (plane, edge, vertex) is degenerate:
    ///   there exists an infinity of points in space for which the nearest
    ///   distance to the triangle is on a vertex.
    void distanceToTriangle (
            Array<T,3> const& point, plint iTriangle,
            T& distance, bool& pointIsBehind ) const;

    /// Function to reverse the orientation of the given surface mesh.
    void reverseOrientation();

    /// Detect holes in the mesh and fill each of them by creating a lid,
    ///   i.e. a collection of triangles created by adding a single new
    ///   vertex at the barycenter of the hole, and connecting it radially
    ///   with each boundary vertex of the hole. Returns a Lid structure
    ///   for each created lid.
    std::vector<Lid> closeHoles();
    /// Returns, for each detected hole, a list of vertices.
    std::vector<std::vector<plint> > detectHoles();
    void avoidIntegerPositions();
    void avoidIntegerPosition(plint iVertex);
    void inflate(T amount=1.e-3);
public:
    /// Get a handle to the vertices.
    std::vector<Array<T,3> >const& vertices() const {
        PLB_PRECONDITION(vertexList);
        return *vertexList;
    }
    /// Get a handle to the emanating edges.
    std::vector<plint> const& emanatingEdges() const {
        PLB_PRECONDITION(emanatingEdgeList);
        return *emanatingEdgeList;
    }
    /// Get a handle to the edges.
    std::vector<Edge> const& edges() const {
        PLB_PRECONDITION(edgeList);
        return *edgeList;
    }
    /// Get one of the three vertices of a given triangle (non-const).
    ///   "localVertex" must be 0, 1 or 2.
    Array<T,3>& getVertex(plint iTriangle, int localVertex);
    /// Get the coordinates of one of the vertices by providing its global index (non-const).
    Array<T,3>& getVertex(plint iVertex);
public:
    /// Export the surface mesh as an HTML file.
    void writeHTML(std::string fname);
    void writeHTML(std::string fname, std::string title, T phys_dx, Array<T,3> phys_location);
    void writeX3D(std::string fname);
    void writeX3D(std::string fname, std::string title, T phys_dx, Array<T,3> phys_location);
private:
    /// Ensure the fact that a vertex is in a valid range by an assertion,
    ///   if STL vertices are bounded by IOpolicy().
    void assertVertex(Array<T,3> const& vertex) const;
    /// Get a non-const handle to the vertices.
    std::vector<Array<T,3> >& vertices() {
        PLB_PRECONDITION(vertexList);
        return *vertexList;
    }
    /// Get a non-const handle to the emanating edges.
    std::vector<plint>& emanatingEdges() {
        PLB_PRECONDITION(emanatingEdgeList);
        return *emanatingEdgeList;
    }
    /// Get a non-const handle to the edges.
    std::vector<Edge>& edges() {
        PLB_PRECONDITION(edgeList);
        return *edgeList;
    }
private:
    /// Close a single hole by creating a lid.
    Lid closeHole(std::vector<plint> const& hole);
private:
    plint prev(plint iEdge) const;
    plint next(plint iEdge) const;
    plint changeEdgeId(plint iEdge) const;
private:
    std::vector<Array<T,3> >* vertexList;
    std::vector<plint>* emanatingEdgeList;
    std::vector<Edge>* edgeList;
    plint numTriangles, numVertices;
public:
    static const T eps0, eps1;
};

template<typename T>
class LidLessThan {
public:
    LidLessThan(plint mainDirection_, TriangularSurfaceMesh<T> const& mesh_)
        : mainDirection(mainDirection_),
          mesh(mesh_)
    { }
    bool operator()(Lid const& lid1, Lid const& lid2) const
    {
        plint dim1 = mainDirection;
        plint dim2 = (dim1+1)%3;
        plint dim3 = (dim2+1)%3;
        // Compare on bary-center for main coordinate, and, in the unlikely
        //   case that these two floats are equal, on the two subsequent
        //   coordinates.
        Array<T,3> baryCenter1 = computeBaryCenter(mesh, lid1);
        Array<T,3> baryCenter2 = computeBaryCenter(mesh, lid2);
        return
          (baryCenter1[dim1] < baryCenter2[dim1]) || (
                  equiv(baryCenter1[dim1],baryCenter2[dim1]) && (
                      (baryCenter1[dim2] < baryCenter2[dim2]) || (
                          equiv(baryCenter1[dim2],baryCenter2[dim2]) &&
                          (baryCenter1[dim3] < baryCenter2[dim3]) ) ) ) ;
    }
    static bool equiv(T a, T b) {
        return !(a<b || b<a);
    }
private:
    plint mainDirection;
    TriangularSurfaceMesh<T> const& mesh;
};

/// Returns the scaling factor.
template<typename T>
T toLatticeUnits (
        TriangularSurfaceMesh<T>& mesh,
        plint resolution, plint referenceDirection );



/* ******* Lid operations ************************************************** */

template<typename T>
Array<T,3> computeBaryCenter (
        TriangularSurfaceMesh<T> const& mesh, Lid const& lid );

template<typename T>
void computeBoundingBox (
        TriangularSurfaceMesh<T> const& mesh, Lid const& lid,
        Array<T,2>& xLim, Array<T,2>& yLim, Array<T,2>& zLim );

template<typename T>
T computeInnerRadius (
        TriangularSurfaceMesh<T> const& mesh, Lid const& lid );

template<typename T>
T computeOuterRadius (
        TriangularSurfaceMesh<T> const& mesh, Lid const& lid );

template<typename T>
T computeArea (
        TriangularSurfaceMesh<T> const& mesh, Lid const& lid );

template<typename T>
Array<T,3> computeNormal (
        TriangularSurfaceMesh<T> const& mesh, Lid const& lid );

template<typename T>
void reCenter (
        TriangularSurfaceMesh<T>& mesh, Lid const& lid );

} // namespace plb

#endif  // TRIANGULAR_SURFACE_MESH_H