mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-04-04 18:06:22 +03:00
0026180: Modeling Algorithms - Provide shape self-intersection detector
Small correction of test case for issue CR26180 Fix GCC compilation warnings.
This commit is contained in:
parent
d5f061b671
commit
ae9a414af0
48
src/BRepExtrema/BRepExtrema_ElementFilter.hxx
Normal file
48
src/BRepExtrema/BRepExtrema_ElementFilter.hxx
Normal file
@ -0,0 +1,48 @@
|
||||
// Created on: 2015-05-07
|
||||
// Created by: Denis BOGOLEPOV
|
||||
// Copyright (c) 2015 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.
|
||||
|
||||
#ifndef _BRepExtrema_ElementFilter_HeaderFile
|
||||
#define _BRepExtrema_ElementFilter_HeaderFile
|
||||
|
||||
#include <Standard_TypeDef.hxx>
|
||||
|
||||
//! Filtering tool used to detect if two given mesh elements
|
||||
//! should be tested for overlapping/intersection or not.
|
||||
struct BRepExtrema_ElementFilter
|
||||
{
|
||||
//! Result of filtering function.
|
||||
enum FilterResult
|
||||
{
|
||||
NoCheck,
|
||||
Overlap,
|
||||
DoCheck
|
||||
};
|
||||
|
||||
//! Releases resources of element filter.
|
||||
virtual ~BRepExtrema_ElementFilter()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
//! Checks if two mesh elements should be tested for overlapping/intersection
|
||||
//! (used for detection correct/incorrect cases of shared edges and vertices).
|
||||
virtual FilterResult PreCheckElements (const Standard_Integer /*theIndex1*/,
|
||||
const Standard_Integer /*theIndex2*/)
|
||||
{
|
||||
return DoCheck;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // _BRepExtrema_ElementFilter_HeaderFile
|
@ -0,0 +1,20 @@
|
||||
// Created on: 2015-05-13
|
||||
// Created by: Denis BOGOLEPOV
|
||||
// Copyright (c) 2015 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 <NCollection_DataMap.hxx>
|
||||
#include <TColStd_PackedMapOfInteger.hxx>
|
||||
|
||||
//! Set of overlapped sub-shapes.
|
||||
typedef NCollection_DataMap<Standard_Integer, TColStd_PackedMapOfInteger> BRepExtrema_MapOfIntegerPackedMapOfInteger;
|
831
src/BRepExtrema/BRepExtrema_OverlapTool.cxx
Normal file
831
src/BRepExtrema/BRepExtrema_OverlapTool.cxx
Normal file
@ -0,0 +1,831 @@
|
||||
// Created on: 2015-04-26
|
||||
// Created by: Denis BOGOLEPOV
|
||||
// Copyright (c) 2015 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 <BRepExtrema_OverlapTool.hxx>
|
||||
|
||||
//=======================================================================
|
||||
//function : BRepExtrema_OverlapTool
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
BRepExtrema_OverlapTool::BRepExtrema_OverlapTool()
|
||||
: myFilter (NULL)
|
||||
{
|
||||
myIsDone = Standard_False;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : BRepExtrema_OverlapTool
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
BRepExtrema_OverlapTool::BRepExtrema_OverlapTool (const Handle(BRepExtrema_TriangleSet)& theSet1,
|
||||
const Handle(BRepExtrema_TriangleSet)& theSet2)
|
||||
: myFilter (NULL)
|
||||
{
|
||||
LoadTriangleSets (theSet1, theSet2);
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : LoadTriangleSets
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
void BRepExtrema_OverlapTool::LoadTriangleSets (const Handle(BRepExtrema_TriangleSet)& theSet1,
|
||||
const Handle(BRepExtrema_TriangleSet)& theSet2)
|
||||
{
|
||||
mySet1 = theSet1;
|
||||
mySet2 = theSet2;
|
||||
|
||||
myIsDone = Standard_False;
|
||||
}
|
||||
|
||||
#ifndef DBL_EPSILON
|
||||
#define DBL_EPSILON std::numeric_limits<Standard_Real>::epsilon()
|
||||
#endif
|
||||
|
||||
namespace
|
||||
{
|
||||
//! Tool class to describe stack item in traverse function.
|
||||
struct BRepExtrema_StackItem
|
||||
{
|
||||
Standard_Integer Node1;
|
||||
Standard_Integer Node2;
|
||||
|
||||
BRepExtrema_StackItem (const Standard_Integer theNode1 = 0,
|
||||
const Standard_Integer theNode2 = 0)
|
||||
: Node1 (theNode1),
|
||||
Node2 (theNode2)
|
||||
{
|
||||
//
|
||||
}
|
||||
};
|
||||
|
||||
//! Bounding triangular prism for specified triangle.
|
||||
class BRepExtrema_BoundingPrism
|
||||
{
|
||||
public:
|
||||
|
||||
//! Vertices of the prism.
|
||||
BVH_Vec3d Vertices[6];
|
||||
|
||||
//! Edges of the prism.
|
||||
BVH_Vec3d Edges[3];
|
||||
|
||||
//! Normal to prism caps.
|
||||
BVH_Vec3d Normal;
|
||||
|
||||
//! Normals to prism edges.
|
||||
BVH_Vec3d EdgeNormals[3];
|
||||
|
||||
//! Is prism initialized?
|
||||
Standard_Boolean IsInited;
|
||||
|
||||
public:
|
||||
|
||||
//! Creates uninitialized bounding prism.
|
||||
BRepExtrema_BoundingPrism() : IsInited (Standard_False)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
//! Creates new bounding prism for the given triangle.
|
||||
BRepExtrema_BoundingPrism (const BVH_Vec3d& theVertex0,
|
||||
const BVH_Vec3d& theVertex1,
|
||||
const BVH_Vec3d& theVertex2,
|
||||
const Standard_Real theDeflect)
|
||||
{
|
||||
Init (theVertex0,
|
||||
theVertex1,
|
||||
theVertex2,
|
||||
theDeflect);
|
||||
}
|
||||
|
||||
//! Calculates bounding prism for the given triangle.
|
||||
void Init (const BVH_Vec3d& theVertex0,
|
||||
const BVH_Vec3d& theVertex1,
|
||||
const BVH_Vec3d& theVertex2,
|
||||
const Standard_Real theDeflect)
|
||||
{
|
||||
Edges[0] = theVertex1 - theVertex0;
|
||||
Edges[1] = theVertex2 - theVertex0;
|
||||
Edges[2] = theVertex2 - theVertex1;
|
||||
|
||||
Normal = BVH_Vec3d::Cross (Edges[0], Edges[1]);
|
||||
|
||||
EdgeNormals[0] = BVH_Vec3d::Cross (Edges[0], Normal);
|
||||
EdgeNormals[1] = BVH_Vec3d::Cross (Edges[1], Normal);
|
||||
EdgeNormals[2] = BVH_Vec3d::Cross (Edges[2], Normal);
|
||||
|
||||
EdgeNormals[0] *= 1.0 / Max (EdgeNormals[0].Modulus(), Precision::Confusion());
|
||||
EdgeNormals[1] *= 1.0 / Max (EdgeNormals[1].Modulus(), Precision::Confusion());
|
||||
EdgeNormals[2] *= 1.0 / Max (EdgeNormals[2].Modulus(), Precision::Confusion());
|
||||
|
||||
const BVH_Vec3d aDirect01 = EdgeNormals[0] - EdgeNormals[1];
|
||||
const BVH_Vec3d aDirect02 = EdgeNormals[0] + EdgeNormals[2];
|
||||
const BVH_Vec3d aDirect12 = EdgeNormals[2] - EdgeNormals[1];
|
||||
|
||||
Vertices[0] = Vertices[3] = theVertex0 + aDirect01 * (theDeflect / aDirect01.Dot (EdgeNormals[0]));
|
||||
Vertices[1] = Vertices[4] = theVertex1 + aDirect02 * (theDeflect / aDirect02.Dot (EdgeNormals[2]));
|
||||
Vertices[2] = Vertices[5] = theVertex2 + aDirect12 * (theDeflect / aDirect12.Dot (EdgeNormals[2]));
|
||||
|
||||
const BVH_Vec3d aNormOffset = Normal * (theDeflect / Max (Normal.Modulus(), Precision::Confusion()));
|
||||
|
||||
for (Standard_Integer aVertIdx = 0; aVertIdx < 3; ++aVertIdx)
|
||||
{
|
||||
Vertices[aVertIdx + 0] += aNormOffset;
|
||||
Vertices[aVertIdx + 3] -= aNormOffset;
|
||||
}
|
||||
|
||||
IsInited = Standard_True;
|
||||
}
|
||||
|
||||
//! Checks if two prisms are separated along the given axis.
|
||||
Standard_Boolean Separated (const BRepExtrema_BoundingPrism& thePrism, const BVH_Vec3d& theAxis) const
|
||||
{
|
||||
Standard_Real aMin1 = DBL_MAX;
|
||||
Standard_Real aMax1 = -DBL_MAX;
|
||||
|
||||
Standard_Real aMin2 = DBL_MAX;
|
||||
Standard_Real aMax2 = -DBL_MAX;
|
||||
|
||||
for (Standard_Integer aVertIdx = 0; aVertIdx < 6; ++aVertIdx)
|
||||
{
|
||||
const Standard_Real aProj1 = Vertices[aVertIdx].Dot (theAxis);
|
||||
|
||||
aMin1 = Min (aMin1, aProj1);
|
||||
aMax1 = Max (aMax1, aProj1);
|
||||
|
||||
const Standard_Real aProj2 = thePrism.Vertices[aVertIdx].Dot (theAxis);
|
||||
|
||||
aMin2 = Min (aMin2, aProj2);
|
||||
aMax2 = Max (aMax2, aProj2);
|
||||
|
||||
if (aMin1 <= aMax2 && aMax1 >= aMin2)
|
||||
{
|
||||
return Standard_False;
|
||||
}
|
||||
}
|
||||
|
||||
return aMin1 > aMax2 || aMax1 < aMin2;
|
||||
}
|
||||
};
|
||||
|
||||
// =======================================================================
|
||||
// function : sign
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
Standard_Real sign (const BVH_Vec3d& theVertex0,
|
||||
const BVH_Vec3d& theVertex1,
|
||||
const BVH_Vec3d& theVertex2,
|
||||
const Standard_Integer theX,
|
||||
const Standard_Integer theY)
|
||||
{
|
||||
return (theVertex0[theX] - theVertex2[theX]) * (theVertex1[theY] - theVertex2[theY]) -
|
||||
(theVertex1[theX] - theVertex2[theX]) * (theVertex0[theY] - theVertex2[theY]);
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : pointInTriangle
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
Standard_Boolean pointInTriangle (const BVH_Vec3d& theTestPnt,
|
||||
const BVH_Vec3d& theTrgVtx0,
|
||||
const BVH_Vec3d& theTrgVtx1,
|
||||
const BVH_Vec3d& theTrgVtx2,
|
||||
const Standard_Integer theX,
|
||||
const Standard_Integer theY)
|
||||
{
|
||||
const Standard_Boolean aSign0 = sign (theTestPnt, theTrgVtx0, theTrgVtx1, theX, theY) <= 0.0;
|
||||
const Standard_Boolean aSign1 = sign (theTestPnt, theTrgVtx1, theTrgVtx2, theX, theY) <= 0.0;
|
||||
const Standard_Boolean aSign2 = sign (theTestPnt, theTrgVtx2, theTrgVtx0, theX, theY) <= 0.0;
|
||||
|
||||
return (aSign0 == aSign1) && (aSign1 == aSign2);
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : segmentsIntersected
|
||||
// purpose : Checks if two line segments are intersected
|
||||
// =======================================================================
|
||||
Standard_Boolean segmentsIntersected (const BVH_Vec2d& theOriginSeg0,
|
||||
const BVH_Vec2d& theOriginSeg1,
|
||||
const BVH_Vec2d& theDirectSeg0,
|
||||
const BVH_Vec2d& theDirectSeg1)
|
||||
{
|
||||
const Standard_Real aDet = -theDirectSeg1.x() * theDirectSeg0.y() +
|
||||
theDirectSeg0.x() * theDirectSeg1.y();
|
||||
|
||||
if (fabs (aDet) < DBL_EPSILON) // segments are parallel
|
||||
{
|
||||
const BVH_Vec2d aDirect = theDirectSeg0 * (1.0 / theDirectSeg0.Modulus());
|
||||
|
||||
const Standard_Real aEdge0Time0 = theOriginSeg0.Dot (aDirect);
|
||||
const Standard_Real aEdge1Time0 = theOriginSeg1.Dot (aDirect);
|
||||
|
||||
const Standard_Real aEdge0Time1 = aEdge0Time0 + theDirectSeg0.Dot (aDirect);
|
||||
const Standard_Real aEdge1Time1 = aEdge1Time0 + theDirectSeg1.Dot (aDirect);
|
||||
|
||||
const Standard_Real aEdge0Min = Min (aEdge0Time0, aEdge0Time1);
|
||||
const Standard_Real aEdge1Min = Min (aEdge1Time0, aEdge1Time1);
|
||||
const Standard_Real aEdge0Max = Max (aEdge0Time0, aEdge0Time1);
|
||||
const Standard_Real aEdge1Max = Max (aEdge1Time0, aEdge1Time1);
|
||||
|
||||
if (Max (aEdge0Min, aEdge1Min) > Min (aEdge0Max, aEdge1Max))
|
||||
{
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
const BVH_Vec2d aNormal (-aDirect.y(), aDirect.x());
|
||||
|
||||
return fabs (theOriginSeg0.Dot (aNormal) - theOriginSeg1.Dot (aNormal)) < DBL_EPSILON;
|
||||
}
|
||||
|
||||
const BVH_Vec2d aDelta = theOriginSeg0 - theOriginSeg1;
|
||||
|
||||
const Standard_Real aU = (-theDirectSeg0.y() * aDelta.x() + theDirectSeg0.x() * aDelta.y()) / aDet;
|
||||
const Standard_Real aV = ( theDirectSeg1.x() * aDelta.y() - theDirectSeg1.y() * aDelta.x()) / aDet;
|
||||
|
||||
return aU >= 0.0 && aU <= 1.0 && aV >= 0.0 && aV <= 1.0;
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : trianglesIntersected
|
||||
// purpose : Checks if two triangles are intersected
|
||||
// ("A Fast Triangle-Triangle Intersection Test" by T. Moller)
|
||||
// =======================================================================
|
||||
Standard_Boolean trianglesIntersected (const BVH_Vec3d& theTrng0Vert0,
|
||||
const BVH_Vec3d& theTrng0Vert1,
|
||||
const BVH_Vec3d& theTrng0Vert2,
|
||||
const BVH_Vec3d& theTrng1Vert0,
|
||||
const BVH_Vec3d& theTrng1Vert1,
|
||||
const BVH_Vec3d& theTrng1Vert2)
|
||||
{
|
||||
const BVH_Vec3d aTrng1Normal = BVH_Vec3d::Cross (theTrng1Vert1 - theTrng1Vert0,
|
||||
theTrng1Vert2 - theTrng1Vert0).Normalized();
|
||||
|
||||
const Standard_Real aTrng1PlaneDist = aTrng1Normal.Dot (-theTrng1Vert0);
|
||||
|
||||
Standard_Real aDistTrng0Vert0 = aTrng1Normal.Dot (theTrng0Vert0) + aTrng1PlaneDist;
|
||||
Standard_Real aDistTrng0Vert1 = aTrng1Normal.Dot (theTrng0Vert1) + aTrng1PlaneDist;
|
||||
Standard_Real aDistTrng0Vert2 = aTrng1Normal.Dot (theTrng0Vert2) + aTrng1PlaneDist;
|
||||
|
||||
if ((aDistTrng0Vert0 < 0.0 && aDistTrng0Vert1 < 0.0 && aDistTrng0Vert2 < 0.0)
|
||||
|| (aDistTrng0Vert0 > 0.0 && aDistTrng0Vert1 > 0.0 && aDistTrng0Vert2 > 0.0))
|
||||
{
|
||||
return Standard_False; // 1st triangle lies on one side of the 2nd triangle
|
||||
}
|
||||
|
||||
if (fabs (aDistTrng0Vert0) > Precision::Confusion()
|
||||
|| fabs (aDistTrng0Vert1) > Precision::Confusion()
|
||||
|| fabs (aDistTrng0Vert2) > Precision::Confusion()) // general 3D case
|
||||
{
|
||||
const BVH_Vec3d aTrng0Normal = BVH_Vec3d::Cross (theTrng0Vert1 - theTrng0Vert0,
|
||||
theTrng0Vert2 - theTrng0Vert0).Normalized();
|
||||
|
||||
const Standard_Real aTrng0PlaneDist = aTrng0Normal.Dot (-theTrng0Vert0);
|
||||
|
||||
Standard_Real aDistTrng1Vert0 = aTrng0Normal.Dot (theTrng1Vert0) + aTrng0PlaneDist;
|
||||
Standard_Real aDistTrng1Vert1 = aTrng0Normal.Dot (theTrng1Vert1) + aTrng0PlaneDist;
|
||||
Standard_Real aDistTrng1Vert2 = aTrng0Normal.Dot (theTrng1Vert2) + aTrng0PlaneDist;
|
||||
|
||||
if ((aDistTrng1Vert0 < 0.0 && aDistTrng1Vert1 < 0.0 && aDistTrng1Vert2 < 0.0)
|
||||
|| (aDistTrng1Vert0 > 0.0 && aDistTrng1Vert1 > 0.0 && aDistTrng1Vert2 > 0.0))
|
||||
{
|
||||
return Standard_False; // 2nd triangle lies on one side of the 1st triangle
|
||||
}
|
||||
|
||||
const BVH_Vec3d aCrossLine = BVH_Vec3d::Cross (aTrng0Normal,
|
||||
aTrng1Normal);
|
||||
|
||||
Standard_Real aProjTrng0Vert0 = theTrng0Vert0.Dot (aCrossLine);
|
||||
Standard_Real aProjTrng0Vert1 = theTrng0Vert1.Dot (aCrossLine);
|
||||
Standard_Real aProjTrng0Vert2 = theTrng0Vert2.Dot (aCrossLine);
|
||||
|
||||
if (aDistTrng0Vert0 * aDistTrng0Vert1 > 0.0)
|
||||
{
|
||||
std::swap (aDistTrng0Vert1, aDistTrng0Vert2);
|
||||
std::swap (aProjTrng0Vert1, aProjTrng0Vert2);
|
||||
}
|
||||
else if (aDistTrng0Vert1 * aDistTrng0Vert2 > 0.0)
|
||||
{
|
||||
std::swap (aDistTrng0Vert1, aDistTrng0Vert0);
|
||||
std::swap (aProjTrng0Vert1, aProjTrng0Vert0);
|
||||
}
|
||||
|
||||
Standard_Real aTime1 = fabs (aDistTrng0Vert0) <= DBL_EPSILON ? aProjTrng0Vert0 :
|
||||
aProjTrng0Vert0 + (aProjTrng0Vert1 - aProjTrng0Vert0) * aDistTrng0Vert0 / (aDistTrng0Vert0 - aDistTrng0Vert1);
|
||||
Standard_Real aTime2 = fabs (aDistTrng0Vert2) <= DBL_EPSILON ? aProjTrng0Vert2 :
|
||||
aProjTrng0Vert2 + (aProjTrng0Vert1 - aProjTrng0Vert2) * aDistTrng0Vert2 / (aDistTrng0Vert2 - aDistTrng0Vert1);
|
||||
|
||||
const Standard_Real aTimeMin1 = Min (aTime1, aTime2);
|
||||
const Standard_Real aTimeMax1 = Max (aTime1, aTime2);
|
||||
|
||||
Standard_Real aProjTrng1Vert0 = theTrng1Vert0.Dot (aCrossLine);
|
||||
Standard_Real aProjTrng1Vert1 = theTrng1Vert1.Dot (aCrossLine);
|
||||
Standard_Real aProjTrng1Vert2 = theTrng1Vert2.Dot (aCrossLine);
|
||||
|
||||
if (aDistTrng1Vert0 * aDistTrng1Vert1 > 0.0)
|
||||
{
|
||||
std::swap (aDistTrng1Vert1, aDistTrng1Vert2);
|
||||
std::swap (aProjTrng1Vert1, aProjTrng1Vert2);
|
||||
}
|
||||
else if (aDistTrng1Vert1 * aDistTrng1Vert2 > 0.0)
|
||||
{
|
||||
std::swap (aDistTrng1Vert1, aDistTrng1Vert0);
|
||||
std::swap (aProjTrng1Vert1, aProjTrng1Vert0);
|
||||
}
|
||||
|
||||
aTime1 = fabs (aDistTrng1Vert0) <= DBL_EPSILON ? aProjTrng1Vert0 :
|
||||
aProjTrng1Vert0 + (aProjTrng1Vert1 - aProjTrng1Vert0) * aDistTrng1Vert0 / (aDistTrng1Vert0 - aDistTrng1Vert1);
|
||||
aTime2 = fabs (aDistTrng1Vert2) <= DBL_EPSILON ? aProjTrng1Vert2 :
|
||||
aProjTrng1Vert2 + (aProjTrng1Vert1 - aProjTrng1Vert2) * aDistTrng1Vert2 / (aDistTrng1Vert2 - aDistTrng1Vert1);
|
||||
|
||||
const Standard_Real aTimeMin2 = Min (aTime1, aTime2);
|
||||
const Standard_Real aTimeMax2 = Max (aTime1, aTime2);
|
||||
|
||||
aTime1 = Max (aTimeMin1, aTimeMin2);
|
||||
aTime2 = Min (aTimeMax1, aTimeMax2);
|
||||
|
||||
return aTime1 <= aTime2; // intervals intersected --> triangles overlapped
|
||||
}
|
||||
else // triangles are co-planar
|
||||
{
|
||||
Standard_Integer anX;
|
||||
Standard_Integer anY;
|
||||
|
||||
if (fabs (aTrng1Normal[0]) > fabs (aTrng1Normal[1]))
|
||||
{
|
||||
anX = fabs (aTrng1Normal[0]) > fabs (aTrng1Normal[2]) ? 1 : 0;
|
||||
anY = fabs (aTrng1Normal[0]) > fabs (aTrng1Normal[2]) ? 2 : 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
anX = fabs (aTrng1Normal[1]) > fabs (aTrng1Normal[2]) ? 0 : 0;
|
||||
anY = fabs (aTrng1Normal[1]) > fabs (aTrng1Normal[2]) ? 2 : 1;
|
||||
}
|
||||
|
||||
const BVH_Vec2d aOriginSeg0 [] = {BVH_Vec2d (theTrng0Vert0[anX], theTrng0Vert0[anY]),
|
||||
BVH_Vec2d (theTrng0Vert1[anX], theTrng0Vert1[anY]),
|
||||
BVH_Vec2d (theTrng0Vert2[anX], theTrng0Vert2[anY]) };
|
||||
|
||||
const BVH_Vec2d aDirectSeg0 [] = {aOriginSeg0[1] - aOriginSeg0[0],
|
||||
aOriginSeg0[2] - aOriginSeg0[1],
|
||||
aOriginSeg0[0] - aOriginSeg0[2] };
|
||||
|
||||
const BVH_Vec2d aOriginSeg1 [] = {BVH_Vec2d (theTrng1Vert0[anX], theTrng1Vert0[anY]),
|
||||
BVH_Vec2d (theTrng1Vert1[anX], theTrng1Vert1[anY]),
|
||||
BVH_Vec2d (theTrng1Vert2[anX], theTrng1Vert2[anY]) };
|
||||
|
||||
const BVH_Vec2d aDirectSeg1 [] = {aOriginSeg1[1] - aOriginSeg1[0],
|
||||
aOriginSeg1[2] - aOriginSeg1[1],
|
||||
aOriginSeg1[0] - aOriginSeg1[2] };
|
||||
|
||||
for (Standard_Integer aTrg0Edge = 0; aTrg0Edge < 3; ++aTrg0Edge)
|
||||
{
|
||||
for (Standard_Integer aTrg1Edge = 0; aTrg1Edge < 3; ++aTrg1Edge)
|
||||
{
|
||||
if (segmentsIntersected (aOriginSeg0[aTrg0Edge],
|
||||
aOriginSeg1[aTrg1Edge],
|
||||
aDirectSeg0[aTrg0Edge],
|
||||
aDirectSeg1[aTrg1Edge]))
|
||||
{
|
||||
return Standard_True; // edges intersected --> triangles overlapped
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pointInTriangle (theTrng1Vert0,
|
||||
theTrng0Vert0,
|
||||
theTrng0Vert1,
|
||||
theTrng0Vert2,
|
||||
anX,
|
||||
anY))
|
||||
{
|
||||
return Standard_True; // 1st triangle inside 2nd --> triangles overlapped
|
||||
}
|
||||
|
||||
if (pointInTriangle (theTrng0Vert0,
|
||||
theTrng1Vert0,
|
||||
theTrng1Vert1,
|
||||
theTrng1Vert2,
|
||||
anX,
|
||||
anY))
|
||||
{
|
||||
return Standard_True; // 2nd triangle inside 1st --> triangles overlapped
|
||||
}
|
||||
}
|
||||
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : prismsIntersected
|
||||
// purpose : Checks if two triangular prisms are intersected
|
||||
// (test uses SAT - Separating Axis Theorem)
|
||||
// =======================================================================
|
||||
Standard_Boolean prismsIntersected (const BRepExtrema_BoundingPrism& thePrism1,
|
||||
const BRepExtrema_BoundingPrism& thePrism2)
|
||||
{
|
||||
if (thePrism1.Separated (thePrism2, thePrism1.Normal))
|
||||
{
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
if (thePrism1.Separated (thePrism2, thePrism2.Normal))
|
||||
{
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
for (Standard_Integer anIdx = 0; anIdx < 3; ++anIdx)
|
||||
{
|
||||
if (thePrism1.Separated (thePrism2, thePrism1.EdgeNormals[anIdx]))
|
||||
{
|
||||
return Standard_False;
|
||||
}
|
||||
}
|
||||
|
||||
for (Standard_Integer anIdx = 0; anIdx < 3; ++anIdx)
|
||||
{
|
||||
if (thePrism1.Separated (thePrism2, thePrism2.EdgeNormals[anIdx]))
|
||||
{
|
||||
return Standard_False;
|
||||
}
|
||||
}
|
||||
|
||||
for (Standard_Integer anIdx1 = 0; anIdx1 < 4; ++anIdx1)
|
||||
{
|
||||
const BVH_Vec3d& aEdge1 = (anIdx1 == 3) ? thePrism1.Normal : thePrism1.Edges[anIdx1];
|
||||
|
||||
for (Standard_Integer anIdx2 = 0; anIdx2 < 4; ++anIdx2)
|
||||
{
|
||||
const BVH_Vec3d& aEdge2 = (anIdx2 == 3) ? thePrism2.Normal : thePrism2.Edges[anIdx2];
|
||||
|
||||
if (thePrism1.Separated (thePrism2, BVH_Vec3d::Cross (aEdge1, aEdge2)))
|
||||
{
|
||||
return Standard_False;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Standard_True;
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : overlapBoxes
|
||||
// purpose : Checks if two boxes (AABBs) are overlapped
|
||||
// =======================================================================
|
||||
inline Standard_Boolean overlapBoxes (const BVH_Vec3d& theBoxMin1,
|
||||
const BVH_Vec3d& theBoxMax1,
|
||||
const BVH_Vec3d& theBoxMin2,
|
||||
const BVH_Vec3d& theBoxMax2,
|
||||
const Standard_Real theTolerance)
|
||||
{
|
||||
// Check for overlap
|
||||
return !(theBoxMin1.x() > theBoxMax2.x() + theTolerance ||
|
||||
theBoxMax1.x() < theBoxMin2.x() - theTolerance ||
|
||||
theBoxMin1.y() > theBoxMax2.y() + theTolerance ||
|
||||
theBoxMax1.y() < theBoxMin2.y() - theTolerance ||
|
||||
theBoxMin1.z() > theBoxMax2.z() + theTolerance ||
|
||||
theBoxMax1.z() < theBoxMin2.z() - theTolerance);
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : getSetOfFaces
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
TColStd_PackedMapOfInteger& getSetOfFaces (
|
||||
BRepExtrema_MapOfIntegerPackedMapOfInteger& theFaces, const Standard_Integer theFaceIdx)
|
||||
{
|
||||
if (!theFaces.IsBound (theFaceIdx))
|
||||
{
|
||||
theFaces.Bind (theFaceIdx, TColStd_PackedMapOfInteger());
|
||||
}
|
||||
|
||||
return theFaces.ChangeFind (theFaceIdx);
|
||||
}
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : intersectTriangleRangesExact
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
void BRepExtrema_OverlapTool::intersectTriangleRangesExact (const BVH_Vec4i& theLeaf1,
|
||||
const BVH_Vec4i& theLeaf2)
|
||||
{
|
||||
for (Standard_Integer aTrgIdx1 = theLeaf1.y(); aTrgIdx1 <= theLeaf1.z(); ++aTrgIdx1)
|
||||
{
|
||||
const Standard_Integer aFaceIdx1 = mySet1->GetFaceID (aTrgIdx1);
|
||||
|
||||
BVH_Vec3d aTrg1Vert1;
|
||||
BVH_Vec3d aTrg1Vert2;
|
||||
BVH_Vec3d aTrg1Vert3;
|
||||
|
||||
mySet1->GetVertices (aTrgIdx1,
|
||||
aTrg1Vert1,
|
||||
aTrg1Vert2,
|
||||
aTrg1Vert3);
|
||||
|
||||
const Standard_Boolean aIsInSet = myOverlapSubShapes1.IsBound (aFaceIdx1);
|
||||
|
||||
for (Standard_Integer aTrgIdx2 = theLeaf2.y(); aTrgIdx2 <= theLeaf2.z(); ++aTrgIdx2)
|
||||
{
|
||||
const Standard_Integer aFaceIdx2 = mySet2->GetFaceID (aTrgIdx2);
|
||||
|
||||
if (aIsInSet && myOverlapSubShapes1.Find (aFaceIdx1).Contains (aFaceIdx2))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
BRepExtrema_ElementFilter::FilterResult aResult = myFilter == NULL ?
|
||||
BRepExtrema_ElementFilter::DoCheck : myFilter->PreCheckElements (aTrgIdx1, aTrgIdx2);
|
||||
|
||||
if (aResult == BRepExtrema_ElementFilter::Overlap)
|
||||
{
|
||||
getSetOfFaces (myOverlapSubShapes1, aFaceIdx1).Add (aFaceIdx2);
|
||||
getSetOfFaces (myOverlapSubShapes2, aFaceIdx2).Add (aFaceIdx1);
|
||||
|
||||
#ifdef OVERLAP_TOOL_OUTPUT_TRIANGLES
|
||||
if (mySet1 == mySet2)
|
||||
{
|
||||
myOverlapTriangles1.Add (aTrgIdx1);
|
||||
myOverlapTriangles1.Add (aTrgIdx2);
|
||||
}
|
||||
else
|
||||
{
|
||||
myOverlapTriangles1.Add (aTrgIdx1);
|
||||
myOverlapTriangles2.Add (aTrgIdx2);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else if (aResult == BRepExtrema_ElementFilter::DoCheck)
|
||||
{
|
||||
BVH_Vec3d aTrg2Vert1;
|
||||
BVH_Vec3d aTrg2Vert2;
|
||||
BVH_Vec3d aTrg2Vert3;
|
||||
|
||||
mySet2->GetVertices (aTrgIdx2, aTrg2Vert1, aTrg2Vert2, aTrg2Vert3);
|
||||
|
||||
if (trianglesIntersected (aTrg1Vert1,
|
||||
aTrg1Vert2,
|
||||
aTrg1Vert3,
|
||||
aTrg2Vert1,
|
||||
aTrg2Vert2,
|
||||
aTrg2Vert3))
|
||||
{
|
||||
getSetOfFaces (myOverlapSubShapes1, aFaceIdx1).Add (aFaceIdx2);
|
||||
getSetOfFaces (myOverlapSubShapes2, aFaceIdx2).Add (aFaceIdx1);
|
||||
|
||||
#ifdef OVERLAP_TOOL_OUTPUT_TRIANGLES
|
||||
if (mySet1 == mySet2)
|
||||
{
|
||||
myOverlapTriangles1.Add (aTrgIdx1);
|
||||
myOverlapTriangles1.Add (aTrgIdx2);
|
||||
}
|
||||
else
|
||||
{
|
||||
myOverlapTriangles1.Add (aTrgIdx1);
|
||||
myOverlapTriangles2.Add (aTrgIdx2);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : intersectTriangleRangesToler
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
void BRepExtrema_OverlapTool::intersectTriangleRangesToler (const BVH_Vec4i& theLeaf1,
|
||||
const BVH_Vec4i& theLeaf2,
|
||||
const Standard_Real theToler)
|
||||
{
|
||||
for (Standard_Integer aTrgIdx1 = theLeaf1.y(); aTrgIdx1 <= theLeaf1.z(); ++aTrgIdx1)
|
||||
{
|
||||
const Standard_Integer aFaceIdx1 = mySet1->GetFaceID (aTrgIdx1);
|
||||
|
||||
BVH_Vec3d aTrg1Vert1;
|
||||
BVH_Vec3d aTrg1Vert2;
|
||||
BVH_Vec3d aTrg1Vert3;
|
||||
|
||||
mySet1->GetVertices (aTrgIdx1,
|
||||
aTrg1Vert1,
|
||||
aTrg1Vert2,
|
||||
aTrg1Vert3);
|
||||
|
||||
BRepExtrema_BoundingPrism aPrism1; // not initialized
|
||||
|
||||
const Standard_Boolean aIsInSet = myOverlapSubShapes1.IsBound (aFaceIdx1);
|
||||
|
||||
for (Standard_Integer aTrgIdx2 = theLeaf2.y(); aTrgIdx2 <= theLeaf2.z(); ++aTrgIdx2)
|
||||
{
|
||||
const Standard_Integer aFaceIdx2 = mySet2->GetFaceID (aTrgIdx2);
|
||||
|
||||
if (aIsInSet && myOverlapSubShapes1.Find (aFaceIdx1).Contains (aFaceIdx2))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
BRepExtrema_ElementFilter::FilterResult aResult = myFilter == NULL ?
|
||||
BRepExtrema_ElementFilter::DoCheck : myFilter->PreCheckElements (aTrgIdx1, aTrgIdx2);
|
||||
|
||||
if (aResult == BRepExtrema_ElementFilter::Overlap)
|
||||
{
|
||||
getSetOfFaces (myOverlapSubShapes1, aFaceIdx1).Add (aFaceIdx2);
|
||||
getSetOfFaces (myOverlapSubShapes2, aFaceIdx2).Add (aFaceIdx1);
|
||||
|
||||
#ifdef OVERLAP_TOOL_OUTPUT_TRIANGLES
|
||||
if (mySet1 == mySet2)
|
||||
{
|
||||
myOverlapTriangles1.Add (aTrgIdx1);
|
||||
myOverlapTriangles1.Add (aTrgIdx2);
|
||||
}
|
||||
else
|
||||
{
|
||||
myOverlapTriangles1.Add (aTrgIdx1);
|
||||
myOverlapTriangles2.Add (aTrgIdx2);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else if (aResult == BRepExtrema_ElementFilter::DoCheck)
|
||||
{
|
||||
if (!aPrism1.IsInited)
|
||||
{
|
||||
aPrism1.Init (aTrg1Vert1, aTrg1Vert2, aTrg1Vert3, theToler);
|
||||
}
|
||||
|
||||
BVH_Vec3d aTrg2Vert1;
|
||||
BVH_Vec3d aTrg2Vert2;
|
||||
BVH_Vec3d aTrg2Vert3;
|
||||
|
||||
mySet2->GetVertices (aTrgIdx2,
|
||||
aTrg2Vert1,
|
||||
aTrg2Vert2,
|
||||
aTrg2Vert3);
|
||||
|
||||
BRepExtrema_BoundingPrism aPrism2 (aTrg2Vert1,
|
||||
aTrg2Vert2,
|
||||
aTrg2Vert3,
|
||||
theToler);
|
||||
|
||||
if (prismsIntersected (aPrism1, aPrism2))
|
||||
{
|
||||
getSetOfFaces (myOverlapSubShapes1, aFaceIdx1).Add (aFaceIdx2);
|
||||
getSetOfFaces (myOverlapSubShapes2, aFaceIdx2).Add (aFaceIdx1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : Perform
|
||||
//purpose : Performs search for overlapped faces
|
||||
//=======================================================================
|
||||
void BRepExtrema_OverlapTool::Perform (const Standard_Real theTolerance)
|
||||
{
|
||||
if (mySet1.IsNull() || mySet2.IsNull())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
BRepExtrema_StackItem aStack[96];
|
||||
|
||||
const NCollection_Handle<BVH_Tree<Standard_Real, 3> >& aBVH1 = mySet1->BVH();
|
||||
const NCollection_Handle<BVH_Tree<Standard_Real, 3> >& aBVH2 = mySet2->BVH();
|
||||
|
||||
if (aBVH1.IsNull() || aBVH2.IsNull())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
BRepExtrema_StackItem aNodes; // current pair of nodes
|
||||
|
||||
Standard_Integer aHead = -1; // stack head position
|
||||
|
||||
for (;;)
|
||||
{
|
||||
BVH_Vec4i aNodeData1 = aBVH1->NodeInfoBuffer()[aNodes.Node1];
|
||||
BVH_Vec4i aNodeData2 = aBVH2->NodeInfoBuffer()[aNodes.Node2];
|
||||
|
||||
if (aNodeData1.x() != 0 && aNodeData2.x() != 0) // leaves
|
||||
{
|
||||
if (theTolerance == 0.0)
|
||||
{
|
||||
intersectTriangleRangesExact (aNodeData1, aNodeData2);
|
||||
}
|
||||
else
|
||||
{
|
||||
intersectTriangleRangesToler (aNodeData1, aNodeData2, theTolerance);
|
||||
}
|
||||
|
||||
if (aHead < 0)
|
||||
break;
|
||||
|
||||
aNodes = aStack[aHead--];
|
||||
}
|
||||
else
|
||||
{
|
||||
BRepExtrema_StackItem aPairsToProcess[4];
|
||||
|
||||
Standard_Integer aNbPairs = 0;
|
||||
|
||||
if (aNodeData1.x() == 0) // inner node
|
||||
{
|
||||
const BVH_Vec3d& aMinPntLft1 = aBVH1->MinPoint (aNodeData1.y());
|
||||
const BVH_Vec3d& aMaxPntLft1 = aBVH1->MaxPoint (aNodeData1.y());
|
||||
const BVH_Vec3d& aMinPntRgh1 = aBVH1->MinPoint (aNodeData1.z());
|
||||
const BVH_Vec3d& aMaxPntRgh1 = aBVH1->MaxPoint (aNodeData1.z());
|
||||
|
||||
if (aNodeData2.x() == 0) // inner node
|
||||
{
|
||||
const BVH_Vec3d& aMinPntLft2 = aBVH2->MinPoint (aNodeData2.y());
|
||||
const BVH_Vec3d& aMaxPntLft2 = aBVH2->MaxPoint (aNodeData2.y());
|
||||
const BVH_Vec3d& aMinPntRgh2 = aBVH2->MinPoint (aNodeData2.z());
|
||||
const BVH_Vec3d& aMaxPntRgh2 = aBVH2->MaxPoint (aNodeData2.z());
|
||||
|
||||
if (overlapBoxes (aMinPntLft1, aMaxPntLft1, aMinPntLft2, aMaxPntLft2, theTolerance))
|
||||
{
|
||||
aPairsToProcess[aNbPairs++] = BRepExtrema_StackItem (aNodeData1.y(), aNodeData2.y());
|
||||
}
|
||||
if (overlapBoxes (aMinPntLft1, aMaxPntLft1, aMinPntRgh2, aMaxPntRgh2, theTolerance))
|
||||
{
|
||||
aPairsToProcess[aNbPairs++] = BRepExtrema_StackItem (aNodeData1.y(), aNodeData2.z());
|
||||
}
|
||||
if (overlapBoxes (aMinPntRgh1, aMaxPntRgh1, aMinPntLft2, aMaxPntLft2, theTolerance))
|
||||
{
|
||||
aPairsToProcess[aNbPairs++] = BRepExtrema_StackItem (aNodeData1.z(), aNodeData2.y());
|
||||
}
|
||||
if (overlapBoxes (aMinPntRgh1, aMaxPntRgh1, aMinPntRgh2, aMaxPntRgh2, theTolerance))
|
||||
{
|
||||
aPairsToProcess[aNbPairs++] = BRepExtrema_StackItem (aNodeData1.z(), aNodeData2.z());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const BVH_Vec3d& aMinPntLeaf = aBVH2->MinPoint (aNodes.Node2);
|
||||
const BVH_Vec3d& aMaxPntLeaf = aBVH2->MaxPoint (aNodes.Node2);
|
||||
|
||||
if (overlapBoxes (aMinPntLft1, aMaxPntLft1, aMinPntLeaf, aMaxPntLeaf, theTolerance))
|
||||
{
|
||||
aPairsToProcess[aNbPairs++] = BRepExtrema_StackItem (aNodeData1.y(), aNodes.Node2);
|
||||
}
|
||||
if (overlapBoxes (aMinPntRgh1, aMaxPntRgh1, aMinPntLeaf, aMaxPntLeaf, theTolerance))
|
||||
{
|
||||
aPairsToProcess[aNbPairs++] = BRepExtrema_StackItem (aNodeData1.z(), aNodes.Node2);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const BVH_Vec3d& aMinPntLeaf = aBVH1->MinPoint (aNodes.Node1);
|
||||
const BVH_Vec3d& aMaxPntLeaf = aBVH1->MaxPoint (aNodes.Node1);
|
||||
|
||||
const BVH_Vec3d& aMinPntLft2 = aBVH2->MinPoint (aNodeData2.y());
|
||||
const BVH_Vec3d& aMaxPntLft2 = aBVH2->MaxPoint (aNodeData2.y());
|
||||
const BVH_Vec3d& aMinPntRgh2 = aBVH2->MinPoint (aNodeData2.z());
|
||||
const BVH_Vec3d& aMaxPntRgh2 = aBVH2->MaxPoint (aNodeData2.z());
|
||||
|
||||
if (overlapBoxes (aMinPntLft2, aMaxPntLft2, aMinPntLeaf, aMaxPntLeaf, theTolerance))
|
||||
{
|
||||
aPairsToProcess[aNbPairs++] = BRepExtrema_StackItem (aNodes.Node1, aNodeData2.y());
|
||||
}
|
||||
if (overlapBoxes (aMinPntRgh2, aMaxPntRgh2, aMinPntLeaf, aMaxPntLeaf, theTolerance))
|
||||
{
|
||||
aPairsToProcess[aNbPairs++] = BRepExtrema_StackItem (aNodes.Node1, aNodeData2.z());
|
||||
}
|
||||
}
|
||||
|
||||
if (aNbPairs > 0)
|
||||
{
|
||||
aNodes = aPairsToProcess[0];
|
||||
|
||||
for (Standard_Integer anIdx = 1; anIdx < aNbPairs; ++anIdx)
|
||||
{
|
||||
aStack[++aHead] = aPairsToProcess[anIdx];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (aHead < 0)
|
||||
break;
|
||||
|
||||
aNodes = aStack[aHead--];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
myIsDone = Standard_True;
|
||||
}
|
118
src/BRepExtrema/BRepExtrema_OverlapTool.hxx
Normal file
118
src/BRepExtrema/BRepExtrema_OverlapTool.hxx
Normal file
@ -0,0 +1,118 @@
|
||||
// Created on: 2015-04-26
|
||||
// Created by: Denis BOGOLEPOV
|
||||
// Copyright (c) 2015 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.
|
||||
|
||||
#ifndef _BRepExtrema_OverlapTool_HeaderFile
|
||||
#define _BRepExtrema_OverlapTool_HeaderFile
|
||||
|
||||
#include <BVH_Geometry.hxx>
|
||||
#include <BRepExtrema_TriangleSet.hxx>
|
||||
#include <BRepExtrema_ElementFilter.hxx>
|
||||
#include <BRepExtrema_MapOfIntegerPackedMapOfInteger.hxx>
|
||||
|
||||
//! Enables storing of individual overlapped triangles (useful for debug).
|
||||
// #define OVERLAP_TOOL_OUTPUT_TRIANGLES
|
||||
|
||||
//! Tool class for for detection of overlapping of two BVH primitive sets.
|
||||
//! This tool is not intended to be used independently, and is integrated
|
||||
//! in other classes, implementing algorithms based on shape tessellation
|
||||
//! (BRepExtrema_ShapeProximity and BRepExtrema_SelfIntersection).
|
||||
//!
|
||||
//! Note that input element sets may correspond to different shapes or to
|
||||
//! the same shape. In first case, tessellations of two given shapes will
|
||||
//! be tested for intersection (or overlapping, if tolerance is not zero).
|
||||
//! In second case, tessellation of single shape will be tested for self-
|
||||
//! intersections. Please note that algorithm results are approximate and
|
||||
//! depend greatly on the quality of input tessellation(s).
|
||||
class BRepExtrema_OverlapTool
|
||||
{
|
||||
public:
|
||||
|
||||
//! Creates new unitialized overlap tool.
|
||||
BRepExtrema_OverlapTool();
|
||||
|
||||
//! Creates new overlap tool for the given element sets.
|
||||
BRepExtrema_OverlapTool (const Handle(BRepExtrema_TriangleSet)& theSet1,
|
||||
const Handle(BRepExtrema_TriangleSet)& theSet2);
|
||||
|
||||
public:
|
||||
|
||||
//! Loads the given element sets into the overlap tool.
|
||||
void LoadTriangleSets (const Handle(BRepExtrema_TriangleSet)& theSet1,
|
||||
const Handle(BRepExtrema_TriangleSet)& theSet2);
|
||||
|
||||
//! Performs searching of overlapped mesh elements.
|
||||
void Perform (const Standard_Real theTolerance = 0.0);
|
||||
|
||||
//! Is overlap test completed?
|
||||
Standard_Boolean IsDone() const { return myIsDone; }
|
||||
|
||||
//! Marks test results as outdated.
|
||||
void MarkDirty() { myIsDone = Standard_False; }
|
||||
|
||||
//! Returns set of overlapped sub-shapes of 1st shape (currently only faces are detected).
|
||||
const BRepExtrema_MapOfIntegerPackedMapOfInteger& OverlapSubShapes1() const { return myOverlapSubShapes1; }
|
||||
|
||||
//! Returns set of overlapped sub-shapes of 2nd shape (currently only faces are detected).
|
||||
const BRepExtrema_MapOfIntegerPackedMapOfInteger& OverlapSubShapes2() const { return myOverlapSubShapes2; }
|
||||
|
||||
#ifdef OVERLAP_TOOL_OUTPUT_TRIANGLES
|
||||
//! Returns set of overlapped triangles from the 1st shape (for debug).
|
||||
const TColStd_PackedMapOfInteger& OverlapTriangles1() const { return myOverlapTriangles1; }
|
||||
|
||||
//! Returns set of overlapped triangles from the 2nd shape (for debug).
|
||||
const TColStd_PackedMapOfInteger& OverlapTriangles2() const { return myOverlapTriangles2; }
|
||||
#endif
|
||||
|
||||
//! Sets filtering tool for preliminary checking pairs of mesh elements.
|
||||
void SetElementFilter (BRepExtrema_ElementFilter* theFilter) { myFilter = theFilter; }
|
||||
|
||||
protected:
|
||||
|
||||
//! Performs narrow-phase of overlap test (exact intersection).
|
||||
void intersectTriangleRangesExact (const BVH_Vec4i& theLeaf1,
|
||||
const BVH_Vec4i& theLeaf2);
|
||||
|
||||
//! Performs narrow-phase of overlap test (intersection with non-zero tolerance).
|
||||
void intersectTriangleRangesToler (const BVH_Vec4i& theLeaf1,
|
||||
const BVH_Vec4i& theLeaf2,
|
||||
const Standard_Real theToler);
|
||||
|
||||
private:
|
||||
|
||||
//! Set of all mesh elements (triangles) of the 1st shape.
|
||||
Handle(BRepExtrema_TriangleSet) mySet1;
|
||||
//! Set of all mesh elements (triangles) of the 2nd shape.
|
||||
Handle(BRepExtrema_TriangleSet) mySet2;
|
||||
|
||||
//! Filter for preliminary checking pairs of mesh elements.
|
||||
BRepExtrema_ElementFilter* myFilter;
|
||||
|
||||
//! Resulted set of overlapped sub-shapes of 1st shape (only faces).
|
||||
BRepExtrema_MapOfIntegerPackedMapOfInteger myOverlapSubShapes1;
|
||||
//! Resulted set of overlapped sub-shapes of 2nd shape (only faces).
|
||||
BRepExtrema_MapOfIntegerPackedMapOfInteger myOverlapSubShapes2;
|
||||
|
||||
#ifdef OVERLAP_TOOL_OUTPUT_TRIANGLES
|
||||
//! Set of overlapped elements from the 1st shape (only triangles).
|
||||
TColStd_PackedMapOfInteger myOverlapTriangles1;
|
||||
//! Set of overlapped elements from the 2nd shape (only triangles).
|
||||
TColStd_PackedMapOfInteger myOverlapTriangles2;
|
||||
#endif
|
||||
|
||||
//! Is overlap test test completed?
|
||||
Standard_Boolean myIsDone;
|
||||
};
|
||||
|
||||
#endif // _BRepExtrema_OverlapTool_HeaderFile
|
312
src/BRepExtrema/BRepExtrema_SelfIntersection.cxx
Normal file
312
src/BRepExtrema/BRepExtrema_SelfIntersection.cxx
Normal file
@ -0,0 +1,312 @@
|
||||
// Created on: 2015-04-26
|
||||
// Created by: Denis BOGOLEPOV
|
||||
// Copyright (c) 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 <BRepExtrema_SelfIntersection.hxx>
|
||||
|
||||
#include <Precision.hxx>
|
||||
#include <TopExp_Explorer.hxx>
|
||||
|
||||
//=======================================================================
|
||||
//function : BRepExtrema_SelfIntersection
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
BRepExtrema_SelfIntersection::BRepExtrema_SelfIntersection (const Standard_Real theTolerance)
|
||||
: myTolerance (theTolerance)
|
||||
{
|
||||
myIsInit = Standard_False;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : BRepExtrema_SelfIntersection
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
BRepExtrema_SelfIntersection::BRepExtrema_SelfIntersection (const TopoDS_Shape& theShape, const Standard_Real theTolerance)
|
||||
: myTolerance (theTolerance)
|
||||
{
|
||||
LoadShape (theShape);
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : LoadShape
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
Standard_Boolean BRepExtrema_SelfIntersection::LoadShape (const TopoDS_Shape& theShape)
|
||||
{
|
||||
myFaceList.Clear();
|
||||
|
||||
for (TopExp_Explorer anIter (theShape, TopAbs_FACE); anIter.More(); anIter.Next())
|
||||
{
|
||||
myFaceList.Append (static_cast<const TopoDS_Face&> (anIter.Current()));
|
||||
}
|
||||
|
||||
if (myElementSet.IsNull())
|
||||
{
|
||||
myElementSet = new BRepExtrema_TriangleSet;
|
||||
}
|
||||
|
||||
myIsInit = myElementSet->Init (myFaceList);
|
||||
|
||||
if (myIsInit)
|
||||
{
|
||||
myOverlapTool.LoadTriangleSets (myElementSet,
|
||||
myElementSet);
|
||||
}
|
||||
|
||||
return myIsInit;
|
||||
}
|
||||
|
||||
#define ZERO_VEC BVH_Vec3d (0.0, 0.0, 0.0)
|
||||
|
||||
namespace
|
||||
{
|
||||
// =======================================================================
|
||||
// function : ccw
|
||||
// purpose : Check if triple is in counterclockwise order
|
||||
// =======================================================================
|
||||
Standard_Boolean ccw (const BVH_Vec3d& theVertex0,
|
||||
const BVH_Vec3d& theVertex1,
|
||||
const BVH_Vec3d& theVertex2,
|
||||
const Standard_Integer theX,
|
||||
const Standard_Integer theY)
|
||||
{
|
||||
const Standard_Real aSum =
|
||||
(theVertex1[theX] - theVertex0[theX]) * (theVertex1[theY] + theVertex0[theY]) +
|
||||
(theVertex2[theX] - theVertex1[theX]) * (theVertex2[theY] + theVertex1[theY]) +
|
||||
(theVertex0[theX] - theVertex2[theX]) * (theVertex0[theY] + theVertex2[theY]);
|
||||
|
||||
return aSum < 0.0;
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : rayInsideAngle
|
||||
// purpose : Check the given ray is inside the angle
|
||||
// =======================================================================
|
||||
Standard_Boolean rayInsideAngle (const BVH_Vec3d& theDirec,
|
||||
const BVH_Vec3d& theEdge0,
|
||||
const BVH_Vec3d& theEdge1,
|
||||
const Standard_Integer theX,
|
||||
const Standard_Integer theY)
|
||||
{
|
||||
const Standard_Boolean aCCW = ccw (ZERO_VEC, theEdge0, theEdge1, theX, theY);
|
||||
|
||||
return ccw (ZERO_VEC, theEdge0, theDirec, theX, theY) == aCCW
|
||||
&& ccw (ZERO_VEC, theDirec, theEdge1, theX, theY) == aCCW;
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : getProjectionAxes
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void getProjectionAxes (const BVH_Vec3d& theNorm,
|
||||
Standard_Integer& theAxisX,
|
||||
Standard_Integer& theAxisY)
|
||||
{
|
||||
if (fabs (theNorm[0]) > fabs (theNorm[1]))
|
||||
{
|
||||
theAxisX = fabs (theNorm[0]) > fabs (theNorm[2]) ? 1 : 0;
|
||||
theAxisY = fabs (theNorm[0]) > fabs (theNorm[2]) ? 2 : 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
theAxisX = fabs (theNorm[1]) > fabs (theNorm[2]) ? 0 : 0;
|
||||
theAxisY = fabs (theNorm[1]) > fabs (theNorm[2]) ? 2 : 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : isRegularSharedVertex
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
BRepExtrema_ElementFilter::FilterResult BRepExtrema_SelfIntersection::isRegularSharedVertex (const BVH_Vec3d& theSharedVert,
|
||||
const BVH_Vec3d& theTrng0Vtxs1,
|
||||
const BVH_Vec3d& theTrng0Vtxs2,
|
||||
const BVH_Vec3d& theTrng1Vtxs1,
|
||||
const BVH_Vec3d& theTrng1Vtxs2)
|
||||
{
|
||||
const BVH_Vec3d aTrng0Edges[] = { (theTrng0Vtxs1 - theSharedVert).Normalized(),
|
||||
(theTrng0Vtxs2 - theSharedVert).Normalized() };
|
||||
|
||||
const BVH_Vec3d aTrng1Edges[] = { (theTrng1Vtxs1 - theSharedVert).Normalized(),
|
||||
(theTrng1Vtxs2 - theSharedVert).Normalized() };
|
||||
|
||||
const BVH_Vec3d aTrng0Normal = BVH_Vec3d::Cross (aTrng0Edges[0], aTrng0Edges[1]);
|
||||
const BVH_Vec3d aTrng1Normal = BVH_Vec3d::Cross (aTrng1Edges[0], aTrng1Edges[1]);
|
||||
|
||||
BVH_Vec3d aCrossLine = BVH_Vec3d::Cross (aTrng0Normal,
|
||||
aTrng1Normal);
|
||||
|
||||
Standard_Integer anX;
|
||||
Standard_Integer anY;
|
||||
|
||||
if (aCrossLine.SquareModulus() < Precision::SquareConfusion()) // coplanar case
|
||||
{
|
||||
getProjectionAxes (aTrng0Normal, anX, anY);
|
||||
|
||||
if (rayInsideAngle (aTrng1Edges[0], aTrng0Edges[0], aTrng0Edges[1], anX, anY)
|
||||
|| rayInsideAngle (aTrng1Edges[1], aTrng0Edges[0], aTrng0Edges[1], anX, anY)
|
||||
|| rayInsideAngle (aTrng0Edges[0], aTrng1Edges[0], aTrng1Edges[1], anX, anY)
|
||||
|| rayInsideAngle (aTrng0Edges[1], aTrng1Edges[0], aTrng1Edges[1], anX, anY))
|
||||
{
|
||||
return BRepExtrema_ElementFilter::Overlap;
|
||||
}
|
||||
|
||||
return BRepExtrema_ElementFilter::NoCheck;
|
||||
}
|
||||
else // shared line should lie outside at least one triangle
|
||||
{
|
||||
getProjectionAxes (aTrng0Normal, anX, anY);
|
||||
|
||||
const Standard_Boolean aPosOutTrgn0 = !rayInsideAngle ( aCrossLine, aTrng0Edges[0], aTrng0Edges[1], anX, anY);
|
||||
const Standard_Boolean aNegOutTrgn0 = !rayInsideAngle (-aCrossLine, aTrng0Edges[0], aTrng0Edges[1], anX, anY);
|
||||
|
||||
Standard_ASSERT_RAISE (aPosOutTrgn0 || aNegOutTrgn0,
|
||||
"Failed to detect if shared vertex is regular or not");
|
||||
|
||||
if (aPosOutTrgn0 && aNegOutTrgn0)
|
||||
{
|
||||
return BRepExtrema_ElementFilter::NoCheck;
|
||||
}
|
||||
|
||||
getProjectionAxes (aTrng1Normal, anX, anY);
|
||||
|
||||
const Standard_Boolean aPosOutTrgn1 = !rayInsideAngle ( aCrossLine, aTrng1Edges[0], aTrng1Edges[1], anX, anY);
|
||||
const Standard_Boolean aNegOutTrgn1 = !rayInsideAngle (-aCrossLine, aTrng1Edges[0], aTrng1Edges[1], anX, anY);
|
||||
|
||||
Standard_ASSERT_RAISE (aPosOutTrgn1 || aNegOutTrgn1,
|
||||
"Failed to detect if shared vertex is regular or not");
|
||||
|
||||
if (aPosOutTrgn1 && aNegOutTrgn1)
|
||||
{
|
||||
return BRepExtrema_ElementFilter::NoCheck;
|
||||
}
|
||||
|
||||
return (aPosOutTrgn0 || aPosOutTrgn1) && (aNegOutTrgn0 || aNegOutTrgn1) ?
|
||||
BRepExtrema_ElementFilter::NoCheck : BRepExtrema_ElementFilter::Overlap;
|
||||
}
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : isRegularSharedEdge
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
BRepExtrema_ElementFilter::FilterResult BRepExtrema_SelfIntersection::isRegularSharedEdge (const BVH_Vec3d& theTrng0Vtxs0,
|
||||
const BVH_Vec3d& theTrng0Vtxs1,
|
||||
const BVH_Vec3d& theTrng0Vtxs2,
|
||||
const BVH_Vec3d& theTrng1Vtxs2)
|
||||
{
|
||||
const BVH_Vec3d aSharedEdge = (theTrng0Vtxs1 - theTrng0Vtxs0).Normalized();
|
||||
|
||||
const BVH_Vec3d aUniqueEdges[] = { (theTrng0Vtxs2 - theTrng0Vtxs0).Normalized(),
|
||||
(theTrng1Vtxs2 - theTrng0Vtxs0).Normalized() };
|
||||
|
||||
const BVH_Vec3d aTrng0Normal = BVH_Vec3d::Cross (aSharedEdge, aUniqueEdges[0]);
|
||||
const BVH_Vec3d aTrng1Normal = BVH_Vec3d::Cross (aSharedEdge, aUniqueEdges[1]);
|
||||
|
||||
BVH_Vec3d aCrossLine = BVH_Vec3d::Cross (aTrng0Normal,
|
||||
aTrng1Normal);
|
||||
|
||||
if (aCrossLine.SquareModulus() > Precision::SquareConfusion()) // non-coplanar case
|
||||
{
|
||||
return BRepExtrema_ElementFilter::NoCheck;
|
||||
}
|
||||
|
||||
Standard_Integer anX;
|
||||
Standard_Integer anY;
|
||||
|
||||
getProjectionAxes (aTrng0Normal, anX, anY);
|
||||
|
||||
return ccw (ZERO_VEC, aSharedEdge, aUniqueEdges[0], anX, anY) !=
|
||||
ccw (ZERO_VEC, aSharedEdge, aUniqueEdges[1], anX, anY) ? BRepExtrema_ElementFilter::NoCheck
|
||||
: BRepExtrema_ElementFilter::Overlap;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : PreCheckElements
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
BRepExtrema_ElementFilter::FilterResult BRepExtrema_SelfIntersection::PreCheckElements (const Standard_Integer theIndex1,
|
||||
const Standard_Integer theIndex2)
|
||||
{
|
||||
if (myElementSet->GetFaceID (theIndex1) == myElementSet->GetFaceID (theIndex2))
|
||||
{
|
||||
return BRepExtrema_ElementFilter::NoCheck; // triangles are from the same face
|
||||
}
|
||||
|
||||
BVH_Vec3d aTrng0Vtxs[3];
|
||||
BVH_Vec3d aTrng1Vtxs[3];
|
||||
|
||||
myElementSet->GetVertices (theIndex1,
|
||||
aTrng0Vtxs[0],
|
||||
aTrng0Vtxs[1],
|
||||
aTrng0Vtxs[2]);
|
||||
|
||||
myElementSet->GetVertices (theIndex2,
|
||||
aTrng1Vtxs[0],
|
||||
aTrng1Vtxs[1],
|
||||
aTrng1Vtxs[2]);
|
||||
|
||||
std::vector<std::pair<Standard_Integer, Standard_Integer> > aSharedVtxs;
|
||||
|
||||
for (Standard_Integer aVertIdx1 = 0; aVertIdx1 < 3; ++aVertIdx1)
|
||||
{
|
||||
for (Standard_Integer aVertIdx2 = 0; aVertIdx2 < 3; ++aVertIdx2)
|
||||
{
|
||||
if ((aTrng0Vtxs[aVertIdx1] - aTrng1Vtxs[aVertIdx2]).SquareModulus() < Precision::SquareConfusion())
|
||||
{
|
||||
aSharedVtxs.push_back (std::pair<Standard_Integer, Standard_Integer> (aVertIdx1, aVertIdx2));
|
||||
|
||||
break; // go to next vertex of the 1st triangle
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (aSharedVtxs.size() == 2) // check shared edge
|
||||
{
|
||||
return isRegularSharedEdge (aTrng0Vtxs[aSharedVtxs[0].first],
|
||||
aTrng0Vtxs[aSharedVtxs[1].first],
|
||||
aTrng0Vtxs[3 - aSharedVtxs[0]. first - aSharedVtxs[1]. first],
|
||||
aTrng1Vtxs[3 - aSharedVtxs[0].second - aSharedVtxs[1].second]);
|
||||
}
|
||||
else if (aSharedVtxs.size() == 1) // check shared vertex
|
||||
{
|
||||
std::swap (*aTrng0Vtxs, aTrng0Vtxs[aSharedVtxs.front(). first]);
|
||||
std::swap (*aTrng1Vtxs, aTrng1Vtxs[aSharedVtxs.front().second]);
|
||||
|
||||
return isRegularSharedVertex (aTrng0Vtxs[0],
|
||||
aTrng0Vtxs[1],
|
||||
aTrng0Vtxs[2],
|
||||
aTrng1Vtxs[1],
|
||||
aTrng1Vtxs[2]);
|
||||
}
|
||||
|
||||
return BRepExtrema_ElementFilter::DoCheck;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : Perform
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
void BRepExtrema_SelfIntersection::Perform()
|
||||
{
|
||||
if (!myIsInit || myOverlapTool.IsDone())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
myOverlapTool.SetElementFilter (this);
|
||||
|
||||
myOverlapTool.Perform (myTolerance);
|
||||
}
|
134
src/BRepExtrema/BRepExtrema_SelfIntersection.hxx
Normal file
134
src/BRepExtrema/BRepExtrema_SelfIntersection.hxx
Normal file
@ -0,0 +1,134 @@
|
||||
// Created on: 2015-04-26
|
||||
// Created by: Denis BOGOLEPOV
|
||||
// Copyright (c) 2015 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.
|
||||
|
||||
#ifndef _BRepExtrema_SelfIntersection_HeaderFile
|
||||
#define _BRepExtrema_SelfIntersection_HeaderFile
|
||||
|
||||
#include <BRepExtrema_OverlapTool.hxx>
|
||||
|
||||
//! Tool class for detection of self-sections in the given shape.
|
||||
//! This class is based on BRepExtrema_OverlapTool and thus uses
|
||||
//! shape tessellation to detect incorrect mesh fragments (pairs
|
||||
//! of overlapped triangles belonging to different faces). Thus,
|
||||
//! a result depends critically on the quality of mesh generator
|
||||
//! (e.g., BREP mesh is not always a good choice, because it can
|
||||
//! contain gaps between adjacent face triangulations, which may
|
||||
//! not share vertices on common edge; thus false overlap can be
|
||||
//! detected). As a result, this tool can be used for relatively
|
||||
//! fast approximated test which provides sub-set of potentially
|
||||
//! overlapped faces.
|
||||
class BRepExtrema_SelfIntersection : public BRepExtrema_ElementFilter
|
||||
{
|
||||
friend class BRepExtrema_OverlapTool;
|
||||
|
||||
public:
|
||||
|
||||
//! Creates unitialized self-intersection tool.
|
||||
Standard_EXPORT BRepExtrema_SelfIntersection (const Standard_Real theTolerance = 0.0);
|
||||
|
||||
//! Creates self-intersection tool for the given shape.
|
||||
Standard_EXPORT BRepExtrema_SelfIntersection (const TopoDS_Shape& theShape, const Standard_Real theTolerance = 0.0);
|
||||
|
||||
public:
|
||||
|
||||
//! Returns tolerance value used for self-intersection test.
|
||||
Standard_Real Tolerance() const
|
||||
{
|
||||
return myTolerance;
|
||||
}
|
||||
|
||||
//! Sets tolerance value used for self-intersection test.
|
||||
void SetTolerance (const Standard_Real theTolerance)
|
||||
{
|
||||
myTolerance = theTolerance;
|
||||
}
|
||||
|
||||
//! Loads shape for detection of self-intersections.
|
||||
Standard_EXPORT Standard_Boolean LoadShape (const TopoDS_Shape& theShape);
|
||||
|
||||
//! Performs detection of self-intersections.
|
||||
Standard_EXPORT void Perform();
|
||||
|
||||
//! True if the detection is completed.
|
||||
Standard_Boolean IsDone() const
|
||||
{
|
||||
return myOverlapTool.IsDone();
|
||||
}
|
||||
|
||||
//! Returns set of IDs of overlapped sub-shapes (started from 0).
|
||||
const BRepExtrema_MapOfIntegerPackedMapOfInteger& OverlapElements() const
|
||||
{
|
||||
return myOverlapTool.OverlapSubShapes1();
|
||||
}
|
||||
|
||||
//! Returns sub-shape from the shape for the given index (started from 0).
|
||||
const TopoDS_Face& GetSubShape (const Standard_Integer theID) const
|
||||
{
|
||||
return myFaceList.Value (theID);
|
||||
}
|
||||
|
||||
//! Returns set of all the face triangles of the shape.
|
||||
const Handle(BRepExtrema_TriangleSet)& ElementSet() const
|
||||
{
|
||||
return myElementSet;
|
||||
}
|
||||
|
||||
#ifdef OVERLAP_TOOL_OUTPUT_TRIANGLES
|
||||
//! Returns set of overlapped mesh elements (only triangles).
|
||||
const TColStd_PackedMapOfInteger& OverlapTriangles() const
|
||||
{
|
||||
return myOverlapTool.OverlapTriangles1();
|
||||
}
|
||||
#endif
|
||||
|
||||
protected:
|
||||
|
||||
//! Filter out correct adjacent mesh elements.
|
||||
virtual BRepExtrema_ElementFilter::FilterResult PreCheckElements (const Standard_Integer theIndex1,
|
||||
const Standard_Integer theIndex2);
|
||||
|
||||
//! Checks if the given triangles have only single common vertex.
|
||||
BRepExtrema_ElementFilter::FilterResult isRegularSharedVertex (const BVH_Vec3d& theSharedVert,
|
||||
const BVH_Vec3d& theTrng1Vtxs1,
|
||||
const BVH_Vec3d& theTrng1Vtxs2,
|
||||
const BVH_Vec3d& theTrng2Vtxs1,
|
||||
const BVH_Vec3d& theTrng2Vtxs2);
|
||||
|
||||
//! Checks if the given triangles have only single common edge.
|
||||
BRepExtrema_ElementFilter::FilterResult isRegularSharedEdge (const BVH_Vec3d& theTrng1Vtxs0,
|
||||
const BVH_Vec3d& theTrng1Vtxs1,
|
||||
const BVH_Vec3d& theTrng1Vtxs2,
|
||||
const BVH_Vec3d& theTrng2Vtxs2);
|
||||
|
||||
private:
|
||||
|
||||
//! Self-intersection tolerance.
|
||||
Standard_Real myTolerance;
|
||||
|
||||
//! Is the input shape inited?
|
||||
Standard_Boolean myIsInit;
|
||||
|
||||
//! List of triangulated faces of the shape.
|
||||
BRepExtrema_ShapeList myFaceList;
|
||||
|
||||
//! Set of all the face triangles of the shape.
|
||||
Handle(BRepExtrema_TriangleSet) myElementSet;
|
||||
|
||||
//! Overlap tool used for self-intersection test.
|
||||
BRepExtrema_OverlapTool myOverlapTool;
|
||||
|
||||
};
|
||||
|
||||
#endif // _BRepExtrema_SelfIntersection_HeaderFile
|
@ -20,15 +20,15 @@
|
||||
|
||||
//=======================================================================
|
||||
//function : BRepExtrema_ShapeProximity
|
||||
//purpose : Creates empty proximity tool
|
||||
//purpose : Creates uninitialized proximity tool
|
||||
//=======================================================================
|
||||
BRepExtrema_ShapeProximity::BRepExtrema_ShapeProximity (const Standard_Real theTolerance)
|
||||
: myTolerance (theTolerance),
|
||||
myPrimitiveSet1 (new BRepExtrema_TriangleSet),
|
||||
myPrimitiveSet2 (new BRepExtrema_TriangleSet)
|
||||
: myTolerance (theTolerance),
|
||||
myElementSet1 (new BRepExtrema_TriangleSet),
|
||||
myElementSet2 (new BRepExtrema_TriangleSet)
|
||||
{
|
||||
// Should be initialized later
|
||||
myIsDone = myIsInitS1 = myIsInitS2 = Standard_False;
|
||||
myIsInitS1 = myIsInitS2 = Standard_False;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
@ -38,9 +38,9 @@ BRepExtrema_ShapeProximity::BRepExtrema_ShapeProximity (const Standard_Real theT
|
||||
BRepExtrema_ShapeProximity::BRepExtrema_ShapeProximity (const TopoDS_Shape& theShape1,
|
||||
const TopoDS_Shape& theShape2,
|
||||
const Standard_Real theTolerance)
|
||||
: myTolerance (theTolerance),
|
||||
myPrimitiveSet1 (new BRepExtrema_TriangleSet),
|
||||
myPrimitiveSet2 (new BRepExtrema_TriangleSet)
|
||||
: myTolerance (theTolerance),
|
||||
myElementSet1 (new BRepExtrema_TriangleSet),
|
||||
myElementSet2 (new BRepExtrema_TriangleSet)
|
||||
{
|
||||
LoadShape1 (theShape1);
|
||||
LoadShape2 (theShape2);
|
||||
@ -59,9 +59,9 @@ Standard_Boolean BRepExtrema_ShapeProximity::LoadShape1 (const TopoDS_Shape& the
|
||||
myFaceList1.Append (static_cast<const TopoDS_Face&> (anIter.Current()));
|
||||
}
|
||||
|
||||
myIsDone = Standard_False;
|
||||
myOverlapTool.MarkDirty();
|
||||
|
||||
return myIsInitS1 = myPrimitiveSet1->Init (myFaceList1);
|
||||
return myIsInitS1 = myElementSet1->Init (myFaceList1);
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
@ -77,569 +77,24 @@ Standard_Boolean BRepExtrema_ShapeProximity::LoadShape2 (const TopoDS_Shape& the
|
||||
myFaceList2.Append (static_cast<const TopoDS_Face&> (anIter.Current()));
|
||||
}
|
||||
|
||||
myIsDone = Standard_False;
|
||||
myOverlapTool.MarkDirty();
|
||||
|
||||
return myIsInitS2 = myPrimitiveSet2->Init (myFaceList2);
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
//! Tool class to describe stack item in traverse function.
|
||||
struct BRepExtrema_StackItem
|
||||
{
|
||||
Standard_Integer Node1;
|
||||
Standard_Integer Node2;
|
||||
|
||||
BRepExtrema_StackItem (const Standard_Integer theNode1 = 0,
|
||||
const Standard_Integer theNode2 = 0)
|
||||
: Node1 (theNode1),
|
||||
Node2 (theNode2)
|
||||
{
|
||||
//
|
||||
}
|
||||
};
|
||||
|
||||
//! Bounding triangular prism for specified triangle.
|
||||
class BRepExtrema_BoundingPrism
|
||||
{
|
||||
public:
|
||||
|
||||
//! Vertices of the prism.
|
||||
BVH_Vec3d Vertices[6];
|
||||
|
||||
//! Edges of the prism.
|
||||
BVH_Vec3d Edges[3];
|
||||
|
||||
//! Normal to prism caps.
|
||||
BVH_Vec3d Normal;
|
||||
|
||||
//! Normals to prism edges.
|
||||
BVH_Vec3d EdgeNormals[3];
|
||||
|
||||
//! Is prism initialized?
|
||||
Standard_Boolean IsInited;
|
||||
|
||||
public:
|
||||
|
||||
//! Creates uninitialized bounding prism.
|
||||
BRepExtrema_BoundingPrism() : IsInited (Standard_False)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
//! Creates new bounding prism for the given triangle.
|
||||
BRepExtrema_BoundingPrism (const BVH_Vec3d& theVertex0,
|
||||
const BVH_Vec3d& theVertex1,
|
||||
const BVH_Vec3d& theVertex2,
|
||||
const Standard_Real theDeflect)
|
||||
{
|
||||
Init (theVertex0,
|
||||
theVertex1,
|
||||
theVertex2,
|
||||
theDeflect);
|
||||
}
|
||||
|
||||
//! Calculates bounding prism for the given triangle.
|
||||
void Init (const BVH_Vec3d& theVertex0,
|
||||
const BVH_Vec3d& theVertex1,
|
||||
const BVH_Vec3d& theVertex2,
|
||||
const Standard_Real theDeflect)
|
||||
{
|
||||
Edges[0] = theVertex1 - theVertex0;
|
||||
Edges[1] = theVertex2 - theVertex0;
|
||||
Edges[2] = theVertex2 - theVertex1;
|
||||
|
||||
Normal = BVH_Vec3d::Cross (Edges[0], Edges[1]);
|
||||
|
||||
EdgeNormals[0] = BVH_Vec3d::Cross (Edges[0], Normal);
|
||||
EdgeNormals[1] = BVH_Vec3d::Cross (Edges[1], Normal);
|
||||
EdgeNormals[2] = BVH_Vec3d::Cross (Edges[2], Normal);
|
||||
|
||||
EdgeNormals[0] *= 1.0 / Max (EdgeNormals[0].Modulus(), Precision::Confusion());
|
||||
EdgeNormals[1] *= 1.0 / Max (EdgeNormals[1].Modulus(), Precision::Confusion());
|
||||
EdgeNormals[2] *= 1.0 / Max (EdgeNormals[2].Modulus(), Precision::Confusion());
|
||||
|
||||
const BVH_Vec3d aDirect01 = EdgeNormals[0] - EdgeNormals[1];
|
||||
const BVH_Vec3d aDirect02 = EdgeNormals[0] + EdgeNormals[2];
|
||||
const BVH_Vec3d aDirect12 = EdgeNormals[2] - EdgeNormals[1];
|
||||
|
||||
Vertices[0] = Vertices[3] = theVertex0 + aDirect01 * (theDeflect / aDirect01.Dot (EdgeNormals[0]));
|
||||
Vertices[1] = Vertices[4] = theVertex1 + aDirect02 * (theDeflect / aDirect02.Dot (EdgeNormals[2]));
|
||||
Vertices[2] = Vertices[5] = theVertex2 + aDirect12 * (theDeflect / aDirect12.Dot (EdgeNormals[2]));
|
||||
|
||||
const BVH_Vec3d aNormOffset = Normal * (theDeflect / Max (Normal.Modulus(), Precision::Confusion()));
|
||||
|
||||
for (Standard_Integer aVertIdx = 0; aVertIdx < 3; ++aVertIdx)
|
||||
{
|
||||
Vertices[aVertIdx + 0] += aNormOffset;
|
||||
Vertices[aVertIdx + 3] -= aNormOffset;
|
||||
}
|
||||
|
||||
IsInited = Standard_True;
|
||||
}
|
||||
|
||||
//! Checks if two prisms are separated along the given axis.
|
||||
Standard_Boolean Separated (const BRepExtrema_BoundingPrism& thePrism, const BVH_Vec3d& theAxis) const
|
||||
{
|
||||
Standard_Real aMin1 = DBL_MAX;
|
||||
Standard_Real aMax1 = -DBL_MAX;
|
||||
|
||||
Standard_Real aMin2 = DBL_MAX;
|
||||
Standard_Real aMax2 = -DBL_MAX;
|
||||
|
||||
for (Standard_Integer aVertIdx = 0; aVertIdx < 6; ++aVertIdx)
|
||||
{
|
||||
const Standard_Real aProj1 = Vertices[aVertIdx].Dot (theAxis);
|
||||
|
||||
aMin1 = Min (aMin1, aProj1);
|
||||
aMax1 = Max (aMax1, aProj1);
|
||||
|
||||
const Standard_Real aProj2 = thePrism.Vertices[aVertIdx].Dot (theAxis);
|
||||
|
||||
aMin2 = Min (aMin2, aProj2);
|
||||
aMax2 = Max (aMax2, aProj2);
|
||||
|
||||
if (aMin1 <= aMax2 && aMax1 >= aMin2)
|
||||
{
|
||||
return Standard_False;
|
||||
}
|
||||
}
|
||||
|
||||
return aMin1 > aMax2 || aMax1 < aMin2;
|
||||
}
|
||||
};
|
||||
|
||||
// =======================================================================
|
||||
// function : Separated
|
||||
// purpose : Checks if triangles can be separated along the given axis
|
||||
// (projects vertices on this axis and performs interval test)
|
||||
// =======================================================================
|
||||
inline Standard_Boolean SeparateTriangles (const BVH_Vec3d& theTrg1Vert0,
|
||||
const BVH_Vec3d& theTrg1Vert1,
|
||||
const BVH_Vec3d& theTrg1Vert2,
|
||||
const BVH_Vec3d& theTrg2Vert0,
|
||||
const BVH_Vec3d& theTrg2Vert1,
|
||||
const BVH_Vec3d& theTrg2Vert2,
|
||||
const BVH_Vec3d& theSplitAxis)
|
||||
{
|
||||
const Standard_Real aA1 = theTrg1Vert0.Dot (theSplitAxis);
|
||||
const Standard_Real aB1 = theTrg1Vert1.Dot (theSplitAxis);
|
||||
const Standard_Real aC1 = theTrg1Vert2.Dot (theSplitAxis);
|
||||
|
||||
const Standard_Real aA2 = theTrg2Vert0.Dot (theSplitAxis);
|
||||
const Standard_Real aB2 = theTrg2Vert1.Dot (theSplitAxis);
|
||||
const Standard_Real aC2 = theTrg2Vert2.Dot (theSplitAxis);
|
||||
|
||||
const Standard_Real aMin1 = Min (aA1, Min (aB1, aC1));
|
||||
const Standard_Real aMax1 = Max (aA1, Max (aB1, aC1));
|
||||
|
||||
if (aMax1 < Min (aA2, Min (aB2, aC2)))
|
||||
{
|
||||
return Standard_True;
|
||||
}
|
||||
|
||||
return aMin1 > Max (aA2, Max (aB2, aC2));
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : TrianglesIntersected
|
||||
// purpose : Checks if two triangles are intersected
|
||||
// (test uses SAT - Separating Axis Theorem)
|
||||
// =======================================================================
|
||||
Standard_Boolean TrianglesIntersected (const BVH_Vec3d& theTrg1Vert0,
|
||||
const BVH_Vec3d& theTrg1Vert1,
|
||||
const BVH_Vec3d& theTrg1Vert2,
|
||||
const BVH_Vec3d& theTrg2Vert0,
|
||||
const BVH_Vec3d& theTrg2Vert1,
|
||||
const BVH_Vec3d& theTrg2Vert2)
|
||||
{
|
||||
const BVH_Vec3d aEdges1[3] = { theTrg1Vert1 - theTrg1Vert0,
|
||||
theTrg1Vert2 - theTrg1Vert0,
|
||||
theTrg1Vert2 - theTrg1Vert1 };
|
||||
|
||||
const BVH_Vec3d aTrg1Normal = BVH_Vec3d::Cross (aEdges1[0], aEdges1[1]);
|
||||
|
||||
if (SeparateTriangles (theTrg1Vert0,
|
||||
theTrg1Vert1,
|
||||
theTrg1Vert2,
|
||||
theTrg2Vert0,
|
||||
theTrg2Vert1,
|
||||
theTrg2Vert2,
|
||||
aTrg1Normal))
|
||||
{
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
const BVH_Vec3d aEdges2[3] = { theTrg2Vert1 - theTrg2Vert0,
|
||||
theTrg2Vert2 - theTrg2Vert0,
|
||||
theTrg2Vert2 - theTrg2Vert1 };
|
||||
|
||||
const BVH_Vec3d aTrg2Normal = BVH_Vec3d::Cross (aEdges2[0], aEdges2[1]);
|
||||
|
||||
if (SeparateTriangles (theTrg1Vert0,
|
||||
theTrg1Vert1,
|
||||
theTrg1Vert2,
|
||||
theTrg2Vert0,
|
||||
theTrg2Vert1,
|
||||
theTrg2Vert2,
|
||||
aTrg2Normal))
|
||||
{
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
for (Standard_Integer anIdx1 = 0; anIdx1 < 3; ++anIdx1)
|
||||
{
|
||||
for (Standard_Integer anIdx2 = 0; anIdx2 < 3; ++anIdx2)
|
||||
{
|
||||
const BVH_Vec3d aSplitAxis = BVH_Vec3d::Cross (aEdges1[anIdx1], aEdges2[anIdx2]);
|
||||
|
||||
if (SeparateTriangles (theTrg1Vert0,
|
||||
theTrg1Vert1,
|
||||
theTrg1Vert2,
|
||||
theTrg2Vert0,
|
||||
theTrg2Vert1,
|
||||
theTrg2Vert2,
|
||||
aSplitAxis))
|
||||
{
|
||||
return Standard_False;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Standard_True;
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : PrismsIntersected
|
||||
// purpose : Checks if two triangular prisms are intersected
|
||||
// (test uses SAT - Separating Axis Theorem)
|
||||
// =======================================================================
|
||||
Standard_Boolean PrismsIntersected (const BRepExtrema_BoundingPrism& thePrism1,
|
||||
const BRepExtrema_BoundingPrism& thePrism2)
|
||||
{
|
||||
if (thePrism1.Separated (thePrism2, thePrism1.Normal))
|
||||
{
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
if (thePrism1.Separated (thePrism2, thePrism2.Normal))
|
||||
{
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
for (Standard_Integer anIdx = 0; anIdx < 3; ++anIdx)
|
||||
{
|
||||
if (thePrism1.Separated (thePrism2, thePrism1.EdgeNormals[anIdx]))
|
||||
{
|
||||
return Standard_False;
|
||||
}
|
||||
}
|
||||
|
||||
for (Standard_Integer anIdx = 0; anIdx < 3; ++anIdx)
|
||||
{
|
||||
if (thePrism1.Separated (thePrism2, thePrism2.EdgeNormals[anIdx]))
|
||||
{
|
||||
return Standard_False;
|
||||
}
|
||||
}
|
||||
|
||||
for (Standard_Integer anIdx1 = 0; anIdx1 < 4; ++anIdx1)
|
||||
{
|
||||
const BVH_Vec3d& aEdge1 = (anIdx1 == 3) ? thePrism1.Normal : thePrism1.Edges[anIdx1];
|
||||
|
||||
for (Standard_Integer anIdx2 = 0; anIdx2 < 4; ++anIdx2)
|
||||
{
|
||||
const BVH_Vec3d& aEdge2 = (anIdx2 == 3) ? thePrism2.Normal : thePrism2.Edges[anIdx2];
|
||||
|
||||
if (thePrism1.Separated (thePrism2, BVH_Vec3d::Cross (aEdge1, aEdge2)))
|
||||
{
|
||||
return Standard_False;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Standard_True;
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : OverlapBoxes
|
||||
// purpose : Checks if two boxes (AABBs) are overlapped
|
||||
// =======================================================================
|
||||
inline Standard_Boolean OverlapBoxes (const BVH_Vec3d& theBoxMin1,
|
||||
const BVH_Vec3d& theBoxMax1,
|
||||
const BVH_Vec3d& theBoxMin2,
|
||||
const BVH_Vec3d& theBoxMax2,
|
||||
const Standard_Real theTolerance)
|
||||
{
|
||||
// Check for overlap
|
||||
return !(theBoxMin1.x() > theBoxMax2.x() + theTolerance ||
|
||||
theBoxMax1.x() < theBoxMin2.x() - theTolerance ||
|
||||
theBoxMin1.y() > theBoxMax2.y() + theTolerance ||
|
||||
theBoxMax1.y() < theBoxMin2.y() - theTolerance ||
|
||||
theBoxMin1.z() > theBoxMax2.z() + theTolerance ||
|
||||
theBoxMax1.z() < theBoxMin2.z() - theTolerance);
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : getSetOfFaces
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
TColStd_PackedMapOfInteger& getSetOfFaces (BRepExtrema_OverlappedSubShapes& theShapes,
|
||||
const Standard_Integer theFaceIdx)
|
||||
{
|
||||
if (!theShapes.IsBound (theFaceIdx))
|
||||
{
|
||||
theShapes.Bind (theFaceIdx, TColStd_PackedMapOfInteger());
|
||||
}
|
||||
|
||||
return theShapes.ChangeFind (theFaceIdx);
|
||||
}
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : IntersectLeavesExact
|
||||
//purpose : Narrow-phase of overlap test (exact intersection)
|
||||
//=======================================================================
|
||||
void BRepExtrema_ShapeProximity::IntersectLeavesExact (const BVH_Vec4i& theLeaf1,
|
||||
const BVH_Vec4i& theLeaf2)
|
||||
{
|
||||
for (Standard_Integer aTrgIdx1 = theLeaf1.y(); aTrgIdx1 <= theLeaf1.z(); ++aTrgIdx1)
|
||||
{
|
||||
const Standard_Integer aFaceIdx1 = myPrimitiveSet1->GetFaceID (aTrgIdx1);
|
||||
|
||||
BVH_Vec3d aTrg1Vert1;
|
||||
BVH_Vec3d aTrg1Vert2;
|
||||
BVH_Vec3d aTrg1Vert3;
|
||||
|
||||
myPrimitiveSet1->GetVertices (aTrgIdx1,
|
||||
aTrg1Vert1,
|
||||
aTrg1Vert2,
|
||||
aTrg1Vert3);
|
||||
|
||||
const Standard_Boolean aIsInSet = myOverlapSubShapes1.IsBound (aFaceIdx1);
|
||||
|
||||
for (Standard_Integer aTrgIdx2 = theLeaf2.y(); aTrgIdx2 <= theLeaf2.z(); ++aTrgIdx2)
|
||||
{
|
||||
const Standard_Integer aFaceIdx2 = myPrimitiveSet2->GetFaceID (aTrgIdx2);
|
||||
|
||||
if (!aIsInSet || !myOverlapSubShapes1.Find (aFaceIdx1).Contains (aFaceIdx2))
|
||||
{
|
||||
BVH_Vec3d aTrg2Vert1;
|
||||
BVH_Vec3d aTrg2Vert2;
|
||||
BVH_Vec3d aTrg2Vert3;
|
||||
|
||||
myPrimitiveSet2->GetVertices (aTrgIdx2, aTrg2Vert1, aTrg2Vert2, aTrg2Vert3);
|
||||
|
||||
if (TrianglesIntersected (aTrg1Vert1,
|
||||
aTrg1Vert2,
|
||||
aTrg1Vert3,
|
||||
aTrg2Vert1,
|
||||
aTrg2Vert2,
|
||||
aTrg2Vert3))
|
||||
{
|
||||
getSetOfFaces (myOverlapSubShapes1, aFaceIdx1).Add (aFaceIdx2);
|
||||
getSetOfFaces (myOverlapSubShapes2, aFaceIdx2).Add (aFaceIdx1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : IntersectLeavesToler
|
||||
//purpose : Narrow-phase of overlap test (with non-zero tolerance)
|
||||
//=======================================================================
|
||||
void BRepExtrema_ShapeProximity::IntersectLeavesToler (const BVH_Vec4i& theLeaf1,
|
||||
const BVH_Vec4i& theLeaf2)
|
||||
{
|
||||
for (Standard_Integer aTrgIdx1 = theLeaf1.y(); aTrgIdx1 <= theLeaf1.z(); ++aTrgIdx1)
|
||||
{
|
||||
const Standard_Integer aFaceIdx1 = myPrimitiveSet1->GetFaceID (aTrgIdx1);
|
||||
|
||||
BVH_Vec3d aTrg1Vert1;
|
||||
BVH_Vec3d aTrg1Vert2;
|
||||
BVH_Vec3d aTrg1Vert3;
|
||||
|
||||
myPrimitiveSet1->GetVertices (aTrgIdx1,
|
||||
aTrg1Vert1,
|
||||
aTrg1Vert2,
|
||||
aTrg1Vert3);
|
||||
|
||||
BRepExtrema_BoundingPrism aPrism1; // not initialized
|
||||
|
||||
const Standard_Boolean aIsInSet = myOverlapSubShapes1.IsBound (aFaceIdx1);
|
||||
|
||||
for (Standard_Integer aTrgIdx2 = theLeaf2.y(); aTrgIdx2 <= theLeaf2.z(); ++aTrgIdx2)
|
||||
{
|
||||
const Standard_Integer aFaceIdx2 = myPrimitiveSet2->GetFaceID (aTrgIdx2);
|
||||
|
||||
if (!aIsInSet || !myOverlapSubShapes1.Find (aFaceIdx1).Contains (aFaceIdx2))
|
||||
{
|
||||
if (!aPrism1.IsInited)
|
||||
{
|
||||
aPrism1.Init (aTrg1Vert1, aTrg1Vert2, aTrg1Vert3, myTolerance);
|
||||
}
|
||||
|
||||
BVH_Vec3d aTrg2Vert1;
|
||||
BVH_Vec3d aTrg2Vert2;
|
||||
BVH_Vec3d aTrg2Vert3;
|
||||
|
||||
myPrimitiveSet2->GetVertices (aTrgIdx2,
|
||||
aTrg2Vert1,
|
||||
aTrg2Vert2,
|
||||
aTrg2Vert3);
|
||||
|
||||
BRepExtrema_BoundingPrism aPrism2 (aTrg2Vert1,
|
||||
aTrg2Vert2,
|
||||
aTrg2Vert3,
|
||||
myTolerance);
|
||||
|
||||
if (PrismsIntersected (aPrism1, aPrism2))
|
||||
{
|
||||
getSetOfFaces (myOverlapSubShapes1, aFaceIdx1).Add (aFaceIdx2);
|
||||
getSetOfFaces (myOverlapSubShapes2, aFaceIdx2).Add (aFaceIdx1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return myIsInitS2 = myElementSet2->Init (myFaceList2);
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : Perform
|
||||
//purpose : Performs search for overlapped faces
|
||||
//purpose : Performs search of overlapped faces
|
||||
//=======================================================================
|
||||
void BRepExtrema_ShapeProximity::Perform()
|
||||
{
|
||||
if (myIsDone || !myIsInitS1 || !myIsInitS2)
|
||||
if (!myIsInitS1 || !myIsInitS2 || myOverlapTool.IsDone())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
BRepExtrema_StackItem aStack[96];
|
||||
myOverlapTool.LoadTriangleSets (myElementSet1,
|
||||
myElementSet2);
|
||||
|
||||
const NCollection_Handle<BVH_Tree<Standard_Real, 3> >& aBVH1 = myPrimitiveSet1->BVH();
|
||||
const NCollection_Handle<BVH_Tree<Standard_Real, 3> >& aBVH2 = myPrimitiveSet2->BVH();
|
||||
|
||||
if (aBVH1.IsNull() || aBVH2.IsNull())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
BRepExtrema_StackItem aNodes; // current pair of nodes
|
||||
|
||||
Standard_Integer aHead = -1; // stack head position
|
||||
|
||||
for (;;)
|
||||
{
|
||||
BVH_Vec4i aNodeData1 = aBVH1->NodeInfoBuffer()[aNodes.Node1];
|
||||
BVH_Vec4i aNodeData2 = aBVH2->NodeInfoBuffer()[aNodes.Node2];
|
||||
|
||||
if (aNodeData1.x() != 0 && aNodeData2.x() != 0) // leaves
|
||||
{
|
||||
if (myTolerance == 0.0)
|
||||
{
|
||||
IntersectLeavesExact (aNodeData1, aNodeData2);
|
||||
}
|
||||
else
|
||||
{
|
||||
IntersectLeavesToler (aNodeData1, aNodeData2);
|
||||
}
|
||||
|
||||
if (aHead < 0)
|
||||
break;
|
||||
|
||||
aNodes = aStack[aHead--];
|
||||
}
|
||||
else
|
||||
{
|
||||
BRepExtrema_StackItem aPairsToProcess[4];
|
||||
|
||||
Standard_Integer aNbPairs = 0;
|
||||
|
||||
if (aNodeData1.x() == 0) // inner node
|
||||
{
|
||||
const BVH_Vec3d& aMinPntLft1 = aBVH1->MinPoint (aNodeData1.y());
|
||||
const BVH_Vec3d& aMaxPntLft1 = aBVH1->MaxPoint (aNodeData1.y());
|
||||
const BVH_Vec3d& aMinPntRgh1 = aBVH1->MinPoint (aNodeData1.z());
|
||||
const BVH_Vec3d& aMaxPntRgh1 = aBVH1->MaxPoint (aNodeData1.z());
|
||||
|
||||
if (aNodeData2.x() == 0) // inner node
|
||||
{
|
||||
const BVH_Vec3d& aMinPntLft2 = aBVH2->MinPoint (aNodeData2.y());
|
||||
const BVH_Vec3d& aMaxPntLft2 = aBVH2->MaxPoint (aNodeData2.y());
|
||||
const BVH_Vec3d& aMinPntRgh2 = aBVH2->MinPoint (aNodeData2.z());
|
||||
const BVH_Vec3d& aMaxPntRgh2 = aBVH2->MaxPoint (aNodeData2.z());
|
||||
|
||||
if (OverlapBoxes (aMinPntLft1, aMaxPntLft1, aMinPntLft2, aMaxPntLft2, myTolerance))
|
||||
{
|
||||
aPairsToProcess[aNbPairs++] = BRepExtrema_StackItem (aNodeData1.y(), aNodeData2.y());
|
||||
}
|
||||
if (OverlapBoxes (aMinPntLft1, aMaxPntLft1, aMinPntRgh2, aMaxPntRgh2, myTolerance))
|
||||
{
|
||||
aPairsToProcess[aNbPairs++] = BRepExtrema_StackItem (aNodeData1.y(), aNodeData2.z());
|
||||
}
|
||||
if (OverlapBoxes (aMinPntRgh1, aMaxPntRgh1, aMinPntLft2, aMaxPntLft2, myTolerance))
|
||||
{
|
||||
aPairsToProcess[aNbPairs++] = BRepExtrema_StackItem (aNodeData1.z(), aNodeData2.y());
|
||||
}
|
||||
if (OverlapBoxes (aMinPntRgh1, aMaxPntRgh1, aMinPntRgh2, aMaxPntRgh2, myTolerance))
|
||||
{
|
||||
aPairsToProcess[aNbPairs++] = BRepExtrema_StackItem (aNodeData1.z(), aNodeData2.z());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const BVH_Vec3d& aMinPntLeaf = aBVH2->MinPoint (aNodes.Node2);
|
||||
const BVH_Vec3d& aMaxPntLeaf = aBVH2->MaxPoint (aNodes.Node2);
|
||||
|
||||
if (OverlapBoxes (aMinPntLft1, aMaxPntLft1, aMinPntLeaf, aMaxPntLeaf, myTolerance))
|
||||
{
|
||||
aPairsToProcess[aNbPairs++] = BRepExtrema_StackItem (aNodeData1.y(), aNodes.Node2);
|
||||
}
|
||||
if (OverlapBoxes (aMinPntRgh1, aMaxPntRgh1, aMinPntLeaf, aMaxPntLeaf, myTolerance))
|
||||
{
|
||||
aPairsToProcess[aNbPairs++] = BRepExtrema_StackItem (aNodeData1.z(), aNodes.Node2);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const BVH_Vec3d& aMinPntLeaf = aBVH1->MinPoint (aNodes.Node1);
|
||||
const BVH_Vec3d& aMaxPntLeaf = aBVH1->MaxPoint (aNodes.Node1);
|
||||
|
||||
const BVH_Vec3d& aMinPntLft2 = aBVH2->MinPoint (aNodeData2.y());
|
||||
const BVH_Vec3d& aMaxPntLft2 = aBVH2->MaxPoint (aNodeData2.y());
|
||||
const BVH_Vec3d& aMinPntRgh2 = aBVH2->MinPoint (aNodeData2.z());
|
||||
const BVH_Vec3d& aMaxPntRgh2 = aBVH2->MaxPoint (aNodeData2.z());
|
||||
|
||||
if (OverlapBoxes (aMinPntLft2, aMaxPntLft2, aMinPntLeaf, aMaxPntLeaf, myTolerance))
|
||||
{
|
||||
aPairsToProcess[aNbPairs++] = BRepExtrema_StackItem (aNodes.Node1, aNodeData2.y());
|
||||
}
|
||||
if (OverlapBoxes (aMinPntRgh2, aMaxPntRgh2, aMinPntLeaf, aMaxPntLeaf, myTolerance))
|
||||
{
|
||||
aPairsToProcess[aNbPairs++] = BRepExtrema_StackItem (aNodes.Node1, aNodeData2.z());
|
||||
}
|
||||
}
|
||||
|
||||
if (aNbPairs > 0)
|
||||
{
|
||||
aNodes = aPairsToProcess[0];
|
||||
|
||||
for (Standard_Integer anIdx = 1; anIdx < aNbPairs; ++anIdx)
|
||||
{
|
||||
aStack[++aHead] = aPairsToProcess[anIdx];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (aHead < 0)
|
||||
break;
|
||||
|
||||
aNodes = aStack[aHead--];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
myIsDone = Standard_True;
|
||||
myOverlapTool.Perform (myTolerance);
|
||||
}
|
||||
|
@ -17,12 +17,11 @@
|
||||
#define _BRepExtrema_ShapeProximity_HeaderFile
|
||||
|
||||
#include <BVH_Geometry.hxx>
|
||||
#include <BRepExtrema_TriangleSet.hxx>
|
||||
#include <TColStd_PackedMapOfInteger.hxx>
|
||||
#include <NCollection_DataMap.hxx>
|
||||
#include <TColStd_PackedMapOfInteger.hxx>
|
||||
|
||||
//! Set of overlapped sub-shapes.
|
||||
typedef NCollection_DataMap<Standard_Integer, TColStd_PackedMapOfInteger > BRepExtrema_OverlappedSubShapes;
|
||||
#include <BRepExtrema_TriangleSet.hxx>
|
||||
#include <BRepExtrema_OverlapTool.hxx>
|
||||
|
||||
//! Tool class for shape proximity detection.
|
||||
//! For two given shapes and given tolerance (offset from the mesh) the algorithm allows
|
||||
@ -38,7 +37,7 @@ typedef NCollection_DataMap<Standard_Integer, TColStd_PackedMapOfInteger > BRepE
|
||||
//! on distance less than the given tolerance from each other.
|
||||
class BRepExtrema_ShapeProximity
|
||||
{
|
||||
public:
|
||||
public:
|
||||
|
||||
//! Creates empty proximity tool.
|
||||
Standard_EXPORT BRepExtrema_ShapeProximity (const Standard_Real theTolerance = 0.0);
|
||||
@ -68,58 +67,50 @@ public:
|
||||
//! Loads 2nd shape into proximity tool.
|
||||
Standard_EXPORT Standard_Boolean LoadShape2 (const TopoDS_Shape& theShape2);
|
||||
|
||||
//! Performs search for overlapped faces.
|
||||
//! Performs search of overlapped faces.
|
||||
Standard_EXPORT void Perform();
|
||||
|
||||
//! True if the search is completed.
|
||||
Standard_Boolean IsDone() const
|
||||
{
|
||||
return myIsDone;
|
||||
return myOverlapTool.IsDone();
|
||||
}
|
||||
|
||||
//! Returns set of all the face triangles of the 1st shape.
|
||||
const NCollection_Handle<BRepExtrema_TriangleSet>& PrimitiveSet1() const
|
||||
//! Returns set of IDs of overlapped faces of 1st shape (started from 0).
|
||||
const BRepExtrema_MapOfIntegerPackedMapOfInteger& OverlapSubShapes1() const
|
||||
{
|
||||
return myPrimitiveSet1;
|
||||
return myOverlapTool.OverlapSubShapes1();
|
||||
}
|
||||
|
||||
//! Returns set of all the face triangles of the 2nd shape.
|
||||
const NCollection_Handle<BRepExtrema_TriangleSet>& PrimitiveSet2() const
|
||||
//! Returns set of IDs of overlapped faces of 2nd shape (started from 0).
|
||||
const BRepExtrema_MapOfIntegerPackedMapOfInteger& OverlapSubShapes2() const
|
||||
{
|
||||
return myPrimitiveSet2;
|
||||
return myOverlapTool.OverlapSubShapes2();
|
||||
}
|
||||
|
||||
//! Returns set of IDs of overlapped faces of 1st shape.
|
||||
const BRepExtrema_OverlappedSubShapes& OverlapSubShapes1() const
|
||||
{
|
||||
return myOverlapSubShapes1;
|
||||
}
|
||||
|
||||
//! Returns set of IDs of overlapped faces of 2nd shape.
|
||||
const BRepExtrema_OverlappedSubShapes& OverlapSubShapes2() const
|
||||
{
|
||||
return myOverlapSubShapes2;
|
||||
}
|
||||
|
||||
//! Returns sub-shape from 1st shape with the given index.
|
||||
//! Returns sub-shape from 1st shape with the given index (started from 0).
|
||||
const TopoDS_Face& GetSubShape1 (const Standard_Integer theID) const
|
||||
{
|
||||
return myFaceList1.Value (theID);
|
||||
}
|
||||
|
||||
//! Returns sub-shape from 1st shape with the given index.
|
||||
//! Returns sub-shape from 1st shape with the given index (started from 0).
|
||||
const TopoDS_Face& GetSubShape2 (const Standard_Integer theID) const
|
||||
{
|
||||
return myFaceList2.Value (theID);
|
||||
}
|
||||
|
||||
protected:
|
||||
//! Returns set of all the face triangles of the 1st shape.
|
||||
const Handle(BRepExtrema_TriangleSet)& ElementSet1() const
|
||||
{
|
||||
return myElementSet1;
|
||||
}
|
||||
|
||||
//! Performs narrow-phase of overlap test (exact intersection).
|
||||
void IntersectLeavesExact (const BVH_Vec4i& theLeaf1, const BVH_Vec4i& theLeaf2);
|
||||
|
||||
//! Performs narrow-phase of overlap test (intersection with non-zero tolerance).
|
||||
void IntersectLeavesToler (const BVH_Vec4i& theLeaf1, const BVH_Vec4i& theLeaf2);
|
||||
//! Returns set of all the face triangles of the 2nd shape.
|
||||
const Handle(BRepExtrema_TriangleSet)& ElementSet2() const
|
||||
{
|
||||
return myElementSet2;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@ -137,17 +128,12 @@ private:
|
||||
BRepExtrema_ShapeList myFaceList2;
|
||||
|
||||
//! Set of all the face triangles of the 1st shape.
|
||||
NCollection_Handle<BRepExtrema_TriangleSet> myPrimitiveSet1;
|
||||
Handle(BRepExtrema_TriangleSet) myElementSet1;
|
||||
//! Set of all the face triangles of the 2nd shape.
|
||||
NCollection_Handle<BRepExtrema_TriangleSet> myPrimitiveSet2;
|
||||
Handle(BRepExtrema_TriangleSet) myElementSet2;
|
||||
|
||||
//! Set of overlapped faces of 1st shape.
|
||||
BRepExtrema_OverlappedSubShapes myOverlapSubShapes1;
|
||||
//! Set of overlapped faces of 2nd shape.
|
||||
BRepExtrema_OverlappedSubShapes myOverlapSubShapes2;
|
||||
|
||||
//! Is overlap test completed?
|
||||
Standard_Boolean myIsDone;
|
||||
//! Overlap tool used for intersection/overlap test.
|
||||
BRepExtrema_OverlapTool myOverlapTool;
|
||||
|
||||
};
|
||||
|
||||
|
@ -21,6 +21,9 @@
|
||||
#include <Poly_Triangulation.hxx>
|
||||
#include <TColgp_Array1OfPnt2d.hxx>
|
||||
|
||||
IMPLEMENT_STANDARD_HANDLE (BRepExtrema_TriangleSet, Standard_Transient)
|
||||
IMPLEMENT_STANDARD_RTTIEXT(BRepExtrema_TriangleSet, Standard_Transient)
|
||||
|
||||
//=======================================================================
|
||||
//function : BRepExtrema_TriangleSet
|
||||
//purpose : Creates empty triangle set
|
||||
@ -224,3 +227,4 @@ Standard_Boolean BRepExtrema_TriangleSet::Init (const BRepExtrema_ShapeList& the
|
||||
|
||||
return Standard_True;
|
||||
}
|
||||
|
||||
|
@ -17,14 +17,13 @@
|
||||
#define _BRepExtrema_TriangleSet_HeaderFile
|
||||
|
||||
#include <TopoDS_Face.hxx>
|
||||
|
||||
#include <BVH_PrimitiveSet.hxx>
|
||||
|
||||
//! List of shapes and their IDs for collision detection.
|
||||
typedef NCollection_Vector<TopoDS_Face> BRepExtrema_ShapeList;
|
||||
|
||||
//! Triangle set corresponding to specific face.
|
||||
class BRepExtrema_TriangleSet : public BVH_PrimitiveSet<Standard_Real, 3>
|
||||
class BRepExtrema_TriangleSet : public BVH_PrimitiveSet<Standard_Real, 3>, public Standard_Transient
|
||||
{
|
||||
public:
|
||||
|
||||
@ -79,6 +78,12 @@ protected:
|
||||
//! Array of vertex coordinates.
|
||||
BVH_Array3d myVertexArray;
|
||||
|
||||
public:
|
||||
|
||||
DEFINE_STANDARD_RTTI(BRepExtrema_TriangleSet)
|
||||
|
||||
};
|
||||
|
||||
DEFINE_STANDARD_HANDLE (BRepExtrema_TriangleSet, Standard_Transient)
|
||||
|
||||
#endif // _BRepExtrema_TriangleSet_HeaderFile
|
||||
|
@ -19,5 +19,11 @@ BRepExtrema_SolutionElem.hxx
|
||||
BRepExtrema_SupportType.hxx
|
||||
BRepExtrema_TriangleSet.hxx
|
||||
BRepExtrema_TriangleSet.cxx
|
||||
BRepExtrema_OverlapTool.hxx
|
||||
BRepExtrema_OverlapTool.cxx
|
||||
BRepExtrema_ElementFilter.hxx
|
||||
BRepExtrema_ShapeProximity.hxx
|
||||
BRepExtrema_ShapeProximity.cxx
|
||||
BRepExtrema_SelfIntersection.hxx
|
||||
BRepExtrema_SelfIntersection.cxx
|
||||
BRepExtrema_MapOfIntegerPackedMapOfInteger.hxx
|
||||
|
@ -21,8 +21,10 @@
|
||||
#include <BRepExtrema_Poly.hxx>
|
||||
#include <BRepExtrema_DistShapeShape.hxx>
|
||||
#include <BRepExtrema_ShapeProximity.hxx>
|
||||
#include <BRepExtrema_SelfIntersection.hxx>
|
||||
#include <BRepLib_MakeEdge.hxx>
|
||||
#include <BRepLib_MakeVertex.hxx>
|
||||
#include <BRepBuilderAPI_MakeEdge.hxx>
|
||||
#include <TopoDS_Builder.hxx>
|
||||
#include <TopoDS_Compound.hxx>
|
||||
#include <Draw.hxx>
|
||||
@ -233,18 +235,18 @@ static int ShapeProximity (Draw_Interpretor& theDI, Standard_Integer theNbArgs,
|
||||
|
||||
if (aProfile)
|
||||
{
|
||||
theDI << "Number of primitives in shape 1: " << aTool.PrimitiveSet1()->Size() << "\n";
|
||||
theDI << "Number of primitives in shape 2: " << aTool.PrimitiveSet2()->Size() << "\n";
|
||||
theDI << "Number of primitives in shape 1: " << aTool.ElementSet1()->Size() << "\n";
|
||||
theDI << "Number of primitives in shape 2: " << aTool.ElementSet2()->Size() << "\n";
|
||||
theDI << "Building data structures: " << aInitTime << "\n";
|
||||
theDI << "Executing proximity test: " << aWorkTime << "\n";
|
||||
}
|
||||
|
||||
TopoDS_Builder aCompBuilder;
|
||||
TopoDS_Builder aCompBuilder;
|
||||
|
||||
TopoDS_Compound aFaceCompound1;
|
||||
aCompBuilder.MakeCompound (aFaceCompound1);
|
||||
|
||||
for (BRepExtrema_OverlappedSubShapes::Iterator anIt1 (aTool.OverlapSubShapes1()); anIt1.More(); anIt1.Next())
|
||||
for (BRepExtrema_MapOfIntegerPackedMapOfInteger::Iterator anIt1 (aTool.OverlapSubShapes1()); anIt1.More(); anIt1.Next())
|
||||
{
|
||||
TCollection_AsciiString aStr = TCollection_AsciiString (theArgs[1]) + "_" + (anIt1.Key() + 1);
|
||||
|
||||
@ -258,7 +260,7 @@ static int ShapeProximity (Draw_Interpretor& theDI, Standard_Integer theNbArgs,
|
||||
TopoDS_Compound aFaceCompound2;
|
||||
aCompBuilder.MakeCompound (aFaceCompound2);
|
||||
|
||||
for (BRepExtrema_OverlappedSubShapes::Iterator anIt2 (aTool.OverlapSubShapes2()); anIt2.More(); anIt2.Next())
|
||||
for (BRepExtrema_MapOfIntegerPackedMapOfInteger::Iterator anIt2 (aTool.OverlapSubShapes2()); anIt2.More(); anIt2.Next())
|
||||
{
|
||||
TCollection_AsciiString aStr = TCollection_AsciiString (theArgs[2]) + "_" + (anIt2.Key() + 1);
|
||||
|
||||
@ -275,6 +277,123 @@ static int ShapeProximity (Draw_Interpretor& theDI, Standard_Integer theNbArgs,
|
||||
return 0;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
//function : ShapeSelfIntersection
|
||||
//purpose :
|
||||
//==============================================================================
|
||||
static int ShapeSelfIntersection (Draw_Interpretor& theDI, Standard_Integer theNbArgs, const char** theArgs)
|
||||
{
|
||||
if (theNbArgs < 2 || theNbArgs > 5)
|
||||
{
|
||||
std::cout << "Usage: " << theArgs[0] <<
|
||||
" Shape [-tol <value>] [-profile]" << std::endl;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
TopoDS_Shape aShape = DBRep::Get (theArgs[1]);
|
||||
|
||||
if (aShape.IsNull())
|
||||
{
|
||||
std::cout << "Error: Failed to find specified shape" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
Standard_Real aTolerance = 0.0;
|
||||
Standard_Boolean aToProfile = Standard_False;
|
||||
|
||||
for (Standard_Integer anArgIdx = 2; anArgIdx < theNbArgs; ++anArgIdx)
|
||||
{
|
||||
TCollection_AsciiString aFlag (theArgs[anArgIdx]);
|
||||
aFlag.LowerCase();
|
||||
|
||||
if (aFlag == "-tol")
|
||||
{
|
||||
if (++anArgIdx >= theNbArgs)
|
||||
{
|
||||
std::cout << "Error: wrong syntax at argument '" << aFlag << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
const Standard_Real aValue = Draw::Atof (theArgs[anArgIdx]);
|
||||
if (aValue < 0.0)
|
||||
{
|
||||
std::cout << "Error: Tolerance value should be non-negative" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
aTolerance = aValue;
|
||||
}
|
||||
}
|
||||
|
||||
if (aFlag == "-profile")
|
||||
{
|
||||
aToProfile = Standard_True;
|
||||
}
|
||||
}
|
||||
|
||||
OSD_Timer aTimer;
|
||||
|
||||
Standard_Real aInitTime = 0.0;
|
||||
Standard_Real aWorkTime = 0.0;
|
||||
|
||||
if (aToProfile)
|
||||
{
|
||||
aTimer.Start();
|
||||
}
|
||||
|
||||
BRepExtrema_SelfIntersection aTool (aShape, aTolerance);
|
||||
|
||||
if (aToProfile)
|
||||
{
|
||||
aInitTime = aTimer.ElapsedTime();
|
||||
|
||||
aTimer.Reset();
|
||||
aTimer.Start();
|
||||
}
|
||||
|
||||
// Perform shape self-intersection test
|
||||
aTool.Perform();
|
||||
|
||||
if (!aTool.IsDone())
|
||||
{
|
||||
std::cout << "Error: Failed to perform proximity test" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (aToProfile)
|
||||
{
|
||||
aWorkTime = aTimer.ElapsedTime();
|
||||
aTimer.Stop();
|
||||
|
||||
theDI << "Building data structure (BVH): " << aInitTime << "\n";
|
||||
theDI << "Executing self-intersection test: " << aWorkTime << "\n";
|
||||
}
|
||||
|
||||
// Extract output faces
|
||||
TopoDS_Builder aCompBuilder;
|
||||
TopoDS_Compound aFaceCompound;
|
||||
|
||||
aCompBuilder.MakeCompound (aFaceCompound);
|
||||
|
||||
for (BRepExtrema_MapOfIntegerPackedMapOfInteger::Iterator anIt (aTool.OverlapElements()); anIt.More(); anIt.Next())
|
||||
{
|
||||
TCollection_AsciiString aStr = TCollection_AsciiString (theArgs[1]) + "_" + (anIt.Key() + 1);
|
||||
|
||||
const TopoDS_Face& aFace = aTool.GetSubShape (anIt.Key());
|
||||
aCompBuilder.Add (aFaceCompound, aFace);
|
||||
DBRep::Set (aStr.ToCString(), aFace);
|
||||
|
||||
theDI << aStr << " \n";
|
||||
}
|
||||
|
||||
theDI << "Compound of overlapped sub-faces: " << theArgs[1] << "_overlapped\n";
|
||||
DBRep::Set ((TCollection_AsciiString (theArgs[1]) + "_" + "overlapped").ToCString(), aFaceCompound);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : ExtremaCommands
|
||||
//purpose :
|
||||
@ -313,4 +432,17 @@ void BRepTest::ExtremaCommands (Draw_Interpretor& theCommands)
|
||||
__FILE__,
|
||||
ShapeProximity,
|
||||
aGroup);
|
||||
|
||||
theCommands.Add ("selfintersect",
|
||||
"selfintersect Shape [-tol <value>] [-profile]"
|
||||
"\n\t\t: Searches for intersected/overlapped faces in the given shape."
|
||||
"\n\t\t: The algorithm uses shape tessellation (should be computed in"
|
||||
"\n\t\t: advance), and provides approximate results. The options are:"
|
||||
"\n\t\t: -tol : non-negative tolerance value used for overlapping"
|
||||
"\n\t\t: test (for zero tolerance, the strict intersection"
|
||||
"\n\t\t: test will be performed)"
|
||||
"\n\t\t: -profile : outputs execution time for main algorithm stages",
|
||||
__FILE__,
|
||||
ShapeSelfIntersection,
|
||||
aGroup);
|
||||
}
|
||||
|
42
tests/bugs/modalg_6/bug26180
Normal file
42
tests/bugs/modalg_6/bug26180
Normal file
@ -0,0 +1,42 @@
|
||||
puts "========"
|
||||
puts "OCC26180"
|
||||
puts "========"
|
||||
puts ""
|
||||
##################################################################
|
||||
## Modeling Algorithms - Provide shape self-intersection detector
|
||||
##################################################################
|
||||
|
||||
list aBoxNames
|
||||
|
||||
set BOX_SIZE 5
|
||||
set BOX_GRID_SIZE 30
|
||||
|
||||
for {set i 0} {$i < $BOX_GRID_SIZE} {incr i} {
|
||||
for {set j 0} {$j < $BOX_GRID_SIZE} {incr j} {
|
||||
box b_[expr $i]_[expr $j] [expr $i * 6] [expr $j * 6] 0 5 5 5
|
||||
lappend aBoxNames b_[expr $i]_[expr $j]
|
||||
lappend aBoxNames " "
|
||||
}
|
||||
}
|
||||
|
||||
psphere s 30
|
||||
ttranslate s 90.0 90.0 0.0
|
||||
incmesh s 0.002
|
||||
trinfo s
|
||||
|
||||
set aCompName "C"
|
||||
compound {*}$aBoxNames s $aCompName
|
||||
|
||||
vinit
|
||||
vsetdispmode 1
|
||||
vdisplay $aCompName
|
||||
vsettransparency $aCompName 0.8
|
||||
vdump $imagedir/${casename}_1.png
|
||||
|
||||
selfintersect $aCompName -tol 0.0 -profile
|
||||
|
||||
vdisplay [set aCompName]_overlapped
|
||||
vsetcolor [set aCompName]_overlapped red
|
||||
vsettransparency [set aCompName]_overlapped 0.5
|
||||
vfit
|
||||
vdump $imagedir/${casename}_2.png
|
Loading…
x
Reference in New Issue
Block a user