Loading files
This file is pinned to the selected release. Download the original to open it in your design tool.
c5f20409cThis file is pinned to the selected release. Download the original to open it in your design tool.
// Created on: 2014-10-20
// Created by: Denis BOGOLEPOV
// Copyright (c) 2014 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 <BRepExtrema_TriangleSet.hxx>
#include <BRep_Tool.hxx>
#include <BVH_LinearBuilder.hxx>
#include <Poly_Triangulation.hxx>
#include <TopoDS.hxx>
IMPLEMENT_STANDARD_RTTIEXT(BRepExtrema_TriangleSet, BVH_PrimitiveSet3d)
//=======================================================================
// function : BRepExtrema_TriangleSet
// purpose : Creates empty triangle set
//=======================================================================
BRepExtrema_TriangleSet::BRepExtrema_TriangleSet()
{
// Set default builder - linear BVH (LBVH)
myBuilder = new BVH_LinearBuilder<Standard_Real, 3>(BVH_Constants_LeafNodeSizeDefault,
BVH_Constants_MaxTreeDepth);
}
//=======================================================================
// function : BRepExtrema_TriangleSet
// purpose : Creates triangle set from the given face
//=======================================================================
BRepExtrema_TriangleSet::BRepExtrema_TriangleSet(const BRepExtrema_ShapeList& theFaces)
{
// Set default builder - linear BVH (LBVH)
myBuilder = new BVH_LinearBuilder<Standard_Real, 3>(BVH_Constants_LeafNodeSizeDefault,
BVH_Constants_MaxTreeDepth);
Init(theFaces);
}
//=======================================================================
// function : ~BRepExtrema_TriangleSet
// purpose : Releases resources of triangle set
//=======================================================================
BRepExtrema_TriangleSet::~BRepExtrema_TriangleSet()
{
//
}
//=======================================================================
// function : Size
// purpose : Returns total number of triangles
//=======================================================================
Standard_Integer BRepExtrema_TriangleSet::Size() const
{
return static_cast<Standard_Integer>(myTriangles.size());
}
//=======================================================================
// function : Box
// purpose : Returns AABB of the given triangle
//=======================================================================
BVH_Box<Standard_Real, 3> BRepExtrema_TriangleSet::Box(const Standard_Integer theIndex) const
{
const BVH_Vec4i& aTriangle = myTriangles[theIndex];
BVH_Vec3d aMinPnt = myVertexArray[aTriangle.x()].cwiseMin(
myVertexArray[aTriangle.y()].cwiseMin(myVertexArray[aTriangle.z()]));
BVH_Vec3d aMaxPnt = myVertexArray[aTriangle.x()].cwiseMax(
myVertexArray[aTriangle.y()].cwiseMax(myVertexArray[aTriangle.z()]));
return BVH_Box<Standard_Real, 3>(aMinPnt, aMaxPnt);
}
//=======================================================================
// function : Center
// purpose : Returns centroid position along specified axis
//=======================================================================
Standard_Real BRepExtrema_TriangleSet::Center(const Standard_Integer theIndex,
const Standard_Integer theAxis) const
{
const BVH_Vec4i& aTriangle = myTriangles[theIndex];
if (theAxis == 0)
{
return (1.0 / 3.0)
* (myVertexArray[aTriangle.x()].x() + myVertexArray[aTriangle.y()].x()
+ myVertexArray[aTriangle.z()].x());
}
else if (theAxis == 1)
{
return (1.0 / 3.0)
* (myVertexArray[aTriangle.x()].y() + myVertexArray[aTriangle.y()].y()
+ myVertexArray[aTriangle.z()].y());
}
else
{
return (1.0 / 3.0)
* (myVertexArray[aTriangle.x()].z() + myVertexArray[aTriangle.y()].z()
+ myVertexArray[aTriangle.z()].z());
}
}
//=======================================================================
// function : Swap
// purpose : Swaps indices of two specified triangles
//=======================================================================
void BRepExtrema_TriangleSet::Swap(const Standard_Integer theIndex1,
const Standard_Integer theIndex2)
{
std::swap(myTriangles[theIndex1], myTriangles[theIndex2]);
std::swap(myTrgIdxMap(theIndex1), myTrgIdxMap(theIndex2));
}
//=======================================================================
// function : GetFaceID
// purpose : Returns face ID of the given vertex
//=======================================================================
Standard_Integer BRepExtrema_TriangleSet::GetFaceID(const Standard_Integer theIndex) const
{
return myTriangles[theIndex].w();
}
//=======================================================================
// function : GetShapeIDOfVtx
// purpose : Returns shape ID of the given vertex index
//=======================================================================
Standard_Integer BRepExtrema_TriangleSet::GetShapeIDOfVtx(const Standard_Integer theIndex) const
{
return myShapeIdxOfVtxVec.Value(theIndex);
}
//=======================================================================
// function : GetVtxIdxInShape
// purpose : Returns vertex index in tringulation of the shape, which vertex belongs,
// with the given vtx ID in whole set
//=======================================================================
Standard_Integer BRepExtrema_TriangleSet::GetVtxIdxInShape(const Standard_Integer theIndex) const
{
Standard_Integer aShID = myShapeIdxOfVtxVec.Value(theIndex);
Standard_Integer aNumVertices = 0;
for (Standard_Integer aSIdx = 0; aSIdx < aShID; aSIdx++)
{
aNumVertices += myNumVtxInShapeVec.Value(aSIdx);
}
return theIndex - aNumVertices;
}
//=======================================================================
// function : GetTrgIdxInShape
// purpose : Returns triangle index (before swapping) in tringulation of the shape, which triangle
// belongs,
// with the given trg ID in whole set (after swapping)
//=======================================================================
Standard_Integer BRepExtrema_TriangleSet::GetTrgIdxInShape(const Standard_Integer theIndex) const
{
Standard_Integer aShID = GetFaceID(theIndex);
Standard_Integer aNumTriangles = 0;
for (Standard_Integer aSIdx = 0; aSIdx < aShID; aSIdx++)
{
aNumTriangles += myNumTrgInShapeVec.Value(aSIdx);
}
return myTrgIdxMap(theIndex) - aNumTriangles;
}
//=======================================================================
// function : GetVertices
// purpose : Returns vertices of the given triangle
//=======================================================================
void BRepExtrema_TriangleSet::GetVertices(const Standard_Integer theIndex,
BVH_Vec3d& theVertex1,
BVH_Vec3d& theVertex2,
BVH_Vec3d& theVertex3) const
{
BVH_Vec4i aTriangle = myTriangles[theIndex];
theVertex1 = myVertexArray[aTriangle.x()];
theVertex2 = myVertexArray[aTriangle.y()];
theVertex3 = myVertexArray[aTriangle.z()];
}
//=======================================================================
// function : GetVertices
// purpose : Returns vertices of the given triangle
//=======================================================================
void BRepExtrema_TriangleSet::GetVtxIndices(
const Standard_Integer theIndex,
NCollection_Array1<Standard_Integer>& theVtxIndices) const
{
BVH_Vec4i aTriangle = myTriangles[theIndex];
theVtxIndices = NCollection_Array1<Standard_Integer>(0, 2);
theVtxIndices.SetValue(0, aTriangle.x());
theVtxIndices.SetValue(1, aTriangle.y());
theVtxIndices.SetValue(2, aTriangle.z());
}
//=======================================================================
// function : Clear
// purpose : Clears triangle set data
//=======================================================================
void BRepExtrema_TriangleSet::Clear()
{
BVH_Array4i anEmptyTriangles;
myTriangles.swap(anEmptyTriangles);
BVH_Array3d anEmptyVertexArray;
myVertexArray.swap(anEmptyVertexArray);
}
//=======================================================================
// function : Init
// purpose : Initializes triangle set
//=======================================================================
Standard_Boolean BRepExtrema_TriangleSet::Init(const BRepExtrema_ShapeList& theShapes)
{
Clear();
Standard_Boolean isOK = Standard_True;
for (Standard_Integer aShapeIdx = 0; aShapeIdx < theShapes.Size() && isOK; ++aShapeIdx)
{
if (theShapes(aShapeIdx).ShapeType() == TopAbs_FACE)
isOK = initFace(TopoDS::Face(theShapes(aShapeIdx)), aShapeIdx);
else if (theShapes(aShapeIdx).ShapeType() == TopAbs_EDGE)
isOK = initEdge(TopoDS::Edge(theShapes(aShapeIdx)), aShapeIdx);
}
Standard_Integer aNumTrg = static_cast<Standard_Integer>(myTriangles.size());
myTrgIdxMap.Clear();
myTrgIdxMap.ReSize(aNumTrg);
for (Standard_Integer aTrgIdx = 0; aTrgIdx < aNumTrg; ++aTrgIdx)
{
myTrgIdxMap.Bind(aTrgIdx, aTrgIdx);
}
MarkDirty(); // needs BVH rebuilding
Standard_ASSERT_RETURN(!BVH().IsNull(),
"Error: Failed to build BVH for primitive set",
Standard_False);
return Standard_True;
}
//=======================================================================
// function : initFace
// purpose : Initializes triangle set
//=======================================================================
Standard_Boolean BRepExtrema_TriangleSet::initFace(const TopoDS_Face& theFace,
const Standard_Integer theIndex)
{
TopLoc_Location aLocation;
Handle(Poly_Triangulation) aTriangulation = BRep_Tool::Triangulation(theFace, aLocation);
if (aTriangulation.IsNull())
{
return Standard_False;
}
const Standard_Integer aVertOffset = static_cast<Standard_Integer>(myVertexArray.size()) - 1;
initNodes(aTriangulation->MapNodeArray()->ChangeArray1(), aLocation.Transformation(), theIndex);
for (Standard_Integer aTriIdx = 1; aTriIdx <= aTriangulation->NbTriangles(); ++aTriIdx)
{
Standard_Integer aVertex1;
Standard_Integer aVertex2;
Standard_Integer aVertex3;
aTriangulation->Triangle(aTriIdx).Get(aVertex1, aVertex2, aVertex3);
myTriangles.push_back(
BVH_Vec4i(aVertex1 + aVertOffset, aVertex2 + aVertOffset, aVertex3 + aVertOffset, theIndex));
}
myNumTrgInShapeVec.SetValue(theIndex, aTriangulation->NbTriangles());
return Standard_True;
}
//=======================================================================
// function : initEdge
// purpose : Initializes triangle set
//=======================================================================
Standard_Boolean BRepExtrema_TriangleSet::initEdge(const TopoDS_Edge& theEdge,
const Standard_Integer theIndex)
{
TopLoc_Location aLocation;
Handle(Poly_Polygon3D) aPolygon = BRep_Tool::Polygon3D(theEdge, aLocation);
if (aPolygon.IsNull())
{
return Standard_False;
}
const Standard_Integer aVertOffset = static_cast<Standard_Integer>(myVertexArray.size()) - 1;
initNodes(aPolygon->Nodes(), aLocation.Transformation(), theIndex);
for (Standard_Integer aVertIdx = 1; aVertIdx < aPolygon->NbNodes(); ++aVertIdx)
{
// segment as degenerate triangle
myTriangles.push_back(BVH_Vec4i(aVertIdx + aVertOffset,
aVertIdx + aVertOffset + 1,
aVertIdx + aVertOffset + 1,
theIndex));
}
return Standard_True;
}
//=======================================================================
// function : initNodes
// purpose : Initializes nodes
//=======================================================================
void BRepExtrema_TriangleSet::initNodes(const TColgp_Array1OfPnt& theNodes,
const gp_Trsf& theTrsf,
const Standard_Integer theIndex)
{
for (Standard_Integer aVertIdx = 1; aVertIdx <= theNodes.Size(); ++aVertIdx)
{
gp_Pnt aVertex = theNodes.Value(aVertIdx);
aVertex.Transform(theTrsf);
myVertexArray.push_back(BVH_Vec3d(aVertex.X(), aVertex.Y(), aVertex.Z()));
myShapeIdxOfVtxVec.Append(theIndex);
}
myNumVtxInShapeVec.SetValue(theIndex, theNodes.Size());
}