mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-04-09 18:50:54 +03:00
Performance update applied: - moving to const reference as much as possible Result of CLANG_TIDY (static analyzing filter: perform*)
527 lines
15 KiB
C++
527 lines
15 KiB
C++
// Created on: 1994-12-23
|
|
// Created by: Remi LEQUETTE
|
|
// Copyright (c) 1994-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 <BRep_Builder.hxx>
|
|
#include <BRep_Tool.hxx>
|
|
#include <BRepTools_Quilt.hxx>
|
|
#include <Geom2d_Curve.hxx>
|
|
#include <Standard_NoSuchObject.hxx>
|
|
#include <TopExp_Explorer.hxx>
|
|
#include <TopoDS.hxx>
|
|
#include <TopoDS_Compound.hxx>
|
|
#include <TopoDS_Edge.hxx>
|
|
#include <TopoDS_Face.hxx>
|
|
#include <TopoDS_Iterator.hxx>
|
|
#include <TopoDS_Shape.hxx>
|
|
#include <TopoDS_Shell.hxx>
|
|
#include <TopoDS_Vertex.hxx>
|
|
#include <TopoDS_Wire.hxx>
|
|
#include <TopTools_DataMapOfShapeShape.hxx>
|
|
#include <TopTools_IndexedDataMapOfShapeShape.hxx>
|
|
#include <TopTools_MapOfShape.hxx>
|
|
|
|
//=======================================================================
|
|
//function : BRepTools_Quilt
|
|
//purpose :
|
|
//=======================================================================
|
|
BRepTools_Quilt::BRepTools_Quilt() : hasCopy(Standard_False)
|
|
{
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : Add
|
|
//purpose :
|
|
//=======================================================================
|
|
static Standard_Boolean NeedCopied(const TopoDS_Shape& theShape,const TopTools_IndexedDataMapOfShapeShape& myBounds)
|
|
{
|
|
// test if the shape must be copied
|
|
// i.e. it contains a bound subshape
|
|
Standard_Boolean IsCopied = Standard_False;
|
|
TopoDS_Iterator itv(theShape) ;
|
|
for ( ; itv.More(); itv.Next()) {
|
|
if (myBounds.Contains(itv.Value())) {
|
|
IsCopied = Standard_True;
|
|
break;
|
|
}
|
|
}
|
|
return IsCopied;
|
|
}
|
|
static void CopyShape(const TopoDS_Edge& E,TopTools_IndexedDataMapOfShapeShape& myBounds)
|
|
{
|
|
TopoDS_Edge NE = E;
|
|
NE.EmptyCopy();
|
|
NE.Orientation(TopAbs_FORWARD);
|
|
BRep_Builder B;
|
|
// add the edges
|
|
TopoDS_Iterator itv;
|
|
itv.Initialize(E,Standard_False) ; //TCollection_DataMap
|
|
for ( ; itv.More(); itv.Next()) {
|
|
const TopoDS_Shape& V = itv.Value();
|
|
if (myBounds.Contains(V)) {
|
|
B.Add(NE,myBounds.FindFromKey(V).Oriented(V.Orientation()));
|
|
}
|
|
else {
|
|
B.Add(NE,V);
|
|
}
|
|
}
|
|
// set the 3d range
|
|
Standard_Real f,l;
|
|
BRep_Tool::Range(E,f,l);
|
|
B.Range(NE,f,l);
|
|
myBounds.Add(E,NE.Oriented(TopAbs_FORWARD));
|
|
}
|
|
/*static void CopyShape(const TopoDS_Wire& W,TopTools_DataMapOfShapeShape& myBounds)
|
|
{
|
|
TopoDS_Wire NW;
|
|
B.MakeWire(NW);
|
|
TopoDS_Iterator ite(W,Standard_False);
|
|
for ( ; ite.More(); ite.Next()){
|
|
const TopoDS_Edge& E = TopoDS::Edge(ite.Value());
|
|
TopAbs_Orientation OE = E.Orientation();
|
|
if (myBounds.IsBound(E)) {
|
|
TopoDS_Edge& NE = TopoDS::Edge(myBounds(E));
|
|
B.Add(NW,NE.Oriented(OE));
|
|
}
|
|
else
|
|
B.Add(NW,E);
|
|
}
|
|
NW.Orientation(W.Orientation());
|
|
myBounds.Bind(W,NW);
|
|
}*/
|
|
void BRepTools_Quilt::Add(const TopoDS_Shape& S)
|
|
{
|
|
//std::cout <<" Version of sewing with free edges"<<std::endl;
|
|
// Binds all the faces of S
|
|
// - to the face itself if it is not copied
|
|
// - to the copy if it is copied
|
|
if(myBounds.Contains(S))
|
|
{
|
|
return;
|
|
}
|
|
|
|
BRep_Builder B;
|
|
for (TopExp_Explorer wex(S,TopAbs_WIRE,TopAbs_FACE); wex.More(); wex.Next())
|
|
{
|
|
myBounds.Add(wex.Current(),wex.Current());
|
|
}
|
|
|
|
for (TopExp_Explorer eex(S,TopAbs_EDGE,TopAbs_WIRE); eex.More(); eex.Next())
|
|
{
|
|
myBounds.Add(eex.Current(),eex.Current());
|
|
}
|
|
|
|
for (TopExp_Explorer vex(S,TopAbs_VERTEX,TopAbs_EDGE); vex.More(); vex.Next())
|
|
{
|
|
myBounds.Add(vex.Current(),vex.Current());
|
|
}
|
|
|
|
// explore the faces
|
|
for (TopExp_Explorer fex(S,TopAbs_FACE); fex.More(); fex.Next()) {
|
|
|
|
// explore the edges of the face and try to copy them
|
|
// if one edge is bound the face must be copied
|
|
|
|
Standard_Boolean copyFace = Standard_False;
|
|
const TopoDS_Face& F = TopoDS::Face(fex.Current());
|
|
|
|
if (hasCopy) { // if their is no binding, do not test for copy
|
|
|
|
for (TopExp_Explorer fed(F,TopAbs_EDGE); fed.More(); fed.Next()) {
|
|
|
|
if (myBounds.Contains(fed.Current())) {
|
|
copyFace = Standard_True;
|
|
}
|
|
else {
|
|
// test if the edge must be copied
|
|
// i.e. it contains a bound vertex
|
|
|
|
Standard_Boolean copyEdge = NeedCopied(fed.Current(),myBounds);
|
|
//Standard_Boolean copyEdge = Standard_False;
|
|
const TopoDS_Edge& E = TopoDS::Edge(fed.Current());
|
|
|
|
// TopoDS_Iterator itv(E) ;
|
|
// for ( ; itv.More(); itv.Next()) {
|
|
// if (myBounds.IsBound(itv.Value())) {
|
|
// copyEdge = Standard_True;
|
|
// break;
|
|
// }
|
|
// }
|
|
|
|
if (copyEdge) {
|
|
|
|
// copy of an edge
|
|
|
|
copyFace = Standard_True;
|
|
CopyShape(E,myBounds);
|
|
//TopoDS_Edge NE = E; //gka version for free edges
|
|
//NE.EmptyCopy();
|
|
|
|
//NE.Orientation(TopAbs_FORWARD);
|
|
// add the edges
|
|
//itv.Initialize(E,Standard_False) ;
|
|
//for ( ; itv.More(); itv.Next()) {
|
|
//const TopoDS_Shape& V = itv.Value();
|
|
//if (myBounds.IsBound(V)) {
|
|
// B.Add(NE,myBounds(V).Oriented(V.Orientation()));
|
|
//}
|
|
//else {
|
|
// B.Add(NE,V);
|
|
//}
|
|
//}
|
|
// set the 3d range
|
|
//Standard_Real f,l;
|
|
//BRep_Tool::Range(E,f,l);
|
|
//B.Range(NE,f,l);
|
|
|
|
//myBounds.Bind(E,NE.Oriented(TopAbs_FORWARD));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// NF will be the copy of F or F itself
|
|
TopoDS_Face NF = F;
|
|
|
|
if (copyFace) {
|
|
|
|
// copy of a face
|
|
|
|
NF.EmptyCopy();
|
|
NF.Orientation(TopAbs_FORWARD);
|
|
|
|
for (TopoDS_Iterator itw(F,Standard_False); itw.More(); itw.Next()) {
|
|
const TopoDS_Wire& W = TopoDS::Wire(itw.Value());
|
|
|
|
TopoDS_Wire NW;
|
|
B.MakeWire(NW);
|
|
TopoDS_Iterator ite(W,Standard_False);
|
|
Standard_Real UFirst,ULast;
|
|
|
|
// Reconstruction des wires.
|
|
|
|
for ( ; ite.More(); ite.Next()){
|
|
const TopoDS_Edge& E = TopoDS::Edge(ite.Value());
|
|
TopAbs_Orientation OE = E.Orientation();
|
|
if (myBounds.Contains(E)) {
|
|
const TopoDS_Edge& NE = TopoDS::Edge(myBounds.FindFromKey(E));
|
|
// pcurve.
|
|
if (NE.Orientation() == TopAbs_FORWARD) {
|
|
B.UpdateEdge(NE,
|
|
BRep_Tool::CurveOnSurface(E,F,UFirst,ULast),
|
|
F,BRep_Tool::Tolerance(E));
|
|
}
|
|
else {
|
|
// Si NE est REVERSED
|
|
// => les curve3d n ont pas la meme orientation.
|
|
// ( C est une convention cf BRepTools_Quilt.cdl. et la methode
|
|
// Bind.)
|
|
// => la PCurve de E sur F doit etre inversee.
|
|
|
|
OE = TopAbs::Reverse(OE);
|
|
Handle(Geom2d_Curve) CE =
|
|
BRep_Tool::CurveOnSurface(E,F,UFirst,ULast);
|
|
Handle(Geom2d_Curve) NCE = CE->Reversed();
|
|
B.UpdateEdge(NE,NCE,F,BRep_Tool::Tolerance(E));
|
|
Standard_Real tmp = UFirst;
|
|
UFirst = CE->ReversedParameter(ULast);
|
|
ULast = CE->ReversedParameter(tmp);
|
|
}
|
|
// pcurve range
|
|
B.Range(NE,F,UFirst,ULast);
|
|
|
|
B.Add(NW,NE.Oriented(OE));
|
|
}
|
|
else {
|
|
B.Add(NW,E);
|
|
}
|
|
}
|
|
NW.Orientation(W.Orientation());
|
|
B.Add(NF,NW);
|
|
}
|
|
NF.Orientation(F.Orientation());
|
|
}
|
|
|
|
// binds the face to itself or its copy
|
|
myBounds.Add(F,NF);
|
|
}
|
|
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : Bind
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
void BRepTools_Quilt::Bind(const TopoDS_Vertex& Vold,
|
|
const TopoDS_Vertex& Vnew)
|
|
{
|
|
if (!myBounds.Contains(Vold)) {
|
|
myBounds.Add(Vold,Vnew);
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : Bind
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
void BRepTools_Quilt::Bind(const TopoDS_Edge& Eold, const TopoDS_Edge& Enew)
|
|
{
|
|
if (!myBounds.Contains(Eold)) {
|
|
TopoDS_Edge ENew = Enew;
|
|
if (IsCopied(Enew)) {
|
|
ENew = TopoDS::Edge(Copy(Enew));
|
|
ENew.Orientation(Enew.Orientation());
|
|
}
|
|
|
|
if (Eold.Orientation() != ENew.Orientation()) {
|
|
myBounds.Add(Eold.Oriented(TopAbs_FORWARD),
|
|
ENew.Oriented(TopAbs_REVERSED));
|
|
}
|
|
else {
|
|
myBounds.Add(Eold.Oriented(TopAbs_FORWARD),
|
|
ENew.Oriented(TopAbs_FORWARD));
|
|
}
|
|
// if new binding bind also the vertices
|
|
TopoDS_Iterator itold(Eold);
|
|
while (itold.More()) {
|
|
if (!myBounds.Contains(itold.Value())) {
|
|
// find the vertex of Enew with same orientation
|
|
TopAbs_Orientation anOrien = itold.Value().Orientation();
|
|
TopoDS_Iterator itnew(ENew);
|
|
while (itnew.More()) {
|
|
if (itnew.Value().Orientation() == anOrien) {
|
|
TopoDS_Vertex VNew = TopoDS::Vertex(itnew.Value());
|
|
if (IsCopied(VNew)) {
|
|
// if VNew has been copied take the copy
|
|
VNew = TopoDS::Vertex(Copy(VNew));
|
|
}
|
|
myBounds.Add(itold.Value(),VNew);
|
|
break;
|
|
}
|
|
itnew.Next();
|
|
}
|
|
}
|
|
itold.Next();
|
|
}
|
|
hasCopy = Standard_True;
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : IsBound
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
Standard_Boolean BRepTools_Quilt::IsCopied(const TopoDS_Shape& S) const
|
|
{
|
|
if (myBounds.Contains(S)) {
|
|
return !S.IsSame(myBounds.FindFromKey(S));
|
|
}
|
|
else
|
|
return Standard_False;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : Copy
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
const TopoDS_Shape& BRepTools_Quilt::Copy(const TopoDS_Shape& S) const
|
|
{
|
|
Standard_NoSuchObject_Raise_if(!IsCopied(S),"BRepTools_Quilt::Copy");
|
|
return myBounds.FindFromKey(S);
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : Shells
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
TopoDS_Shape BRepTools_Quilt::Shells() const
|
|
{
|
|
// Outline of the algorithm
|
|
//
|
|
// In the map M we bind the free edges to their shells
|
|
// We explore all the faces in myBounds
|
|
// For each one we search the edges in the map and either :
|
|
//
|
|
// - Start a new shell if no edge is a free edge.
|
|
// - Add the face to an existing shell
|
|
// - Connect other shells if the face touch more than one shell
|
|
|
|
// In the Map M the Shell is bound with the relative orientation of E
|
|
// in the shell
|
|
// In the map MF we binb the face to its shell.
|
|
// In the Map MF the Shell is bound with the relative orientation of F
|
|
// in the shell
|
|
|
|
TopTools_DataMapOfShapeShape M, MF;
|
|
BRep_Builder B;
|
|
TopoDS_Compound result;
|
|
|
|
B.MakeCompound(result);
|
|
|
|
TopTools_MapOfShape MapOtherShape; //gka
|
|
TopTools_MapOfShape EdgesFaces;
|
|
|
|
// loop on the face in myBounds
|
|
//TopTools_DataMapIteratorOfDataMapOfShapeShape it(myBounds);
|
|
|
|
//while (it.More())
|
|
for(Standard_Integer ii =1; ii <= myBounds.Extent(); ii++) {
|
|
const TopoDS_Shape& Shape = myBounds.FindFromIndex(ii); //it.Value();
|
|
if (Shape.ShapeType() == TopAbs_FACE) {
|
|
for(TopExp_Explorer aExpEdg(Shape,TopAbs_EDGE); aExpEdg.More(); aExpEdg.Next()) //gka
|
|
EdgesFaces.Add(aExpEdg.Current());
|
|
|
|
TopoDS_Shell SH;
|
|
TopAbs_Orientation NewO;
|
|
|
|
TopExp_Explorer itf1( Shape,TopAbs_EDGE);
|
|
for ( ; itf1.More(); itf1.Next()) {
|
|
const TopoDS_Shape& E = itf1.Current();
|
|
if (M.IsBound(E)) {
|
|
SH = TopoDS::Shell(M(E));
|
|
if (SH.Orientation() == E.Orientation())
|
|
NewO = TopAbs::Reverse(Shape.Orientation());
|
|
else
|
|
NewO = Shape.Orientation();
|
|
|
|
MF.Bind (Shape,SH.Oriented(NewO));
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (SH.IsNull()) {
|
|
// Create a new shell, closed. Add it to the result.
|
|
B.MakeShell(SH);
|
|
SH.Closed(Standard_True);
|
|
B.Add(result,SH);
|
|
MF.Bind (Shape,SH.Oriented(Shape.Orientation()));
|
|
}
|
|
|
|
|
|
// Add the face to the shell
|
|
SH.Free(Standard_True);
|
|
// B.Add(SH.Oriented(TopAbs_FORWARD), F .Oriented(MF(F).Orientation()));
|
|
TopoDS_Shape arefShape = SH.Oriented(TopAbs_FORWARD) ;
|
|
B.Add( arefShape , Shape.Oriented(MF(Shape).Orientation()));
|
|
|
|
TopExp_Explorer itf(Shape.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
|
|
|
|
for ( ;itf.More(); itf.Next()) {
|
|
const TopoDS_Edge& E = TopoDS::Edge(itf.Current());
|
|
|
|
if (M.IsBound(E)) {
|
|
const TopoDS_Shape oldShell = M(E);
|
|
if (!oldShell.IsSame(SH)) {
|
|
// Fuse the old shell with the new one
|
|
// Compare the orientation of E in SH and in oldshell.
|
|
TopAbs_Orientation anOrien = E.Orientation();
|
|
if (MF(Shape).Orientation() == TopAbs_REVERSED)
|
|
anOrien = TopAbs::Reverse(anOrien);
|
|
|
|
Standard_Boolean Rev = (anOrien == oldShell.Orientation());
|
|
//if rev = True oldShell has to be reversed.
|
|
|
|
// Add the faces of oldShell in SH.
|
|
for (TopoDS_Iterator its(oldShell); its.More(); its.Next()) {
|
|
const TopoDS_Face Fo = TopoDS::Face(its.Value());
|
|
TopAbs_Orientation NewOFo;
|
|
// update the orientation of Fo in SH.
|
|
if (Rev)
|
|
NewOFo = TopAbs::Reverse(MF(Fo).Orientation());
|
|
else
|
|
NewOFo = MF(Fo).Orientation();
|
|
|
|
MF.Bind(Fo,SH.Oriented(NewOFo));
|
|
// B.Add (SH.Oriented(TopAbs_FORWARD),Fo.Oriented(NewO));
|
|
TopoDS_Shape arefShapeFo = SH.Oriented(TopAbs_FORWARD) ;
|
|
B.Add ( arefShapeFo,Fo.Oriented(NewOFo));
|
|
}
|
|
// Rebind the free edges of the old shell to the new shell
|
|
//gka BUG 6491
|
|
TopExp_Explorer aexp(SH,TopAbs_EDGE);
|
|
for( ; aexp.More(); aexp.Next()) {
|
|
//for (TopTools_DataMapIteratorOfDataMapOfShapeShape itm(M);
|
|
// itm.More(); ) {
|
|
if(!M.IsBound(aexp.Current()))
|
|
continue;
|
|
const TopoDS_Shape& ae = aexp.Current();
|
|
TopoDS_Shape as = M.Find(ae);
|
|
if (as.IsSame(oldShell)) {
|
|
// update the orientation of free edges in SH.
|
|
if (Rev)
|
|
NewO = TopAbs::Reverse(as.Orientation());
|
|
else
|
|
NewO = as.Orientation();
|
|
|
|
M.Bind(ae,SH.Oriented(NewO));
|
|
}
|
|
}
|
|
// remove the old shell from the result
|
|
B.Remove(result,oldShell.Oriented(TopAbs_FORWARD));
|
|
}
|
|
// Test if SH is always orientable.
|
|
TopAbs_Orientation anOrien = E.Orientation();
|
|
if (MF(Shape).Orientation() == TopAbs_REVERSED)
|
|
anOrien = TopAbs::Reverse(anOrien);
|
|
|
|
if (M(E).Orientation() == anOrien)
|
|
SH.Orientable(Standard_False);
|
|
|
|
// remove the edge from M (no more a free edge)
|
|
M.UnBind(E);
|
|
}
|
|
else {
|
|
NewO = E.Orientation();
|
|
if (MF(Shape).Orientation() == TopAbs_REVERSED)
|
|
NewO = TopAbs::Reverse(NewO);
|
|
if(!E.IsNull())
|
|
M.Bind(E,SH.Oriented(NewO));
|
|
else
|
|
continue;
|
|
}
|
|
}
|
|
|
|
// freeze the shell
|
|
SH.Free(Standard_False);
|
|
}
|
|
else
|
|
MapOtherShape.Add(Shape);
|
|
|
|
//it.Next();
|
|
}
|
|
|
|
// Unclose all shells having free edges
|
|
for (TopTools_DataMapIteratorOfDataMapOfShapeShape it(M); it.More(); it.Next()) {
|
|
TopoDS_Shape S = it.Value();
|
|
S.Closed (Standard_False);
|
|
}
|
|
|
|
TopTools_MapIteratorOfMapOfShape itother(MapOtherShape); //gka version for free edges
|
|
for( ; itother.More() ; itother.Next()) {
|
|
if(!EdgesFaces.Contains(itother.Key()) && myBounds.Contains(itother.Key())) {
|
|
TopoDS_Shape aSh = myBounds.FindFromKey(itother.Key());
|
|
B.Add(result,aSh);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|