mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-04-07 18:30:55 +03:00
Modifications: 1. class BOPTools_AlgoTools 1.1. method Standard_Boolean BOPTools_AlgoTools::ComputeTolerance (const Handle(Geom_Curve)& theCurve3D, const Handle(Geom2d_Curve)& theCurve2D, const Handle(Geom_Surface)& theSurf, const Standard_Real theFirst, const Standard_Real theLast, Standard_Real& theMaxDist, Standard_Real& theMaxPar) It computes the max distance between points taken from 3D and 2D curves by the same parameter 1.2. method Standard_Boolean BOPTools_AlgoTools::ComputeTolerance (const TopoDS_Face& theFace, const TopoDS_Edge& theEdge, Standard_Real& theMaxDist, Standard_Real& theParameter) Computes the valid value of the tolerance for the edge using the function above. 2. Added possibility to check shape on the validity of the curves on the surfaces. 2.1. New status BOPAlgo_InvalidCurveOnSurface has been added to the enumeration BOPAlgo_CheckStatus 2.2. class BOPAlgo_ArgumentAnalyzer method void BOPAlgo_ArgumentAnalyzer::TestCurveOnSurface() It checks each edge/face pair in the shape using the method ComputeTolerance from BOPTools_AlgoTools and stores invalid pairs to myResults. Invalid pairs are those which contain the edge with tolerance value less then the value computed by the ComputeTolerance method. 2.3. class BOPAlgo_CheckResult Added new fields: myMaxDist1 : Real from Standard; myMaxDist2 : Real from Standard; myMaxPar1 : Real from Standard; myMaxPar2 : Real from Standard; and corresponding setters and getters. These fields are used to store the results of the TestCurveOnSurface() check. 3. Added new option to the bopargcheck command and two new commands. class BOPTest_CheckCommands 3.1. command bopargcheck As it is using the BOPAlgo_ArgumentAnalyzer class to check the shapes it checks also the validity of the curves on the surfaces. The output for the invalid shapes is following: Draw[]> bopargcheck b2 /ic #f Made faulty shape: s1COnS_1 (MaxDist = 0.0013334343378738308, MaxPar = 0.02884285498274167) Made faulty shape: s1COnS_2 (MaxDist = 0.0013334340648766174, MaxPar = 0.02884285497934707) Made faulty shape: s1COnS_3 (MaxDist = 0.0013335086668628978, MaxPar = 1.4133051942712607) Made faulty shape: s1COnS_4 (MaxDist = 0.0013335086525838983, MaxPar = 1.4133051942713901) Faulties for FIRST shape found : 4 --------------------------------- Shapes are not suppotrted by BOP: NO Self-Intersections : NO Check for SI has been aborted : NO Too small edges : NO Bad faces : NO Too close vertices : NO Too close edges : NO Shapes with Continuity C0 : NO Invalid Curve on Surface : YES Cases(4) Total shapes(8) Faulties for SECOND shape found : 0 The compounds s1COnS_* contain pair of edge and face. MaxDist is maximal distance between points taken from 3D curve of the edge and 2D curve of that edge on the face. MaxPar is a parameter in which the MaxDist is reached. To disable this check it is necessary to use option /S (bopargcheck shape /S). 3.2. command xdistef Usage of the command: xdistef edge face It computes distance between points taken from 3D curve of the edge and 2D curve of that edge on the face. Example: Draw[]> explode s1COnS_1 s1COnS_1_1 s1COnS_1_2 Draw[]> whatis s1COnS_1_1 s1COnS_1_1 is a shape EDGE FORWARD Modified Orientable Draw[]> whatis s1COnS_1_2 s1COnS_1_2 is a shape FACE FORWARD Modified Orientable Draw[]> xdistef s1COnS_1_1 s1COnS_1_2 Max Distance = 0.0013334343378738308; Parameter on curve = 0.02884285498274167 3.3. command checkcurveonsurf Usage of the command: checkcurveonsurf shape. It checks each edge/face pair in the shape using the method ComputeTolerance from BOPTools_AlgoTools. Example: Draw[]> checkcurveonsurf b2 Invalid curves on surface: edge e_0 on face f_0 (max dist: 0.0013334343378738, parameter on curve: 0.0288428549827417) edge e_1 on face f_0 (max dist: 0.0013334340648766, parameter on curve: 0.0288428549793471) edge e_2 on face f_1 (max dist: 0.0013335086668629, parameter on curve: 1.4133051942712607) edge e_3 on face f_1 (max dist: 0.0013335086525839, parameter on curve: 1.4133051942713901) Sugestions to fix the shape: explode b2 e; settolerance b2_6 0.0013335086668629; settolerance b2_7 0.0013334343378738; settolerance b2_8 0.0013334340648766; settolerance b2_10 0.0013335086525839; The command gives suggestions to fix the shape by increasing tolerance values of the invalid edges. In some cases the tolerance values suggested by the tool can be very large. Such values should be used very carefully, because setting large tolerance values to the sub-shapes of the shape can make it non valid (self-interfered) or lead to unexpected result when using such shapes in some operations (boolean for example). Test case for issue CR25410
877 lines
24 KiB
C++
877 lines
24 KiB
C++
// Created on: 2004-09-02
|
|
// Copyright (c) 2004-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 <BOPAlgo_ArgumentAnalyzer.ixx>
|
|
|
|
#include <Standard_ErrorHandler.hxx>
|
|
#include <Standard_Failure.hxx>
|
|
|
|
#include <TColStd_Array2OfBoolean.hxx>
|
|
|
|
#include <gp_Pnt.hxx>
|
|
|
|
#include <Geom_Surface.hxx>
|
|
|
|
#include <TopoDS_Iterator.hxx>
|
|
#include <TopoDS.hxx>
|
|
#include <TopoDS_Vertex.hxx>
|
|
#include <TopoDS_Edge.hxx>
|
|
#include <TopoDS_Wire.hxx>
|
|
#include <TopoDS_Shell.hxx>
|
|
#include <TopoDS_Solid.hxx>
|
|
|
|
#include <BRep_Builder.hxx>
|
|
#include <BRep_Tool.hxx>
|
|
|
|
#include <TopExp.hxx>
|
|
#include <TopExp_Explorer.hxx>
|
|
|
|
#include <BRepExtrema_DistShapeShape.hxx>
|
|
//
|
|
#include <BOPCol_ListOfShape.hxx>
|
|
#include <BOPCol_SequenceOfShape.hxx>
|
|
#include <BOPCol_MapOfShape.hxx>
|
|
|
|
#include <IntTools_Range.hxx>
|
|
#include <IntTools_EdgeEdge.hxx>
|
|
#include <IntTools_CommonPrt.hxx>
|
|
|
|
#include <IntTools_Context.hxx>
|
|
|
|
#include <BOPTools_AlgoTools3D.hxx>
|
|
#include <BOPTools_AlgoTools.hxx>
|
|
|
|
#include <BOPDS_DS.hxx>
|
|
#include <BOPDS_MapOfPassKey.hxx>
|
|
|
|
#include <BOPAlgo_Operation.hxx>
|
|
#include <BOPAlgo_CheckerSI.hxx>
|
|
#include <BOPAlgo_BuilderFace.hxx>
|
|
|
|
// ================================================================================
|
|
// function: Constructor
|
|
// purpose:
|
|
// ================================================================================
|
|
BOPAlgo_ArgumentAnalyzer::BOPAlgo_ArgumentAnalyzer() :
|
|
myStopOnFirst(Standard_False),
|
|
myOperation(BOPAlgo_UNKNOWN),
|
|
myArgumentTypeMode(Standard_False),
|
|
mySelfInterMode(Standard_False),
|
|
mySmallEdgeMode(Standard_False),
|
|
myRebuildFaceMode(Standard_False),
|
|
myTangentMode(Standard_False),
|
|
myMergeVertexMode(Standard_False),
|
|
myMergeEdgeMode(Standard_False),
|
|
myContinuityMode(Standard_False),
|
|
myCurveOnSurfaceMode(Standard_False),
|
|
myEmpty1(Standard_False),
|
|
myEmpty2(Standard_False)
|
|
{
|
|
}
|
|
|
|
// ================================================================================
|
|
// function: SetShape1
|
|
// purpose:
|
|
// ================================================================================
|
|
void BOPAlgo_ArgumentAnalyzer::SetShape1(const TopoDS_Shape & TheShape)
|
|
{
|
|
myShape1 = TheShape;
|
|
}
|
|
|
|
// ================================================================================
|
|
// function: SetShape2
|
|
// purpose:
|
|
// ================================================================================
|
|
void BOPAlgo_ArgumentAnalyzer::SetShape2(const TopoDS_Shape & TheShape)
|
|
{
|
|
myShape2 = TheShape;
|
|
}
|
|
|
|
// ================================================================================
|
|
// function: GetShape1
|
|
// purpose:
|
|
// ================================================================================
|
|
const TopoDS_Shape & BOPAlgo_ArgumentAnalyzer::GetShape1() const
|
|
{
|
|
return myShape1;
|
|
}
|
|
|
|
// ================================================================================
|
|
// function: GetShape2
|
|
// purpose:
|
|
// ================================================================================
|
|
const TopoDS_Shape & BOPAlgo_ArgumentAnalyzer::GetShape2() const
|
|
{
|
|
return myShape2;
|
|
}
|
|
|
|
// ================================================================================
|
|
// function: OperationType
|
|
// purpose:
|
|
// ================================================================================
|
|
BOPAlgo_Operation& BOPAlgo_ArgumentAnalyzer::OperationType()
|
|
{
|
|
return myOperation;
|
|
}
|
|
|
|
// ================================================================================
|
|
// function: StopOnFirstFaulty
|
|
// purpose:
|
|
// ================================================================================
|
|
Standard_Boolean & BOPAlgo_ArgumentAnalyzer::StopOnFirstFaulty()
|
|
{
|
|
return myStopOnFirst;
|
|
}
|
|
|
|
// ================================================================================
|
|
// function: Prepare
|
|
// purpose:
|
|
// ================================================================================
|
|
void BOPAlgo_ArgumentAnalyzer::Prepare()
|
|
{
|
|
Standard_Boolean isS1 = myShape1.IsNull(), isS2 = myShape2.IsNull();
|
|
if (!isS1) {
|
|
myEmpty1 = BOPTools_AlgoTools3D::IsEmptyShape(myShape1);
|
|
}
|
|
if (!isS2) {
|
|
myEmpty2 = BOPTools_AlgoTools3D::IsEmptyShape(myShape2);
|
|
}
|
|
}
|
|
// ================================================================================
|
|
// function: Perform
|
|
// purpose:
|
|
// ================================================================================
|
|
void BOPAlgo_ArgumentAnalyzer::Perform()
|
|
{
|
|
try {
|
|
OCC_CATCH_SIGNALS
|
|
myResult.Clear();
|
|
|
|
Prepare();
|
|
|
|
if(myArgumentTypeMode) {
|
|
TestTypes();
|
|
}
|
|
|
|
if(mySelfInterMode) {
|
|
TestSelfInterferences();
|
|
}
|
|
|
|
if(mySmallEdgeMode) {
|
|
if(!(!myResult.IsEmpty() && myStopOnFirst))
|
|
TestSmallEdge();
|
|
}
|
|
|
|
if(myRebuildFaceMode) {
|
|
if(!(!myResult.IsEmpty() && myStopOnFirst))
|
|
TestRebuildFace();
|
|
}
|
|
|
|
if(myTangentMode) {
|
|
if(!(!myResult.IsEmpty() && myStopOnFirst))
|
|
TestTangent();
|
|
}
|
|
|
|
if(myMergeVertexMode) {
|
|
if(!(!myResult.IsEmpty() && myStopOnFirst))
|
|
TestMergeVertex();
|
|
}
|
|
|
|
if(myMergeEdgeMode) {
|
|
if(!(!myResult.IsEmpty() && myStopOnFirst))
|
|
TestMergeEdge();
|
|
}
|
|
|
|
if(myContinuityMode) {
|
|
if(!(!myResult.IsEmpty() && myStopOnFirst))
|
|
TestContinuity();
|
|
}
|
|
|
|
if(myCurveOnSurfaceMode) {
|
|
if(!(!myResult.IsEmpty() && myStopOnFirst))
|
|
TestCurveOnSurface();
|
|
}
|
|
}
|
|
catch(Standard_Failure) {
|
|
BOPAlgo_CheckResult aResult;
|
|
aResult.SetCheckStatus(BOPAlgo_CheckUnknown);
|
|
myResult.Append(aResult);
|
|
}
|
|
}
|
|
|
|
// ================================================================================
|
|
// function: HasFaulty
|
|
// purpose:
|
|
// ================================================================================
|
|
Standard_Boolean BOPAlgo_ArgumentAnalyzer::HasFaulty() const
|
|
{
|
|
return ( !myResult.IsEmpty());
|
|
}
|
|
|
|
// ================================================================================
|
|
// function: GetCheckResult
|
|
// purpose:
|
|
// ================================================================================
|
|
const BOPAlgo_ListOfCheckResult& BOPAlgo_ArgumentAnalyzer::GetCheckResult() const
|
|
{
|
|
return myResult;
|
|
}
|
|
|
|
// ================================================================================
|
|
// function: TestTypes
|
|
// purpose:
|
|
// ================================================================================
|
|
void BOPAlgo_ArgumentAnalyzer::TestTypes()
|
|
{
|
|
Standard_Boolean isS1 = myShape1.IsNull(), isS2 = myShape2.IsNull();
|
|
|
|
if(isS1 && isS2) {
|
|
BOPAlgo_CheckResult aResult;
|
|
aResult.SetCheckStatus(BOPAlgo_BadType);
|
|
myResult.Append(aResult);
|
|
return;
|
|
}
|
|
|
|
//single shape check
|
|
if((isS1 && !isS2) || (!isS1 && isS2)) {
|
|
Standard_Boolean bIsEmpty = (isS1) ? myEmpty2 : myEmpty1;
|
|
|
|
if(bIsEmpty || myOperation!=BOPAlgo_UNKNOWN) {
|
|
const TopoDS_Shape & aS = (isS1) ? myShape2 : myShape1;
|
|
BOPAlgo_CheckResult aResult;
|
|
aResult.SetShape1(aS);
|
|
aResult.SetCheckStatus(BOPAlgo_BadType);
|
|
myResult.Append(aResult);
|
|
return;
|
|
}
|
|
}
|
|
// two shapes check (begin)
|
|
else {
|
|
if(myEmpty1 || myEmpty2) {
|
|
BOPAlgo_CheckResult aResult;
|
|
if(myEmpty1 && myEmpty2) {
|
|
aResult.SetShape1(myShape1);
|
|
aResult.SetShape2(myShape2);
|
|
}
|
|
else {
|
|
const TopoDS_Shape & aS = myEmpty1 ? myShape1 : myShape2;
|
|
if(myEmpty1)
|
|
aResult.SetShape1(aS);
|
|
else
|
|
aResult.SetShape2(aS);
|
|
}
|
|
aResult.SetCheckStatus(BOPAlgo_BadType);
|
|
myResult.Append(aResult);
|
|
return;
|
|
}
|
|
//
|
|
Standard_Integer aDim1, aDim2;
|
|
Standard_Boolean bBadTypes = Standard_False;
|
|
//
|
|
aDim1 = BOPTools_AlgoTools::Dimension(myShape1);
|
|
aDim2 = BOPTools_AlgoTools::Dimension(myShape2);
|
|
if (aDim1 < aDim2) {
|
|
if (myOperation == BOPAlgo_FUSE ||
|
|
myOperation == BOPAlgo_CUT21) {
|
|
bBadTypes = Standard_True;
|
|
}
|
|
}
|
|
else if (aDim1 > aDim2) {
|
|
if (myOperation == BOPAlgo_FUSE ||
|
|
myOperation == BOPAlgo_CUT) {
|
|
bBadTypes = Standard_True;
|
|
}
|
|
}
|
|
if (bBadTypes) {
|
|
BOPAlgo_CheckResult aResult;
|
|
aResult.SetShape1(myShape1);
|
|
aResult.SetShape2(myShape2);
|
|
aResult.SetCheckStatus(BOPAlgo_BadType);
|
|
myResult.Append(aResult);
|
|
}
|
|
}
|
|
}
|
|
//=======================================================================
|
|
//function : TestSelfInterferences
|
|
//purpose :
|
|
//=======================================================================
|
|
void BOPAlgo_ArgumentAnalyzer::TestSelfInterferences()
|
|
{
|
|
Standard_Integer ii;
|
|
//
|
|
for(ii = 0; ii < 2; ii++) {
|
|
const TopoDS_Shape& aS = (ii == 0) ? myShape1 : myShape2;
|
|
if(aS.IsNull()) {
|
|
continue;
|
|
}
|
|
//
|
|
Standard_Boolean bIsEmpty = (ii == 0) ? myEmpty1 : myEmpty2;
|
|
if (bIsEmpty) {
|
|
continue;
|
|
}
|
|
//
|
|
Standard_Integer iErr, n1, n2;
|
|
BOPDS_MapIteratorMapOfPassKey aItMPK;
|
|
BOPCol_ListOfShape anArgs;
|
|
BOPAlgo_CheckerSI aChecker;
|
|
//
|
|
anArgs.Append(aS);
|
|
aChecker.SetArguments(anArgs);
|
|
aChecker.SetNonDestructive(Standard_True);
|
|
//
|
|
aChecker.Perform();
|
|
iErr=aChecker.ErrorStatus();
|
|
//
|
|
const BOPDS_DS& aDS=*(aChecker.PDS());
|
|
const BOPDS_MapOfPassKey& aMPK=aDS.Interferences();
|
|
//
|
|
aItMPK.Initialize(aMPK);
|
|
for (; aItMPK.More(); aItMPK.Next()) {
|
|
const BOPDS_PassKey& aPK=aItMPK.Value();
|
|
aPK.Ids(n1, n2);
|
|
if(aDS.IsNewShape(n1) || aDS.IsNewShape(n2)) {
|
|
continue;
|
|
}
|
|
//
|
|
const TopoDS_Shape& aS1=aDS.Shape(n1);
|
|
const TopoDS_Shape& aS2=aDS.Shape(n2);
|
|
//
|
|
BOPAlgo_CheckResult aResult;
|
|
if(ii == 0) {
|
|
aResult.SetShape1(myShape1);
|
|
aResult.AddFaultyShape1(aS1);
|
|
aResult.AddFaultyShape1(aS2);
|
|
}
|
|
else {
|
|
aResult.SetShape2(myShape2);
|
|
aResult.AddFaultyShape2(aS1);
|
|
aResult.AddFaultyShape2(aS2);
|
|
}
|
|
aResult.SetCheckStatus(BOPAlgo_SelfIntersect);
|
|
myResult.Append(aResult);
|
|
}
|
|
//
|
|
if (iErr) {
|
|
BOPAlgo_CheckResult aResult;
|
|
if(ii == 0) {
|
|
aResult.SetShape1(myShape1);
|
|
aResult.AddFaultyShape1(myShape1);
|
|
}
|
|
else {
|
|
aResult.SetShape2(myShape2);
|
|
aResult.AddFaultyShape2(myShape2);
|
|
}
|
|
aResult.SetCheckStatus(BOPAlgo_OperationAborted);
|
|
myResult.Append(aResult);
|
|
}
|
|
}// for(ii = 0; ii < 2; ii++) {
|
|
}
|
|
// ================================================================================
|
|
// function: TestSmallEdge
|
|
// purpose:
|
|
// ================================================================================
|
|
void BOPAlgo_ArgumentAnalyzer::TestSmallEdge()
|
|
{
|
|
Standard_Integer i = 0;
|
|
BRepExtrema_DistShapeShape aDist;
|
|
Handle(IntTools_Context) aCtx;
|
|
//
|
|
aCtx = new IntTools_Context;
|
|
|
|
for(i = 0; i < 2; i++) {
|
|
const TopoDS_Shape& aS = (i == 0) ? myShape1 : myShape2;
|
|
|
|
if(aS.IsNull())
|
|
continue;
|
|
|
|
TopExp_Explorer anExp(aS, TopAbs_EDGE);
|
|
|
|
for(; anExp.More(); anExp.Next()) {
|
|
const TopoDS_Edge& anEdge = *(TopoDS_Edge*)&anExp.Current();
|
|
if (BRep_Tool::Degenerated(anEdge)) {
|
|
continue;
|
|
}
|
|
|
|
if(BOPTools_AlgoTools::IsMicroEdge(anEdge, aCtx)) {
|
|
Standard_Boolean bKeepResult = Standard_True;
|
|
|
|
if(myOperation == BOPAlgo_SECTION) {
|
|
const TopoDS_Shape& anOtherS = (i == 0) ? myShape2 : myShape1;
|
|
|
|
if(!anOtherS.IsNull()) {
|
|
aDist.LoadS2(anOtherS);
|
|
|
|
Standard_Boolean bVertexIsOnShape = Standard_False;
|
|
Standard_Integer ii = 0;
|
|
TopExp_Explorer anExpV(anEdge, TopAbs_VERTEX);
|
|
|
|
for(; anExpV.More(); anExpV.Next()) {
|
|
const TopoDS_Shape& aV = anExpV.Current();
|
|
|
|
aDist.LoadS1(aV);
|
|
aDist.Perform();
|
|
|
|
if(aDist.IsDone()) {
|
|
|
|
for(ii = 1; ii <= aDist.NbSolution(); ii++) {
|
|
Standard_Real aTolerance = BRep_Tool::Tolerance(*(TopoDS_Vertex*)&aV);
|
|
const TopoDS_Shape& aSupportShape = aDist.SupportOnShape2(ii);
|
|
|
|
switch(aSupportShape.ShapeType()) {
|
|
case TopAbs_VERTEX: {
|
|
aTolerance += BRep_Tool::Tolerance(*(TopoDS_Vertex*)&(aSupportShape));
|
|
break;
|
|
}
|
|
case TopAbs_EDGE: {
|
|
aTolerance += BRep_Tool::Tolerance(*(TopoDS_Edge*)&(aSupportShape));
|
|
break;
|
|
}
|
|
case TopAbs_FACE: {
|
|
aTolerance += BRep_Tool::Tolerance(*(TopoDS_Face*)&(aSupportShape));
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if(aDist.Value() < aTolerance) {
|
|
bVertexIsOnShape = Standard_True;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if(!bVertexIsOnShape) {
|
|
bKeepResult = Standard_False;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(bKeepResult) {
|
|
BOPAlgo_CheckResult aResult;
|
|
|
|
if(i == 0) {
|
|
aResult.SetShape1(myShape1);
|
|
aResult.AddFaultyShape1(anEdge);
|
|
}
|
|
else {
|
|
aResult.SetShape2(myShape2);
|
|
aResult.AddFaultyShape2(anEdge);
|
|
}
|
|
|
|
aResult.SetCheckStatus(BOPAlgo_TooSmallEdge);
|
|
myResult.Append(aResult);
|
|
|
|
if(myStopOnFirst) {
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// ================================================================================
|
|
// function: TestRebuildFace
|
|
// purpose:
|
|
// ================================================================================
|
|
void BOPAlgo_ArgumentAnalyzer::TestRebuildFace()
|
|
{
|
|
if((myOperation == BOPAlgo_SECTION) ||
|
|
(myOperation == BOPAlgo_UNKNOWN))
|
|
return;
|
|
Standard_Integer i = 0;
|
|
|
|
for(i = 0; i < 2; i++) {
|
|
const TopoDS_Shape& aS = (i == 0) ? myShape1 : myShape2;
|
|
|
|
if(aS.IsNull())
|
|
continue;
|
|
|
|
TopExp_Explorer anExp(aS, TopAbs_FACE);
|
|
BOPCol_ListOfShape aLS;
|
|
|
|
for(; anExp.More(); anExp.Next()) {
|
|
const TopoDS_Face& aFace = *(TopoDS_Face*)&(anExp.Current());
|
|
|
|
TopoDS_Face aFF = aFace;
|
|
aFF.Orientation(TopAbs_FORWARD);
|
|
TopExp_Explorer anExpE(aFF, TopAbs_EDGE);
|
|
Standard_Integer nbstartedges = 0;
|
|
aLS.Clear();
|
|
//
|
|
for(; anExpE.More(); anExpE.Next()) {
|
|
const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&anExpE.Current()));
|
|
TopAbs_Orientation anOriE=aE.Orientation();
|
|
//
|
|
if (anOriE==TopAbs_INTERNAL) {
|
|
TopoDS_Edge aEE=aE;
|
|
aEE.Orientation(TopAbs_FORWARD);
|
|
aLS.Append(aEE);
|
|
aEE.Orientation(TopAbs_REVERSED);
|
|
aLS.Append(aEE);
|
|
}
|
|
else {
|
|
aLS.Append(aE);
|
|
}
|
|
nbstartedges++;
|
|
}
|
|
BOPAlgo_BuilderFace aBF;
|
|
aBF.SetFace(aFace);
|
|
aBF.SetShapes(aLS);
|
|
aBF.Perform();
|
|
const BOPCol_ListOfShape& aLF = aBF.Areas();
|
|
Standard_Boolean bBadFace = Standard_False;
|
|
|
|
if(aLF.Extent() != 1) {
|
|
bBadFace = Standard_True;
|
|
}
|
|
else {
|
|
Standard_Integer nbedgeused = 0;
|
|
anExpE.Init(aLF.First(), TopAbs_EDGE);
|
|
|
|
for(; anExpE.More(); anExpE.Next(), nbedgeused++);
|
|
|
|
if(nbstartedges != nbedgeused) {
|
|
bBadFace = Standard_True;
|
|
}
|
|
}
|
|
|
|
if(bBadFace) {
|
|
BOPAlgo_CheckResult aResult;
|
|
|
|
if(i == 0) {
|
|
aResult.SetShape1(myShape1);
|
|
aResult.AddFaultyShape1(aFace);
|
|
}
|
|
else {
|
|
aResult.SetShape2(myShape2);
|
|
aResult.AddFaultyShape2(aFace);
|
|
}
|
|
|
|
aResult.SetCheckStatus(BOPAlgo_NonRecoverableFace);
|
|
myResult.Append(aResult);
|
|
|
|
if(myStopOnFirst) {
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// ================================================================================
|
|
// function: TestTangent
|
|
// purpose:
|
|
// ================================================================================
|
|
void BOPAlgo_ArgumentAnalyzer::TestTangent()
|
|
{
|
|
// not implemented
|
|
}
|
|
|
|
// ================================================================================
|
|
// function: TestMergeSubShapes
|
|
// purpose:
|
|
// ================================================================================
|
|
void BOPAlgo_ArgumentAnalyzer::TestMergeSubShapes(const TopAbs_ShapeEnum theType)
|
|
{
|
|
if(myShape1.IsNull() || myShape2.IsNull())
|
|
return;
|
|
|
|
if (myEmpty1 || myEmpty2)
|
|
return;
|
|
|
|
BOPAlgo_CheckStatus aStatus = BOPAlgo_CheckUnknown;
|
|
|
|
switch(theType) {
|
|
case TopAbs_VERTEX: {
|
|
aStatus = BOPAlgo_IncompatibilityOfVertex;
|
|
break;
|
|
}
|
|
case TopAbs_EDGE: {
|
|
aStatus = BOPAlgo_IncompatibilityOfEdge;
|
|
break;
|
|
}
|
|
case TopAbs_FACE: {
|
|
aStatus = BOPAlgo_IncompatibilityOfFace;
|
|
break;
|
|
}
|
|
default:
|
|
return;
|
|
}
|
|
TopExp_Explorer anExp1(myShape1, theType);
|
|
TopExp_Explorer anExp2(myShape2, theType);
|
|
BOPCol_SequenceOfShape aSeq1, aSeq2;
|
|
BOPCol_MapOfShape aMap1, aMap2;
|
|
|
|
for(; anExp1.More(); anExp1.Next()) {
|
|
const TopoDS_Shape& aS1 = anExp1.Current();
|
|
|
|
if(aMap1.Contains(aS1))
|
|
continue;
|
|
aSeq1.Append(aS1);
|
|
aMap1.Add(aS1);
|
|
}
|
|
|
|
for(; anExp2.More(); anExp2.Next()) {
|
|
const TopoDS_Shape& aS2 = anExp2.Current();
|
|
if(aMap2.Contains(aS2))
|
|
continue;
|
|
aSeq2.Append(aS2);
|
|
aMap2.Add(aS2);
|
|
}
|
|
|
|
TColStd_Array2OfBoolean anArrayOfFlag(1, aSeq1.Length(), 1, aSeq2.Length());
|
|
Standard_Integer i = 0, j = 0;
|
|
for(i = 1; i <= aSeq1.Length(); i++)
|
|
for(j = 1; j <= aSeq2.Length(); j++)
|
|
anArrayOfFlag.SetValue(i, j, Standard_False);
|
|
|
|
for(i = 1; i <= aSeq1.Length(); i++) {
|
|
const TopoDS_Shape& aS1 = aSeq1.Value(i);
|
|
BOPCol_ListOfShape aListOfS2;
|
|
Standard_Integer nbs = 0;
|
|
|
|
for(j = 1; j <= aSeq2.Length(); j++) {
|
|
const TopoDS_Shape& aS2 = aSeq2.Value(j);
|
|
Standard_Boolean bIsEqual = Standard_False;
|
|
|
|
if(theType == TopAbs_VERTEX) {
|
|
|
|
const TopoDS_Vertex& aV1 = *(TopoDS_Vertex*)&(aS1);
|
|
const TopoDS_Vertex& aV2 = *(TopoDS_Vertex*)&(aS2);
|
|
gp_Pnt aP1 = BRep_Tool::Pnt(aV1);
|
|
gp_Pnt aP2 = BRep_Tool::Pnt(aV2);
|
|
Standard_Real aDist = aP1.Distance(aP2);
|
|
|
|
if(aDist <= (BRep_Tool::Tolerance(aV1) + BRep_Tool::Tolerance(aV2))) {
|
|
bIsEqual = Standard_True;
|
|
}
|
|
}
|
|
else if(theType == TopAbs_EDGE) {
|
|
const TopoDS_Edge& aE1 = *(TopoDS_Edge*)&(aS1);
|
|
const TopoDS_Edge& aE2 = *(TopoDS_Edge*)&(aS2);
|
|
//
|
|
IntTools_EdgeEdge aEE(aE1, aE2);
|
|
//
|
|
aEE.Perform();
|
|
if (aEE.IsDone()) {
|
|
const IntTools_SequenceOfCommonPrts& aCPrts = aEE.CommonParts();
|
|
Standard_Integer ii = 0;
|
|
|
|
for (ii = 1; ii <= aCPrts.Length(); ii++) {
|
|
const IntTools_CommonPrt& aCPart = aCPrts(ii);
|
|
|
|
if (aCPart.Type() == TopAbs_EDGE) {
|
|
bIsEqual = Standard_True;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if(theType == TopAbs_FACE) {
|
|
// not yet implemented!
|
|
}
|
|
|
|
if(bIsEqual) {
|
|
anArrayOfFlag.SetValue(i, j, Standard_True );
|
|
aListOfS2.Append(aS2);
|
|
nbs++;
|
|
}
|
|
}
|
|
|
|
if(nbs > 1) {
|
|
BOPAlgo_CheckResult aResult;
|
|
|
|
aResult.SetShape1(myShape1);
|
|
aResult.SetShape2(myShape2);
|
|
aResult.AddFaultyShape1(aS1);
|
|
BOPCol_ListIteratorOfListOfShape anIt(aListOfS2);
|
|
|
|
for(; anIt.More(); anIt.Next()) {
|
|
aResult.AddFaultyShape2(anIt.Value());
|
|
}
|
|
|
|
aResult.SetCheckStatus(aStatus);
|
|
myResult.Append(aResult);
|
|
|
|
if(myStopOnFirst) {
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
for(i = 1; i <= aSeq2.Length(); i++) {
|
|
const TopoDS_Shape& aS2 = aSeq2.Value(i);
|
|
BOPCol_ListOfShape aListOfS1;
|
|
Standard_Integer nbs = 0;
|
|
|
|
for(j = 1; j <= aSeq1.Length(); j++) {
|
|
const TopoDS_Shape& aS1 = aSeq1.Value(j);
|
|
|
|
if(anArrayOfFlag.Value(j, i)) {
|
|
aListOfS1.Append(aS1);
|
|
nbs++;
|
|
}
|
|
}
|
|
|
|
if(nbs > 1) {
|
|
BOPAlgo_CheckResult aResult;
|
|
|
|
aResult.SetShape1(myShape1);
|
|
aResult.SetShape2(myShape2);
|
|
BOPCol_ListIteratorOfListOfShape anIt(aListOfS1);
|
|
|
|
for(; anIt.More(); anIt.Next()) {
|
|
aResult.AddFaultyShape1(anIt.Value());
|
|
}
|
|
aResult.AddFaultyShape2(aS2);
|
|
|
|
aResult.SetCheckStatus(aStatus);
|
|
myResult.Append(aResult);
|
|
|
|
if(myStopOnFirst) {
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// ================================================================================
|
|
// function: TestMergeVertex
|
|
// purpose:
|
|
// ================================================================================
|
|
void BOPAlgo_ArgumentAnalyzer::TestMergeVertex()
|
|
{
|
|
TestMergeSubShapes(TopAbs_VERTEX);
|
|
}
|
|
|
|
// ================================================================================
|
|
// function: TestMergeEdge
|
|
// purpose:
|
|
// ================================================================================
|
|
void BOPAlgo_ArgumentAnalyzer::TestMergeEdge()
|
|
{
|
|
TestMergeSubShapes(TopAbs_EDGE);
|
|
}
|
|
|
|
// ================================================================================
|
|
// function: TestContinuity
|
|
// purpose:
|
|
// ================================================================================
|
|
void BOPAlgo_ArgumentAnalyzer::TestContinuity()
|
|
{
|
|
Standard_Integer i;
|
|
Standard_Real f, l;
|
|
TopExp_Explorer aExp;
|
|
BOPCol_MapIteratorOfMapOfShape aIt;
|
|
//
|
|
for (i = 0; i < 2; ++i) {
|
|
const TopoDS_Shape& aS = !i ? myShape1 : myShape2;
|
|
if(aS.IsNull()) {
|
|
continue;
|
|
}
|
|
//
|
|
BOPCol_MapOfShape aMS;
|
|
//Edges
|
|
aExp.Init(aS, TopAbs_EDGE);
|
|
for (; aExp.More(); aExp.Next()) {
|
|
const TopoDS_Edge& aE = *(TopoDS_Edge*)&aExp.Current();
|
|
if (BRep_Tool::Degenerated(aE)) {
|
|
continue;
|
|
}
|
|
const Handle(Geom_Curve)& aC = BRep_Tool::Curve(aE, f, l);
|
|
if (aC->Continuity() == GeomAbs_C0) {
|
|
aMS.Add(aE);
|
|
}
|
|
}
|
|
//Faces
|
|
aExp.Init(aS, TopAbs_FACE);
|
|
for (; aExp.More(); aExp.Next()) {
|
|
const TopoDS_Face& aF = *(TopoDS_Face*)&aExp.Current();
|
|
const Handle(Geom_Surface)& aS = BRep_Tool::Surface(aF);
|
|
if (aS->Continuity() == GeomAbs_C0) {
|
|
aMS.Add(aF);
|
|
}
|
|
}
|
|
//
|
|
//add shapes with continuity C0 to result
|
|
aIt.Initialize(aMS);
|
|
for (; aIt.More(); aIt.Next()) {
|
|
const TopoDS_Shape& aFS = aIt.Value();
|
|
BOPAlgo_CheckResult aResult;
|
|
if(i == 0) {
|
|
aResult.SetShape1(myShape1);
|
|
aResult.AddFaultyShape1(aFS);
|
|
} else {
|
|
aResult.SetShape2(myShape2);
|
|
aResult.AddFaultyShape2(aFS);
|
|
}
|
|
aResult.SetCheckStatus(BOPAlgo_GeomAbs_C0);
|
|
myResult.Append(aResult);
|
|
}
|
|
}
|
|
}
|
|
|
|
// ================================================================================
|
|
// function: TestCurveOnSurface
|
|
// purpose:
|
|
// ================================================================================
|
|
void BOPAlgo_ArgumentAnalyzer::TestCurveOnSurface()
|
|
{
|
|
Standard_Integer i;
|
|
Standard_Real aT, aD, aTolE;
|
|
TopExp_Explorer aExpF, aExpE;
|
|
//
|
|
for(i = 0; i < 2; i++) {
|
|
const TopoDS_Shape& aS = (i == 0) ? myShape1 : myShape2;
|
|
if(aS.IsNull()) {
|
|
continue;
|
|
}
|
|
//
|
|
aExpF.Init(aS, TopAbs_FACE);
|
|
for (; aExpF.More(); aExpF.Next()) {
|
|
const TopoDS_Face& aF = *(TopoDS_Face*)&aExpF.Current();
|
|
//
|
|
aExpE.Init(aF, TopAbs_EDGE);
|
|
for (; aExpE.More(); aExpE.Next()) {
|
|
const TopoDS_Edge& aE = *(TopoDS_Edge*)&aExpE.Current();
|
|
//
|
|
if (BOPTools_AlgoTools::ComputeTolerance(aF, aE, aD, aT)) {
|
|
aTolE = BRep_Tool::Tolerance(aE);
|
|
if (aD > aTolE) {
|
|
BOPAlgo_CheckResult aResult;
|
|
aResult.SetCheckStatus(BOPAlgo_InvalidCurveOnSurface);
|
|
if(i == 0) {
|
|
aResult.SetShape1(myShape1);
|
|
aResult.AddFaultyShape1(aE);
|
|
aResult.AddFaultyShape1(aF);
|
|
aResult.SetMaxDistance1(aD);
|
|
aResult.SetMaxParameter1(aT);
|
|
}
|
|
else {
|
|
aResult.SetShape2(myShape2);
|
|
aResult.AddFaultyShape2(aE);
|
|
aResult.AddFaultyShape2(aF);
|
|
aResult.SetMaxDistance2(aD);
|
|
aResult.SetMaxParameter2(aT);
|
|
}
|
|
myResult.Append(aResult);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|