Skip to content

Commit

Permalink
Merge branch 'task/dxf-sync' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
HuguesDelorme committed Dec 6, 2023
2 parents df7a7e8 + 5f66a7a commit 763c890
Show file tree
Hide file tree
Showing 10 changed files with 2,737 additions and 1,818 deletions.
9 changes: 9 additions & 0 deletions src/base/brep_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,15 @@ void BRepUtils::addShape(TopoDS_Shape* ptrTargetShape, const TopoDS_Shape& shape
builder.Add(*ptrTargetShape, shape);
}

TopoDS_Edge BRepUtils::makeEdge(const Handle(Poly_Polygon3D)& polygon)
{
TopoDS_Edge edge;
BRep_Builder builder;
builder.MakeEdge(edge);
builder.UpdateEdge(edge, polygon);
return edge;
}

TopoDS_Face BRepUtils::makeFace(const Handle(Poly_Triangulation)& mesh)
{
TopoDS_Face face;
Expand Down
5 changes: 5 additions & 0 deletions src/base/brep_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@

#include "occ_brep_mesh_parameters.h"

#include <Poly_Polygon3D.hxx>
#include <Poly_Triangulation.hxx>
#include <TopoDS_Edge.hxx>
#include <TopoDS_Face.hxx>
#include <TopExp_Explorer.hxx>
#include <TopoDS.hxx>
Expand All @@ -26,6 +28,9 @@ struct BRepUtils {
// Adds 'shape' in target shape 'ptrTargetShape'
static void addShape(TopoDS_Shape* ptrTargetShape, const TopoDS_Shape& shape);

// Creates a non-geometric TopoDS_Edge wrapping 'polygon'
static TopoDS_Edge makeEdge(const Handle(Poly_Polygon3D)& polygon);

// Creates a non-geometric TopoDS_Face wrapping triangulation 'mesh'
static TopoDS_Face makeFace(const Handle(Poly_Triangulation)& mesh);

Expand Down
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
20 changes: 10 additions & 10 deletions src/base/property_value_conversion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,18 @@ namespace {
static std::string toString(double value, int prec = 6)
{
#if __cpp_lib_to_chars
char buff[64] = {};
auto toCharsFormat = std::chars_format::general;
auto resToChars = std::to_chars(std::begin(buff), std::end(buff), value, toCharsFormat, prec);
if (resToChars.ec != std::errc())
throw std::runtime_error("value_too_large");
char buff[64] = {};
auto toCharsFormat = std::chars_format::general;
auto resToChars = std::to_chars(std::begin(buff), std::end(buff), value, toCharsFormat, prec);
if (resToChars.ec != std::errc())
throw std::runtime_error("value_too_large");

return std::string(buff, resToChars.ptr - buff);
return std::string(buff, resToChars.ptr - buff);
#else
std::stringstream sstr;
sstr.precision(prec);
sstr << value;
return sstr.str();
std::stringstream sstr;
sstr.precision(prec);
sstr << value;
return sstr.str();
#endif
}

Expand Down
Loading

0 comments on commit 763c890

Please sign in to comment.