/* This file is part of the OpenLB library
*
* Copyright (C) 2010-2015 Thomas Henn, Mathias J. Krause
* E-mail contact: info@openlb.net
* The most recent release of OpenLB can be downloaded at
*
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/** \file
* Input in STL format -- header file.
*/
#ifndef STL_READER_H
#define STL_READER_H
#include
#include
#include
#include
#include
#include "communication/loadBalancer.h"
#include "geometry/cuboidGeometry3D.h"
#include "functors/analytical/indicator/indicatorF3D.h"
#include "functors/analytical/indicator/indicatorBaseF3D.h"
#include "utilities/vectorHelpers.h"
#include "octree.h"
#include "core/vector.h"
using namespace olb::util;
/// All OpenLB code is contained in this namespace.
namespace olb {
template
class Octree;
template
struct STLpoint {
/// Constructor constructs
STLpoint() : r() {};
/// Operator= equals
STLpoint& operator=(STLpoint const& rhs)
{
r = rhs.r;
return *this;
};
/// CopyConstructor copies
STLpoint(STLpoint const& rhs):r(rhs.r) {};
/// Point coordinates in SI units
Vector r;
};
template
struct STLtriangle {
/** Test intersection between ray and triangle
* \param pt Raypoint
* \param dir Direction
* \param q Point of intersection (if intersection occurs)
* \param alpha Explained in http://www.uninformativ.de/bin/RaytracingSchnitttests-76a577a-CC-BY.pdf page 7-12
* q = pt + alpha * dir
* \param rad It's complicated. Imagine you have a sphere with radius rad moving a long the ray. Then q becomes the first point of the sphere to touch the triangle.
*/
bool testRayIntersect(const Vector& pt,const Vector& dir, Vector& q, T& alpha, const T& rad = T(), bool print = false);
Vector closestPtPointTriangle(const Vector& pt) const;
/// A triangle contains 3 Points
std::vector > point;
/// normal of triangle
Vector normal;
/// variables explained in http://www.uninformativ.de/bin/RaytracingSchnitttests-76a577a-CC-BY.pdf page 7-12
/// precomputed for speedup
Vector uBeta, uGamma;
T d, kBeta, kGamma;
public:
/// Constructor constructs
STLtriangle():point(3, STLpoint()), normal(T()), uBeta(T()), uGamma(T()), d(T()), kBeta(T()), kGamma(T()) {};
/// CopyConstructor copies
STLtriangle(STLtriangle const& tri):point(tri.point), normal(tri.normal), uBeta(tri.uBeta), uGamma(tri.uGamma), d(tri.d), kBeta(tri.kBeta), kGamma(tri.kGamma) {};
/// Operator= equals
STLtriangle& operator=(STLtriangle const& tri)
{
point = tri.point;
normal = tri.normal;
uBeta = tri.uBeta;
uGamma = tri.uGamma;
d = tri.d;
kBeta = tri.kBeta;
kGamma = tri.kGamma;
return *this;
};
~STLtriangle() {};
/// Initializes triangle and precomputes member variables.
void init();
/// Return write access to normal
inline Vector& getNormal()
{
return normal;
}
/// Returns Pt0-Pt1
std::vector getE0();
/// Returns Pt0-Pt2
std::vector getE1();
};
template
class STLmesh {
/// Computes distance squared betwenn p1 and p2
T distPoints(STLpoint& p1, STLpoint& p2);
/// Filename
const std::string _fName;
/// Vector of Triangles
std::vector > _triangles;
/// Min and Max points of axis aligned bounding box coordinate in SI units
Vector _min, _max;
/// largest squared length of edge of all triangles
T _maxDist2;
/// OstreamManager
mutable OstreamManager clout;
public:
/**
* Constructs a new STLmesh from a file
* \param Filename - Filename
* \param stlSize - Conversion factor for STL (e.g. STL in mm stlSize=10^-3)
*/
STLmesh(std::string, T stlSize = 1.);
/**
* Constructs a new STLmesh from a file
* \param Filename - Filename
* \param stlSize - Conversion factor for STL (e.g. STL in mm stlSize=10^-3)
*/
STLmesh(const std::vector> meshPoints, T stlSize = 1.);
/// Returns reference to a triangle
inline STLtriangle& getTri(unsigned int i)
{
return _triangles[i];
}
/// Returns number of triangles
inline unsigned int triangleSize() const
{
return _triangles.size();
}
/// Returns _min
inline Vector& getMin()
{
return _min;
};
/// Returns _max
inline Vector& getMax()
{
return _max;
};
/// Returns maxDist squared
inline float maxDist2() const
{
return _maxDist2;
}
/// Prints console output
void print(bool full = false);
/// Writes STL mesh in Si units
void write(std::string fName);
/// Compute intersection between Ray and set of triangles; returns true if intersection is found
bool testRayIntersect(const std::set& tris, const Vector& pt,const Vector& dir, Vector& q, T& alpha);
};
template
class STLreader : public IndicatorF3D {
private:
/*
* Old indicate function (slower, more stable)
* Define three rays (X-, Y-, Z-direction) for each leaf and count intersections
* with STL for each ray. Odd number of intersection means inside (Majority vote).
*/
void indicate1();
/*
* New indicate function (faster, less stable)
* Define ray in Z-direction for each Voxel in XY-layer. Indicate all nodes on the fly.
*/
void indicate2();
/*
* Double ray approach: two times (X-, Y-, Z-direction) for each leaf.
* Could be use to deal with double layer triangles and face intersections.
*/
void indicate3();
/// Size of the smallest voxel
T _voxelSize;
/// Factor to get Si unit (m), i.e. "0.001" means mm
T _stlSize;
/// Overlap increases Octree radius by _overlap
T _overlap;
/// Pointer to tree
Octree* _tree;
/// The filename
const std::string _fName;
/// The mesh
STLmesh _mesh;
/// Variable for output
bool _verbose;
/// The OstreamManager
mutable OstreamManager clout;
public:
/**
* Constructs a new STLreader from a file
* \param fName The STL file name
* \param voxelSize Voxelsize in SI units
* \param stlSize Conversion factor for STL (e.g. STL in mm stlSize=10^-3)
* \param method Choose indication method
* 0: fast, less stable
* 1: slow, more stable (for untight STLs)
* \param verbose Get additional information.
*/
STLreader(const std::string fName, T voxelSize, T stlSize=1, unsigned short int method=2,
bool verbose = false, T overlap=0., T max=0.);
/**
* Constructs a new STLreader from a file
* \param fName The STL file name
* \param voxelSize Voxelsize in SI units
* \param stlSize Conversion factor for STL (e.g. STL in mm stlSize=10^-3)
* \param method Choose indication method
* 0: fast, less stable
* 1: slow, more stable (for untight STLs)
* \param verbose Get additional information.
*/
STLreader(const std::vector> meshPoints, T voxelSize, T stlSize=1, unsigned short int method=2,
bool verbose = false, T overlap=0., T max=0.);
~STLreader() override;
/// Returns whether node is inside or not.
bool operator() (bool output[], const T input[]) override;
/// Computes distance to closest triangle intersection
bool distance(T& distance,const Vector& origin, const Vector& direction, int iC=-1) override;
/// Prints console output
void print();
/// Writes STL mesh in Si units
void writeSTL(std::string stlName="");
/// Writes Octree
void writeOctree();
/// Rearranges normals of triangles to point outside of geometry
void setNormalsOutside();
/// Returns tree
inline Octree* getTree() const
{
return _tree;
};
/// Returns mesh
inline STLmesh& getMesh()
{
return _mesh;
};
};
} // namespace olb
#endif