1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-10 18:51:21 +03:00
occt/src/QANewBRepNaming/QANewBRepNaming_BooleanOperation.cxx
emv e45b5ff7f2 0028567: Get rid of the unused DRAW commands based on old Boolean Operations (BRepAlgo)
1. Removal of the traces of the usage of old Boolean operations in BRepFeat package.

2. The DRAW commands *fubl* and *cubl* based on old Boolean operations have been removed.
The alternative for these commands are the commands *bfuseblend* and *bcutblend* respectively.
The last two commands are based on the modern Boolean operations.

3. The DRAW command *ksection* based on old Boolean operations has been removed.
The command *bsection* should be used as alternative.

Test cases which have been using the *ksection* command have been modified to use the *bsection* command.

4. The class QANewBRepNaming_BooleanOperation has been modified to use modern Boolean operations.

The class QANewBRepNaming_BooleanOperation has been removed as not used.
The class QANewBRepNaming_BooleanOperationFeat has been renamed to QANewBRepNaming_BooleanOperation as it has nothing to do with Feat algorithm.
2017-03-23 15:57:27 +03:00

1618 lines
55 KiB
C++

// Created on: 1999-09-27
// Created by: Sergey ZARITCHNY
// Copyright (c) 1999-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 <Adaptor3d_HCurve.hxx>
#include <BRep_Tool.hxx>
#include <BRepAdaptor_Surface.hxx>
#include <BRepAlgoAPI_BooleanOperation.hxx>
#include <BRepGProp.hxx>
#include <Geom_Ellipse.hxx>
#include <GeomAbs_SurfaceType.hxx>
#include <gp.hxx>
#include <gp_Cone.hxx>
#include <gp_Cylinder.hxx>
#include <GProp_GProps.hxx>
#include <Precision.hxx>
#include <QANewBRepNaming_BooleanOperation.hxx>
#include <QANewBRepNaming_Loader.hxx>
#include <Standard_NullObject.hxx>
#include <TColgp_Array1OfDir.hxx>
#include <TColgp_Array1OfPnt.hxx>
#include <TColStd_Array1OfInteger.hxx>
#include <TDataStd_Integer.hxx>
#include <TDataStd_IntegerArray.hxx>
#include <TDataStd_Name.hxx>
#include <TDataStd_Real.hxx>
#include <TDF_Label.hxx>
#include <TDF_TagSource.hxx>
#include <TNaming_Builder.hxx>
#include <TNaming_NamedShape.hxx>
#include <TopExp.hxx>
#include <TopExp_Explorer.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Edge.hxx>
#include <TopoDS_Iterator.hxx>
#include <TopoDS_Shape.hxx>
#include <TopoDS_Vertex.hxx>
#include <TopTools_Array1OfShape.hxx>
#include <TopTools_IndexedMapOfShape.hxx>
#include <TopTools_ListIteratorOfListOfShape.hxx>
#include <TopTools_MapOfShape.hxx>
#ifdef OCCT_DEBUG
#include <TDataStd_Name.hxx>
#endif
#ifdef OCCT_DEBUG
#include <TCollection_AsciiString.hxx>
#include <TDF_Tool.hxx>
#include <BRepTools.hxx>
#include <TNaming_Tool.hxx>
static void ModDbgTools_Write(const TopoDS_Shape& shape,
const Standard_CString filename)
{
ofstream save;
save.open(filename);
save << "DBRep_DrawableShape" << endl << endl;
if(!shape.IsNull()) BRepTools::Write(shape, save);
save.close();
}
#endif
//=======================================================================
//function : QANewBRepNaming_BooleanOperation
//purpose :
//=======================================================================
QANewBRepNaming_BooleanOperation::QANewBRepNaming_BooleanOperation() {}
//=======================================================================
//function : QANewBRepNaming_BooleanOperation
//purpose :
//=======================================================================
QANewBRepNaming_BooleanOperation::QANewBRepNaming_BooleanOperation(const TDF_Label& ResultLabel):QANewBRepNaming_TopNaming(ResultLabel) {}
//=======================================================================
//function : Init
//purpose :
//=======================================================================
void QANewBRepNaming_BooleanOperation::Init(const TDF_Label& ResultLabel) {
if(ResultLabel.IsNull())
throw Standard_NullObject("QANewBRepNaming_BooleanOperation::Init The Result label is Null ...");
myResultLabel = ResultLabel;
}
//=======================================================================
//function : ModifiedFaces
//purpose :
//=======================================================================
TDF_Label QANewBRepNaming_BooleanOperation::ModifiedFaces() const {
#ifdef OCCT_DEBUG
const TDF_Label& ModifiedFacesLabel = ResultLabel().NewChild();
TDataStd_Name::Set(ModifiedFacesLabel, "ModifiedFaces");
return ModifiedFacesLabel;
#else
return ResultLabel().NewChild();
#endif
}
//=======================================================================
//function : ModifiedEdges
//purpose :
//=======================================================================
TDF_Label QANewBRepNaming_BooleanOperation::ModifiedEdges() const {
#ifdef OCCT_DEBUG
const TDF_Label& ModifiedEdgesLabel = ResultLabel().NewChild();
TDataStd_Name::Set(ModifiedEdgesLabel, "ModifiedEdges");
return ModifiedEdgesLabel;
#else
return ResultLabel().NewChild();
#endif
}
//=======================================================================
//function : DeletedFaces
//purpose :
//=======================================================================
TDF_Label QANewBRepNaming_BooleanOperation::DeletedFaces() const {
#ifdef OCCT_DEBUG
const TDF_Label& DeletedFacesLabel = ResultLabel().NewChild();
TDataStd_Name::Set(DeletedFacesLabel, "DeletedFaces");
return DeletedFacesLabel;
#else
return ResultLabel().NewChild();
#endif
}
//=======================================================================
//function : DeletedEdges
//purpose :
//=======================================================================
TDF_Label QANewBRepNaming_BooleanOperation::DeletedEdges() const {
#ifdef OCCT_DEBUG
const TDF_Label& DeletedEdgesLabel = ResultLabel().NewChild();
TDataStd_Name::Set(DeletedEdgesLabel, "DeletedEdges");
return DeletedEdgesLabel;
#else
return ResultLabel().NewChild();
#endif
}
//=======================================================================
//function : DeletedVertices
//purpose :
//=======================================================================
TDF_Label QANewBRepNaming_BooleanOperation::DeletedVertices() const {
#ifdef OCCT_DEBUG
const TDF_Label& DeletedVerticesLabel = ResultLabel().NewChild();
TDataStd_Name::Set(DeletedVerticesLabel, "DeletedVertices");
return DeletedVerticesLabel;
#else
return ResultLabel().NewChild();
#endif
}
//=======================================================================
//function : NewShapes
//purpose :
//=======================================================================
TDF_Label QANewBRepNaming_BooleanOperation::NewShapes() const {
#ifdef OCCT_DEBUG
const TDF_Label& NewShapesLabel = ResultLabel().NewChild();
TDataStd_Name::Set(NewShapesLabel, "NewShapes");
return NewShapesLabel;
#else
return ResultLabel().NewChild();
#endif
}
//=======================================================================
//function : Content
//purpose :
//=======================================================================
TDF_Label QANewBRepNaming_BooleanOperation::Content() const {
#ifdef OCCT_DEBUG
const TDF_Label& ContentLabel = ResultLabel().NewChild();
TDataStd_Name::Set(ContentLabel, "Content");
return ContentLabel;
#else
return ResultLabel().NewChild();
#endif
}
//=======================================================================
//function : DeletedDegeneratedEdges
//purpose :
//=======================================================================
TDF_Label QANewBRepNaming_BooleanOperation::DeletedDegeneratedEdges() const {
#ifdef OCCT_DEBUG
const TDF_Label& DegeneratedLabel = ResultLabel().NewChild();
TDataStd_Name::Set(DegeneratedLabel, "DeletedDegeneratedEdges");
return DegeneratedLabel;
#else
return ResultLabel().NewChild();
#endif
}
//=======================================================================
//function : ShapeType
//purpose :
//=======================================================================
TopAbs_ShapeEnum QANewBRepNaming_BooleanOperation::ShapeType(const TopoDS_Shape& theShape) {
TopAbs_ShapeEnum TypeSh = theShape.ShapeType();
if (TypeSh == TopAbs_COMPOUND || TypeSh == TopAbs_COMPSOLID) {
TopoDS_Iterator itr(theShape);
if (!itr.More()) return TypeSh;
TypeSh = ShapeType(itr.Value());
if(TypeSh == TopAbs_COMPOUND) return TypeSh;
itr.Next();
for(; itr.More(); itr.Next())
if(ShapeType(itr.Value()) != TypeSh) return TopAbs_COMPOUND;
}
return TypeSh;
}
//=======================================================================
//function : GetShape
//purpose :
//=======================================================================
TopoDS_Shape QANewBRepNaming_BooleanOperation::GetShape(const TopoDS_Shape& theShape) const {
if (theShape.ShapeType() == TopAbs_COMPOUND || theShape.ShapeType() == TopAbs_COMPSOLID) {
TopoDS_Iterator itr(theShape);
if (itr.More()) return itr.Value();
}
return theShape;
}
//=======================================================================
//function : LoadWire
//purpose :
//=======================================================================
void QANewBRepNaming_BooleanOperation::LoadWire(BRepAlgoAPI_BooleanOperation& MS) const {
// Naming of modified edges:
TNaming_Builder ModBuilder(ModifiedEdges());
QANewBRepNaming_Loader::LoadModifiedShapes (MS, MS.Shape1(), TopAbs_EDGE, ModBuilder);
// load generated vertexes
if(MS.HasGenerated()) {
TNaming_Builder nBuilder (NewShapes());
QANewBRepNaming_Loader::LoadGeneratedShapes (MS, MS.Shape1(), TopAbs_EDGE, nBuilder);
QANewBRepNaming_Loader::LoadGeneratedShapes (MS, MS.Shape2(), TopAbs_FACE, nBuilder);
}
// Naming of deleted edges, dangle vertices
if(MS.HasDeleted()){
TNaming_Builder DelEBuilder(DeletedEdges());
QANewBRepNaming_Loader::LoadDeletedShapes(MS, MS.Shape1(), TopAbs_EDGE, DelEBuilder);
TNaming_Builder DelVBuilder(DeletedVertices());
QANewBRepNaming_Loader::LoadDeletedShapes(MS, MS.Shape1(), TopAbs_VERTEX, DelEBuilder);
}
}
//=======================================================================
//function : LoadShell
//purpose :
//=======================================================================
void QANewBRepNaming_BooleanOperation::LoadShell(BRepAlgoAPI_BooleanOperation& MS) const {
// Naming of modified faces and dangle edges
TNaming_Builder ModFBuilder(ModifiedFaces());
QANewBRepNaming_Loader::LoadModifiedShapes(MS, MS.Shape1(), TopAbs_FACE, ModFBuilder);
TNaming_Builder ModEBuilder(ModifiedEdges());
QANewBRepNaming_Loader::LoadModifiedShapes(MS, MS.Shape1(), TopAbs_EDGE, ModEBuilder);
if(MS.HasGenerated()) {
TNaming_Builder nBuilder (NewShapes());
// generated Edges
QANewBRepNaming_Loader::LoadGeneratedShapes (MS, MS.Shape2(), TopAbs_FACE, nBuilder);
QANewBRepNaming_Loader::LoadGeneratedShapes (MS, MS.Shape1(), TopAbs_FACE, nBuilder);
}
// Naming of deleted faces edges:
if(MS.HasDeleted()){
TNaming_Builder DelFBuilder(DeletedFaces());
QANewBRepNaming_Loader::LoadDeletedShapes(MS, MS.Shape1(), TopAbs_FACE, DelFBuilder);
TNaming_Builder DelEBuilder(DeletedEdges());
QANewBRepNaming_Loader::LoadDeletedShapes(MS, MS.Shape1(), TopAbs_EDGE, DelEBuilder);
}
}
//=======================================================================
//function : LoadContent
//purpose :
//=======================================================================
void QANewBRepNaming_BooleanOperation::LoadContent(BRepAlgoAPI_BooleanOperation& MS) const {
if (MS.Shape().ShapeType() == TopAbs_COMPSOLID || MS.Shape().ShapeType() == TopAbs_COMPOUND) {
TopoDS_Iterator itr(MS.Shape());
Standard_Integer nbShapes = 0;
while (itr.More()) {
nbShapes++;
itr.Next();
}
if (nbShapes > 1) {
for (itr.Initialize(MS.Shape()); itr.More(); itr.Next()) {
TNaming_Builder bContent(Content());
bContent.Generated(itr.Value());
}
}
}
}
//=======================================================================
//function : LoadResult
//purpose :
//=======================================================================
void QANewBRepNaming_BooleanOperation::LoadResult(BRepAlgoAPI_BooleanOperation& MS) const {
Handle(TDF_TagSource) Tagger = TDF_TagSource::Set(ResultLabel());
if (Tagger.IsNull()) return;
Tagger->Set(0);
TNaming_Builder Builder (ResultLabel());
TopoDS_Shape aResult = MS.Shape();
if (aResult.ShapeType() == TopAbs_COMPOUND) {
Standard_Integer nbSubResults = 0;
TopoDS_Iterator itr(aResult);
for (; itr.More(); itr.Next()) nbSubResults++;
if (nbSubResults == 1) {
itr.Initialize(aResult);
if (itr.More()) aResult = itr.Value();
}
}
if (MS.Shape1().IsNull()) Builder.Generated(aResult);
else Builder.Modify(MS.Shape1(), aResult);
}
//=======================================================================
//function : LoadDegenerated
//purpose :
//=======================================================================
void QANewBRepNaming_BooleanOperation::LoadDegenerated(BRepAlgoAPI_BooleanOperation& MS) const {
TopTools_IndexedMapOfShape allEdges;
TopExp::MapShapes(MS.Shape1(), TopAbs_EDGE, allEdges);
Standard_Integer i = 1;
for (; i <= allEdges.Extent(); i++) {
if (BRep_Tool::Degenerated(TopoDS::Edge(allEdges.FindKey(i)))) {
if (MS.IsDeleted(allEdges.FindKey(i))) {
TNaming_Builder DegeneratedBuilder(DeletedDegeneratedEdges());
DegeneratedBuilder.Generated(allEdges.FindKey(i));
#ifdef OCCT_DEBUG
TDataStd_Name::Set(DegeneratedBuilder.NamedShape()->Label(), "DeletedDegenerated");
#endif
}
}
}
}
//=======================================================================
//function : IsResultChanged
//purpose :
//=======================================================================
Standard_Boolean QANewBRepNaming_BooleanOperation::IsResultChanged(BRepAlgoAPI_BooleanOperation& MS) const {
TopoDS_Shape ResSh = MS.Shape();
if (MS.Shape().ShapeType() == TopAbs_COMPOUND) {
Standard_Integer nbSubResults = 0;
TopoDS_Iterator itr(MS.Shape());
for (; itr.More(); itr.Next()) nbSubResults++;
if (nbSubResults == 1) {
itr.Initialize(MS.Shape());
if (itr.More()) ResSh = itr.Value();
}
}
return MS.Shape1().IsSame(ResSh);
}
//=======================================================================
// Workaround for evolution 1:n
//=======================================================================
static Standard_Boolean IsValidSurfType(const TopoDS_Face& theFace) {
BRepAdaptor_Surface anAdapt(theFace);
Handle( Adaptor3d_HCurve ) aBasisCurve;
const GeomAbs_SurfaceType& aType = anAdapt.GetType();
if(aType == GeomAbs_Cylinder || aType == GeomAbs_Cone)
return Standard_True;
else if(aType == GeomAbs_SurfaceOfRevolution){
aBasisCurve = anAdapt.BasisCurve();
if (aBasisCurve->GetType() == GeomAbs_Line)
return Standard_True;
}
else if(aType == GeomAbs_SurfaceOfExtrusion) {
aBasisCurve = anAdapt.BasisCurve();
if (aBasisCurve->GetType() == GeomAbs_Circle || aBasisCurve->GetType() == GeomAbs_Ellipse)
return Standard_True;
}
#ifdef OCCT_DEBUG
ModDbgTools_Write(theFace, "Surf");
#endif
return Standard_False;
}
//=======================================================================
//function : IsWRCase
//purpose :
//=======================================================================
Standard_Boolean QANewBRepNaming_BooleanOperation::IsWRCase(const BRepAlgoAPI_BooleanOperation& MS) {
const TopoDS_Shape& ObjSh = MS.Shape1();
const TopoDS_Shape& ToolSh = MS.Shape2();
const TopAbs_ShapeEnum& Type1 = ShapeType(ObjSh);
if(Type1 == TopAbs_COMPOUND || Type1 > TopAbs_FACE) return Standard_False;
const TopAbs_ShapeEnum& Type2 = ShapeType(ToolSh);
if(Type2 == TopAbs_COMPOUND || Type2 > TopAbs_FACE) return Standard_False;
TopTools_ListOfShape aList;
if(Type1 != TopAbs_FACE) {
TopExp_Explorer anExp(ObjSh, TopAbs_FACE);
for(;anExp.More();anExp.Next()) {
if(IsValidSurfType(TopoDS::Face(anExp.Current())))
aList.Append(anExp.Current());
}
} else
if(IsValidSurfType(TopoDS::Face(ObjSh)))
aList.Append(ObjSh);
if(aList.Extent() == 1) {
if(Type2 != TopAbs_FACE) {
TopExp_Explorer anExp(ToolSh, TopAbs_FACE);
for(;anExp.More();anExp.Next()) {
if(IsValidSurfType(TopoDS::Face(anExp.Current())))
aList.Append(anExp.Current());
}
} else
if(IsValidSurfType(TopoDS::Face(ToolSh)))
aList.Append(ToolSh);
if(aList.Extent() == 2) return Standard_True;
}
return Standard_False;
}
//=======================================================================
static gp_Ax1 ComputeAxis(const TopoDS_Shape& theShape) {
TopoDS_Face aFace;
TopExp_Explorer anExp(theShape, TopAbs_FACE);
for(;anExp.More();anExp.Next()) {
aFace = TopoDS::Face(anExp.Current());
BRepAdaptor_Surface anAdapt(aFace);
Handle( Adaptor3d_HCurve ) aBasisCurve;
const GeomAbs_SurfaceType& aType = anAdapt.GetType();
if(aType == GeomAbs_Cylinder)
return anAdapt.Cylinder().Axis();
else if(aType == GeomAbs_Cone)
return anAdapt.Cone().Axis();
else if(aType == GeomAbs_SurfaceOfRevolution)
return anAdapt.AxeOfRevolution();
else if(aType == GeomAbs_SurfaceOfExtrusion) {
aBasisCurve = anAdapt.BasisCurve();
if (aBasisCurve->GetType() == GeomAbs_Circle)
return aBasisCurve->Circle().Axis();
else if(aBasisCurve->GetType() == GeomAbs_Ellipse)
return aBasisCurve->Ellipse().Axis();
}
}
return gp::OX();
}
//==============================================================================
//
//==========================================================================
static Standard_Integer Identify(const TopoDS_Face& theFace, const gp_Ax1& theAx) {
GProp_GProps aGProp;
BRepGProp::SurfaceProperties(theFace, aGProp);
gp_Pnt aPoint = aGProp.CentreOfMass();
gp_Vec aV1(theAx.Direction());
gp_Vec aV2(theAx.Location(), aPoint);
#ifdef OCCT_DEBUG
gp_Vec v1 = aV1.Crossed(aV2);
cout <<" Z of V1 = " << v1.XYZ().Z() << endl;
#endif
if((aV1.Crossed(aV2)).XYZ().Z() >= 0) return 1; //right orientation
return (-1); //left orientation
}
//=======================================================================
//function : LoadModified11
//purpose : 1 : 1
//=======================================================================
void QANewBRepNaming_BooleanOperation::LoadModified11 (BRepAlgoAPI_BooleanOperation& MS,
const TopoDS_Shape& ShapeIn,
const TopAbs_ShapeEnum KindOfShape) const
{
TopTools_MapOfShape View;
Standard_Boolean found = Standard_False;
TopExp_Explorer ShapeExplorer (ShapeIn, KindOfShape);
for (; ShapeExplorer.More(); ShapeExplorer.Next ()) {
const TopoDS_Shape& Root = ShapeExplorer.Current ();
if (!View.Add(Root)) continue;
const TopTools_ListOfShape& Shapes = MS.Modified (Root);
if(Shapes.Extent() == 1) {found = Standard_True; break;}
}
if(found) {
View.Clear();
ShapeExplorer.Init (ShapeIn, KindOfShape);
TNaming_Builder Builder(ModifiedFaces());
for (; ShapeExplorer.More(); ShapeExplorer.Next ()) {
const TopoDS_Shape& Root = ShapeExplorer.Current ();
if (!View.Add(Root)) continue;
const TopTools_ListOfShape& Shapes = MS.Modified (Root);
if(Shapes.Extent() > 1) continue;
TopTools_ListIteratorOfListOfShape ShapesIterator (Shapes);
for (;ShapesIterator.More (); ShapesIterator.Next ()) {
const TopoDS_Shape& newShape = ShapesIterator.Value ();
if (!Root.IsSame (newShape)) {
//put shapes with evolution 1:1 (may be Compound)
#ifdef OCCT_DEBUG
TCollection_AsciiString entry;
TDF_Tool::Entry(Builder.NamedShape()->Label(), entry);
cout << "Add shape to Compound at Label = "<< entry <<endl;
#endif
Builder.Modify (Root,newShape);
}
}
}
}
}
//======================================================================
static gp_Pnt GetCenterPoint(const TopoDS_Shape& theEdge)
{
GProp_GProps aGProp;
BRepGProp::LinearProperties(theEdge, aGProp);
return aGProp.CentreOfMass();
}
//===================================================================
static void SortRootFaces(TopTools_ListOfShape& theList, const TopoDS_Shape& theShape)
{
TopTools_ListOfShape aList;
Standard_Integer aNum = theList.Extent();
if(aNum <= 1) return;
gp_Ax1 anAx = ComputeAxis(theShape);
TopTools_Array1OfShape ArS(1, aNum);
TColgp_Array1OfPnt ArP(1, aNum);
TColStd_Array1OfInteger ArI(1, aNum);
TopTools_ListIteratorOfListOfShape It(theList);
Standard_Integer i;
for(i=1;It.More();It.Next(),i++) {
ArS.SetValue(i, It.Value ());
ArI.SetValue(i,0);
ArP.SetValue(i, GetCenterPoint(It.Value()));
}
gp_Pnt aPnt = anAx.Location();
Standard_Integer I, j;
for(j=1;j <= aNum; j++) {
if(ArI.Value(j) == -1) continue;
Standard_Real aD1 = aPnt.Distance(ArP(j));
I = 0;
for(i=1;i <= aNum; i++) {
if(i==j) continue;
if(ArI.Value(i) == -1) continue;
Standard_Real aD2 = aPnt.Distance(ArP(i));
if(aD2 < aD1) {
I = i;
aD1 = aD2;
}
}
if (I == 0) continue;
ArI.SetValue(I, -1);
aList.Append(ArS.Value(I));
if(aList.Extent() == aNum -1) {
for(i=1; i<=aNum;i++)
if(ArI.Value(i) != -1) aList.Append(ArS.Value(i));
}
}
theList.Assign(aList);
}
//=======================================================================
static void Sort2Faces(const TopTools_ListOfShape& Shapes,
const gp_Ax1& theAx, TopTools_ListOfShape& theList)
{
TopTools_ListIteratorOfListOfShape It(Shapes);
for(;It.More();It.Next()) {
if(Identify(TopoDS::Face(It.Value()), theAx) == 1)
theList.Prepend(It.Value()); //Pos
else theList.Append(It.Value()); //Neg
}
}
//=======================================================================
static void Sort3Faces(const TopTools_ListOfShape& theListIn, TopTools_ListOfShape& theListOut)
{
TopTools_ListIteratorOfListOfShape It (theListIn);
TopTools_Array1OfShape ArS(1, theListIn.Extent());
TColgp_Array1OfPnt ArP(1, theListIn.Extent());
Standard_Integer i;
for(i=1;It.More();It.Next(),i++) {
ArS.SetValue(i, It.Value());
ArP.SetValue(i, GetCenterPoint(It.Value()));
}
Standard_Boolean found = Standard_False;
Standard_Integer j, i1 = 0, i2 = 0, i3 = 0;
TopoDS_Edge anEdge;
for(i=1;i<=3;i++) {
TopExp_Explorer anExp1(ArS.Value(i), TopAbs_EDGE);
for(;anExp1.More();anExp1.Next()) {
for(j=1;j<=3;j++) {
if(i==j) continue;
TopExp_Explorer anExp2(ArS.Value(j), TopAbs_EDGE);
for(;anExp2.More();anExp2.Next()) {
if(anExp1.Current().IsSame(anExp2.Current())){
found = Standard_True;
anEdge = TopoDS::Edge(anExp1.Current());
break;
}
}
if(found) break;
}
if(found) {
switch(i+j) {
case 3: //12
i1=1;i2=2; i3=3;
break;
case 4: //13
i1=1;i2=3; i3=2;
break;
case 5: //23
i1=2;i2=3; i3=1;
}
break;
}
}
if(found) break;
}
//i1,i2 - two adjacent faces via sim-edge
gp_Pnt aPnt1 = BRep_Tool::Pnt(TopExp::FirstVertex(anEdge));
gp_Pnt aPnt2 = BRep_Tool::Pnt(TopExp::LastVertex(anEdge));
gp_Vec aVec(aPnt1, aPnt2);
gp_Ax1 anAx(aPnt1, gp_Dir(aVec));
if (Identify(TopoDS::Face(ArS.Value(i1)), anAx) == -1) {//neg
i=i2; i2=i1; //i1 < = > i2
i1=i;
}
theListOut.Append(ArS.Value(i1));
theListOut.Append(ArS.Value(i2));
theListOut.Append(ArS.Value(i3)); //single
}
//=======================================================================
//function : Load1nFaces
//purpose :
//=======================================================================
void QANewBRepNaming_BooleanOperation::Load1nFaces(BRepAlgoAPI_BooleanOperation& MS, const TopoDS_Shape& ShapeIn) const
{
TopTools_MapOfShape View;
TopTools_ListOfShape aListR;
TopExp_Explorer ShapeExplorer (ShapeIn, TopAbs_FACE);
for (; ShapeExplorer.More(); ShapeExplorer.Next ()) {
const TopoDS_Shape& Root = ShapeExplorer.Current ();
if (!View.Add(Root)) continue;
const TopTools_ListOfShape& Shapes = MS.Modified (Root);
if(Shapes.Extent() < 2) continue;
aListR.Append(Root);
}
if(ShapeIn.IsEqual(MS.Shape1()))
if(aListR.Extent() > 1) SortRootFaces(aListR, ShapeIn);
TopTools_ListIteratorOfListOfShape Itr(aListR);
for(;Itr.More();Itr.Next()) {
const TopoDS_Shape& Root = Itr.Value();
const TopTools_ListOfShape& Shapes = MS.Modified (Root);
TopTools_ListOfShape aList;
gp_Ax1 anAx = ComputeAxis(MS.Shape2());
if(Shapes.Extent() == 2)
Sort2Faces(Shapes, anAx, aList);
else if(Shapes.Extent() == 3)
Sort3Faces(Shapes, aList);
TopTools_ListIteratorOfListOfShape It(aList);
for(;It.More();It.Next()) {
TNaming_Builder aBuilder(NewShapes());
// aBuilder.Modify(Root,It.Value ());
aBuilder.Generated(It.Value ());
}
}
}
//=======================================================================
//function : LoadModified faces
//purpose : 1 : n modification
//=======================================================================
void QANewBRepNaming_BooleanOperation::LoadModified1n (BRepAlgoAPI_BooleanOperation& MS,
const TopoDS_Shape& ShapeIn,
const TopAbs_ShapeEnum KindOfShape) const
{
//fill modification 1:n
TopTools_MapOfShape View;
Standard_Integer aNum = 0;
TopExp_Explorer ShapeExplorer (ShapeIn, KindOfShape);
for (; ShapeExplorer.More(); ShapeExplorer.Next ()) {
const TopoDS_Shape& Root = ShapeExplorer.Current ();
if (!View.Add(Root)) continue;
const TopTools_ListOfShape& Shapes = MS.Modified (Root);
if(Shapes.Extent() >= 2) aNum += Shapes.Extent();
}
View.Clear();
const TopoDS_Shape& Tool = MS.Shape2();
ShapeExplorer.Init (Tool, KindOfShape);
for (; ShapeExplorer.More(); ShapeExplorer.Next ()) {
const TopoDS_Shape& Root = ShapeExplorer.Current ();
if (!View.Add(Root)) continue;
const TopTools_ListOfShape& Shapes = MS.Modified (Root);
if(Shapes.Extent() >= 2) aNum += Shapes.Extent();
}
Handle(TDataStd_IntegerArray) aSAR;
if(!ResultLabel().FindAttribute(TDataStd_IntegerArray::GetID(), aSAR) ) {
//not find
aSAR = TDataStd_IntegerArray::Set(ResultLabel(), 1, 2);
aSAR->SetValue(1, 0); //tag num for faces structure
aSAR->SetValue(2, 0); //tag num for edges structure
}
if(aSAR->Value(2)) {
Standard_Integer aNE =0;
TDF_Label aLab = ResultLabel().FindChild(aSAR->Value(2));
Handle(TDataStd_Integer) anAtt;
if(aLab.FindAttribute(TDataStd_Integer::GetID(), anAtt) )
aNE = anAtt->Get();
TDF_Label aFLab = ResultLabel().FindChild(aLab.Tag() + aNE);
if(!aFLab.FindAttribute(TDataStd_Integer::GetID(), anAtt))
aSAR->SetValue(1, 0);
}
TDF_Label aLabelFDS;
if(aSAR->Value(1))
aLabelFDS = ResultLabel().FindChild(aSAR->Value(1)); // !=0 -already exist
else {
// initial creation of FDS structure
Handle(TDF_TagSource) aTS;
ResultLabel().FindAttribute (TDF_TagSource::GetID (), aTS);
aLabelFDS = NewShapes();
// aLabelFDS = ResultLabel().FindChild(aSAR->Value(1));
aSAR->SetValue(1, aLabelFDS.Tag()); //keep tag
aTS->Set(aLabelFDS.Tag()-1);
}
Handle(TDataStd_Integer) anAtt;
if(aLabelFDS.FindAttribute(TDataStd_Integer::GetID(), anAtt) ) {
// modification : check compatibility
if(anAtt->Get() != aNum) {
cout << "WARNING: Case isn't mantained - Number of Faces was changed!"<<endl;
// mark all structure as Deleted
Standard_Integer aN = aLabelFDS.Tag()+anAtt->Get();
for(Standard_Integer i=aLabelFDS.Tag(); i < aN; i++) {
TDF_Label aLab = ResultLabel().FindChild(i, Standard_False);
if(!aLab.IsNull()) {
Handle(TNaming_NamedShape) aNS;
if(aLab.FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
TopoDS_Shape aShape = aNS->Get();
TNaming_Builder aBuilder(aLab);
aBuilder.Delete(aShape); //Deleted
}
}
}
//
Handle(TDF_TagSource) aTS;
ResultLabel().FindAttribute (TDF_TagSource::GetID (), aTS);
if(!aTS.IsNull())
aTS->Set(aLabelFDS.Tag());
anAtt->Set(aNum);
}
} else
TDataStd_Integer::Set(aLabelFDS, aNum); //keep number of faces
Load1nFaces(MS, ShapeIn);
Load1nFaces(MS, Tool);
}
//======================================================================
static Standard_Boolean IsDirectionPositive (const gp_Ax1& theAx, const gp_Pnt thePnt1,
const gp_Pnt thePnt2) {
Standard_Boolean isPositive;
gp_Vec aVec1(theAx.Direction());
gp_Vec aVec2(thePnt1, thePnt2);
#ifdef OCCT_DEBUG
// gp_Vec v1 = aVec1.Crossed(aVec2);
// cout <<" Z of V1 = " << v1.XYZ().Z() << endl;
#endif
if((aVec1.Crossed(aVec2)).XYZ().Z() >= 0) isPositive = Standard_True;
else
isPositive = Standard_False;
return isPositive;
}
//======================================================================
// i => ArS[i] : ArP[i] ; i = ArI[j]
//======================================================================
static void SortEdges2(const TColgp_Array1OfPnt& theArP, const gp_Ax1& theAx,
TColStd_Array1OfInteger& theArI)
{
gp_Pnt aPnt = theAx.Location();
//sort : the nearest point must be first
Standard_Real aD1 = aPnt.Distance(theArP.Value(1));
Standard_Real aD2 = aPnt.Distance(theArP.Value(2));
if(aD1 < aD2) {
theArI.SetValue(1, 1);
theArI.SetValue(2, 2);
} else {
theArI.SetValue(1, 2); //change order
theArI.SetValue(2, 1);
}
}
//======================================================================
// i => ArS[i] : ArP[i] ; i = ArI[j]
//======================================================================
static void SortEdges3(const TopTools_Array1OfShape& theArS, const TColgp_Array1OfPnt& theArP,
const gp_Ax1& theAx, TColStd_Array1OfInteger& theArI)
{
Standard_Integer i, j, i1 = 0,i2 = 0, i3 = 0;
TopoDS_Shape aV;
Standard_Boolean adjacent = Standard_False;
for(i=1;i<=3;i++) {
for(j=1;j<=3;j++) {
if(i==j) continue;
const TopoDS_Shape& aV11 = TopExp::FirstVertex(TopoDS::Edge(theArS.Value(i)));
const TopoDS_Shape& aV21 = TopExp::FirstVertex(TopoDS::Edge(theArS.Value(j)));
const TopoDS_Shape& aV22 = TopExp::LastVertex(TopoDS::Edge(theArS.Value(j)));
if(aV11.IsSame(aV21) || aV11.IsSame(aV22)) {adjacent = Standard_True;aV = aV11;}
else {
const TopoDS_Shape& aV12 = TopExp::LastVertex(TopoDS::Edge(theArS.Value(i)));
if(aV12.IsSame(aV21) || aV12.IsSame(aV22)) {adjacent = Standard_True;aV = aV12;}
}
if(adjacent) {
Standard_Integer aSum = i+j;
switch(aSum) {
case 3: //12
i1 = 3;i2 = 1;i3 = 2;
break;
case 4: //13
i1 = 2; i2 = 1;i3 = 3;
break;
case 5: //23
i1 = 1; i2 = 2;i3 = 3;
}
break;
}
}
if(adjacent) break;
}
gp_Pnt aPnt = theAx.Location();
// i1 - index of single edge
Standard_Real aD1 = aPnt.Distance(theArP.Value(i1));
Standard_Real aD2 = aPnt.Distance(theArP.Value(i2));
if(aD1 > aD2) { //cyclic shift
Standard_Integer aN = i3;// i1 => i3 - to the end
i3 = i1; i1 = aN;
// pair of adjacent i1, i2
gp_Pnt aCP = BRep_Tool::Pnt(TopoDS::Vertex(aV));
if(!IsDirectionPositive(theAx, aCP, theArP.Value(i1))) {//first must be positive direction
// change i1 <=>i2
aN = i2; i2 = i1;
i1 = aN;
}
} else {
// pair of adjacent i2, i3
gp_Pnt aCP = BRep_Tool::Pnt(TopoDS::Vertex(aV));
if(!IsDirectionPositive(theAx, aCP, theArP.Value(i2))) {//first must be positive direction
// change i2 <=>i3
Standard_Integer aN = i3; i3 = i2;
i2 = aN;
}
}
// order i1, i2, i3
theArI.SetValue(1, i1);
theArI.SetValue(2, i2);
theArI.SetValue(3, i3);
}
//======================================================================
// i => ArS[i] : ArP[i] ; i = ArI[j]
//======================================================================
static void SortEdges4(const TopTools_Array1OfShape& theArS, const TColgp_Array1OfPnt& theArP,
const gp_Ax1& theAx, TColStd_Array1OfInteger& theArI)
{
// 1. find adjacent edges, build pairs in ArI
// 2. find nearest pair, reorganize ArI
// 3. sort inside pairs
// =======================================
Standard_Integer i, j, i1 = 0,i2 = 0, i3 = 0, i4 = 0;
// 1.
TopoDS_Shape aV1;
for(i=1;i<=4;i++) {
const TopoDS_Shape& aV11 = TopExp::FirstVertex(TopoDS::Edge(theArS.Value(i)));
const TopoDS_Shape& aV12 = TopExp::LastVertex(TopoDS::Edge(theArS.Value(i)));
Standard_Boolean aDjacent = Standard_False;
for(j=1;j<=4;j++) {
if(i==j) continue;
const TopoDS_Shape& aV21 = TopExp::FirstVertex(TopoDS::Edge(theArS.Value(j)));
const TopoDS_Shape& aV22 = TopExp::LastVertex(TopoDS::Edge(theArS.Value(j)));
aDjacent = Standard_False;
if(aV11.IsSame(aV21) || aV11.IsSame(aV22)) {aDjacent = Standard_True;aV1 = aV11;}
else
if(aV12.IsSame(aV21) || aV12.IsSame(aV22)) {aDjacent = Standard_True;aV1 = aV12;}
if(aDjacent) {
aDjacent = Standard_True;
Standard_Integer aSum = i+j;
i1 = i; i2 = j;
switch(aSum) {
case 3: //12
i3 = 3; i4 = 4;
break;
case 4: //13
i3 = 2; i4 = 4;
break;
case 5: //14
i3 = 2; i4 = 3;
break;
}
break;
}
}
if(aDjacent) break;
}
// i1,i2 - first pair of adjacent: aV1.
// i3,i4 - next pair of adjacent: aV2.
// find agjacent V (i3-i4)
TopoDS_Shape aV2;
const TopoDS_Shape& aV11 = TopExp::FirstVertex(TopoDS::Edge(theArS.Value(i3)));
const TopoDS_Shape& aV21 = TopExp::FirstVertex(TopoDS::Edge(theArS.Value(i4)));
const TopoDS_Shape& aV22 = TopExp::LastVertex(TopoDS::Edge(theArS.Value(i4)));
if(aV11.IsSame(aV21) || aV11.IsSame(aV22)) aV2 = aV11;
else {
const TopoDS_Shape& aV12 = TopExp::LastVertex(TopoDS::Edge(theArS.Value(i3)));
if(aV12.IsSame(aV21) || aV12.IsSame(aV22)) aV2 = aV12;
}
// 2. find nearest pair
gp_Pnt aCP1 = BRep_Tool::Pnt(TopoDS::Vertex(aV1));
gp_Pnt aCP2 = BRep_Tool::Pnt(TopoDS::Vertex(aV2));
gp_Pnt aPnt = theAx.Location();
Standard_Real aD1 = aPnt.Distance(aCP1);//i1-i2
Standard_Real aD2 = aPnt.Distance(aCP2);//i3-i4
if(aD1 > aD2) { //change order of pairs
Standard_Integer a3 = i3;// i1,i2 => i3,i4 - to the end
Standard_Integer a4 = i4;
i3 = i1; i4 = i2;
i1 = a3; i2 = a4;
gp_Pnt aP = aCP2;
aCP2 = aCP1;
aCP1 = aP;
// pair of adjacent i1-i2 is the nearest
}
// 3. sort inside pairs
if(!IsDirectionPositive(theAx, aCP1, theArP.Value(i1))) {//first must be positive direction
// change i1 <=> i2
Standard_Integer aN = i2; i2 = i1;
i1 = aN;
}
if(!IsDirectionPositive(theAx, aCP2, theArP.Value(i3))) {//first must be positive direction
// change i3 <=> i4
#ifdef OCCT_DEBUG
cout << "SortEdges4: i3 = "<<i3<< "i4 = "<< i4 << endl;
#endif
Standard_Integer aN = i4; i4 = i3;
i3 = aN;
}
// 4. final order i1, i2, i3, i4 - Ok
#ifdef OCCT_DEBUG
cout << "SortEdges4: i1 = " <<i1<<" i2 = "<<i2<< " i3 = "<<i3<< "i4 = "<< i4 << endl;
#endif
theArI.SetValue(1, i1);
theArI.SetValue(2, i2);
theArI.SetValue(3, i3);
theArI.SetValue(4, i4);
}
// ======================================================================
static void SortEdges5 (const TopTools_Array1OfShape& theArS, const TColgp_Array1OfPnt& theArP,
const gp_Ax1& theAx, TColStd_Array1OfInteger& theArI)
{
// =======================================
// 1. find middle edge from gr. of 3 edges, build two groups in ArI
// 2. find nearest group, reorganize ArI - nerest => top
// 3. sort inside groups
// 3.1. sort inside group of 2 edges
// 3.2. sort inside group of 3 edges
// =======================================
Standard_Integer i, j, i1,i2, i3, i4, i5;
// 1.
TopoDS_Shape aV1, aV2, aV;
Standard_Integer I=0, J1=0, J2=0;
for(i=1;i<=5;i++) {
Standard_Boolean found = Standard_False;
const TopoDS_Shape& aV11 = TopExp::FirstVertex(TopoDS::Edge(theArS.Value(i)));
for(j=1;j<=5;j++) {
if(i==j) continue;
const TopoDS_Shape& aV21 = TopExp::FirstVertex(TopoDS::Edge(theArS.Value(j)));
const TopoDS_Shape& aV22 = TopExp::LastVertex(TopoDS::Edge(theArS.Value(j)));
if(aV11.IsSame(aV21) || aV11.IsSame(aV22)) {
aV1 = aV11; I = i; J1 = j;
found = Standard_True;
break;
}
}
if (found) {
found = Standard_False;
const TopoDS_Shape& aV12 = TopExp::LastVertex(TopoDS::Edge(theArS.Value(i)));
for(j=1;j<=5;j++) {
if(i==j) continue;
const TopoDS_Shape& aV21 = TopExp::FirstVertex(TopoDS::Edge(theArS.Value(j)));
const TopoDS_Shape& aV22 = TopExp::LastVertex(TopoDS::Edge(theArS.Value(j)));
if(aV12.IsSame(aV21) || aV12.IsSame(aV22)) {
aV2 = aV12; J2 = j;
#ifdef OCCT_DEBUG
if(I != i) cout << "WARNING:: I != i, I = " << I << ", i = " << i <<endl;
#endif
found = Standard_True;
break;
}
}
}
if (found) break;
}
// aV1, aV2 - vetexes of middle Edge, I - index of middle Edge, J1, J2 = indexes of
// adjacent edges of the middle edge
// init & shift group from 3 edges on the top
i1=J1; i2=I; i3 = J2; i4=0; i5=0;
for(i=1; i<=5;i++) {
if(i==i1 || i==i2 ||i==i3) continue;
if(!i4) i4=i;
else i5 = i;
}
// find agjacent V (i4-i5)
TopoDS_Shape aV3;
const TopoDS_Shape& aV11 = TopExp::FirstVertex(TopoDS::Edge(theArS.Value(i4)));
const TopoDS_Shape& aV21 = TopExp::FirstVertex(TopoDS::Edge(theArS.Value(i5)));
const TopoDS_Shape& aV22 = TopExp::LastVertex(TopoDS::Edge(theArS.Value(i5)));
if(aV11.IsSame(aV21) || aV11.IsSame(aV22)) aV3 = aV11;
else {
const TopoDS_Shape& aV12 = TopExp::LastVertex(TopoDS::Edge(theArS.Value(i4)));
if(aV12.IsSame(aV21) || aV12.IsSame(aV22)) aV3 = aV12;
}
// 2. find nearest group (aV1, aV3), reorganize ArI - nerest => top
gp_Pnt aDP1 = BRep_Tool::Pnt(TopoDS::Vertex(aV1));
gp_Pnt aDP3 = BRep_Tool::Pnt(TopoDS::Vertex(aV3));
gp_Pnt aPnt = theAx.Location();
Standard_Real aD1 = aPnt.Distance(aDP1);//i1-i2-i3
Standard_Real aD2 = aPnt.Distance(aDP3);//i4-i5
Standard_Integer aTop = 3;
if(aD1 > aD2) { //change order of groups
aTop = 2;
Standard_Integer a4 = i4;// i1,i2 => i4,i5 - to the end
Standard_Integer a5 = i5;
i4 = i2; i5 = i1; // i4 - middle edge
i1 = a4; i2 = a5;
gp_Pnt aP1 = aDP1;
aDP1 = aDP3;
aDP3 = aP1;
// goup of 2 edges i1-i2 is the nearest
}
// 3.1. sort inside group of 2 edges
gp_Pnt aDP, aCP;
if(aTop == 2) {aDP = aDP1; aCP = theArP.Value(i1);} //i1,i2
else {aDP = aDP3; aCP = theArP.Value(i4);} //i4, i5 - group of 2 edges at the bottom
if(!IsDirectionPositive(theAx, aDP, aCP)) {//first must be positive direction
Standard_Integer aN;
if(aTop == 2) {
// change i1 <=> i2
aN = i2; i2 = i1;
i1 = aN;
} else {
// change i4 <=> i5
aN = i5; i5 = i4;
i4 = aN;
}
}
// 3.2. sort inside group of 3 edges
if(aTop == 2) {
//i3,i4,i5
aDP = theArP.Value(i4); //center of middle edge
aCP = theArP.Value(i3);
} else {
//i1,i2,i3
aDP = theArP.Value(i2);
aCP = theArP.Value(i1);
}
if(!IsDirectionPositive(theAx, aDP, aCP)) {//first must be positive direction
Standard_Integer aN;
if(aTop == 2) {
// change i3 <=> i5
aN = i5; i5 = i3;
i3 = aN;
} else {
// change i1 <=> i3
aN = i3; i3 = i1;
i1 = aN;
}
}
// 4. final order i1, i2, i3, i4, i5 - Ok
theArI.SetValue(1, i1);
theArI.SetValue(2, i2);
theArI.SetValue(3, i3);
theArI.SetValue(4, i4);
theArI.SetValue(5, i5);
}
//=======================================================================
static void FindAdjacent2(const TopTools_ListOfShape& theList,
TopTools_ListOfShape& theListOfEdges) {
TopTools_ListIteratorOfListOfShape It (theList);
const TopoDS_Shape& aShape1 = It.Value (); It.Next ();
const TopoDS_Shape& aShape2 = It.Value ();
if(!aShape1.IsNull() && !aShape2.IsNull()) {
TopExp_Explorer anExp1(aShape1, TopAbs_EDGE);
for(;anExp1.More();anExp1.Next()) {
TopExp_Explorer anExp2(aShape2, TopAbs_EDGE);
for(;anExp2.More();anExp2.Next()) {
if(anExp1.Current().IsSame(anExp2.Current()))
theListOfEdges.Append(anExp1.Current());
}
}
}
}
//=======================================================================
static void FindAdjacent3(const TopTools_ListOfShape& theList,
TopTools_ListOfShape& theListOfEdges) {
TopTools_ListIteratorOfListOfShape It (theList);
TopTools_Array1OfShape ArS(1, theList.Extent());
TColgp_Array1OfPnt ArP(1, theList.Extent());
TColgp_Array1OfDir ArD(1, theList.Extent());
Standard_Integer i;
for(i=1;It.More();It.Next(),i++) {
ArS.SetValue(i, It.Value());
gp_Ax1 anAx = ComputeAxis(It.Value());
ArP.SetValue(i, anAx.Location());
ArD.SetValue(i, anAx.Direction());
}
Standard_Boolean aDjacent = Standard_False;
Standard_Integer j, i2 = 0, i3 = 0; //i2, i3 - indexes of two adjacent faces having the same surface
Standard_Integer i1 = 0; //single face
for(i=1;i<=3;i++) {
for(j=1;j<=3;j++) {
if(i==j) continue;
if(ArP.Value(i).IsEqual(ArP.Value(j), Precision::Confusion())
&& ArD.Value(i).IsEqual(ArD.Value(j), Precision::Angular())) {
aDjacent = Standard_True;
Standard_Integer aSum = i+j;
switch(aSum) {
case 3: //12
i1 = 3; i2 = 1; i3 = 2;
break;
case 4: //13
i1 = 2; i2 = 1; i3 = 3;
break;
case 5: //23
i1 = 1; i2 = 2; i3 = 3;
break;
default:
i1 = 1; i2 = 2; i3 = 3;
}
break;
}
}
if(aDjacent) break;
}
TopExp_Explorer anExp1(ArS.Value(i1), TopAbs_EDGE);
for(;anExp1.More();anExp1.Next()) {
Standard_Boolean found = Standard_False;
TopExp_Explorer anExp2(ArS.Value(i2), TopAbs_EDGE);
for(;anExp2.More();anExp2.Next()) {
if(anExp1.Current().IsSame(anExp2.Current()))
{theListOfEdges.Append(anExp1.Current()); found=Standard_True; break;}
}
if(!found) {
TopExp_Explorer anExp3(ArS.Value(i3), TopAbs_EDGE);
for(;anExp3.More();anExp3.Next()) {
if(anExp1.Current().IsSame(anExp3.Current()))
{theListOfEdges.Append(anExp1.Current());break;}
}
}
}
}
//=======================================================================
static void FindAdjacent4(const TopTools_ListOfShape& theList,
TopTools_ListOfShape& theListOfEdges) {
TopTools_ListIteratorOfListOfShape It (theList);
TopTools_Array1OfShape ArS(1, theList.Extent());
TColgp_Array1OfPnt ArP(1, theList.Extent());
TColgp_Array1OfDir ArD(1, theList.Extent());
Standard_Integer i;
for(i=1;It.More();It.Next(),i++) {
ArS.SetValue(i, It.Value());
gp_Ax1 anAx = ComputeAxis(It.Value());
ArP.SetValue(i, anAx.Location());
ArD.SetValue(i, anAx.Direction());
}
//find pairs
Standard_Integer j, i3=0, i4 = 0;//i3, i4 - indexes of two adjacent faces having the same surface
Standard_Integer i1 = 0, i2 = 0;
Standard_Boolean aDjacent = Standard_False;
for(i=1;i<=4;i++) {
for(j=1;j<=4;j++) {
if(i==j) continue;
if(ArP.Value(i).IsEqual(ArP.Value(j), Precision::Confusion())
&& ArD.Value(i).IsEqual(ArD.Value(j), Precision::Angular())) {
aDjacent = Standard_True;
Standard_Integer aSum = i+j;
i1 = i; i2 = j;
switch(aSum) {
case 3: //12
i3 = 3; i4 = 4;
break;
case 4: //13
i3 = 2; i4 = 4;
break;
case 5: //14
i3 = 2; i4 = 3;
break;
default:
i3 = 3; i4 = 4;
}
break;
}
}
if(aDjacent) break;
}
TopExp_Explorer anExp1(ArS.Value(i1), TopAbs_EDGE);
for(;anExp1.More();anExp1.Next()) {
Standard_Boolean found = Standard_False;
TopExp_Explorer anExp2(ArS.Value(i3), TopAbs_EDGE);
for(;anExp2.More();anExp2.Next()) {
if(anExp1.Current().IsSame(anExp2.Current()))
{theListOfEdges.Append(anExp1.Current()); found=Standard_True; break;}
}
if(!found) {
TopExp_Explorer anExp3(ArS.Value(i4), TopAbs_EDGE);
for(;anExp3.More();anExp3.Next()) {
if(anExp1.Current().IsSame(anExp3.Current()))
{theListOfEdges.Append(anExp1.Current());break;}
}
}
}
//
anExp1.Init(ArS.Value(i2), TopAbs_EDGE);
for(;anExp1.More();anExp1.Next()) {
Standard_Boolean found = Standard_False;
TopExp_Explorer anExp2(ArS.Value(i3), TopAbs_EDGE);
for(;anExp2.More();anExp2.Next()) {
if(anExp1.Current().IsSame(anExp2.Current()))
{theListOfEdges.Append(anExp1.Current()); found=Standard_True; break;}
}
if(!found) {
TopExp_Explorer anExp3(ArS.Value(i4), TopAbs_EDGE);
for(;anExp3.More();anExp3.Next()) {
if(anExp1.Current().IsSame(anExp3.Current()))
{theListOfEdges.Append(anExp1.Current());break;}
}
}
}
}
//=======================================================================
// SortEdges: returns
//=======================================================================
static void SortEdges(const TopTools_ListOfShape& theListE, const gp_Ax1& theAx,
TopTools_Array1OfShape& theARS)
{
Standard_Integer aNE1 = theListE.Extent();
TopTools_Array1OfShape ArS(1, aNE1);
TColgp_Array1OfPnt ArP(1, aNE1);
TColStd_Array1OfInteger ArI(1, aNE1);
TopTools_ListIteratorOfListOfShape It (theListE);//pairs of edges
//for (Standard_Integer i=1;It.More (); It.Next (),i++) {
Standard_Integer i;
for (i=1;It.More (); It.Next (),i++) {
ArS.SetValue(i, It.Value ());
ArI.SetValue(i,0);
ArP.SetValue(i, GetCenterPoint(It.Value()));
}
switch(aNE1) {
case 2:
// Identify position
SortEdges2(ArP, theAx, ArI);
break;
case 3:
SortEdges3(ArS, ArP, theAx, ArI);
break;
case 4:
SortEdges4(ArS, ArP, theAx, ArI);
break;
case 5:
SortEdges5(ArS, ArP, theAx, ArI);
break;
}
for(i=1;i<=ArI.Upper();i++) {
#ifdef OCCT_DEBUG
cout << "SortEdges: i = " <<i<<" ArI.Value(i) = " <<ArI.Value(i)<< endl;
#endif
theARS.SetValue(i, ArS.Value(ArI.Value(i)));
}
}
//=======================================================================
//function : LoadSymmetricalEdges
//purpose :
//=======================================================================
void QANewBRepNaming_BooleanOperation::LoadSymmetricalEdges (BRepAlgoAPI_BooleanOperation& MS) const
{
const TopoDS_Shape& aResult = MS.Shape();
if(aResult.IsNull()) return;
const TopoDS_Shape& ObjSh = MS.Shape1();
const TopoDS_Shape& ToolSh = MS.Shape2();
const TopAbs_ShapeEnum& Type1 = ShapeType(ObjSh);
if(Type1 == TopAbs_COMPOUND || Type1 > TopAbs_FACE) return;
const TopAbs_ShapeEnum& Type2 = ShapeType(ToolSh);
if(Type2 == TopAbs_COMPOUND || Type2 > TopAbs_FACE) return;
TopTools_ListOfShape aList0;
if (aResult.ShapeType() == TopAbs_COMPOUND) {
TopoDS_Iterator itr(aResult);
for (; itr.More(); itr.Next())
aList0.Append(itr.Value()); //collect separated entities (bodies)
}
if(aList0.Extent() > 2) return; // case > 2 ent. is not considered
TopTools_ListOfShape aList1, aList2;
TopTools_ListIteratorOfListOfShape It (aList0); //each item (body) must have at least 1 pair
// of "cyl/con" surfaces (in some cases may be 3 or 4 faces depending on sim-edge position)
for (;It.More (); It.Next ()) {
const TopoDS_Shape& aShape = It.Value (); //1-st solid/shell
TopTools_ListOfShape aList;
aList.Clear();
#ifdef OCCT_DEBUG
// ModDbgTools_Write(aShape, "S0");
#endif
if(aShape.ShapeType() != TopAbs_FACE) {
TopExp_Explorer anExp(aShape, TopAbs_FACE);
for(;anExp.More();anExp.Next()) {
if(IsValidSurfType(TopoDS::Face(anExp.Current())))
aList.Append(anExp.Current()); // faces of the current entity
}
} else
if(IsValidSurfType(TopoDS::Face(ObjSh)))
aList.Append(aShape);
if(aList1.Extent() == 0 )
aList1.Assign(aList);
else
aList2.Assign(aList);
}
// aList1,2 contain pairs of faces having more then 1 neghbour edge (each pair)
const Standard_Integer aNF1 = aList1.Extent(); // keep n of faces of the first entity
const Standard_Integer aNF2 = aList2.Extent(); // keep n of faces of the second entity
if(aNF1 + aNF2 < 2) return;
//find Edges
TopTools_ListOfShape aListE1, aListE2;
Standard_Integer aNE1=0,aNE2=0;
if(aNF1 == 2 && !aNF2) {//trivial case - only 2 faces
FindAdjacent2(aList1, aListE1);
aNE1 = aListE1.Extent();
}
else { // result is compound of two ent.
if (aNF1 == 2) //first ent. has 2 valid faces
FindAdjacent2(aList1, aListE1); // find adjacent edges
else if (aNF1 == 3) // first ent. has 3 valid faces
FindAdjacent3(aList1, aListE1);
else if (aNF1 == 4) //first ent. has 4 valid faces
FindAdjacent4(aList1, aListE1);
// set number of symmetry Edges of the first ent.
aNE1 = aListE1.Extent();
// Second ent.
if (aNF2 == 2) //second ent. has 2 valid faces
FindAdjacent2(aList2, aListE2);
else if (aNF2 == 3)
FindAdjacent3(aList2, aListE2);
else if (aNF2 == 4)
FindAdjacent4(aList2, aListE2);
aNE2 = aListE2.Extent();
}
//aListE1, aListE2 - contains Edges
// if(aNE1 < 2) return;
// check topological compatibility
//if exist
Handle(TDataStd_IntegerArray) aSAR;
if(!ResultLabel().FindAttribute(TDataStd_IntegerArray::GetID(), aSAR) ) {
aSAR = TDataStd_IntegerArray::Set(ResultLabel(), 1, 2);
aSAR->SetValue(1, 0); //tag num for faces structure
aSAR->SetValue(2, 0); //tag num for edges structure
}
TDF_Label aLabelEDS;
if(aSAR->Value(2)) aLabelEDS = ResultLabel().FindChild(aSAR->Value(2)); // !=0
else {
// initial creation of EDS structure
aLabelEDS = NewShapes();
aSAR->SetValue(2, aLabelEDS.Tag()); //keep tag
}
Handle(TDataStd_Integer) anAtt;
if(aLabelEDS.FindAttribute(TDataStd_Integer::GetID(), anAtt) ) {
// modification : check compatibility
if(anAtt->Get() != aNE1+aNE2) {
cout << "WARNING: Case isn't mantained - Number of Edges was changed!"<<endl;
// mark all structure as Deleted
Standard_Integer aN = aLabelEDS.Tag()+anAtt->Get();
for(Standard_Integer i=aLabelEDS.Tag(); i < aN; i++) {
TDF_Label aLab = ResultLabel().FindChild(i, Standard_False);
if(!aLab.IsNull()) {
Handle(TNaming_NamedShape) aNS;
if(aLab.FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
TopoDS_Shape aShape = aNS->Get();
TNaming_Builder aBuilder(aLab);
aBuilder.Delete(aShape); //Deleted
}
}
}
//
Handle(TDF_TagSource) aTS;
ResultLabel().FindAttribute (TDF_TagSource::GetID (), aTS);
if(!aTS.IsNull())
aTS->Set(aLabelEDS.Tag());
anAtt->Set(aNE1+aNE2);
}
} else
TDataStd_Integer::Set(aLabelEDS, aNE1+aNE2); //keep number of edges
// Identification
// if(aNE1% 2 > 0) return;
gp_Ax1 anAx = ComputeAxis(MS.Shape2());
Handle(TDF_TagSource) aTS;
ResultLabel().FindAttribute (TDF_TagSource::GetID (), aTS);
if(!aNE2 && aNE1) { // only 1 ent.
//Top || Bot ?
TopTools_Array1OfShape ArS1(1, aNE1);
SortEdges(aListE1, anAx, ArS1);
for(Standard_Integer i=1; i <= aNE1; i++) {
TopoDS_Shape aShape = ArS1.Value(i);
Standard_Integer aLabTag = aLabelEDS.Tag() + i -1;
TDF_Label aLab = ResultLabel().FindChild(aLabTag);
aTS->Set(aLabTag);
TNaming_Builder aBuilder(aLab);
aBuilder.Generated(aShape);
}
} else if(aNE1 && aNE2) { //2 ent.
TopTools_Array1OfShape ArS1(1, aNE1);
SortEdges(aListE1, anAx, ArS1);
TopTools_Array1OfShape ArS2(1, aNE2);
SortEdges(aListE2, anAx, ArS2);
gp_Pnt aPnt1 = GetCenterPoint(aListE1.First());
// gp_Pnt aPnt2 = GetCenterPoint(aListE2.First());
if(IsDirectionPositive(anAx, anAx.Location(), aPnt1)) {
Standard_Integer i;
for(i=1; i <= aNE1; i++) {
TopoDS_Shape aShape = ArS1.Value(i);
Standard_Integer aLabTag = aLabelEDS.Tag() + i - 1;
TDF_Label aLab = ResultLabel().FindChild(aLabTag);
aTS->Set(aLabTag);
TNaming_Builder aBuilder(aLab);
aBuilder.Generated(aShape);
}
Standard_Integer start = aLabelEDS.Tag() + aNE1;
for(i=1; i <= aNE2; i++) {
TopoDS_Shape aShape = ArS2.Value(i);
Standard_Integer aLabTag = start + i - 1;
TDF_Label aLab = ResultLabel().FindChild(aLabTag);
aTS->Set(aLabTag);
TNaming_Builder aBuilder(aLab);
aBuilder.Generated(aShape);
}
}
else {
Standard_Integer i;
for(i=1; i <= aNE2; i++) {
TopoDS_Shape aShape = ArS2.Value(i);
Standard_Integer aLabTag = aLabelEDS.Tag() + i - 1;
TDF_Label aLab = ResultLabel().FindChild(aLabTag);
aTS->Set(aLabTag);
TNaming_Builder aBuilder(aLab);
aBuilder.Generated(aShape);
}
Standard_Integer start = aLabelEDS.Tag() + aNE2;
for(i=1; i <= aNE1; i++) {
TopoDS_Shape aShape = ArS1.Value(i);
Standard_Integer aLabTag = start + i - 1;
TDF_Label aLab = ResultLabel().FindChild(aLabTag);
aTS->Set(aLabTag);
TNaming_Builder aBuilder(aLab);
aBuilder.Generated(aShape);
}
}
}
}
//=======================================================================
//function : ISWRCase2
//purpose :
//=======================================================================
Standard_Boolean QANewBRepNaming_BooleanOperation::IsWRCase2(BRepAlgoAPI_BooleanOperation& MS) {
const TopoDS_Shape& Result = MS.Shape();
const TopAbs_ShapeEnum& ResType = ShapeType(Result);
if(ResType == TopAbs_COMPOUND || ResType >= TopAbs_FACE) return Standard_False;
TopExp_Explorer anExp(Result, TopAbs_FACE);
for(;anExp.More();anExp.Next()) {
if(IsValidSurfType(TopoDS::Face(anExp.Current()))) {
TopExp_Explorer anExp1(Result, TopAbs_FACE);
for(;anExp1.More();anExp1.Next()) {
if(!anExp1.Current().IsSame(anExp.Current()) && !IsValidSurfType(TopoDS::Face(anExp1.Current()))) {
TopTools_ListOfShape aList;
aList.Append(anExp.Current());
aList.Append(anExp1.Current());
TopTools_ListOfShape anEList;
FindAdjacent2(aList, anEList);
if(anEList.Extent() == 2) {
return Standard_True;
}
}
}
}
}
return Standard_False;
}
//=======================================================================
//function : LoadWRCase
//purpose :
//=======================================================================
void QANewBRepNaming_BooleanOperation::LoadWRCase(BRepAlgoAPI_BooleanOperation& MS) const {
const TopoDS_Shape& Result = MS.Shape();
const TopAbs_ShapeEnum& ResType = ShapeType(Result);
if(ResType == TopAbs_COMPOUND || ResType >= TopAbs_FACE) return;
TopExp_Explorer anExp(Result, TopAbs_FACE);
for(;anExp.More();anExp.Next()) {
if(IsValidSurfType(TopoDS::Face(anExp.Current()))) {
TopExp_Explorer anExp1(Result, TopAbs_FACE);
for(;anExp1.More();anExp1.Next()) {
if(!anExp1.Current().IsSame(anExp.Current()) && !IsValidSurfType(TopoDS::Face(anExp1.Current()))) {
TopTools_ListOfShape aList;
aList.Append(anExp.Current());
aList.Append(anExp1.Current());
TopTools_ListOfShape anEList;
FindAdjacent2(aList, anEList);
if(anEList.Extent() == 2) {
TopTools_ListIteratorOfListOfShape anEIt(anEList);
GProp_GProps anE1Props, anE2Props;
BRepGProp::LinearProperties(anEList.First(), anE1Props);
BRepGProp::LinearProperties(anEList.Last(), anE2Props);
const TDF_Label& WRE1Label = ResultLabel().NewChild();
const TDF_Label& WRE2Label = ResultLabel().NewChild();
const TDF_Label& WRV1Label = ResultLabel().NewChild();
const TDF_Label& WRV2Label = ResultLabel().NewChild();
#ifdef OCCT_DEBUG
TDataStd_Name::Set(WRE1Label, "WorkAroundEdge1");
TDataStd_Name::Set(WRE2Label, "WorkAroundEdge2");
TDataStd_Name::Set(WRV1Label, "WorkAroundVertex1");
TDataStd_Name::Set(WRV2Label, "WorkAroundVertex2");
#endif
TNaming_Builder anEBuilder1(WRE1Label);
TNaming_Builder anEBuilder2(WRE2Label);
TNaming_Builder aVBuilder1(WRV1Label);
TNaming_Builder aVBuilder2(WRV2Label);
if(anE1Props.Mass() > anE2Props.Mass()) {
anEBuilder1.Generated(anEList.Last());
anEBuilder2.Generated(anEList.First());
aVBuilder1.Generated(TopExp::FirstVertex(TopoDS::Edge(anEList.Last())));
aVBuilder2.Generated(TopExp::LastVertex(TopoDS::Edge(anEList.Last())));
} else {
anEBuilder1.Generated(anEList.First());
anEBuilder2.Generated(anEList.Last());
aVBuilder1.Generated(TopExp::FirstVertex(TopoDS::Edge(anEList.First())));
aVBuilder2.Generated(TopExp::LastVertex(TopoDS::Edge(anEList.First())));
}
}
}
}
}
}
}