Skip to content

Commit

Permalink
Base: introduce Polygon3dBuilder helper
Browse files Browse the repository at this point in the history
  • Loading branch information
HuguesDelorme committed Nov 24, 2023
1 parent 5769a45 commit 85b553b
Show file tree
Hide file tree
Showing 2 changed files with 161 additions and 54 deletions.
108 changes: 96 additions & 12 deletions src/base/mesh_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,32 @@

#include "mesh_utils.h"
#include "math_utils.h"
#include <Standard_Version.hxx>

#include <cassert>
#include <cmath>
#include <stdexcept>

namespace Mayo {
namespace MeshUtils {

namespace {

double MeshUtils::triangleSignedVolume(const gp_XYZ& p1, const gp_XYZ& p2, const gp_XYZ& p3)
TColStd_Array1OfReal createArray1OfReal(int count)
{
if (count > 0)
return TColStd_Array1OfReal(1 , count);
else
return TColStd_Array1OfReal();
}

} // namespace

double triangleSignedVolume(const gp_XYZ& p1, const gp_XYZ& p2, const gp_XYZ& p3)
{
return p1.Dot(p2.Crossed(p3)) / 6.0f;
}

double MeshUtils::triangleArea(const gp_XYZ& p1, const gp_XYZ& p2, const gp_XYZ& p3)
double triangleArea(const gp_XYZ& p1, const gp_XYZ& p2, const gp_XYZ& p3)
{
const double ax = p2.X() - p1.X();
const double ay = p2.Y() - p1.Y();
Expand All @@ -30,7 +45,7 @@ double MeshUtils::triangleArea(const gp_XYZ& p1, const gp_XYZ& p2, const gp_XYZ&
return 0.5 * std::sqrt(cx*cx + cy*cy + cz*cz);
}

double MeshUtils::triangulationVolume(const Handle_Poly_Triangulation& triangulation)
double triangulationVolume(const Handle_Poly_Triangulation& triangulation)
{
if (!triangulation)
return 0;
Expand All @@ -49,7 +64,7 @@ double MeshUtils::triangulationVolume(const Handle_Poly_Triangulation& triangula
return std::abs(volume);
}

double MeshUtils::triangulationArea(const Handle_Poly_Triangulation& triangulation)
double triangulationArea(const Handle_Poly_Triangulation& triangulation)
{
if (!triangulation)
return 0;
Expand All @@ -68,7 +83,7 @@ double MeshUtils::triangulationArea(const Handle_Poly_Triangulation& triangulati
return area;
}

void MeshUtils::setNode(const Handle_Poly_Triangulation& triangulation, int index, const gp_Pnt& pnt)
void setNode(const Handle_Poly_Triangulation& triangulation, int index, const gp_Pnt& pnt)
{
#if OCC_VERSION_HEX >= 0x070600
triangulation->SetNode(index, pnt);
Expand All @@ -77,7 +92,7 @@ void MeshUtils::setNode(const Handle_Poly_Triangulation& triangulation, int inde
#endif
}

void MeshUtils::setTriangle(const Handle_Poly_Triangulation& triangulation, int index, const Poly_Triangle& triangle)
void setTriangle(const Handle_Poly_Triangulation& triangulation, int index, const Poly_Triangle& triangle)
{
#if OCC_VERSION_HEX >= 0x070600
triangulation->SetTriangle(index, triangle);
Expand All @@ -86,7 +101,7 @@ void MeshUtils::setTriangle(const Handle_Poly_Triangulation& triangulation, int
#endif
}

void MeshUtils::setNormal(const Handle_Poly_Triangulation& triangulation, int index, const Poly_Triangulation_NormalType& n)
void setNormal(const Handle_Poly_Triangulation& triangulation, int index, const Poly_Triangulation_NormalType& n)
{
#if OCC_VERSION_HEX >= 0x070600
triangulation->SetNormal(index, n);
Expand All @@ -98,7 +113,7 @@ void MeshUtils::setNormal(const Handle_Poly_Triangulation& triangulation, int in
#endif
}

void MeshUtils::setUvNode(const Handle_Poly_Triangulation& triangulation, int index, double u, double v)
void setUvNode(const Handle_Poly_Triangulation& triangulation, int index, double u, double v)
{
#if OCC_VERSION_HEX >= 0x070600
triangulation->SetUVNode(index, gp_Pnt2d{u, v});
Expand All @@ -107,7 +122,7 @@ void MeshUtils::setUvNode(const Handle_Poly_Triangulation& triangulation, int in
#endif
}

void MeshUtils::allocateNormals(const Handle_Poly_Triangulation& triangulation)
void allocateNormals(const Handle_Poly_Triangulation& triangulation)
{
#if OCC_VERSION_HEX >= 0x070600
triangulation->AddNormals();
Expand All @@ -117,8 +132,18 @@ void MeshUtils::allocateNormals(const Handle_Poly_Triangulation& triangulation)
#endif
}

const Poly_Array1OfTriangle& triangles(const Handle_Poly_Triangulation& triangulation)
{
#if OCC_VERSION_HEX < 0x070600
return triangulation->Triangles();
#else
// Note: Poly_Triangulation::Triangles() was deprecated starting from OpenCascade v7.6.0
return triangulation->InternalTriangles();
#endif
}

// Adapted from http://cs.smith.edu/~jorourke/Code/polyorient.C
MeshUtils::Orientation MeshUtils::orientation(const AdaptorPolyline2d& polyline)
MeshUtils::Orientation orientation(const AdaptorPolyline2d& polyline)
{
const int pntCount = polyline.pointCount();
if (pntCount < 2)
Expand Down Expand Up @@ -172,7 +197,7 @@ MeshUtils::Orientation MeshUtils::orientation(const AdaptorPolyline2d& polyline)
}
}

gp_Vec MeshUtils::directionAt(const AdaptorPolyline3d& polyline, int i)
gp_Vec directionAt(const AdaptorPolyline3d& polyline, int i)
{
const int pntCount = polyline.pointCount();
if (pntCount > 1) {
Expand All @@ -191,4 +216,63 @@ gp_Vec MeshUtils::directionAt(const AdaptorPolyline3d& polyline, int i)
return gp_Vec();
}

Polygon3dBuilder::Polygon3dBuilder(int nodeCount, ParametersOption option)
#if OCC_VERSION_HEX >= 0x070500
: m_polygon(new Poly_Polygon3D(nodeCount, option == ParametersOption::With)),
m_ptrNodes(&m_polygon->ChangeNodes()),
m_ptrParams(option == ParametersOption::With ? &m_polygon->ChangeParameters() : nullptr)
#else
: m_nodes(1, nodeCount),
m_params(std::move(createArray1OfReal(option == ParametersOption::With ? nodeCount : 0))),
m_ptrNodes(&m_nodes),
m_ptrParams(option == ParametersOption::With ? &m_params : nullptr)
#endif
{
assert(m_ptrNodes);
assert(
(option == ParametersOption::None && !m_ptrParams)
|| (option == ParametersOption::With && m_ptrParams)
);
}

void Polygon3dBuilder::setNode(int i, const gp_Pnt &pnt)
{
if (m_isFinalized)
throw std::runtime_error("Can't call setNode() on finalized Polygon3dBuilder object");

m_ptrNodes->ChangeValue(i) = pnt;
}

void Polygon3dBuilder::setParameter(int i, double u)
{
if (m_isFinalized)
throw std::runtime_error("Can't call setParameter() on finalized Polygon3dBuilder object");

if (m_ptrParams)
m_ptrParams->ChangeValue(i) = u;
}

void Polygon3dBuilder::finalize()
{
if (m_isFinalized)
return;

#if OCC_VERSION_HEX < 0x070500
if (m_ptrParams)
m_polygon = new Poly_Polygon3D(m_nodes, m_params);
else
m_polygon = new Poly_Polygon3D(m_nodes);
#endif
m_isFinalized = true;
}

OccHandle<Poly_Polygon3D> Polygon3dBuilder::get() const
{
if (!m_isFinalized)
throw std::runtime_error("Can't call get() on non finalized Polygon3dBuilder object");

return m_polygon;
}

} // namespace MeshUtils
} // namespace Mayo
107 changes: 65 additions & 42 deletions src/base/mesh_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,63 +6,86 @@

#pragma once

#include "occ_handle.h"

#include <Poly_Polygon3D.hxx>
#include <Poly_Triangulation.hxx>
#include <Standard_Version.hxx>
class gp_XYZ;

namespace Mayo {

// Provides helper functions for mesh and triangle objects
struct MeshUtils {
static double triangleSignedVolume(const gp_XYZ& p1, const gp_XYZ& p2, const gp_XYZ& p3);
static double triangleArea(const gp_XYZ& p1, const gp_XYZ& p2, const gp_XYZ& p3);
namespace MeshUtils {

double triangleSignedVolume(const gp_XYZ& p1, const gp_XYZ& p2, const gp_XYZ& p3);
double triangleArea(const gp_XYZ& p1, const gp_XYZ& p2, const gp_XYZ& p3);

static double triangulationVolume(const Handle_Poly_Triangulation& triangulation);
static double triangulationArea(const Handle_Poly_Triangulation& triangulation);
double triangulationVolume(const Handle_Poly_Triangulation& triangulation);
double triangulationArea(const Handle_Poly_Triangulation& triangulation);

#if OCC_VERSION_HEX >= 0x070600
using Poly_Triangulation_NormalType = gp_Vec3f;
using Poly_Triangulation_NormalType = gp_Vec3f;
#else
using Poly_Triangulation_NormalType = gp_Vec;
using Poly_Triangulation_NormalType = gp_Vec;
#endif

static void setNode(const Handle_Poly_Triangulation& triangulation, int index, const gp_Pnt& pnt);
static void setTriangle(const Handle_Poly_Triangulation& triangulation, int index, const Poly_Triangle& triangle);
static void setNormal(const Handle_Poly_Triangulation& triangulation, int index, const Poly_Triangulation_NormalType& n);
static void setUvNode(const Handle_Poly_Triangulation& triangulation, int index, double u, double v);
static void allocateNormals(const Handle_Poly_Triangulation& triangulation);
void setNode(const Handle_Poly_Triangulation& triangulation, int index, const gp_Pnt& pnt);
void setTriangle(const Handle_Poly_Triangulation& triangulation, int index, const Poly_Triangle& triangle);
void setNormal(const Handle_Poly_Triangulation& triangulation, int index, const Poly_Triangulation_NormalType& n);
void setUvNode(const Handle_Poly_Triangulation& triangulation, int index, double u, double v);
void allocateNormals(const Handle_Poly_Triangulation& triangulation);

static const Poly_Array1OfTriangle& triangles(const Handle_Poly_Triangulation& triangulation) {
#if OCC_VERSION_HEX < 0x070600
return triangulation->Triangles();
#else
// Note: Poly_Triangulation::Triangles() was deprecated starting from OpenCascade v7.6.0
return triangulation->InternalTriangles();
const Poly_Array1OfTriangle& triangles(const Handle_Poly_Triangulation& triangulation);

enum class Orientation {
Unknown,
Clockwise,
CounterClockwise
};

class AdaptorPolyline2d {
public:
virtual gp_Pnt2d pointAt(int index) const = 0;
virtual int pointCount() const = 0;
virtual bool empty() const { return this->pointCount() <= 0; }
};

class AdaptorPolyline3d {
public:
virtual const gp_Pnt& pointAt(int i) const = 0;
virtual int pointCount() const = 0;
virtual int empty() const { return this->pointCount() <= 0; }
};

Orientation orientation(const AdaptorPolyline2d& polyline);
gp_Vec directionAt(const AdaptorPolyline3d& polyline, int i);

// Provides helper to create Poly_Polygon3D objects
// Poly_Polygon3D class interface changed from OpenCascade 7.4 to 7.5 version so using this class
// directly might cause compilation errors
// Prefer Polygon3dBuilder so application code doesn't have to care about OpenCascade version
class Polygon3dBuilder {
public:
enum class ParametersOption { None, With };

Polygon3dBuilder(int nodeCount, ParametersOption option = ParametersOption::None);

void setNode(int i, const gp_Pnt& pnt);
void setParameter(int i, double u);
void finalize();
OccHandle<Poly_Polygon3D> get() const;

private:
bool m_isFinalized = false;
OccHandle<Poly_Polygon3D> m_polygon;
#if OCC_VERSION_HEX < 0x070500
TColgp_Array1OfPnt m_nodes;
TColStd_Array1OfReal m_params;
#endif
}

enum class Orientation {
Unknown,
Clockwise,
CounterClockwise
};

class AdaptorPolyline2d {
public:
virtual gp_Pnt2d pointAt(int index) const = 0;
virtual int pointCount() const = 0;
virtual bool empty() const { return this->pointCount() <= 0; }
};

class AdaptorPolyline3d {
public:
virtual const gp_Pnt& pointAt(int i) const = 0;
virtual int pointCount() const = 0;
virtual int empty() const { return this->pointCount() <= 0; }
};

static Orientation orientation(const AdaptorPolyline2d& polyline);
static gp_Vec directionAt(const AdaptorPolyline3d& polyline, int i);
TColgp_Array1OfPnt* m_ptrNodes = nullptr;
TColStd_Array1OfReal* m_ptrParams = nullptr;
};

} // namespace MeshUtils
} // namespace Mayo

0 comments on commit 85b553b

Please sign in to comment.