1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-06-05 11:24:17 +03:00
occt/src/TopOpeBRepBuild/TopOpeBRepBuild_End.cxx
mpa f1191d3099 0026682: TopExp::MapShapesAndAncestors() will build map with duplicated ancestors.
The new method TopExp::MapShapesAndUniqueAncestors has been implemented, which excludes duplication of ancestors in the list items. The optional Boolean argument 'useOrientation' of this method points whether two same shapes with different orientation will be considered equal.
OCCT code has been inspected and MapShapesAndAncestors has been replaced with MapShapesAndUniqueAncestors where it is necessary.
2017-03-16 17:41:27 +03:00

418 lines
14 KiB
C++

// Created on: 1993-06-14
// Created by: Jean Yves LEBEY
// Copyright (c) 1993-1999 Matra Datavision
// Copyright (c) 1999-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 <Bnd_Box.hxx>
#include <BRep_Builder.hxx>
#include <BRep_Tool.hxx>
#include <BRepAdaptor_Curve.hxx>
#include <BRepAdaptor_Surface.hxx>
#include <Geom2d_Curve.hxx>
#include <Geom_Curve.hxx>
#include <gp_Pnt.hxx>
#include <Standard_NoSuchObject.hxx>
#include <Standard_ProgramError.hxx>
#include <TColgp_Array1OfPnt.hxx>
#include <TCollection_AsciiString.hxx>
#include <TopExp.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Compound.hxx>
#include <TopoDS_Edge.hxx>
#include <TopoDS_Face.hxx>
#include <TopoDS_Shape.hxx>
#include <TopoDS_Vertex.hxx>
#include <TopOpeBRepBuild_Builder.hxx>
#include <TopOpeBRepBuild_define.hxx>
#include <TopOpeBRepBuild_EdgeBuilder.hxx>
#include <TopOpeBRepBuild_FaceBuilder.hxx>
#include <TopOpeBRepBuild_GTopo.hxx>
#include <TopOpeBRepBuild_HBuilder.hxx>
#include <TopOpeBRepBuild_PaveSet.hxx>
#include <TopOpeBRepBuild_ShapeSet.hxx>
#include <TopOpeBRepBuild_ShellFaceSet.hxx>
#include <TopOpeBRepBuild_SolidBuilder.hxx>
#include <TopOpeBRepBuild_WireEdgeSet.hxx>
#include <TopOpeBRepDS_BuildTool.hxx>
#include <TopOpeBRepDS_CurveIterator.hxx>
#include <TopOpeBRepDS_DataMapIteratorOfDataMapOfShapeListOfShapeOn1State.hxx>
#include <TopOpeBRepDS_HDataStructure.hxx>
#include <TopOpeBRepDS_ListOfShapeOn1State.hxx>
#include <TopOpeBRepDS_PointIterator.hxx>
#include <TopOpeBRepDS_SurfaceIterator.hxx>
#include <TopOpeBRepTool_2d.hxx>
#include <TopOpeBRepTool_FuseEdges.hxx>
#include <TopOpeBRepTool_ShapeExplorer.hxx>
#include <TopTools_DataMapIteratorOfDataMapOfIntegerListOfShape.hxx>
//#include <BRepAdaptor_Curve2d.hxx>
#ifdef OCCT_DEBUG
extern Standard_Boolean TopOpeBRepBuild_GetcontextNOFE();
#endif
//=======================================================================
//function : End
//purpose :
//=======================================================================
void TopOpeBRepBuild_Builder::End()
{
const TopOpeBRepDS_DataStructure& BDS = myDataStructure->DS();
{
// recodage de la continuite (edge,(f1,f2)) != C0 perdue lors
// du changement de surface-support d'une arete non decoupee
// d'une face tangente.
for (Standard_Integer i=1;i<=2;i++) {
TopoDS_Shape S; TopAbs_State sta=TopAbs_UNKNOWN;
if ( i==1 ) { S = myShape1; sta = myState1; }
else if ( i==2 ) { S = myShape2; sta = myState2; }
TopExp_Explorer exs;
for (exs.Init(S,TopAbs_SHELL);exs.More();exs.Next()) {
// for (TopExp_Explorer exs(S,TopAbs_SHELL);exs.More();exs.Next()) {
const TopoDS_Shape& SH = exs.Current();
Standard_Boolean SHhassha = BDS.HasShape(SH);
if ( !SHhassha ) continue;
Standard_Boolean Fhassam = Standard_False;
TopExp_Explorer exf;
for (exf.Init(SH,TopAbs_FACE);exf.More(); exf.Next()) {
// for (TopExp_Explorer exf(SH,TopAbs_FACE);exf.More(); exf.Next()) {
Fhassam = myDataStructure->HasSameDomain(exf.Current());
if ( Fhassam ) break;
}
if ( !Fhassam ) continue;
TopTools_IndexedDataMapOfShapeListOfShape M;
TopExp::MapShapesAndAncestors(S,TopAbs_EDGE,TopAbs_FACE,M);
Standard_Integer nE = M.Extent();
for (Standard_Integer iE = 1; iE <= nE; iE++) {
const TopoDS_Edge& E = TopoDS::Edge(M.FindKey(iE));
if ( IsSplit(E,sta) ) continue;
const TopTools_ListOfShape& LF = M.FindFromIndex(iE);
if ( LF.Extent() < 2 ) continue;
// NYI : > 2 faces connexes par E : iterer sur tous les couples
TopTools_ListIteratorOfListOfShape itLF(LF);
const TopoDS_Face& F1 = TopoDS::Face(itLF.Value()); itLF.Next();
const TopoDS_Face& F2 = TopoDS::Face(itLF.Value());
GeomAbs_Shape C = BRep_Tool::Continuity(E,F1,F2);
if ( C == GeomAbs_C0 ) continue;
Standard_Boolean F1hassam = myDataStructure->HasSameDomain(F1);
Standard_Boolean F2hassam = myDataStructure->HasSameDomain(F2);
if ( !F1hassam && !F2hassam ) continue;
Standard_Boolean F1issplit = IsSplit(F1,sta);
Standard_Boolean F2issplit = IsSplit(F2,sta);
F1issplit &= (Splits(F1,sta).Extent() != 0);
F2issplit &= (Splits(F2,sta).Extent() != 0);
if ( !F1issplit && !F2issplit ) continue;
TopoDS_Face FF1=F1,FF2=F2;
for (Standard_Integer ii=1; ii<=2; ii++) {
if ((ii==1 && !F1issplit) || (ii==2 && !F2issplit)) continue;
TopoDS_Face F;
if (ii==1) F = F1;
else F = F2;
Standard_Boolean f = Standard_False;
TopTools_ListIteratorOfListOfShape it;
for (it.Initialize(Splits(F,sta));it.More();it.Next()) {
const TopoDS_Shape& SF = it.Value();
if (SF.ShapeType() != TopAbs_FACE) continue;
TopExp_Explorer ex;
for (ex.Init(SF,TopAbs_EDGE);ex.More();ex.Next()) {
if (ex.Current().IsSame(E)) {
if (ii==1) FF1 = TopoDS::Face(it.Value());
else FF2 = TopoDS::Face(it.Value());
f = Standard_True; break;
}
}
if (f) break;
}
}
BRep_Builder B;
B.Continuity(E,FF1,FF2,C);
}
}
}
}
// M.A.J de la tolerance des vertex
{
// modified by NIZHNY-MKK Fri Oct 6 16:13:33 2000.BEGIN
TopTools_MapOfShape aMapOfNewEdges, aMapOfNewVertices;
TopTools_ListIteratorOfListOfShape anIt;
Standard_Integer iteratorofnewshape=0;
for(iteratorofnewshape=1; iteratorofnewshape <= myDataStructure->NbCurves(); iteratorofnewshape++) {
for(anIt.Initialize(NewEdges(iteratorofnewshape)); anIt.More(); anIt.Next()) {
aMapOfNewEdges.Add(anIt.Value());
}
}
for(iteratorofnewshape=1; iteratorofnewshape <= myDataStructure->NbPoints(); iteratorofnewshape++) {
aMapOfNewVertices.Add(NewVertex(iteratorofnewshape));
}
// modified by NIZHNY-MKK Fri Oct 6 16:13:36 2000.END
TopoDS_Compound R;BRep_Builder B;B.MakeCompound(R);
const TopTools_ListOfShape& lmergesha1 = Merged(myShape1,myState1);
TopTools_ListIteratorOfListOfShape it(lmergesha1); for(;it.More();it.Next()) B.Add(R,it.Value());
const TopTools_ListOfShape& LOES = Section();
#ifdef OCCT_DEBUG
// Standard_Integer nLOES = LOES.Extent();
#endif
TopTools_IndexedDataMapOfShapeListOfShape idmoelof; TopExp::MapShapesAndAncestors(R,TopAbs_EDGE,TopAbs_FACE,idmoelof);
TopTools_IndexedDataMapOfShapeListOfShape idmovloe; TopExp::MapShapesAndUniqueAncestors(R,TopAbs_VERTEX,TopAbs_EDGE,idmovloe);
TopTools_IndexedDataMapOfShapeListOfShape idmovloes; for (TopTools_ListIteratorOfListOfShape I(LOES);I.More();I.Next())
TopExp::MapShapesAndAncestors(I.Value(),TopAbs_VERTEX,TopAbs_EDGE,idmovloes);
Standard_Integer iv,nv = idmovloe.Extent();
for (iv=1;iv<=nv;iv++) {
Standard_Integer nP1 = 0;
const TopoDS_Vertex& V = TopoDS::Vertex(idmovloe.FindKey(iv));
Standard_Boolean isbe = idmovloes.Contains(V);
if ( !isbe ) continue;
const TopTools_ListOfShape& loe = idmovloe.FindFromIndex(iv);
#ifdef OCCT_DEBUG
// Standard_Integer nloe = loe.Extent();
#endif
TopTools_ListIteratorOfListOfShape iloe;
for (iloe.Initialize(loe);iloe.More();iloe.Next()) {
const TopoDS_Edge& E = TopoDS::Edge(iloe.Value());
const TopTools_ListOfShape& lof = idmoelof.FindFromKey(E);
Standard_Integer nlof = lof.Extent();
nP1 += nlof+1;
}
TColgp_Array1OfPnt TP(1,nP1);
Standard_Integer nP2 = 0;
for (iloe.Initialize(loe);iloe.More();iloe.Next()) {
const TopoDS_Edge& E = TopoDS::Edge(iloe.Value());
Standard_Real pv = BRep_Tool::Parameter(V,E);
gp_Pnt Pv;
Standard_Real f,l;Handle(Geom_Curve) C3D = BRep_Tool::Curve(E,f,l);
if (!C3D.IsNull()) {
Pv = C3D->Value(pv);
TP(++nP2) = Pv;
}
const TopTools_ListOfShape& lof = idmoelof.FindFromKey(E);
#ifdef OCCT_DEBUG
// Standard_Integer nlof = lof.Extent();
#endif
for (TopTools_ListIteratorOfListOfShape ilof(lof);ilof.More();ilof.Next()) {
const TopoDS_Face& F = TopoDS::Face(ilof.Value());
Standard_Real tolpc;
Standard_Boolean pcf = FC2D_HasCurveOnSurface(E,F);
Handle(Geom2d_Curve) C2D;
if (!pcf) {
C2D = FC2D_CurveOnSurface(E,F,f,l,tolpc);
if (C2D.IsNull()) throw Standard_ProgramError("TopOpeBRepBuild_Builder::End 1");
Standard_Real tolE = BRep_Tool::Tolerance(E);
Standard_Real tol = Max(tolE,tolpc);
B.UpdateEdge(E,C2D,F,tol);
}
C2D = FC2D_CurveOnSurface(E,F,f,l,tolpc);
gp_Pnt2d P2 = C2D->Value(pv);
BRepAdaptor_Surface BAS(F,Standard_False);
Pv = BAS.Value(P2.X(),P2.Y());
TP(++nP2) = Pv;
// modified by NIZHNY-MKK Fri Sep 29 16:08:28 2000.BEGIN
if(aMapOfNewEdges.Contains(E)) {
Standard_Real anEdgeTol = BRep_Tool::Tolerance(E);
Standard_Real aFaceTol = BRep_Tool::Tolerance(F);
if(anEdgeTol < aFaceTol)
B.UpdateEdge(E, aFaceTol);
}
// modified by NIZHNY-MKK Fri Sep 29 16:08:32 2000.END
}
// modified by NIZHNY-MKK Fri Sep 29 16:54:08 2000.BEGIN
if(aMapOfNewVertices.Contains(V)) {
Standard_Real aVertexTol = BRep_Tool::Tolerance(V);
Standard_Real anEdgeTol = BRep_Tool::Tolerance(E);
if (aVertexTol < anEdgeTol)
B.UpdateVertex(V, anEdgeTol);
}
// modified by NIZHNY-MKK Fri Sep 29 16:54:12 2000.END
}
Standard_Real newtol = BRep_Tool::Tolerance(V);
Bnd_Box BOX;
gp_Pnt Pv = BRep_Tool::Pnt(V);
BOX.Set(Pv);
for (Standard_Integer i=1;i<=nP2;i++) {
const gp_Pnt& Pi = TP(i);
BOX.Update(Pi.X(),Pi.Y(),Pi.Z());
}
Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
BOX.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
gp_Pnt P1(aXmin, aYmin, aZmin);
gp_Pnt P2(aXmax, aYmax, aZmax);
Standard_Real d = P1.Distance(P2);
if (d > newtol) {
#ifdef OCCT_DEBUG
cout<<"\npoint P"<<iv<<" "<<Pv.X()<<" "<<Pv.Y()<<" "<<Pv.Z()<<endl;
cout<<"TopOpeBRepBuild_Builder::End BOX newtol "<<newtol<<" -> "<<d<<endl;
#endif
newtol = d;
B.UpdateVertex(V,newtol);
}
}
}
Standard_Boolean makeFE = Standard_True;
#ifdef OCCT_DEBUG
makeFE = !TopOpeBRepBuild_GetcontextNOFE();
#endif
if (makeFE) {
// TopAbs_State state = myState1;
TopTools_ListOfShape& ls = ChangeMerged(myShape1,myState1);
for (TopTools_ListIteratorOfListOfShape itls(ls);itls.More();itls.Next()) {
TopoDS_Shape& SFE = itls.Value();
TopOpeBRepTool_FuseEdges FE(SFE);
// avoid fusing old edges
TopTools_IndexedMapOfShape mapOldEdges;
TopExp::MapShapes (myShape1, TopAbs_EDGE, mapOldEdges);
TopExp::MapShapes (myShape2, TopAbs_EDGE, mapOldEdges);
FE.AvoidEdges (mapOldEdges);
// Get List of edges that have been fused
TopTools_DataMapOfIntegerListOfShape mle;
FE.Edges(mle);
Standard_Integer nle = mle.Extent();
if ( nle != 0 ) {
FE.Perform();
SFE = FE.Shape();
TopTools_DataMapOfIntegerShape mre;
TopTools_DataMapOfShapeShape mlf;
FE.ResultEdges(mre);
FE.Faces(mlf);
// edit the split to remove to edges to be fused and put them into the Merged
//
UpdateSplitAndMerged(mle, mre, mlf, TopAbs_IN);
UpdateSplitAndMerged(mle, mre, mlf, TopAbs_OUT);
UpdateSplitAndMerged(mle, mre, mlf, TopAbs_ON);
}
} // makeFE
}
}
//=======================================================================
//function : UpdateSplitAndMerged
//purpose : edit the split to remove to edges to be fused and put them into the Merged
//=======================================================================
void TopOpeBRepBuild_Builder::UpdateSplitAndMerged(const TopTools_DataMapOfIntegerListOfShape& mle,
const TopTools_DataMapOfIntegerShape& mre,
const TopTools_DataMapOfShapeShape& mlf,
const TopAbs_State state)
{
const TopOpeBRepDS_DataMapOfShapeListOfShapeOn1State& MapSplit = MSplit(state);
TopOpeBRepDS_DataMapIteratorOfDataMapOfShapeListOfShapeOn1State it;
for (it.Initialize(MapSplit); it.More(); it.Next()) {
const TopoDS_Shape& e = it.Key();
// For each edge of the MapSplit
if ( e.ShapeType() == TopAbs_EDGE ) {
// get the list of splitted edges.
TopTools_ListOfShape& LstSplit = ChangeSplit(e,state);
// for each edge of the list of splitted edges
TopTools_ListIteratorOfListOfShape itSplitEdg;
itSplitEdg.Initialize(LstSplit);
while ( itSplitEdg.More()) {
const TopoDS_Shape& edgecur = itSplitEdg.Value();
// for each "packet" of edges to be fused
TopTools_DataMapIteratorOfDataMapOfIntegerListOfShape itLstEdg;
itLstEdg.Initialize(mle);
Standard_Boolean Found = Standard_False;
while ( itLstEdg.More() && !Found) {
const Standard_Integer& iLst = itLstEdg.Key();
const TopTools_ListOfShape& LmapEdg = mle.Find(iLst);
// look for each edge of the list if it is in the map Split
TopTools_ListIteratorOfListOfShape itEdg;
itEdg.Initialize(LmapEdg);
while ( itEdg.More() && !Found ) {
const TopoDS_Shape& edgefuse = itEdg.Value();
if (edgecur.IsSame(edgefuse)) {
Found = Standard_True;
LstSplit.Remove(itSplitEdg);
// edit the list of merged
TopAbs_State stateMerged;
if (ShapeRank(e) == 1)
stateMerged = myState1;
else
stateMerged = myState2;
TopTools_ListOfShape LstMerged;
LstMerged.Append(mre(iLst));
ChangeMerged(e,stateMerged) = LstMerged;
}
itEdg.Next();
}
itLstEdg.Next();
}
if (!Found) {
itSplitEdg.Next();
}
}
}
// For each face of the MapSplit
else if ( e.ShapeType() == TopAbs_FACE ) {
// get the list of splitted faces.
TopTools_ListOfShape& LstSplit = ChangeSplit(e,state);
// for each face of the list of splitted faces
TopTools_ListIteratorOfListOfShape itSplitFac;
itSplitFac.Initialize(LstSplit);
while ( itSplitFac.More()) {
const TopoDS_Shape& facecur = itSplitFac.Value();
if (mlf.IsBound(facecur)) {
LstSplit.InsertBefore(mlf(facecur),itSplitFac);
LstSplit.Remove(itSplitFac);
}
else {
itSplitFac.Next();
}
}
}
}
}