Loading files
f2929057eThis file is pinned to the selected release. Download the original to open it in your design tool.
// 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 <Precision.hxx>
#include <ShapeAnalysis.hxx>
#include <ShapeBuild_ReShape.hxx>
#include <ShapeExtend_WireData.hxx>
#include <ShapeUpgrade_RemoveInternalWires.hxx>
#include <Standard_Type.hxx>
#include <TopExp.hxx>
#include <TopExp_Explorer.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Edge.hxx>
#include <TopoDS_Face.hxx>
#include <TopoDS_Iterator.hxx>
#include <TopoDS_Shape.hxx>
#include <TopoDS_Wire.hxx>
#include <NCollection_List.hxx>
#include <TopTools_ShapeMapHasher.hxx>
#include <NCollection_IndexedDataMap.hxx>
#include <NCollection_IndexedMap.hxx>
#include <NCollection_Sequence.hxx>
IMPLEMENT_STANDARD_RTTIEXT(ShapeUpgrade_RemoveInternalWires, ShapeUpgrade_Tool)
//=================================================================================================
ShapeUpgrade_RemoveInternalWires::ShapeUpgrade_RemoveInternalWires()
{
myMinArea = 0.;
myRemoveFacesMode = true;
myStatus = ShapeExtend::EncodeStatus(ShapeExtend_OK);
occ::handle<ShapeBuild_ReShape> aContext = new ShapeBuild_ReShape;
SetContext(aContext);
}
//=================================================================================================
ShapeUpgrade_RemoveInternalWires::ShapeUpgrade_RemoveInternalWires(const TopoDS_Shape& theShape)
{
occ::handle<ShapeBuild_ReShape> aContext = new ShapeBuild_ReShape;
SetContext(aContext);
Init(theShape);
}
//=================================================================================================
void ShapeUpgrade_RemoveInternalWires::Init(const TopoDS_Shape& theShape)
{
myShape = theShape;
Context()->Apply(theShape);
TopExp::MapShapesAndAncestors(myShape, TopAbs_EDGE, TopAbs_FACE, myEdgeFaces);
myStatus = ShapeExtend::EncodeStatus(ShapeExtend_OK);
myMinArea = 0.;
myRemoveFacesMode = true;
}
//=================================================================================================
bool ShapeUpgrade_RemoveInternalWires::Perform()
{
Clear();
if (myShape.IsNull())
{
myStatus |= ShapeExtend::EncodeStatus(ShapeExtend_FAIL1);
return false;
}
TopExp_Explorer aExpF(myShape, TopAbs_FACE);
for (; aExpF.More(); aExpF.Next())
{
TopoDS_Face aF = TopoDS::Face(aExpF.Current());
removeSmallWire(aF, TopoDS_Wire());
}
if (myRemoveFacesMode)
{
removeSmallFaces();
}
myResult = Context()->Apply(myShape);
return Status(ShapeExtend_DONE);
}
//=================================================================================================
bool ShapeUpgrade_RemoveInternalWires::Perform(
const NCollection_Sequence<TopoDS_Shape>& theSeqShapes)
{
if (myShape.IsNull())
{
myStatus |= ShapeExtend::EncodeStatus(ShapeExtend_FAIL1);
return false;
}
Clear();
NCollection_IndexedDataMap<TopoDS_Shape, NCollection_List<TopoDS_Shape>, TopTools_ShapeMapHasher>
aWireFaces;
int i = 1, nb = theSeqShapes.Length();
for (; i <= nb; i++)
{
const TopoDS_Shape& aS = theSeqShapes.Value(i);
if (aS.ShapeType() == TopAbs_FACE)
{
removeSmallWire(aS, TopoDS_Wire());
}
else if (aS.ShapeType() == TopAbs_WIRE)
{
if (!aWireFaces.Extent())
{
TopExp::MapShapesAndAncestors(myShape, TopAbs_WIRE, TopAbs_FACE, aWireFaces);
}
if (aWireFaces.Contains(aS))
{
const NCollection_List<TopoDS_Shape>& alfaces = aWireFaces.FindFromKey(aS);
NCollection_List<TopoDS_Shape>::Iterator liter(alfaces);
for (; liter.More(); liter.Next())
{
removeSmallWire(liter.Value(), aS);
}
}
}
}
if (myRemoveFacesMode)
{
removeSmallFaces();
}
myResult = Context()->Apply(myShape);
return Status(ShapeExtend_DONE);
}
//=================================================================================================
void ShapeUpgrade_RemoveInternalWires::removeSmallWire(const TopoDS_Shape& theFace,
const TopoDS_Shape& theWire)
{
TopoDS_Face aF = TopoDS::Face(theFace);
TopoDS_Wire anOutW = ShapeAnalysis::OuterWire(aF);
TopoDS_Iterator aIt(aF);
for (; aIt.More(); aIt.Next())
{
if (aIt.Value().ShapeType() != TopAbs_WIRE || aIt.Value().IsSame(anOutW))
{
continue;
}
// occ::handle<ShapeExtend_WireData> asewd = new ShapeExtend_WireData();
TopoDS_Wire aW = TopoDS::Wire(aIt.Value());
if (!theWire.IsNull() && !theWire.IsSame(aW))
{
continue;
}
double anArea = ShapeAnalysis::ContourArea(aW);
if (anArea < myMinArea - Precision::Confusion())
{
Context()->Remove(aW);
myRemoveWires.Append(aW);
myStatus |= ShapeExtend::EncodeStatus(ShapeExtend_DONE1);
if (!myRemoveFacesMode)
{
continue;
}
TopoDS_Iterator aIte(aW, false);
for (; aIte.More(); aIte.Next())
{
const TopoDS_Shape& aE = aIte.Value();
if (myRemoveEdges.IsBound(aE))
{
myRemoveEdges.ChangeFind(aE).Append(aF);
}
else
{
NCollection_List<TopoDS_Shape> alfaces;
alfaces.Append(aF);
myRemoveEdges.Bind(aE, alfaces);
}
}
}
}
}
//=================================================================================================
void ShapeUpgrade_RemoveInternalWires::removeSmallFaces()
{
int i = 1;
for (; i <= myRemoveWires.Length(); i++)
{
TopoDS_Shape aWire = myRemoveWires.Value(i);
TopoDS_Iterator aIte(aWire, false);
NCollection_IndexedMap<TopoDS_Shape, TopTools_ShapeMapHasher> aFaceCandidates;
// collecting all faces containing edges from removed wire
for (; aIte.More(); aIte.Next())
{
const TopoDS_Shape& aEdge = aIte.Value();
if (!myEdgeFaces.Contains(aEdge))
{
myStatus |= ShapeExtend::EncodeStatus(ShapeExtend_FAIL2);
continue;
}
const NCollection_List<TopoDS_Shape>& aLface1 = myEdgeFaces.FindFromKey(aEdge);
const NCollection_List<TopoDS_Shape>& aLface2 = myRemoveEdges.Find(aEdge);
NCollection_List<TopoDS_Shape>::Iterator aliter(aLface1);
NCollection_List<TopoDS_Shape>::Iterator aliter2(aLface2);
for (; aliter.More(); aliter.Next())
{
TopoDS_Shape aF = Context()->Apply(aliter.Value());
if (aF.IsNull())
{
continue;
}
bool isFind = false;
for (; aliter2.More() && !isFind; aliter2.Next())
{
TopoDS_Shape aF2 = Context()->Apply(aliter2.Value());
isFind = aF.IsSame(aF2);
}
if (!isFind)
{
TopoDS_Wire aWout = ShapeAnalysis::OuterWire(TopoDS::Face(aF));
bool isOuter = false;
TopoDS_Iterator aIter(aWout, false);
for (; aIter.More() && !isOuter; aIter.Next())
{
isOuter = aEdge.IsSame(aIter.Value());
}
if (isOuter)
{
aFaceCandidates.Add(aF);
}
}
}
}
// remove faces which have outer wire consist of only
// edges from removed wires and
// seam edges for faces based on conic surface or
// in the case of a few faces based on the same conic surface
// the edges belogining these faces.
int k = 1;
for (; k <= aFaceCandidates.Extent(); k++)
{
TopoDS_Shape aF = aFaceCandidates.FindKey(k);
TopoDS_Wire anOutW = ShapeAnalysis::OuterWire(TopoDS::Face(aF));
occ::handle<ShapeExtend_WireData> asewd = new ShapeExtend_WireData(anOutW);
int n = 1, nbE = asewd->NbEdges();
int nbNotRemoved = 0;
for (; n <= nbE; n++)
{
if (asewd->IsSeam(n))
{
continue;
}
TopoDS_Edge aE = asewd->Edge(n);
if (!myRemoveEdges.IsBound(aE))
{
const NCollection_List<TopoDS_Shape>& aLface3 = myEdgeFaces.FindFromKey(aE);
NCollection_List<TopoDS_Shape>::Iterator aliter3(aLface3);
for (; aliter3.More(); aliter3.Next())
{
TopoDS_Shape aF2 = Context()->Apply(aliter3.Value());
if (aF2.IsNull())
{
continue;
}
if (!aF.IsSame(aF2) && !aFaceCandidates.Contains(aF2))
{
nbNotRemoved++;
}
}
}
}
if (!nbNotRemoved)
{
Context()->Remove(aF);
myRemovedFaces.Append(aF);
}
}
}
if (myRemovedFaces.Length())
{
myStatus |= ShapeExtend::EncodeStatus(ShapeExtend_DONE2);
}
}
//=================================================================================================
void ShapeUpgrade_RemoveInternalWires::Clear()
{
myRemoveEdges.Clear();
myRemovedFaces.Clear();
myRemoveWires.Clear();
myStatus = ShapeExtend::EncodeStatus(ShapeExtend_OK);
}