mirror of
https://git.salome-platform.org/gitpub/modules/geom.git
synced 2025-04-24 08:02:03 +05:00
519 lines
14 KiB
C++
519 lines
14 KiB
C++
// Copyright (C) 2005 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
|
|
// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
|
|
//
|
|
// This library is free software; you can redistribute it and/or
|
|
// modify it under the terms of the GNU Lesser General Public
|
|
// License as published by the Free Software Foundation; either
|
|
// version 2.1 of the License.
|
|
//
|
|
// This library is distributed in the hope that it will be useful
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
// Lesser General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Lesser General Public
|
|
// License along with this library; if not, write to the Free Software
|
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
//
|
|
// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
|
|
//
|
|
// File: NMTAlgo_Tools.cxx
|
|
// Created: Fri Jan 30 16:30:45 2004
|
|
// Author: Peter KURNEV
|
|
// <pkv@irinox>
|
|
|
|
|
|
#include <NMTAlgo_Tools.ixx>
|
|
|
|
#include <gp_Dir.hxx>
|
|
|
|
#include <TopAbs_Orientation.hxx>
|
|
|
|
#include <TopoDS.hxx>
|
|
#include <TopoDS_Shape.hxx>
|
|
#include <TopoDS_Edge.hxx>
|
|
#include <TopoDS_Solid.hxx>
|
|
#include <TopoDS_Face.hxx>
|
|
#include <TopoDS_Vertex.hxx>
|
|
#include <TopoDS_Compound.hxx>
|
|
|
|
#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
|
|
#include <TopTools_IndexedMapOfShape.hxx>
|
|
#include <TopTools_ListOfShape.hxx>
|
|
#include <TopTools_IndexedMapOfShape.hxx>
|
|
#include <TopTools_ListIteratorOfListOfShape.hxx>
|
|
#include <TopTools_DataMapOfShapeShape.hxx>
|
|
#include <TopTools_MapOfShape.hxx>
|
|
#include <TopTools_MapOfOrientedShape.hxx>
|
|
|
|
#include <BRep_Builder.hxx>
|
|
#include <BRep_Tool.hxx>
|
|
#include <BRepClass3d_SolidClassifier.hxx>
|
|
|
|
#include <TopExp.hxx>
|
|
#include <TopExp_Explorer.hxx>
|
|
|
|
#include <BOPTools_Tools3D.hxx>
|
|
|
|
#include <NMTAlgo_Loop3d.hxx>
|
|
#include <TopoDS_Iterator.hxx>
|
|
|
|
|
|
//=======================================================================
|
|
// function: Sense
|
|
// purpose:
|
|
//=======================================================================
|
|
Standard_Integer NMTAlgo_Tools::Sense (const TopoDS_Face& aF1,
|
|
const TopoDS_Face& aF2)
|
|
{
|
|
Standard_Integer iSense=0;
|
|
gp_Dir aDNF1, aDNF2;
|
|
TopoDS_Edge aE1, aE2;
|
|
TopExp_Explorer anExp;
|
|
//
|
|
anExp.Init(aF1, TopAbs_EDGE);
|
|
for (; anExp.More(); anExp.Next()) {
|
|
aE1=TopoDS::Edge(anExp.Current());
|
|
if (!BRep_Tool::Degenerated(aE1)) {
|
|
if (!BRep_Tool::IsClosed(aE1, aF1)) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
//
|
|
anExp.Init(aF2, TopAbs_EDGE);
|
|
for (; anExp.More(); anExp.Next()) {
|
|
aE2=TopoDS::Edge(anExp.Current());
|
|
if (!BRep_Tool::Degenerated(aE2)) {
|
|
if (!BRep_Tool::IsClosed(aE2, aF2)) {
|
|
if (aE2.IsSame(aE1)) {
|
|
iSense=1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//
|
|
if (!iSense) {
|
|
return iSense;
|
|
}
|
|
//
|
|
BOPTools_Tools3D::GetNormalToFaceOnEdge(aE1, aF1, aDNF1);
|
|
BOPTools_Tools3D::GetNormalToFaceOnEdge(aE2, aF2, aDNF2);
|
|
//
|
|
iSense=BOPTools_Tools3D::SenseFlag(aDNF1, aDNF2);
|
|
//
|
|
return iSense;
|
|
}
|
|
|
|
//=======================================================================
|
|
// function: OrientFacesOnShell
|
|
// purpose:
|
|
//=======================================================================
|
|
void NMTAlgo_Tools::OrientFacesOnShell (const TopoDS_Face& aF1,
|
|
TopoDS_Shell& aSh)
|
|
{
|
|
Standard_Integer aNbFSh, iSenseFlag;
|
|
gp_Dir aDNF1, aDNF2;
|
|
TopExp_Explorer anExp;
|
|
TopoDS_Edge aE1, aESh;
|
|
TopTools_IndexedDataMapOfShapeListOfShape aMEFSh;
|
|
//
|
|
anExp.Init(aF1, TopAbs_EDGE);
|
|
for (; anExp.More(); anExp.Next()) {
|
|
aE1=TopoDS::Edge(anExp.Current());
|
|
if (!BRep_Tool::Degenerated(aE1)) {
|
|
break;
|
|
}
|
|
}
|
|
//
|
|
BOPTools_Tools3D::GetNormalToFaceOnEdge(aE1, aF1, aDNF1);
|
|
//
|
|
TopExp::MapShapesAndAncestors(aSh, TopAbs_EDGE, TopAbs_FACE, aMEFSh);
|
|
if (aMEFSh.Contains(aE1)) {
|
|
const TopTools_ListOfShape& aLFSh=aMEFSh.FindFromKey(aE1);
|
|
aNbFSh=aLFSh.Extent();
|
|
if (aNbFSh==1) {
|
|
const TopoDS_Face& aFSh=TopoDS::Face(aLFSh.First());
|
|
//
|
|
BOPTools_Tools3D::OrientEdgeOnFace(aE1, aFSh, aESh);
|
|
BOPTools_Tools3D::GetNormalToFaceOnEdge(aESh, aFSh, aDNF2);
|
|
//
|
|
iSenseFlag=BOPTools_Tools3D::SenseFlag(aDNF1, aDNF2);
|
|
if (iSenseFlag==1) {
|
|
return;
|
|
}
|
|
//
|
|
anExp.Init(aSh, TopAbs_FACE);
|
|
for (; anExp.More(); anExp.Next()) {
|
|
const TopoDS_Shape& aFx=anExp.Current();
|
|
TopoDS_Shape *pFx=(TopoDS_Shape *)&aFx;
|
|
pFx->Reverse();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//=======================================================================
|
|
// function: OrientFacesOnShell
|
|
// purpose:
|
|
//=======================================================================
|
|
void NMTAlgo_Tools::OrientFacesOnShell (const TopoDS_Shell& aShell,
|
|
TopoDS_Shell& aShellNew)
|
|
{
|
|
Standard_Boolean bIsProcessed1, bIsProcessed2;
|
|
Standard_Integer i, aNbE, aNbF, j;
|
|
TopAbs_Orientation anOrE1, anOrE2;
|
|
|
|
TopTools_IndexedDataMapOfShapeListOfShape aEFMap;
|
|
TopTools_IndexedMapOfShape aProcessedFaces;
|
|
BRep_Builder aBB;
|
|
|
|
aBB.MakeShell(aShellNew);
|
|
|
|
TopExp::MapShapesAndAncestors(aShell, TopAbs_EDGE, TopAbs_FACE, aEFMap);
|
|
|
|
aNbE=aEFMap.Extent();
|
|
//
|
|
// One seam edge in aEFMap contains 2 equivalent faces.
|
|
for (i=1; i<=aNbE; i++) {
|
|
TopTools_ListOfShape& aLF=aEFMap.ChangeFromIndex(i);
|
|
|
|
if (aLF.Extent()>1) {
|
|
TopTools_ListOfShape aLFTmp;
|
|
TopTools_IndexedMapOfShape aFM;
|
|
|
|
TopTools_ListIteratorOfListOfShape anIt(aLF);
|
|
for (; anIt.More(); anIt.Next()) {
|
|
const TopoDS_Shape& aF=anIt.Value();
|
|
if (!aFM.Contains(aF)) {
|
|
aFM.Add(aF);
|
|
aLFTmp.Append(aF);
|
|
}
|
|
}
|
|
aLF.Clear();
|
|
aLF=aLFTmp;
|
|
}
|
|
}
|
|
//
|
|
// Do
|
|
for (i=1; i<=aNbE; i++) {
|
|
const TopoDS_Edge& aE=TopoDS::Edge(aEFMap.FindKey(i));
|
|
|
|
if (BRep_Tool::Degenerated(aE)) {
|
|
continue;
|
|
}
|
|
|
|
const TopTools_ListOfShape& aLF=aEFMap.FindFromIndex(i);
|
|
aNbF=aLF.Extent();
|
|
|
|
if (aNbF==2) {
|
|
TopoDS_Face& aF1=TopoDS::Face(aLF.First());
|
|
TopoDS_Face& aF2=TopoDS::Face(aLF.Last() );
|
|
|
|
|
|
bIsProcessed1=aProcessedFaces.Contains(aF1);
|
|
bIsProcessed2=aProcessedFaces.Contains(aF2);
|
|
|
|
if (bIsProcessed1 && bIsProcessed2) {
|
|
continue;
|
|
}
|
|
|
|
if (!bIsProcessed1 && !bIsProcessed2) {
|
|
aProcessedFaces.Add(aF1);
|
|
aBB.Add(aShellNew, aF1);
|
|
|
|
bIsProcessed1=!bIsProcessed1;
|
|
}
|
|
|
|
//
|
|
TopoDS_Face aF1x, aF2x;
|
|
|
|
aF1x=aF1;
|
|
if (bIsProcessed1) {
|
|
j=aProcessedFaces.FindIndex(aF1);
|
|
aF1x=TopoDS::Face(aProcessedFaces.FindKey(j));
|
|
}
|
|
|
|
aF2x=aF2;
|
|
if (bIsProcessed2) {
|
|
j=aProcessedFaces.FindIndex(aF2);
|
|
aF2x=TopoDS::Face(aProcessedFaces.FindKey(j));
|
|
}
|
|
//
|
|
|
|
anOrE1=NMTAlgo_Tools::Orientation(aE, aF1x);
|
|
anOrE2=NMTAlgo_Tools::Orientation(aE, aF2x);
|
|
|
|
if (bIsProcessed1 && !bIsProcessed2) {
|
|
|
|
if (anOrE1==anOrE2) {
|
|
if (!BRep_Tool::IsClosed(aE, aF1) &&
|
|
!BRep_Tool::IsClosed(aE, aF2)) {
|
|
aF2.Reverse();
|
|
}
|
|
}
|
|
aProcessedFaces.Add(aF2);
|
|
aBB.Add(aShellNew, aF2);
|
|
}
|
|
|
|
else if (!bIsProcessed1 && bIsProcessed2) {
|
|
if (anOrE1==anOrE2) {
|
|
if (!BRep_Tool::IsClosed(aE, aF1) &&
|
|
!BRep_Tool::IsClosed(aE, aF2)) {
|
|
aF1.Reverse();
|
|
}
|
|
}
|
|
aProcessedFaces.Add(aF1);
|
|
aBB.Add(aShellNew, aF1);
|
|
}
|
|
}
|
|
}
|
|
//
|
|
//
|
|
for (i=1; i<=aNbE; i++) {
|
|
const TopoDS_Edge& aE=TopoDS::Edge(aEFMap.FindKey(i));
|
|
|
|
if (BRep_Tool::Degenerated(aE)) {
|
|
continue;
|
|
}
|
|
|
|
const TopTools_ListOfShape& aLF=aEFMap.FindFromIndex(i);
|
|
aNbF=aLF.Extent();
|
|
if (aNbF!=2) {
|
|
TopTools_ListIteratorOfListOfShape anIt(aLF);
|
|
for(; anIt.More(); anIt.Next()) {
|
|
const TopoDS_Face& aF=TopoDS::Face(anIt.Value());
|
|
if (!aProcessedFaces.Contains(aF)) {
|
|
aProcessedFaces.Add(aF);
|
|
aBB.Add(aShellNew, aF);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//=======================================================================
|
|
//function : Orientation
|
|
//purpose :
|
|
//=======================================================================
|
|
TopAbs_Orientation NMTAlgo_Tools::Orientation(const TopoDS_Edge& anE,
|
|
const TopoDS_Face& aF)
|
|
{
|
|
TopAbs_Orientation anOr=TopAbs_INTERNAL;
|
|
|
|
TopExp_Explorer anExp;
|
|
anExp.Init(aF, TopAbs_EDGE);
|
|
for (; anExp.More(); anExp.Next()) {
|
|
const TopoDS_Edge& anEF1=TopoDS::Edge(anExp.Current());
|
|
if (anEF1.IsSame(anE)) {
|
|
anOr=anEF1.Orientation();
|
|
break;
|
|
}
|
|
}
|
|
return anOr;
|
|
}
|
|
//=======================================================================
|
|
//function : IsInside
|
|
//purpose : Return True if the first vertex of S1 inside S2.
|
|
// If S1.IsNull(), check infinite point against S2.
|
|
//=======================================================================
|
|
Standard_Boolean NMTAlgo_Tools::IsInside (const TopoDS_Shape& theS1,
|
|
const TopoDS_Shape& theS2)
|
|
{
|
|
BRepClass3d_SolidClassifier aClassifier( theS2 );
|
|
//
|
|
TopExp_Explorer expl(theS1, TopAbs_VERTEX);
|
|
//
|
|
if (!expl.More()){
|
|
aClassifier.PerformInfinitePoint( ::RealSmall());
|
|
}
|
|
else {
|
|
const TopoDS_Vertex & aVertex = TopoDS::Vertex( expl.Current() );
|
|
aClassifier.Perform (BRep_Tool::Pnt( aVertex ),
|
|
BRep_Tool::Tolerance( aVertex ));
|
|
}
|
|
//
|
|
return ( aClassifier.State() == TopAbs_IN );
|
|
}
|
|
//=======================================================================
|
|
//function : MakeShells
|
|
//purpose :
|
|
//=======================================================================
|
|
void NMTAlgo_Tools::MakeShells (const TopoDS_Shape& aFC,
|
|
TopTools_ListOfShape& aLNS)
|
|
{
|
|
NMTAlgo_Loop3d aShellMaker;
|
|
TopTools_MapOfOrientedShape aMTmp;
|
|
//
|
|
aShellMaker.AddConstFaces(aFC);
|
|
aLNS=aShellMaker.MakeShells(aMTmp);
|
|
}
|
|
//=======================================================================
|
|
//function : MakeSolids
|
|
//purpose :
|
|
//=======================================================================
|
|
void NMTAlgo_Tools::MakeSolids(const TopoDS_Shape& aFC,
|
|
TopTools_ListOfShape& theShellList)
|
|
{
|
|
NMTAlgo_Tools::MakeShells(aFC, theShellList);
|
|
NMTAlgo_Tools::MakeSolids(theShellList);
|
|
}
|
|
//=======================================================================
|
|
//function : MakeSolids
|
|
//purpose :
|
|
//=======================================================================
|
|
void NMTAlgo_Tools::MakeSolids(TopTools_ListOfShape& theShellList)
|
|
{
|
|
TopTools_ListOfShape aHoleShells, aNewSolids;
|
|
TopoDS_Shape anInfinitePointShape;
|
|
TopTools_DataMapOfShapeShape aInOutMap;
|
|
TopTools_ListIteratorOfListOfShape aShellIt, aSolisIt;
|
|
BRep_Builder aBB;
|
|
//
|
|
aShellIt.Initialize(theShellList);
|
|
for ( ; aShellIt.More(); aShellIt.Next()) {
|
|
const TopoDS_Shape & aShell = aShellIt.Value();
|
|
// check if a shell is a hole of theSolid
|
|
if (NMTAlgo_Tools::IsInside(anInfinitePointShape, aShell)){
|
|
aHoleShells.Append(aShell);
|
|
}
|
|
else {
|
|
// make a solid from a shell
|
|
TopoDS_Solid Solid;
|
|
aBB.MakeSolid( Solid );
|
|
aBB.Add (Solid, aShell);
|
|
aNewSolids.Append (Solid);
|
|
}
|
|
}
|
|
//
|
|
// find outer a shell most close to each hole shell
|
|
aShellIt.Initialize(aHoleShells);
|
|
for (; aShellIt.More(); aShellIt.Next()){
|
|
const TopoDS_Shape & aHole = aShellIt.Value();
|
|
//
|
|
aSolisIt.Initialize(aNewSolids);
|
|
for ( ; aSolisIt.More(); aSolisIt.Next()) {
|
|
const TopoDS_Shape & aSolid = aSolisIt.Value();
|
|
//
|
|
if (! NMTAlgo_Tools::IsInside(aHole, aSolid)){
|
|
continue;
|
|
}
|
|
//
|
|
if ( aInOutMap.IsBound (aHole)){
|
|
const TopoDS_Shape & aSolid2 = aInOutMap( aHole );
|
|
if ( IsInside( aSolid, aSolid2 )) {
|
|
aInOutMap.UnBind( aHole );
|
|
aInOutMap.Bind ( aHole, aSolid );
|
|
}
|
|
}
|
|
else{
|
|
aInOutMap.Bind (aHole, aSolid);
|
|
}
|
|
}
|
|
//
|
|
// add aHole to a solid
|
|
if (aInOutMap.IsBound( aHole )){
|
|
TopoDS_Shape & aSolid=aInOutMap(aHole);
|
|
aBB.Add (aSolid, aHole);
|
|
}
|
|
}
|
|
theShellList.Clear();
|
|
theShellList.Append( aNewSolids );
|
|
}
|
|
//=======================================================================
|
|
//function : BreakWebs
|
|
//purpose :
|
|
//=======================================================================
|
|
void NMTAlgo_Tools::BreakWebs(const TopoDS_Shape& aCS,
|
|
TopoDS_Shape& aCSR)
|
|
{
|
|
Standard_Integer i, aNbF, aNbS;
|
|
TopTools_IndexedDataMapOfShapeListOfShape aMFS;
|
|
TopTools_MapOfShape aMF;
|
|
|
|
TopoDS_Compound aFC, aCR;
|
|
BRep_Builder aBB;
|
|
//
|
|
aBB.MakeCompound(aFC);
|
|
TopExp::MapShapesAndAncestors(aCS, TopAbs_FACE, TopAbs_SOLID, aMFS);
|
|
//
|
|
aNbF=aMFS.Extent();
|
|
for (i=1; i<=aNbF; ++i) {
|
|
const TopoDS_Shape& aF=aMFS.FindKey(i);
|
|
const TopTools_ListOfShape& aLS=aMFS(i);
|
|
aNbS=aLS.Extent();
|
|
if (aNbS==2) {
|
|
aMF.Add(aF);
|
|
}
|
|
else {
|
|
aBB.Add(aFC, aF);
|
|
}
|
|
}
|
|
//
|
|
if (!aMF.Extent()) {
|
|
aCSR=aCS;
|
|
return;
|
|
}
|
|
//
|
|
TopTools_ListOfShape aLNS;
|
|
TopTools_ListIteratorOfListOfShape aItS;
|
|
//
|
|
NMTAlgo_Tools::MakeShells(aFC, aLNS);
|
|
NMTAlgo_Tools::MakeSolids(aLNS);
|
|
//
|
|
aBB.MakeCompound(aCR);
|
|
aItS.Initialize(aLNS);
|
|
for ( ;aItS.More(); aItS.Next()) {
|
|
const TopoDS_Shape& aS=aItS.Value();
|
|
aBB.Add(aCR, aS);
|
|
}
|
|
aCSR=aCR;
|
|
}
|
|
//=======================================================================
|
|
//function : FindImageSolid
|
|
//purpose :
|
|
//=======================================================================
|
|
Standard_Boolean NMTAlgo_Tools::FindImageSolid(const TopoDS_Shape& aFC,
|
|
const TopTools_IndexedMapOfShape& aMSo,
|
|
TopoDS_Shape& aSox)
|
|
{
|
|
Standard_Boolean bFound=Standard_False;
|
|
Standard_Integer i, j, aNbSo, aNbF, aNbFSo;
|
|
TopoDS_Iterator aIt;
|
|
TopTools_IndexedMapOfShape aMFC, aMFSo;
|
|
//
|
|
aIt.Initialize(aFC);
|
|
for (; aIt.More(); aIt.Next()) {
|
|
const TopoDS_Shape& aF=aIt.Value();
|
|
aMFC.Add(aF);
|
|
}
|
|
//
|
|
aNbF=aMFC.Extent();
|
|
aNbSo=aMSo.Extent();
|
|
for (i=1; i<=aNbSo; ++i) {
|
|
const TopoDS_Shape& aSo=aMSo(i);
|
|
//
|
|
bFound=Standard_True;
|
|
aMFSo.Clear();
|
|
TopExp::MapShapes(aSo, TopAbs_FACE, aMFSo);
|
|
//
|
|
aNbFSo=aMFSo.Extent();
|
|
if (aNbFSo!=aNbF) {
|
|
bFound=Standard_False;
|
|
continue;
|
|
}
|
|
//
|
|
for (j=1; j<=aNbFSo; ++j) {
|
|
const TopoDS_Shape& aFSo=aMFSo(j);
|
|
if (!aMFC.Contains(aFSo)) {
|
|
bFound=Standard_False;
|
|
break;
|
|
}
|
|
}
|
|
if (bFound) {
|
|
aSox=aSo;
|
|
return bFound;
|
|
}
|
|
}
|
|
return bFound;
|
|
}
|