1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-06-10 11:34:06 +03:00
occt/src/BRepMesh/BRepMesh_Triangulator.cxx
dpasukhi a5a7b3185b Coding - Apply .clang-format formatting #286
Update empty method guards to new style with regex (see PR).
Used clang-format 18.1.8.
New actions to validate code formatting is added.
Update .clang-format with disabling of include sorting.
  It is temporary changes, then include will be sorted.
Apply formatting for /src and /tools folder.
The files with .hxx,.cxx,.lxx,.h,.pxx,.hpp,*.cpp extensions.
2025-01-26 00:43:57 +00:00

277 lines
9.4 KiB
C++

// Created: 2017-12-28
//
// Copyright (c) 2017 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#include <BRepMesh_Triangulator.hxx>
#include <Precision.hxx>
#include <ProjLib.hxx>
#include <Message.hxx>
#include <Message_Messenger.hxx>
#include <BRepMesh_Delaun.hxx>
#ifdef CHECK_PERF
#include <MoniTool_Timer.hxx>
#include <MoniTool_TimerSentry.hxx>
#endif
namespace
{
//=================================================================================================
inline Standard_Integer wireNodesNb(const NCollection_List<TColStd_SequenceOfInteger>& theWires)
{
Standard_Integer nbNodes = 0;
NCollection_List<TColStd_SequenceOfInteger>::Iterator itW(theWires);
for (Standard_Integer i = 1; itW.More(); itW.Next(), i++)
{
nbNodes += itW.Value().Length();
}
return nbNodes;
}
//=================================================================================================
inline void appendTriangle(const int theNode1,
const int theNode2,
const int theNode3,
const TColStd_SequenceOfInteger& theW,
NCollection_List<Poly_Triangle>& thePolyTriangles)
{
const Poly_Triangle aT1(theW(theNode1) + 1, theW(theNode2) + 1, theW(theNode3) + 1);
thePolyTriangles.Append(aT1);
}
} // namespace
//=================================================================================================
Handle(Poly_Triangulation) BRepMesh_Triangulator::ToPolyTriangulation(
const TColgp_Array1OfPnt& theNodes,
const NCollection_List<Poly_Triangle>& thePolyTriangles)
{
Poly_Array1OfTriangle aTriangles(1, thePolyTriangles.Extent());
NCollection_List<Poly_Triangle>::Iterator itT(thePolyTriangles);
for (Standard_Integer i = 1; itT.More(); itT.Next(), i++)
{
aTriangles.SetValue(i, itT.Value());
}
return new Poly_Triangulation(theNodes, aTriangles);
}
//=================================================================================================
BRepMesh_Triangulator::BRepMesh_Triangulator(
const NCollection_Vector<gp_XYZ>& theXYZs,
const NCollection_List<TColStd_SequenceOfInteger>& theWires,
const gp_Dir& theNorm)
: myXYZs(theXYZs),
myWires(theWires),
myPlane(gp::Origin(), theNorm)
{
}
//=================================================================================================
Standard_Boolean BRepMesh_Triangulator::Perform(NCollection_List<Poly_Triangle>& thePolyTriangles)
{
#ifdef CHECK_PERF
MoniTool_TimerSentry MTS01("BRepMesh_Triangulator::Perform");
#endif
if (myMess.IsNull())
{
myMess = Message::DefaultMessenger();
}
if (myWires.Extent() == 1)
{
const TColStd_SequenceOfInteger& aTmpWire = myWires.First();
if (aTmpWire.Length() < 5)
{
// prepare triangles from simple wire (3 or 4 points)
addTriange34(aTmpWire, thePolyTriangles);
return Standard_True;
}
}
if (!prepareMeshStructure())
{
return Standard_False;
}
if (!triangulate(thePolyTriangles))
{
return Standard_False;
}
#ifdef CHECK_PERF
MTS01.Stop();
#endif
return Standard_True;
}
//=======================================================================
// function : addTriange34
// purpose : auxiliary for makeTrianglesUsingBRepMesh
//=======================================================================
void BRepMesh_Triangulator::addTriange34(const TColStd_SequenceOfInteger& theW,
NCollection_List<Poly_Triangle>& thePolyTriangles)
{
// prepare triangles from simple wire (3 or 4 points)
if (theW.Length() == 3)
{
Poly_Triangle aT(theW(1) + 1, theW(2) + 1, theW(3) + 1);
thePolyTriangles.Append(aT);
}
else if (theW.Length() == 4)
{
Standard_Real d13 = (myXYZs.Value(theW(1)) - myXYZs.Value(theW(3))).SquareModulus();
Standard_Real d24 = (myXYZs.Value(theW(2)) - myXYZs.Value(theW(4))).SquareModulus();
Standard_Boolean use13 = Standard_True;
if (d24 < d13)
{
// additional check for inner corner
static int aPivotNodes[4] = {2, 4, 1, 3};
use13 = checkCondition(aPivotNodes, theW);
}
else
{
static int aPivotNodes[4] = {1, 3, 2, 4};
use13 = !checkCondition(aPivotNodes, theW);
}
if (use13)
{
appendTriangle(1, 2, 3, theW, thePolyTriangles);
appendTriangle(3, 4, 1, theW, thePolyTriangles);
}
else
{
appendTriangle(1, 2, 4, theW, thePolyTriangles);
appendTriangle(2, 3, 4, theW, thePolyTriangles);
}
}
}
//=======================================================================
// function : checkCondition
// purpose : auxiliary for addTriange34
//=======================================================================
Standard_Boolean BRepMesh_Triangulator::checkCondition(const int (&theNodes)[4],
const TColStd_SequenceOfInteger& theW)
{
const gp_XYZ aV0 = myXYZs.Value(theW(theNodes[1])) - myXYZs.Value(theW(theNodes[0]));
const gp_XYZ aV1 = myXYZs.Value(theW(theNodes[2])) - myXYZs.Value(theW(theNodes[0]));
const gp_XYZ aV2 = myXYZs.Value(theW(theNodes[3])) - myXYZs.Value(theW(theNodes[0]));
const gp_XYZ aCross1 = aV0.Crossed(aV1);
const gp_XYZ aCross2 = aV0.Crossed(aV2);
return (aCross1.SquareModulus() < Precision::SquareConfusion()
|| aCross2.SquareModulus() < Precision::SquareConfusion()
|| gp_Dir(aCross1).IsEqual(gp_Dir(aCross2), 0.01));
}
//=================================================================================================
Standard_Boolean BRepMesh_Triangulator::prepareMeshStructure()
{
myIndices = new IMeshData::VectorOfInteger(wireNodesNb(myWires));
myMeshStructure = new BRepMesh_DataStructureOfDelaun(new NCollection_IncAllocator);
// fill this structure created BRepMesh_Vertexes using 2d points received
// by projection initial 3d point on plane.
try
{
Standard_Integer aNumNode = 0;
NCollection_List<TColStd_SequenceOfInteger>::Iterator itW(myWires);
for (Standard_Integer i = 1; itW.More(); itW.Next(), i++)
{
const TColStd_SequenceOfInteger& aW = itW.Value();
for (Standard_Integer nn = 1; nn <= aW.Length(); ++nn, ++aNumNode)
{
const gp_Pnt2d aP2d = ProjLib::Project(myPlane, gp_Pnt(myXYZs(aW(nn))));
const BRepMesh_Vertex aVertex(aP2d.XY(), aNumNode, BRepMesh_Frontier);
const Standard_Integer nnn = myMeshStructure->AddNode(aVertex);
myIndices->SetValue(aNumNode, nnn);
myTmpMap.Bind(aNumNode + 1, aW(nn) + 1);
}
const Standard_Integer aOffset = aNumNode - aW.Length();
for (Standard_Integer nn = 1; nn <= aW.Length(); ++nn)
{
const BRepMesh_Edge anEdge(myIndices->Value(aOffset + (nn - 1)),
myIndices->Value(aOffset + (nn % aW.Length())),
BRepMesh_Frontier);
myMeshStructure->AddLink(anEdge);
}
}
}
catch (...)
{
myMess->Send("makeTrianglesUsingBRepMesh: Exception raised during filling of "
"BRepMesh_DataStructureOfDelaun",
Message_Fail);
return Standard_False;
}
return Standard_True;
}
//=================================================================================================
Standard_Boolean BRepMesh_Triangulator::triangulate(
NCollection_List<Poly_Triangle>& thePolyTriangles)
{
try
{
// perform triangulation used created aMeshStructure
BRepMesh_Delaun aTriangulation(myMeshStructure, *myIndices);
const IMeshData::MapOfInteger& aTriangles = myMeshStructure->ElementsOfDomain();
if (aTriangles.Extent() < 1)
{
return Standard_False;
}
// prepare Poly_Triangles from result triangles and add to returned list
for (IMeshData::IteratorOfMapOfInteger aTriIter(aTriangles); aTriIter.More(); aTriIter.Next())
{
const Standard_Integer aTriangleId = aTriIter.Key();
const BRepMesh_Triangle& aTriangle = myMeshStructure->GetElement(aTriangleId);
if (aTriangle.Movability() == BRepMesh_Deleted)
{
continue;
}
Standard_Integer aTri2d[3];
myMeshStructure->ElementNodes(aTriangle, aTri2d);
const Poly_Triangle aT(myTmpMap.Find(aTri2d[0]),
myTmpMap.Find(aTri2d[1]),
myTmpMap.Find(aTri2d[2]));
thePolyTriangles.Append(aT);
}
}
catch (Standard_Failure const& aFailure)
{
TCollection_AsciiString aStr(
"makeTrianglesUsingBRepMesh: Exception raised during polygon triangulation: ");
aStr.AssignCat(aFailure.GetMessageString());
myMess->Send(aStr.ToCString(), Message_Fail);
return Standard_False;
}
return Standard_True;
}