mirror of
https://github.com/Open-Cascade-SAS/OCCT.git
synced 2026-06-15 12:07:41 +08:00
431 lines
12 KiB
C++
Executable File
431 lines
12 KiB
C++
Executable File
// Created on: 1996-09-16
|
|
// Created by: Jacques GOUSSARD
|
|
// Copyright (c) 1996-1999 Matra Datavision
|
|
// Copyright (c) 1999-2012 OPEN CASCADE SAS
|
|
//
|
|
// The content of this file is subject to the Open CASCADE Technology Public
|
|
// License Version 6.5 (the "License"). You may not use the content of this file
|
|
// except in compliance with the License. Please obtain a copy of the License
|
|
// at http://www.opencascade.org and read it completely before using this file.
|
|
//
|
|
// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
|
|
// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
|
|
//
|
|
// The Original Code and all software distributed under the License is
|
|
// distributed on an "AS IS" basis, without warranty of any kind, and the
|
|
// Initial Developer hereby disclaims all such warranties, including without
|
|
// limitation, any warranties of merchantability, fitness for a particular
|
|
// purpose or non-infringement. Please see the License for the specific terms
|
|
// and conditions governing the rights and limitations under the License.
|
|
|
|
|
|
|
|
#include <LocOpe_BuildShape.ixx>
|
|
|
|
|
|
#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
|
|
#include <TopTools_DataMapOfShapeListOfShape.hxx>
|
|
#include <TopTools_IndexedMapOfShape.hxx>
|
|
#include <TColStd_MapOfInteger.hxx>
|
|
|
|
#include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
|
|
#include <TopTools_ListIteratorOfListOfShape.hxx>
|
|
#include <TColStd_MapIteratorOfMapOfInteger.hxx>
|
|
|
|
#include <TopoDS_Compound.hxx>
|
|
#include <TopoDS_Solid.hxx>
|
|
#include <TopoDS_Shell.hxx>
|
|
#include <TopoDS_Edge.hxx>
|
|
|
|
#include <BRep_Tool.hxx>
|
|
#include <BRep_Builder.hxx>
|
|
#include <gp_Pnt.hxx>
|
|
|
|
#include <BRepClass3d_SolidClassifier.hxx>
|
|
|
|
#include <Standard_ConstructionError.hxx>
|
|
|
|
|
|
#include <TopExp.hxx>
|
|
#include <TopAbs.hxx>
|
|
#include <TopoDS.hxx>
|
|
#include <Precision.hxx>
|
|
|
|
|
|
static void Add(const Standard_Integer,
|
|
TColStd_MapOfInteger&,
|
|
TopTools_IndexedMapOfShape&,
|
|
const TopTools_IndexedDataMapOfShapeListOfShape&);
|
|
|
|
static void Propagate(const TopoDS_Shape&, // face
|
|
TopoDS_Shape&, // shell
|
|
const TopTools_IndexedMapOfShape&,
|
|
TColStd_MapOfInteger&);
|
|
|
|
static Standard_Boolean IsInside(const TopoDS_Shape&,
|
|
const TopoDS_Shape&);
|
|
|
|
|
|
//=======================================================================
|
|
//function : Perform
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
void LocOpe_BuildShape::Perform(const TopTools_ListOfShape& L)
|
|
{
|
|
Standard_Integer i ;
|
|
Standard_Integer j ;
|
|
Standard_Integer k ;
|
|
myRes.Nullify();
|
|
|
|
TopoDS_Compound C;
|
|
BRep_Builder B;
|
|
B.MakeCompound(C);
|
|
|
|
TopTools_IndexedMapOfShape mapF;
|
|
TopTools_ListIteratorOfListOfShape itl;
|
|
|
|
for (itl.Initialize(L); itl.More(); itl.Next()) {
|
|
if (itl.Value().ShapeType() == TopAbs_FACE &&
|
|
!mapF.Contains(itl.Value())) {
|
|
mapF.Add(itl.Value());
|
|
B.Add(C,itl.Value());
|
|
}
|
|
}
|
|
|
|
if (mapF.Extent() == 0) {
|
|
return; // no face
|
|
}
|
|
|
|
TopTools_IndexedDataMapOfShapeListOfShape theMapEF;
|
|
TopExp::MapShapesAndAncestors(C,TopAbs_EDGE,TopAbs_FACE,theMapEF);
|
|
|
|
TopTools_DataMapOfShapeListOfShape mapSh;
|
|
TColStd_MapOfInteger mapI,mapIf;
|
|
Standard_Integer Nbedges = theMapEF.Extent();
|
|
|
|
TopTools_ListOfShape lshell;
|
|
TopTools_ListOfShape lresult;
|
|
|
|
do {
|
|
// Recherche du premier edge non traite
|
|
for ( i = 1; i <= Nbedges; i++) {
|
|
if (!mapI.Contains(i)) {
|
|
break;
|
|
}
|
|
}
|
|
if (i <= Nbedges) {
|
|
mapF.Clear();
|
|
mapIf.Clear();
|
|
Add(i,mapI,mapF,theMapEF);
|
|
Standard_Boolean Manifold = Standard_True;
|
|
TopoDS_Shape FaceRef;
|
|
TopAbs_Orientation orient;
|
|
|
|
for ( j = 1; j<= mapF.Extent(); j++) {
|
|
orient = mapF(j).Orientation();
|
|
if (orient == TopAbs_INTERNAL || orient == TopAbs_EXTERNAL) {
|
|
Manifold = Standard_False;
|
|
}
|
|
else if (FaceRef.IsNull()) {
|
|
FaceRef = mapF(j);
|
|
}
|
|
mapIf.Add(j);
|
|
}
|
|
|
|
TopoDS_Shell newSh;
|
|
B.MakeShell(newSh);
|
|
if (!Manifold && FaceRef.IsNull()) {
|
|
// on a un paquet de faces. pas d'orientation possible ?
|
|
for (j = 1; j <= mapF.Extent(); j++) {
|
|
B.Add(newSh,mapF(j));
|
|
}
|
|
}
|
|
else {
|
|
// orienter ce qu`on peut
|
|
if (!Manifold) {
|
|
for (j = 1; j <= mapF.Extent(); j++) {
|
|
if (mapF(j).Orientation() == TopAbs_INTERNAL ||
|
|
mapF(j).Orientation() == TopAbs_EXTERNAL) {
|
|
B.Add(newSh,mapF(j));
|
|
mapIf.Remove(j);
|
|
}
|
|
}
|
|
}
|
|
|
|
B.Add(newSh,FaceRef);
|
|
Propagate(FaceRef,newSh,mapF,mapIf);
|
|
}
|
|
if (!Manifold) {
|
|
lshell.Append(newSh.Oriented(TopAbs_INTERNAL));
|
|
}
|
|
else {
|
|
TopTools_IndexedDataMapOfShapeListOfShape theMapEFbis;
|
|
TopExp::MapShapesAndAncestors(newSh,TopAbs_EDGE,TopAbs_FACE,theMapEFbis);
|
|
for ( k = 1; k<=theMapEFbis.Extent(); k++) {
|
|
const TopoDS_Edge& Ed = TopoDS::Edge(theMapEFbis.FindKey(k));
|
|
TopAbs_Orientation OriEd = Ed.Orientation();
|
|
if (OriEd != TopAbs_INTERNAL && OriEd != TopAbs_EXTERNAL) {
|
|
Standard_Integer Nbfac = theMapEFbis(k).Extent();
|
|
if (Nbfac > 2) { // peu probable
|
|
break;
|
|
}
|
|
else if (Nbfac == 1) {
|
|
if (!BRep_Tool::Degenerated(Ed)) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (k > theMapEFbis.Extent()) {
|
|
TopoDS_Solid newSo;
|
|
B.MakeSolid(newSo);
|
|
B.Add(newSo,newSh); // newSh est FORWARD
|
|
BRepClass3d_SolidClassifier Class(newSo);
|
|
Class.PerformInfinitePoint(Precision::Confusion());
|
|
if (Class.State() == TopAbs_IN) {
|
|
lresult.Append(newSh.Oriented(TopAbs_REVERSED));
|
|
}
|
|
else {
|
|
lresult.Append(newSh);
|
|
}
|
|
}
|
|
else {
|
|
lshell.Append(newSh.Oriented(TopAbs_INTERNAL));
|
|
}
|
|
}
|
|
}
|
|
} while (mapI.Extent() < Nbedges);
|
|
|
|
|
|
// on a une list de shells dans lresult. on suppose qu`ils ne s`intersectent pas.
|
|
// il faut classifier les shells orientes pour en faire des solides...
|
|
// on n`accepte qu`1 niveau d'imbrication
|
|
|
|
TopTools_DataMapOfShapeListOfShape imbSh;
|
|
TopTools_ListOfShape LIntern;
|
|
|
|
for (itl.Initialize(lresult); itl.More(); itl.Next()) {
|
|
const TopoDS_Shape& sh = itl.Value();
|
|
TopoDS_Solid tempo;
|
|
B.MakeSolid(tempo);
|
|
B.Add(tempo,sh);
|
|
|
|
TopTools_ListOfShape thelist;
|
|
imbSh.Bind(sh, thelist);
|
|
TopTools_ListIteratorOfListOfShape itl2;
|
|
for (itl2.Initialize(lresult);
|
|
// for (TopTools_ListIteratorOfListOfShape itl2(lresult);
|
|
itl2.More(); itl2.Next()) {
|
|
const TopoDS_Shape& sh2 = itl2.Value();
|
|
if (!sh2.IsSame(sh)) {
|
|
if (IsInside(sh2, tempo)) {
|
|
LIntern.Append(sh2);
|
|
imbSh(sh).Append(sh2);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// LPA 07/10/98: on vire les shells imbriques comme
|
|
// etant aussi des solides a part entiere.
|
|
for (itl.Initialize(LIntern); itl.More(); itl.Next()) {
|
|
const TopoDS_Shape& sh = itl.Value();
|
|
if (imbSh.IsBound(sh)) {
|
|
imbSh.UnBind(sh);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
TopTools_ListOfShape lsolid;
|
|
do {
|
|
// for (TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itdm(imbSh);
|
|
TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itdm(imbSh);
|
|
for ( ; itdm.More(); itdm.Next()) {
|
|
if (itdm.Value().Extent() != 0) {
|
|
break;
|
|
}
|
|
}
|
|
if (itdm.More()) {
|
|
TopoDS_Solid newSo;
|
|
B.MakeSolid(newSo);
|
|
B.Add(newSo,itdm.Key());
|
|
for (itl.Initialize(itdm.Value()); itl.More(); itl.Next()) {
|
|
B.Add(newSo,itl.Value().Reversed());
|
|
}
|
|
lsolid.Append(newSo);
|
|
imbSh.UnBind(itdm.Key());
|
|
}
|
|
else {
|
|
for (itdm.Reset(); itdm.More(); itdm.Next()) {
|
|
TopoDS_Solid newSo;
|
|
B.MakeSolid(newSo);
|
|
B.Add(newSo,itdm.Key());
|
|
lsolid.Append(newSo);
|
|
}
|
|
imbSh.Clear();
|
|
}
|
|
} while (!imbSh.Extent() == 0);
|
|
|
|
Standard_Integer nbsol = lsolid.Extent();
|
|
Standard_Integer nbshl = lshell.Extent();
|
|
|
|
if (nbsol == 1 && nbshl == 0) {
|
|
myRes = lsolid.First();
|
|
}
|
|
else if (nbsol == 0 && nbshl == 1) {
|
|
myRes = lshell.First();
|
|
}
|
|
else {
|
|
B.MakeCompound(TopoDS::Compound(myRes));
|
|
for (itl.Initialize(lsolid); itl.More(); itl.Next()) {
|
|
B.Add(myRes,itl.Value());
|
|
}
|
|
for (itl.Initialize(lshell); itl.More(); itl.Next()) {
|
|
B.Add(myRes,itl.Value());
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//=======================================================================
|
|
//function : Add
|
|
//purpose : static function
|
|
//=======================================================================
|
|
|
|
static void Add(const Standard_Integer ind,
|
|
TColStd_MapOfInteger& mapI,
|
|
TopTools_IndexedMapOfShape& mapF,
|
|
const TopTools_IndexedDataMapOfShapeListOfShape& mapEF)
|
|
|
|
{
|
|
if (!mapI.Add(ind)) {
|
|
Standard_ConstructionError::Raise();
|
|
}
|
|
|
|
TopTools_ListIteratorOfListOfShape itl(mapEF(ind));
|
|
for (; itl.More(); itl.Next()) {
|
|
if (!mapF.Contains(itl.Value())) {
|
|
mapF.Add(itl.Value());
|
|
TopExp_Explorer exp;
|
|
for (exp.Init(itl.Value(),TopAbs_EDGE);
|
|
// for (TopExp_Explorer exp(itl.Value(),TopAbs_EDGE);
|
|
exp.More(); exp.Next()) {
|
|
const TopoDS_Shape& edg = exp.Current();
|
|
Standard_Integer indedg = mapEF.FindIndex(edg);
|
|
if (indedg == 0) {
|
|
Standard_ConstructionError::Raise();
|
|
}
|
|
if (!mapI.Contains(indedg)) {
|
|
Add(indedg,mapI,mapF,mapEF);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//=======================================================================
|
|
//function : Propagate
|
|
//purpose : static function
|
|
//=======================================================================
|
|
|
|
static void Propagate(const TopoDS_Shape& F,
|
|
TopoDS_Shape& Sh,
|
|
const TopTools_IndexedMapOfShape& mapF,
|
|
TColStd_MapOfInteger& mapIf)
|
|
{
|
|
BRep_Builder B;
|
|
Standard_Integer indf = mapF.FindIndex(F);
|
|
if (!mapIf.Contains(indf)) {
|
|
return;
|
|
}
|
|
mapIf.Remove(indf);
|
|
if (mapIf.Extent() == 0) {
|
|
return;
|
|
}
|
|
|
|
TopExp_Explorer exp;
|
|
for (exp.Init(F,TopAbs_EDGE); exp.More(); exp.Next()) {
|
|
// for (TopExp_Explorer exp(F,TopAbs_EDGE); exp.More(); exp.Next()) {
|
|
const TopoDS_Shape& edg = exp.Current();
|
|
#ifdef DEB
|
|
TopAbs_Orientation ored1 = edg.Orientation(),ored2;
|
|
#else
|
|
TopAbs_Orientation ored1 = edg.Orientation(),ored2 = TopAbs_FORWARD;
|
|
#endif
|
|
if (ored1 == TopAbs_INTERNAL || ored1 == TopAbs_EXTERNAL) {
|
|
continue;
|
|
}
|
|
// for (TColStd_MapIteratorOfMapOfInteger itm(mapIf);
|
|
TColStd_MapIteratorOfMapOfInteger itm(mapIf);
|
|
for ( ; itm.More(); itm.Next()) {
|
|
const TopoDS_Shape& newF = mapF(itm.Key());
|
|
// for (TopExp_Explorer exp2(newF,TopAbs_EDGE);exp2.More(); exp2.Next()) {
|
|
TopExp_Explorer exp2(newF,TopAbs_EDGE) ;
|
|
for ( ;exp2.More(); exp2.Next()) {
|
|
if (exp2.Current().IsSame(edg)) {
|
|
break;
|
|
}
|
|
}
|
|
if (exp2.More()) {
|
|
ored2 = exp2.Current().Orientation();
|
|
break;
|
|
}
|
|
}
|
|
if (itm.More()) {
|
|
TopoDS_Shape FtoAdd = mapF(itm.Key());
|
|
Standard_Boolean added = Standard_False;
|
|
if (ored2 == ored1) {
|
|
FtoAdd.Reverse();
|
|
B.Add(Sh,FtoAdd);
|
|
added = Standard_True;
|
|
}
|
|
else if (ored2 == TopAbs::Reverse(ored1)) {
|
|
B.Add(Sh,FtoAdd);
|
|
added = Standard_True;
|
|
}
|
|
if (added) {
|
|
Propagate(FtoAdd,Sh,mapF,mapIf);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : IsInside
|
|
//purpose : static function
|
|
//=======================================================================
|
|
|
|
static Standard_Boolean IsInside(const TopoDS_Shape& S1,
|
|
const TopoDS_Shape& S2)
|
|
{
|
|
BRepClass3d_SolidClassifier Class(S2);
|
|
TopExp_Explorer exp;
|
|
for (exp.Init(S1,TopAbs_VERTEX);exp.More(); exp.Next()) {
|
|
// for (TopExp_Explorer exp(S1,TopAbs_VERTEX);exp.More(); exp.Next()) {
|
|
const TopoDS_Vertex& vtx = TopoDS::Vertex(exp.Current());
|
|
gp_Pnt Pttest = BRep_Tool::Pnt(vtx);
|
|
Standard_Real Tol = BRep_Tool::Tolerance(vtx);
|
|
Class.Perform(Pttest,Tol);
|
|
if (Class.State() == TopAbs_IN) {
|
|
return Standard_True;
|
|
}
|
|
else if (Class.State() == TopAbs_OUT) {
|
|
return Standard_False;
|
|
}
|
|
}
|
|
#ifdef DEB
|
|
cout << "Classification impossible sur vertex " << endl;
|
|
#endif
|
|
|
|
return Standard_True;
|
|
|
|
}
|
|
|