Loading files
3d097a032This file is pinned to the selected release. Download the original to open it in your design tool.
// Created on: 2019-07-05
// Copyright (c) 2019 OPEN CASCADE SAS
// Created by: Oleg AGASHIN
//
// 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_DelabellaBaseMeshAlgo.hxx>
#include <NCollection_LinearVector.hxx>
#include <BRepMesh_MeshTool.hxx>
#include <BRepMesh_Delaun.hxx>
#include <Message.hxx>
#include <cstring>
#include <cstdarg>
#include "delabella.pxx"
IMPLEMENT_STANDARD_RTTIEXT(BRepMesh_DelabellaBaseMeshAlgo, BRepMesh_CustomBaseMeshAlgo)
namespace
{
//! Redirect algorithm messages to OCCT messenger.
static int logDelabella2Occ(void* theStream, const char* theFormat, ...)
{
(void)theStream;
char aBuffer[1024]; // should be more than enough for Delabella messages
va_list anArgList;
va_start(anArgList, theFormat);
Vsprintf(aBuffer, theFormat, anArgList);
va_end(anArgList);
Message_Gravity aGravity = Message_Warning;
switch ((int)theFormat[1])
{
case int('E'):
aGravity = Message_Fail;
break; // [ERR]
case int('W'):
aGravity = Message_Trace;
break; // [WRN]
case int('N'):
aGravity = Message_Trace;
break; // [NFO]
}
Message::Send(aBuffer, aGravity);
return 0;
}
} // namespace
//=================================================================================================
BRepMesh_DelabellaBaseMeshAlgo::BRepMesh_DelabellaBaseMeshAlgo() = default;
//=================================================================================================
BRepMesh_DelabellaBaseMeshAlgo::~BRepMesh_DelabellaBaseMeshAlgo() = default;
//=================================================================================================
void BRepMesh_DelabellaBaseMeshAlgo::buildBaseTriangulation()
{
const occ::handle<BRepMesh_DataStructureOfDelaun>& aStructure = this->getStructure();
Bnd_B2d aBox;
const int aNodesNb = aStructure->NbNodes();
NCollection_LinearVector<double> aPoints;
aPoints.Resize(2 * (aNodesNb + 4));
for (int aNodeIt = 0; aNodeIt < aNodesNb; ++aNodeIt)
{
const BRepMesh_Vertex& aVertex = aStructure->GetNode(aNodeIt + 1);
const size_t aBaseIdx = 2 * static_cast<size_t>(aNodeIt);
aPoints[aBaseIdx + 0] = aVertex.Coord().X();
aPoints[aBaseIdx + 1] = aVertex.Coord().Y();
aBox.Add(gp_Pnt2d(aVertex.Coord()));
}
aBox.Enlarge(0.1 * (aBox.CornerMax() - aBox.CornerMin()).Modulus());
const gp_XY aMin = aBox.CornerMin();
const gp_XY aMax = aBox.CornerMax();
aPoints[2 * aNodesNb + 0] = aMin.X();
aPoints[2 * aNodesNb + 1] = aMin.Y();
aStructure->AddNode(
BRepMesh_Vertex(aPoints[2 * aNodesNb + 0], aPoints[2 * aNodesNb + 1], BRepMesh_Free));
aPoints[2 * aNodesNb + 2] = aMax.X();
aPoints[2 * aNodesNb + 3] = aMin.Y();
aStructure->AddNode(
BRepMesh_Vertex(aPoints[2 * aNodesNb + 2], aPoints[2 * aNodesNb + 3], BRepMesh_Free));
aPoints[2 * aNodesNb + 4] = aMax.X();
aPoints[2 * aNodesNb + 5] = aMax.Y();
aStructure->AddNode(
BRepMesh_Vertex(aPoints[2 * aNodesNb + 4], aPoints[2 * aNodesNb + 5], BRepMesh_Free));
aPoints[2 * aNodesNb + 6] = aMin.X();
aPoints[2 * aNodesNb + 7] = aMax.Y();
aStructure->AddNode(
BRepMesh_Vertex(aPoints[2 * aNodesNb + 6], aPoints[2 * aNodesNb + 7], BRepMesh_Free));
const double aDiffX = (aMax.X() - aMin.X());
const double aDiffY = (aMax.Y() - aMin.Y());
for (size_t i = 0; i < aPoints.Size(); i += 2)
{
aPoints[i + 0] = (aPoints[i + 0] - aMin.X()) / aDiffX - 0.5;
aPoints[i + 1] = (aPoints[i + 1] - aMin.Y()) / aDiffY - 0.5;
}
IDelaBella* aTriangulator = IDelaBella::Create();
if (aTriangulator == nullptr) // should never happen
{
throw Standard_ProgramError("BRepMesh_DelabellaBaseMeshAlgo::buildBaseTriangulation: unable "
"creating a triangulation algorithm");
}
aTriangulator->SetErrLog(logDelabella2Occ, nullptr);
try
{
const int aVerticesNb = aTriangulator->Triangulate(static_cast<int>(aPoints.Size() / 2),
&aPoints[0],
&aPoints[1],
2 * sizeof(double));
if (aVerticesNb > 0)
{
const DelaBella_Triangle* aTrianglePtr = aTriangulator->GetFirstDelaunayTriangle();
while (aTrianglePtr != nullptr)
{
int aNodes[3] = {aTrianglePtr->v[0]->i + 1,
aTrianglePtr->v[2]->i + 1,
aTrianglePtr->v[1]->i + 1};
int aEdges[3];
bool aOrientations[3];
for (int k = 0; k < 3; ++k)
{
const BRepMesh_Edge aLink(aNodes[k], aNodes[(k + 1) % 3], BRepMesh_Free);
const int aLinkInfo = aStructure->AddLink(aLink);
aEdges[k] = std::abs(aLinkInfo);
aOrientations[k] = aLinkInfo > 0;
}
const BRepMesh_Triangle aTriangle(aEdges, aOrientations, BRepMesh_Free);
aStructure->AddElement(aTriangle);
aTrianglePtr = aTrianglePtr->next;
}
}
aTriangulator->Destroy();
aTriangulator = nullptr;
}
catch (Standard_Failure const& theException)
{
if (aTriangulator != nullptr)
{
aTriangulator->Destroy();
aTriangulator = nullptr;
}
throw Standard_Failure(theException);
}
catch (...)
{
if (aTriangulator != nullptr)
{
aTriangulator->Destroy();
aTriangulator = nullptr;
}
throw Standard_Failure("BRepMesh_DelabellaBaseMeshAlgo::buildBaseTriangulation: exception in "
"triangulation algorithm");
}
}