Loading files
3d097a032This file is pinned to the selected release. Download the original to open it in your design tool.
// Created on: 1996-09-16
// Created by: Jacques GOUSSARD
// Copyright (c) 1996-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 <BRepClass3d_SolidClassifier.hxx>
#include <gp_Pnt.hxx>
#include <LocOpe_BuildShape.hxx>
#include <Precision.hxx>
#include <Standard_ConstructionError.hxx>
#include <Standard_Integer.hxx>
#include <NCollection_Map.hxx>
#include <TopAbs.hxx>
#include <TopExp.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Compound.hxx>
#include <TopoDS_Edge.hxx>
#include <TopoDS_Shape.hxx>
#include <TopoDS_Shell.hxx>
#include <TopoDS_Solid.hxx>
#include <NCollection_List.hxx>
#include <TopTools_ShapeMapHasher.hxx>
#include <NCollection_DataMap.hxx>
#include <NCollection_IndexedDataMap.hxx>
#include <NCollection_IndexedMap.hxx>
static void Add(const int,
NCollection_Map<int>&,
NCollection_IndexedMap<TopoDS_Shape, TopTools_ShapeMapHasher>&,
const NCollection_IndexedDataMap<TopoDS_Shape,
NCollection_List<TopoDS_Shape>,
TopTools_ShapeMapHasher>&);
static void Propagate(const TopoDS_Shape&, // face
TopoDS_Shape&, // shell
const NCollection_IndexedMap<TopoDS_Shape, TopTools_ShapeMapHasher>&,
NCollection_Map<int>&);
static bool IsInside(const TopoDS_Shape&, const TopoDS_Shape&);
//=================================================================================================
void LocOpe_BuildShape::Perform(const NCollection_List<TopoDS_Shape>& L)
{
int i;
int j;
int k;
myRes.Nullify();
TopoDS_Compound C;
BRep_Builder B;
B.MakeCompound(C);
NCollection_IndexedMap<TopoDS_Shape, TopTools_ShapeMapHasher> mapF;
NCollection_List<TopoDS_Shape>::Iterator 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
}
NCollection_IndexedDataMap<TopoDS_Shape, NCollection_List<TopoDS_Shape>, TopTools_ShapeMapHasher>
theMapEF;
TopExp::MapShapesAndAncestors(C, TopAbs_EDGE, TopAbs_FACE, theMapEF);
NCollection_DataMap<TopoDS_Shape, NCollection_List<TopoDS_Shape>, TopTools_ShapeMapHasher> mapSh;
NCollection_Map<int> mapI, mapIf;
int Nbedges = theMapEF.Extent();
NCollection_List<TopoDS_Shape> lshell;
NCollection_List<TopoDS_Shape> 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);
bool Manifold = 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 = 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);
}
newSh.Closed(BRep_Tool::IsClosed(newSh));
if (!Manifold)
{
lshell.Append(newSh.Oriented(TopAbs_INTERNAL));
}
else
{
NCollection_IndexedDataMap<TopoDS_Shape,
NCollection_List<TopoDS_Shape>,
TopTools_ShapeMapHasher>
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)
{
int 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
NCollection_DataMap<TopoDS_Shape, NCollection_List<TopoDS_Shape>, TopTools_ShapeMapHasher> imbSh;
NCollection_List<TopoDS_Shape> 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);
NCollection_List<TopoDS_Shape> thelist;
imbSh.Bind(sh, thelist);
NCollection_List<TopoDS_Shape>::Iterator itl2;
for (itl2.Initialize(lresult);
// for (NCollection_List<TopoDS_Shape>::Iterator 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);
}
}
NCollection_List<TopoDS_Shape> lsolid;
do
{
// for (NCollection_DataMap<TopoDS_Shape, NCollection_List<TopoDS_Shape>,
// TopTools_ShapeMapHasher>::Iterator itdm(imbSh);
NCollection_DataMap<TopoDS_Shape, NCollection_List<TopoDS_Shape>, TopTools_ShapeMapHasher>::
Iterator 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.Initialize(imbSh); itdm.More(); itdm.Next())
{
TopoDS_Solid newSo;
B.MakeSolid(newSo);
B.Add(newSo, itdm.Key());
lsolid.Append(newSo);
}
imbSh.Clear();
}
} while (imbSh.Extent() != 0);
int nbsol = lsolid.Extent();
int 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());
}
}
}
//=================================================================================================
static void Add(const int ind,
NCollection_Map<int>& mapI,
NCollection_IndexedMap<TopoDS_Shape, TopTools_ShapeMapHasher>& mapF,
const NCollection_IndexedDataMap<TopoDS_Shape,
NCollection_List<TopoDS_Shape>,
TopTools_ShapeMapHasher>& mapEF)
{
if (!mapI.Add(ind))
{
throw Standard_ConstructionError();
}
NCollection_List<TopoDS_Shape>::Iterator 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();
int indedg = mapEF.FindIndex(edg);
if (indedg == 0)
{
throw Standard_ConstructionError();
}
if (!mapI.Contains(indedg))
{
Add(indedg, mapI, mapF, mapEF);
}
}
}
}
}
//=================================================================================================
static void Propagate(const TopoDS_Shape& F,
TopoDS_Shape& Sh,
const NCollection_IndexedMap<TopoDS_Shape, TopTools_ShapeMapHasher>& mapF,
NCollection_Map<int>& mapIf)
{
BRep_Builder B;
int 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();
TopAbs_Orientation ored1 = edg.Orientation(), ored2 = TopAbs_FORWARD;
if (ored1 == TopAbs_INTERNAL || ored1 == TopAbs_EXTERNAL)
{
continue;
}
// for (NCollection_Map<int>::Iterator itm(mapIf);
NCollection_Map<int>::Iterator 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());
bool added = false;
if (ored2 == ored1)
{
FtoAdd.Reverse();
B.Add(Sh, FtoAdd);
added = true;
}
else if (ored2 == TopAbs::Reverse(ored1))
{
B.Add(Sh, FtoAdd);
added = true;
}
if (added)
{
Propagate(FtoAdd, Sh, mapF, mapIf);
}
}
}
}
//=================================================================================================
static bool 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);
double Tol = BRep_Tool::Tolerance(vtx);
Class.Perform(Pttest, Tol);
if (Class.State() == TopAbs_IN)
{
return true;
}
else if (Class.State() == TopAbs_OUT)
{
return false;
}
}
#ifdef OCCT_DEBUG
std::cout << "Classification impossible sur vertex " << std::endl;
#endif
return true;
}