Tube and Thickened Mesh Level Set Constructors
Summary
This PR introduces level set constructors for
- capsules
- tapered capsules (different radius at the endpoints)
- tube complex with constant or varying radius
- thickened triangle, quad, or mixed mesh (thickens in all directions)
A base class ConvexVoxelizer, which provides the infrastructure for convex level set construction, is also introduced.
class tools::ConvexVoxelizer
This base class requires the derived class implement methods such as
- intersections of the convex region with rays in the cardinal directions
- signed distance
- a few optional ones too
A simple example that creates a level set sphere can be found in the doxygen here.
tools::createLevelSetCapsule
Implemented in tools/LevelSetTubes.h via class CapsuleVoxelizer:
template <typename GridType, typename InterruptT>
typename GridType::Ptr
createLevelSetCapsule(const Vec3s& pt1, const Vec3s& pt2, float radius, float voxelSize,
float halfWidth = float(LEVEL_SET_HALF_WIDTH),
InterruptT* interrupter = nullptr, bool threaded = true);
and
template <typename GridType>
typename GridType::Ptr
createLevelSetCapsule(const Vec3s& pt1, const Vec3s& pt2, float radius, float voxelSize,
float halfWidth = float(LEVEL_SET_HALF_WIDTH), bool threaded = true);
Example:
const Vec3s p1(15.8f, 13.2f, 16.7f), p2(4.3f, 7.9f, -4.8f);
const float r1 = 4.3f, voxelSize = 0.1f;
FloatGrid::Ptr grid = tools::createLevelSetCapsule<FloatGrid>(p1, p2, r1, voxelSize);
yielding
tools::createLevelSetTaperedCapsule
Implemented in tools/LevelSetTubes.h via class TaperedCapsuleVoxelizer:
template <typename GridType, typename InterruptT>
typename GridType::Ptr
createLevelSetTaperedCapsule(const Vec3s& pt1, const Vec3s& pt2, float radius1, float radius2,
float voxelSize, float halfWidth = float(LEVEL_SET_HALF_WIDTH),
InterruptT* interrupter = nullptr, bool threaded = true);
and
template <typename GridType>
typename GridType::Ptr
createLevelSetTaperedCapsule(const Vec3s& pt1, const Vec3s& pt2, float radius1, float radius2,
float voxelSize, float halfWidth = float(LEVEL_SET_HALF_WIDTH), bool threaded = true);
Example:
const Vec3s p1(15.8f, 13.2f, 16.7f), p2(4.3f, 7.9f, -4.8f);
const float r1 = 4.3f, r2 = 1.2f, voxelSize = 0.1f;
FloatGrid::Ptr grid = tools::createLevelSetTaperedCapsule<FloatGrid>(p1, p2, r1, r2, voxelSize);
yielding
tools::createLevelSetTubeComplex
Implemented in tools/LevelSetTubes.h via class TubeComplexVoxelizer:
template <typename GridType, typename InterruptT = util::NullInterrupter>
typename GridType::Ptr
createLevelSetTubeComplex(const std::vector<Vec3s>& vertices, const std::vector<Vec2I>& segments,
float radius, float voxelSize, float halfWidth = float(LEVEL_SET_HALF_WIDTH),
InterruptT* interrupter = nullptr);
and
template <typename GridType, typename InterruptT = util::NullInterrupter>
typename GridType::Ptr
createLevelSetTubeComplex(const std::vector<Vec3s>& vertices, const std::vector<Vec2I>& segments,
const std::vector<float>& radii, float voxelSize,
float halfWidth = float(LEVEL_SET_HALF_WIDTH), TubeRadiiPolicy radii_policy = TUBE_AUTOMATIC,
InterruptT* interrupter = nullptr);
The different TubeRadiiPolicy are described here.
Example of constant radius:
const Vec3s p0(0.0f, 0.0f, 0.0f), p1(0.0f, 0.0f, 1.0f),
p2(-0.471405f, -0.816497f, -0.333333f), p3(-0.471405f, 0.816497f, -0.333333f),
p4(0.942809f, 0.0f, -0.333333f);
const float r = 0.2f, voxelSize = 0.0125f;
const std::vector<Vec3s> vertices({p0, p1, p2, p3, p4});
const std::vector<Vec2I> segments({Vec2I(0, 1), Vec2I(0, 2), Vec2I(0, 3), Vec2I(0, 4)});
FloatGrid::Ptr grid = tools::createLevelSetTubeComplex<FloatGrid>(vertices, segments, radii, voxelSize);
yielding
Example of varying radius:
const Vec3s p0(0.0f, 0.0f, 0.0f), p1(0.0f, 0.0f, 1.0f),
p2(-0.471405f, -0.816497f, -0.333333f), p3(-0.471405f, 0.816497f, -0.333333f),
p4(0.942809f, 0.0f, -0.333333f);
const std::vector<float> radii({0.15f, 0.15f, 0.1f, 0.05f, 0.0f});
const float voxelSize = 0.0125f;
const std::vector<Vec3s> vertices({p0, p1, p2, p3, p4});
const std::vector<Vec2I> segments({Vec2I(0, 1), Vec2I(0, 2), Vec2I(0, 3), Vec2I(0, 4)});
FloatGrid::Ptr grid = tools::createLevelSetTubeComplex<FloatGrid>(vertices, segments, r, voxelSize);
yielding
tools::createLevelSetThickenedMesh
Implemented in tools/LevelSetThickenedMesh.h via class TubeComplexVoxelizer:
template <typename GridType, typename InterruptT = util::NullInterrupter>
typename GridType::Ptr
createLevelSetThickenedMesh(
const std::vector<Vec3s>& vertices, const std::vector<Vec3I>& triangles,
float radius, float voxelSize, float halfWidth = float(LEVEL_SET_HALF_WIDTH),
InterruptT* interrupter = nullptr);
and
template <typename GridType, typename InterruptT = util::NullInterrupter>
typename GridType::Ptr
createLevelSetThickenedMesh(
const std::vector<Vec3s>& vertices, const std::vector<Vec4I>& quads,
float radius, float voxelSize, float halfWidth = float(LEVEL_SET_HALF_WIDTH),
InterruptT* interrupter = nullptr);
and
template <typename GridType, typename InterruptT = util::NullInterrupter>
typename GridType::Ptr
createLevelSetThickenedMesh(const std::vector<Vec3s>& vertices,
const std::vector<Vec3I>& triangles, const std::vector<Vec4I>& quads,
float radius, float voxelSize, float halfWidth = float(LEVEL_SET_HALF_WIDTH),
InterruptT* interrupter = nullptr);
Initialize mesh data:
const float r = 2.9f;
const Vec3s p0(15.8f, 13.2f, 16.7f), p1(4.3f, 7.9f, -4.8f);
const Vec3s p2(-3.0f, -7.4f, 8.9f), p3(-2.7f, 8.9f, 30.4f);
const Vec3s p4(23.0f, 17.4f, -10.9f), p5(5.2f, -5.7f, 29.0f);
const Vec3s p6(-14.6f, 3.7f, 10.9f), p7(35.8f, 23.4f, 5.8f);
const std::vector<Vec3s> vertices({p0, p1, p2, p3, p4, p5, p6, p7});
const std::vector<Vec3I> triangles1({Vec3I(0, 1, 2), Vec3I(0, 1, 3), Vec3I(0, 1, 4)});
const std::vector<Vec3I> triangles2({Vec3I(0, 1, 4)});
const std::vector<Vec4I> quads1({Vec4I(0, 1, 2, 5), Vec4I(0, 1, 6, 3), Vec4I(0, 1, 4, 7)});
const std::vector<Vec4I> quads2({Vec4I(0, 1, 2, 5), Vec4I(0, 1, 6, 3)});
Example of triangle mesh:
FloatGrid::Ptr grid = tools::createLevelSetThickenedMesh<FloatGrid>(vertices, triangles1, r, voxelSize);
yielding
Example of quad mesh:
FloatGrid::Ptr grid = tools::createLevelSetThickenedMesh<FloatGrid>(vertices, quads1, r, voxelSize);
yielding
Example of mixed mesh:
FloatGrid::Ptr grid = tools::createLevelSetThickenedMesh<FloatGrid>(vertices, triangles2, quads2, r, voxelSize);
yielding