0022775: [CEA 1091] Add an option on GetNonBlocks to retrieve quadrangular faces defined on C1 edges

This commit is contained in:
skv 2015-01-22 12:14:55 +03:00
parent 6733a2afc6
commit 8bfdc37bff
12 changed files with 321 additions and 355 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 8.4 KiB

View File

@ -5,24 +5,45 @@
This operation retrieves all non-block solids and non-quadrangular faces from the selected shape.
A non-block solid is a solid that does not have 6 faces, or has 6 faces, but some of them are not quadrangular.
A block solid is a solid that has 6 faces and 12 edges.
A quadrangular face is a face that has 1 wire with 4 edges. If there are
more than 4 edges in a single wire and C1 continuity mode is switched on,
a face is quadrangular if it has 4 bounds of C1 continuity.
All solids and faces from a shape that do not satisfy these conditions are
returned by this operation.
\image html measures2.png
\b Preview option shows non block solids and faces in the viewer.
It is possible to select an \b Object to be explored, to check or uncheck
<b>Use C1 criterion</b> option and to set the <b>Angular Tolerance</b>
to check C1 continuity between neighbor edges in a wire.
Press \b Apply or <b>Apply and Close</b> button to publish non block solids and faces in the Object
Browser under the processed object. Solids and faces are published separately in two groups.
\b Preview option shows non-block solids and non-quadrangular faces in the viewer.
Press \b Apply or <b>Apply and Close</b> button to publish non-block solids
and non-quadrangular faces in the Object Browser under the processed object.
Solids and faces are published separately in two groups.
If no bad sub-shapes have been found, the corresponding warning is shown.
\image html measures2a.png
\n <b>TUI Command:</b>
<em>geompy.GetNonBlocks(Compound).</em> Returns a tuple of two GEOM_Objects.
<em>geompy.GetNonBlocks(theShape, theIsUseC1 = False, theAngTolerance = 1.e-12).</em> \n
where \n
\em theShape is the shape to explore, \n
\em theIsUseC1 is the flag to check if there are 4 bounds on a face
taking into account C1 continuity, \n
\em theAngTolerance the angular tolerance to check if two neighbor edges are
codirectional in the common vertex with this tolerance. This parameter is
used only if \em theIsUseC1 is set to True.
The first object is a group of all non block solids; the second object is a group of all non
quadrangular faces.
This command returns a tuple of two GEOM_Objects.
The first object is a group of all non-block solids; the second object is a group
of all non-quadrangular faces.
See also a \ref tui_get_non_blocks_page "TUI example".

View File

@ -2781,12 +2781,17 @@ module GEOM
* \brief Retrieve all non blocks solids and faces from a shape.
*
* \param theShape The shape to explore.
* \param theToleranceC1 the tolerance to check if two neighbor edges are
* collinear in the common vertex with this tolerance. Negative
* value means that C1 criterion is not used (old implementation).
* \param theNonQuads Output parameter. Group of all non quadrangular faces.
*
* \return Group of all non block solids (= not 6 faces, or with 6
* faces, but with the presence of non-quadrangular faces).
*/
GEOM_Object GetNonBlocks (in GEOM_Object theShape, out GEOM_Object theNonQuads);
GEOM_Object GetNonBlocks (in GEOM_Object theShape,
in double theToleranceC1,
out GEOM_Object theNonQuads);
/*!
* \brief Remove all seam and degenerated edges from \a theShape.

View File

@ -407,6 +407,10 @@ Please, select face, shell or solid and try again</translation>
<source>GEOM_NONBLOCKS</source>
<translation>NonBlocksGroup</translation>
</message>
<message>
<source>GEOM_USE_C1_CRITERION</source>
<translation>Use C1 criterion</translation>
</message>
<message>
<source>GEOM_CHECK_INFOS</source>
<translation>Object And Its Topological Information</translation>

View File

@ -88,6 +88,7 @@
#include <Bnd_Box.hxx>
#include <GProp_GProps.hxx>
#include <Geom_Curve.hxx>
#include <Geom_Surface.hxx>
#include <ShapeAnalysis_Surface.hxx>
@ -103,6 +104,147 @@
#include <Standard_Failure.hxx>
#include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
/**
* This function returns Standard_True if the face is quadrangular. It means
* that it has only 1 wire with 4 edges. If there are more then 4 edges in
* the wire and theToleranceC1 is not negative the new implementation is used.
* According to it the face is quadrangular if it is quadrangular according to
* an old implementation or if it has a single wire with more then 4 edges
* that form exactly 4 bounds of C1 continuity with the given tolerance.
*
* \param theFace the face to be checked
* \param theToleranceC1 if negative, it is not used; otherwise it is used
* to check if two neighbor edges of face have C1 continuity.
* \return Standard_True if the face is quadrangular; Standard_False otherwise.
*/
static Standard_Boolean IsQuadrangle(const TopoDS_Face &theFace,
const Standard_Real theToleranceC1)
{
TopExp_Explorer aFExp (theFace, TopAbs_WIRE);
if (!aFExp.More()) {
// no wire in the face
return Standard_False;
}
TopoDS_Shape aWire = aFExp.Current();
aFExp.Next();
if (aFExp.More()) {
// multiple wires in the face
return Standard_False;
}
// Check number of edges in the face
Standard_Integer aNbEdges = 0;
TopTools_MapOfShape aMapEdges;
TopExp_Explorer aWExp(aWire, TopAbs_EDGE);
for (; aWExp.More(); aWExp.Next()) {
if (aMapEdges.Add(aWExp.Current())) {
aNbEdges++;
if (aNbEdges > 4) {
break;
}
}
}
if (aNbEdges < 4) {
return Standard_False;
}
if (aNbEdges > 4) {
if (theToleranceC1 < 0.) {
return Standard_False;
}
// Check if a wire has 4 bounds of C1 continuity.
BRepTools_WireExplorer aWireExp(TopoDS::Wire(aWire), theFace);
TopTools_ListOfShape anEdges;
for (aNbEdges = 0; aWireExp.More(); aWireExp.Next()) {
const TopoDS_Edge &anEdge = aWireExp.Current();
// Skip degenerated edges.
if (!BRep_Tool::Degenerated(anEdge)) {
anEdges.Append(anEdge);
++aNbEdges;
}
}
if (aNbEdges < 4) {
return Standard_False;
}
// Compute number of sharp corners.
anEdges.Append(anEdges.First()); // To make a loop.
TopTools_ListIteratorOfListOfShape anIter(anEdges);
Standard_Real aPar[2];
Standard_Integer aNbCorners = 0;
TopoDS_Edge anEdge1 = TopoDS::Edge(anEdges.First());
Handle(Geom_Curve) aCurve1 = BRep_Tool::Curve(anEdge1, aPar[0], aPar[1]);
Handle(Geom_Curve) aCurve2;
TopoDS_Edge anEdge2;
TopoDS_Vertex aCommonVtx;
gp_Pnt aPnt;
gp_Vec aVec1;
gp_Vec aVec2;
Standard_Boolean isReversed1 = (anEdge1.Orientation() == TopAbs_REVERSED);
Standard_Boolean isReversed2;
for (anIter.Next(); anIter.More(); anIter.Next()) {
TopoDS_Edge anEdge2 = TopoDS::Edge(anIter.Value());
if (!TopExp::CommonVertex(anEdge1, anEdge2, aCommonVtx)) {
// NEVERREACHED
return Standard_False;
}
// Check the angle between tangent vectors of 2 curves at this point.
Standard_Real aParam1 = BRep_Tool::Parameter(aCommonVtx, anEdge1);
Standard_Real aParam2 = BRep_Tool::Parameter(aCommonVtx, anEdge2);
aCurve2 = BRep_Tool::Curve(anEdge2, aPar[0], aPar[1]);
isReversed2 = (anEdge2.Orientation() == TopAbs_REVERSED);
aCurve1->D1(aParam1, aPnt, aVec1);
aCurve2->D1(aParam2, aPnt, aVec2);
if (isReversed1) {
aVec1.Reverse();
}
if (isReversed2) {
aVec2.Reverse();
}
const Standard_Real anAngle = aVec1.Angle(aVec2);
if (anAngle > theToleranceC1) {
++aNbCorners;
if (aNbCorners > 4) {
break;
}
}
// Go to the next couple of edges.
anEdge1 = anEdge2;
aCurve1 = aCurve2;
isReversed1 = isReversed2;
}
// Check the total number of corners.
if (aNbCorners != 4) {
return Standard_False;
}
}
return Standard_True;
}
//=============================================================================
/*!
* constructor:
@ -1647,7 +1789,8 @@ void GEOMImpl_IBlocksOperations::AddBlocksFrom (const TopoDS_Shape& theShape,
TopTools_ListOfShape& BLO,
TopTools_ListOfShape& NOT,
TopTools_ListOfShape& EXT,
TopTools_ListOfShape& NOQ)
TopTools_ListOfShape& NOQ,
const Standard_Real theToleranceC1)
{
TopAbs_ShapeEnum aType = theShape.ShapeType();
switch (aType) {
@ -1656,7 +1799,7 @@ void GEOMImpl_IBlocksOperations::AddBlocksFrom (const TopoDS_Shape& theShape,
{
TopoDS_Iterator It (theShape);
for (; It.More(); It.Next()) {
AddBlocksFrom(It.Value(), BLO, NOT, EXT, NOQ);
AddBlocksFrom(It.Value(), BLO, NOT, EXT, NOQ, theToleranceC1);
}
}
break;
@ -1676,41 +1819,12 @@ void GEOMImpl_IBlocksOperations::AddBlocksFrom (const TopoDS_Shape& theShape,
TopExp_Explorer expF (theShape, TopAbs_FACE);
for (; expF.More(); expF.Next()) {
if (mapFaces.Add(expF.Current())) {
TopoDS_Face aF = TopoDS::Face(expF.Current());
if (mapFaces.Add(aF)) {
nbFaces++;
//0021483//if (nbFaces > 6) break;
// get wire
TopoDS_Shape aF = expF.Current();
TopExp_Explorer wires (aF, TopAbs_WIRE);
if (!wires.More()) {
// no wire in the face
hasNonQuadr = Standard_True;
NOQ.Append(aF);//0021483
//0021483//break;
continue;
}
TopoDS_Shape aWire = wires.Current();
wires.Next();
if (wires.More()) {
// multiple wires in the face
hasNonQuadr = Standard_True;
NOQ.Append(aF);//0021483
//0021483//break;
continue;
}
// Check number of edges in the face
Standard_Integer nbEdges = 0;
TopTools_MapOfShape mapEdges;
TopExp_Explorer expW (aWire, TopAbs_EDGE);
for (; expW.More(); expW.Next()) {
if (mapEdges.Add(expW.Current())) {
nbEdges++;
if (nbEdges > 4) break;
}
}
if (nbEdges != 4) {
if (!IsQuadrangle(aF, theToleranceC1)) {
hasNonQuadr = Standard_True;
NOQ.Append(aF);//0021483
}
@ -1732,34 +1846,10 @@ void GEOMImpl_IBlocksOperations::AddBlocksFrom (const TopoDS_Shape& theShape,
TopTools_MapOfShape mapFaces;
TopExp_Explorer expF (theShape, TopAbs_FACE);
for (; expF.More(); expF.Next()) {
if (mapFaces.Add(expF.Current())) {
// get wire
TopoDS_Shape aF = expF.Current();
TopExp_Explorer wires (aF, TopAbs_WIRE);
if (!wires.More()) {
// no wire in the face
NOQ.Append(aF);//0021483
continue;
}
TopoDS_Shape aWire = wires.Current();
wires.Next();
if (wires.More()) {
// multiple wires in the face
NOQ.Append(aF);//0021483
continue;
}
TopoDS_Face aF = TopoDS::Face(expF.Current());
// Check number of edges in the face
Standard_Integer nbEdges = 0;
TopTools_MapOfShape mapEdges;
TopExp_Explorer expW (aWire, TopAbs_EDGE);
for (; expW.More(); expW.Next()) {
if (mapEdges.Add(expW.Current())) {
nbEdges++;
if (nbEdges > 4) break;
}
}
if (nbEdges != 4) {
if (mapFaces.Add(aF)) {
if (!IsQuadrangle(aF, theToleranceC1)) {
NOQ.Append(aF);//0021483
}
}
@ -1771,99 +1861,6 @@ void GEOMImpl_IBlocksOperations::AddBlocksFrom (const TopoDS_Shape& theShape,
}
}
void AddBlocksFromOld (const TopoDS_Shape& theShape,
TopTools_ListOfShape& BLO,
TopTools_ListOfShape& NOT,
TopTools_ListOfShape& DEG,
TopTools_ListOfShape& SEA)
{
TopAbs_ShapeEnum aType = theShape.ShapeType();
switch (aType) {
case TopAbs_COMPOUND:
case TopAbs_COMPSOLID:
{
TopoDS_Iterator It (theShape);
for (; It.More(); It.Next()) {
AddBlocksFromOld(It.Value(), BLO, NOT, DEG, SEA);
}
}
break;
case TopAbs_SOLID:
{
TopTools_MapOfShape mapFaces;
TopExp_Explorer expF (theShape, TopAbs_FACE);
Standard_Integer nbFaces = 0;
Standard_Boolean hasNonQuadr = Standard_False;
Standard_Boolean hasDegenerated = Standard_False;
Standard_Boolean hasSeam = Standard_False;
for (; expF.More(); expF.Next()) {
if (mapFaces.Add(expF.Current())) {
nbFaces++;
if (nbFaces > 6) break;
// Check number of edges in the face
Standard_Integer nbEdges = 0;
TopTools_MapOfShape mapEdges;
// get wire
TopoDS_Shape aF = expF.Current();
TopExp_Explorer wires (aF, TopAbs_WIRE);
if (!wires.More()) {
// no wire in the face
hasNonQuadr = Standard_True;
break;
}
TopoDS_Shape aWire = wires.Current();
wires.Next();
if (wires.More()) {
// multiple wires in the face
hasNonQuadr = Standard_True;
break;
}
// iterate on wire
BRepTools_WireExplorer aWE (TopoDS::Wire(aWire), TopoDS::Face(aF));
for (; aWE.More(); aWE.Next(), nbEdges++) {
if (BRep_Tool::Degenerated(aWE.Current())) {
// degenerated edge found
hasDegenerated = Standard_True;
// break;
}
if (mapEdges.Contains(aWE.Current())) {
// seam edge found
hasSeam = Standard_True;
// break;
}
mapEdges.Add(aWE.Current());
}
if (nbEdges != 4) {
hasNonQuadr = Standard_True;
}
}
}
if (nbFaces == 6) {
if (hasDegenerated || hasSeam) {
if (hasDegenerated) {
DEG.Append(theShape);
}
if (hasSeam) {
SEA.Append(theShape);
}
} else if (hasNonQuadr) {
NOT.Append(theShape);
} else {
BLO.Append(theShape);
}
} else {
NOT.Append(theShape);
}
}
break;
default:
NOT.Append(theShape);
}
}
#define REL_NOT_CONNECTED 0
#define REL_OK 1
#define REL_NOT_GLUED 2
@ -2086,158 +2083,6 @@ Standard_Boolean HasAnyConnection (const Standard_Integer theBlockIndex,
return Standard_False;
}
//=============================================================================
/*!
* CheckCompoundOfBlocksOld
*/
//=============================================================================
Standard_Boolean GEOMImpl_IBlocksOperations::CheckCompoundOfBlocksOld
(Handle(GEOM_Object) theCompound,
std::list<BCError>& theErrors)
{
SetErrorCode(KO);
if (theCompound.IsNull()) return Standard_False;
TopoDS_Shape aBlockOrComp = theCompound->GetValue();
Standard_Boolean isCompOfBlocks = Standard_True;
// Map sub-shapes and their indices
TopTools_IndexedMapOfShape anIndices;
TopExp::MapShapes(aBlockOrComp, anIndices);
// 1. Report non-blocks
TopTools_ListOfShape NOT; // Not blocks
TopTools_ListOfShape DEG; // Hexahedral solids, having degenerated edges
TopTools_ListOfShape SEA; // Hexahedral solids, having seam edges
TopTools_ListOfShape BLO; // All blocks from the given compound
AddBlocksFromOld(aBlockOrComp, BLO, NOT, DEG, SEA);
if (NOT.Extent() > 0) {
isCompOfBlocks = Standard_False;
BCError anErr;
anErr.error = NOT_BLOCK;
TopTools_ListIteratorOfListOfShape it (NOT);
for (; it.More(); it.Next()) {
anErr.incriminated.push_back(anIndices.FindIndex(it.Value()));
}
theErrors.push_back(anErr);
}
if (DEG.Extent() > 0 || SEA.Extent() > 0) {
isCompOfBlocks = Standard_False;
BCError anErr;
anErr.error = EXTRA_EDGE;
TopTools_ListIteratorOfListOfShape itDEG (DEG);
for (; itDEG.More(); itDEG.Next()) {
anErr.incriminated.push_back(anIndices.FindIndex(itDEG.Value()));
}
TopTools_ListIteratorOfListOfShape itSEA (SEA);
for (; itSEA.More(); itSEA.Next()) {
anErr.incriminated.push_back(anIndices.FindIndex(itSEA.Value()));
}
theErrors.push_back(anErr);
}
Standard_Integer nbBlocks = BLO.Extent();
if (nbBlocks == 0) {
isCompOfBlocks = Standard_False;
SetErrorCode(OK);
return isCompOfBlocks;
}
if (nbBlocks == 1) {
SetErrorCode(OK);
return isCompOfBlocks;
}
// Convert list of blocks into array for easy and fast access
Standard_Integer ibl = 1;
TopTools_Array1OfShape aBlocks (1, nbBlocks);
TopTools_ListIteratorOfListOfShape BLOit (BLO);
for (; BLOit.More(); BLOit.Next(), ibl++) {
aBlocks.SetValue(ibl, BLOit.Value());
}
// 2. Find relations between all blocks,
// report connection errors (NOT_GLUED and INVALID_CONNECTION)
TColStd_Array2OfInteger aRelations (1, nbBlocks, 1, nbBlocks);
aRelations.Init(REL_NOT_CONNECTED);
Standard_Integer row = 1;
for (row = 1; row <= nbBlocks; row++) {
TopoDS_Shape aBlock = aBlocks.Value(row);
Standard_Integer col = row + 1;
for (; col <= nbBlocks; col++) {
Standard_Integer aRel = BlocksRelation(aBlock, aBlocks.Value(col));
if (aRel != REL_NOT_CONNECTED) {
aRelations.SetValue(row, col, aRel);
aRelations.SetValue(col, row, aRel);
if (aRel == REL_NOT_GLUED) {
// report connection error
isCompOfBlocks = Standard_False;
BCError anErr;
anErr.error = NOT_GLUED;
anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(row)));
anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(col)));
theErrors.push_back(anErr);
} else if (aRel == REL_COLLISION_VV ||
aRel == REL_COLLISION_FF ||
aRel == REL_COLLISION_EE ||
aRel == REL_UNKNOWN) {
// report connection error
isCompOfBlocks = Standard_False;
BCError anErr;
anErr.error = INVALID_CONNECTION;
anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(row)));
anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(col)));
theErrors.push_back(anErr);
} else {
}
}
}
}
// 3. Find largest set of connected (good connection or not glued) blocks
TColStd_MapOfInteger aProcessedMap;
TColStd_MapOfInteger aLargestSet;
TColStd_MapOfInteger aCurrentSet;
for (ibl = 1; ibl <= nbBlocks; ibl++) {
if (!aProcessedMap.Contains(ibl)) {
aCurrentSet.Clear();
FindConnected(ibl, aRelations, aProcessedMap, aCurrentSet);
if (aCurrentSet.Extent() > aLargestSet.Extent()) {
aLargestSet = aCurrentSet;
}
}
}
// 4. Report all blocks, isolated from <aLargestSet>
BCError anErr;
anErr.error = NOT_CONNECTED;
Standard_Boolean hasIsolated = Standard_False;
for (ibl = 1; ibl <= nbBlocks; ibl++) {
if (!aLargestSet.Contains(ibl)) {
aProcessedMap.Clear();
if (!HasAnyConnection(ibl, aLargestSet, aRelations, aProcessedMap)) {
// report connection absence
hasIsolated = Standard_True;
anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(ibl)));
}
}
}
if (hasIsolated) {
isCompOfBlocks = Standard_False;
theErrors.push_back(anErr);
}
SetErrorCode(OK);
return isCompOfBlocks;
}
//=============================================================================
/*!
* PrintBCErrors
@ -2312,7 +2157,7 @@ Standard_Boolean GEOMImpl_IBlocksOperations::CheckCompoundOfBlocks
TopTools_ListOfShape EXT; // Hexahedral solids, having degenerated and/or seam edges
TopTools_ListOfShape BLO; // All blocks from the given compound
TopTools_ListOfShape NOQ; // All non-quadrangular faces
AddBlocksFrom(aBlockOrComp, BLO, NOT, EXT, NOQ);
AddBlocksFrom(aBlockOrComp, BLO, NOT, EXT, NOQ, -1.);
// Report non-blocks
if (NOT.Extent() > 0) {
@ -2478,7 +2323,8 @@ Standard_Boolean GEOMImpl_IBlocksOperations::CheckCompoundOfBlocks
*/
//=============================================================================
Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetNonBlocks
(Handle(GEOM_Object) theShape,
(Handle(GEOM_Object) theShape,
const Standard_Real theToleranceC1,
Handle(GEOM_Object)& theNonQuads)
{
SetErrorCode(KO);
@ -2491,7 +2337,7 @@ Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetNonBlocks
TopTools_ListOfShape NOT; // Not blocks
TopTools_ListOfShape EXT; // Hexahedral solids, having degenerated and/or seam edges
TopTools_ListOfShape NOQ; // All non-quadrangular faces
AddBlocksFrom(aShape, BLO, NOT, EXT, NOQ);
AddBlocksFrom(aShape, BLO, NOT, EXT, NOQ, theToleranceC1);
if (NOT.IsEmpty() && EXT.IsEmpty() && NOQ.IsEmpty()) {
SetErrorCode("NOT_FOUND_ANY");

View File

@ -125,16 +125,14 @@ class GEOMImpl_IBlocksOperations : public GEOM_IOperations {
std::list<int> incriminated;
};
Standard_EXPORT Standard_Boolean CheckCompoundOfBlocksOld (Handle(GEOM_Object) theCompound,
std::list<BCError>& theErrors);
Standard_EXPORT Standard_Boolean CheckCompoundOfBlocks (Handle(GEOM_Object) theCompound,
std::list<BCError>& theErrors);
Standard_EXPORT TCollection_AsciiString PrintBCErrors (Handle(GEOM_Object) theCompound,
const std::list<BCError>& theErrors);
Standard_EXPORT Handle(GEOM_Object) GetNonBlocks (Handle(GEOM_Object) theShape,
Standard_EXPORT Handle(GEOM_Object) GetNonBlocks (Handle(GEOM_Object) theShape,
const Standard_Real theToleranceC1,
Handle(GEOM_Object)& theNonQuads);
Standard_EXPORT Handle(GEOM_Object) RemoveExtraEdges (Handle(GEOM_Object) theShape,
@ -148,7 +146,8 @@ class GEOMImpl_IBlocksOperations : public GEOM_IOperations {
TopTools_ListOfShape& BLO,
TopTools_ListOfShape& NOT,
TopTools_ListOfShape& EXT,
TopTools_ListOfShape& NOQ);
TopTools_ListOfShape& NOQ,
const Standard_Real theToleranceC1 = -1.);
// Extract blocks from blocks compounds
Standard_EXPORT Handle(TColStd_HSequenceOfTransient) ExplodeCompoundOfBlocks

4
src/GEOM_I/GEOM_IBlocksOperations_i.cc Executable file → Normal file
View File

@ -749,6 +749,7 @@ char* GEOM_IBlocksOperations_i::PrintBCErrors
//=============================================================================
GEOM::GEOM_Object_ptr GEOM_IBlocksOperations_i::GetNonBlocks
(GEOM::GEOM_Object_ptr theShape,
const CORBA::Double theToleranceC1,
GEOM::GEOM_Object_out theNonQuads)
{
GEOM::GEOM_Object_var aGEOMObject;
@ -765,7 +766,8 @@ GEOM::GEOM_Object_ptr GEOM_IBlocksOperations_i::GetNonBlocks
//Get the result
Handle(GEOM_Object) aFaces;
Handle(GEOM_Object) anObject = GetOperations()->GetNonBlocks(aShape, aFaces);
Handle(GEOM_Object) anObject =
GetOperations()->GetNonBlocks(aShape, theToleranceC1, aFaces);
if (!GetOperations()->IsDone())
return aGEOMObject._retn();

View File

@ -122,6 +122,7 @@ class GEOM_I_EXPORT GEOM_IBlocksOperations_i :
const GEOM::GEOM_IBlocksOperations::BCErrors& theErrors);
GEOM::GEOM_Object_ptr GetNonBlocks (GEOM::GEOM_Object_ptr theShape,
const CORBA::Double theToleranceC1,
GEOM::GEOM_Object_out theNonQuads);
GEOM::GEOM_Object_ptr RemoveExtraEdges (GEOM::GEOM_Object_ptr theShape,

View File

@ -80,7 +80,7 @@
## # create and publish cylinder
## cyl = geompy.MakeCylinderRH(100, 100, "cylinder")
## # get non blocks from cylinder
## g1, g2 = geompy.GetNonBlocks(cyl, "nonblock")
## g1, g2 = geompy.GetNonBlocks(cyl, theName="nonblock")
## @endcode
##
## Above example will publish both result compounds (first with non-hexa solids and
@ -88,7 +88,7 @@
## However, if second command is invoked as
##
## @code
## g1, g2 = geompy.GetNonBlocks(cyl, ("nonhexa", "nonquad"))
## g1, g2 = geompy.GetNonBlocks(cyl, theName=("nonhexa", "nonquad"))
## @endcode
##
## ... the first compound will be published with "nonhexa" name, and second will be named "nonquad".
@ -11431,6 +11431,12 @@ class geomBuilder(object, GEOM._objref_GEOM_Gen):
## Retrieve all non blocks solids and faces from \a theShape.
# @param theShape The shape to explore.
# @param theIsUseC1 Flag to check if there are 4 bounds on a face
# taking into account C1 continuity.
# @param theAngTolerance the angular tolerance to check if two neighbor
# edges are codirectional in the common vertex with this
# tolerance. This parameter is used only if
# <VAR>theIsUseC1</VAR> is set to True.
# @param theName Object name; when specified, this parameter is used
# for result publication in the study. Otherwise, if automatic
# publication is switched on, default value is used for result name.
@ -11438,17 +11444,27 @@ class geomBuilder(object, GEOM._objref_GEOM_Gen):
# @return A tuple of two GEOM_Objects. The first object is a group of all
# non block solids (= not 6 faces, or with 6 faces, but with the
# presence of non-quadrangular faces). The second object is a
# group of all non quadrangular faces.
# group of all non quadrangular faces (= faces with more then
# 1 wire or, if <VAR>theIsUseC1</VAR> is set to True, faces
# with 1 wire with not 4 edges that do not form 4 bounds of
# C1 continuity).
#
# @ref tui_measurement_tools_page "Example 1"
# \n @ref swig_GetNonBlocks "Example 2"
@ManageTransactions("BlocksOp")
def GetNonBlocks (self, theShape, theName=None):
def GetNonBlocks (self, theShape, theIsUseC1 = False,
theAngTolerance = 1.e-12, theName=None):
"""
Retrieve all non blocks solids and faces from theShape.
Parameters:
theShape The shape to explore.
theIsUseC1 Flag to check if there are 4 bounds on a face
taking into account C1 continuity.
theAngTolerance the angular tolerance to check if two neighbor
edges are codirectional in the common vertex with this
tolerance. This parameter is used only if
theIsUseC1 is set to True.
theName Object name; when specified, this parameter is used
for result publication in the study. Otherwise, if automatic
publication is switched on, default value is used for result name.
@ -11457,13 +11473,19 @@ class geomBuilder(object, GEOM._objref_GEOM_Gen):
A tuple of two GEOM_Objects. The first object is a group of all
non block solids (= not 6 faces, or with 6 faces, but with the
presence of non-quadrangular faces). The second object is a
group of all non quadrangular faces.
group of all non quadrangular faces (= faces with more then
1 wire or, if <VAR>theIsUseC1</VAR> is set to True, faces
with 1 wire with not 4 edges that do not form 4 bounds of
C1 continuity).
Usage:
(res_sols, res_faces) = geompy.GetNonBlocks(myShape1)
"""
# Example: see GEOM_Spanner.py
aTuple = self.BlocksOp.GetNonBlocks(theShape)
aTolerance = -1.0
if theIsUseC1:
aTolerance = theAngTolerance
aTuple = self.BlocksOp.GetNonBlocks(theShape, aTolerance)
RaiseIfFailed("GetNonBlocks", self.BlocksOp)
self._autoPublish(aTuple, theName, ("groupNonHexas", "groupNonQuads"))
return aTuple

View File

@ -25,7 +25,6 @@
#include "MeasureGUI_GetNonBlocksDlg.h"
#include <DlgRef.h>
#include <GEOMBase.h>
#include <GeometryGUI.h>
@ -33,9 +32,18 @@
#include <SUIT_Session.h>
#include <SUIT_ResourceMgr.h>
#include <SalomeApp_Application.h>
#include <SalomeApp_DoubleSpinBox.h>
#include <LightApp_SelectionMgr.h>
#include <SalomeApp_Tools.h>
#include <QCheckBox>
#include <QGridLayout>
#include <QGroupBox>
#include <QLineEdit>
#include <QPushButton>
#include <QRadioButton>
#include <QVBoxLayout>
//=================================================================================
// class : MeasureGUI_GetNonBlocksDlg()
// purpose : Constructs a MeasureGUI_GetNonBlocksDlg which is a child of 'parent',
@ -44,7 +52,12 @@
// true to construct a modal dialog.
//=================================================================================
MeasureGUI_GetNonBlocksDlg::MeasureGUI_GetNonBlocksDlg (GeometryGUI* theGeometryGUI, QWidget* parent)
: GEOMBase_Skeleton(theGeometryGUI, parent, false)
: GEOMBase_Skeleton(theGeometryGUI, parent, false),
myObjectName (0),
mySelButton (0),
myUseC1Check (0),
myTolLbl (0),
mySpinTol (0)
{
QPixmap image0 (SUIT_Session::session()->resourceMgr()->loadPixmap("GEOM", tr("ICON_DLG_GETNONBLOCKS")));
QPixmap image1 (SUIT_Session::session()->resourceMgr()->loadPixmap("GEOM", tr("ICON_SELECT")));
@ -58,16 +71,36 @@ MeasureGUI_GetNonBlocksDlg::MeasureGUI_GetNonBlocksDlg (GeometryGUI* theGeometry
mainFrame()->RadioButton2->close();
mainFrame()->RadioButton3->setAttribute(Qt::WA_DeleteOnClose);
mainFrame()->RadioButton3->close();
QGroupBox *aGrpParams =
new QGroupBox(tr("GEOM_GETNONBLOCKS"), centralWidget());
QGridLayout *aParamsLayout = new QGridLayout(aGrpParams);
QLabel *anObjLbl = new QLabel(tr("GEOM_OBJECT"), aGrpParams);
myGrp = new DlgRef_1Sel (centralWidget());
myGrp->GroupBox1->setTitle(tr("GEOM_GETNONBLOCKS"));
myGrp->TextLabel1->setText(tr("GEOM_OBJECT"));
myGrp->PushButton1->setIcon(image1);
myGrp->LineEdit1->setReadOnly(true);
myObjectName = new QLineEdit(aGrpParams);
mySelButton = new QPushButton(aGrpParams);
myUseC1Check = new QCheckBox(tr("GEOM_USE_C1_CRITERION"), aGrpParams);
myTolLbl = new QLabel(tr("GEOM_ANGULAR_TOLERANCE"), aGrpParams);
mySpinTol = new SalomeApp_DoubleSpinBox(aGrpParams);
myObjectName->setReadOnly(true);
mySelButton->setIcon(image1);
mySelButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
myUseC1Check->setText(tr("GEOM_USE_C1_CRITERION"));
myUseC1Check->setChecked(true);
aParamsLayout->setMargin(9);
aParamsLayout->setSpacing(6);
aParamsLayout->addWidget(anObjLbl, 0, 0);
aParamsLayout->addWidget(mySelButton, 0, 1);
aParamsLayout->addWidget(myObjectName, 0, 2);
aParamsLayout->addWidget(myUseC1Check, 1, 0, 1, 3);
aParamsLayout->addWidget(myTolLbl, 2, 0);
aParamsLayout->addWidget(mySpinTol, 2, 1, 1, 2);
QVBoxLayout* layout = new QVBoxLayout(centralWidget());
layout->setMargin(0); layout->setSpacing(6);
layout->addWidget(myGrp);
layout->addWidget(aGrpParams);
/***************************************************************/
@ -94,14 +127,20 @@ void MeasureGUI_GetNonBlocksDlg::Init()
showOnlyPreviewControl();
/* init variables */
myEditCurrentArgument = myGrp->LineEdit1;
double SpecificStep = 0.0001;
double aDefaultTol = Precision::Angular();
initSpinBox(mySpinTol, aDefaultTol, MAX_NUMBER, SpecificStep, "ang_tol_precision");
mySpinTol->setValue(aDefaultTol);
myEditCurrentArgument = myObjectName;
/* signals and slots connections */
connect(buttonOk(), SIGNAL(clicked()), this, SLOT(ClickOnOk()));
connect(buttonApply(), SIGNAL(clicked()), this, SLOT(ClickOnApply()));
connect(myGrp->LineEdit1, SIGNAL(returnPressed()), this, SLOT(LineEditReturnPressed()));
connect(myGrp->PushButton1, SIGNAL(clicked()), this, SLOT(SetEditCurrentArgument()));
connect(buttonOk(), SIGNAL(clicked()), this, SLOT(ClickOnOk()));
connect(buttonApply(), SIGNAL(clicked()), this, SLOT(ClickOnApply()));
connect(myUseC1Check, SIGNAL(clicked()), this, SLOT(SetUseC1Tolerance()));
connect(mySpinTol, SIGNAL(valueChanged(double)), this, SLOT(processPreview()));
connect(myObjectName, SIGNAL(returnPressed()), this, SLOT(LineEditReturnPressed()));
connect(mySelButton, SIGNAL(clicked()), this, SLOT(SetEditCurrentArgument()));
connect(((SalomeApp_Application*)(SUIT_Session::session()->activeApplication()))->selectionMgr(),
SIGNAL(currentSelectionChanged()), this, SLOT(SelectionIntoArgument()));
@ -171,11 +210,22 @@ void MeasureGUI_GetNonBlocksDlg::SelectionIntoArgument()
//=================================================================================
void MeasureGUI_GetNonBlocksDlg::SetEditCurrentArgument()
{
myGrp->LineEdit1->setFocus();
myEditCurrentArgument = myGrp->LineEdit1;
myObjectName->setFocus();
myEditCurrentArgument = myObjectName;
SelectionIntoArgument();
}
//=================================================================================
// function : SetUseC1Tolerance()
// purpose :
//=================================================================================
void MeasureGUI_GetNonBlocksDlg::SetUseC1Tolerance()
{
myTolLbl->setEnabled(myUseC1Check->isChecked());
mySpinTol->setEnabled(myUseC1Check->isChecked());
processPreview();
}
//=================================================================================
// function : LineEditReturnPressed()
// purpose :
@ -183,8 +233,8 @@ void MeasureGUI_GetNonBlocksDlg::SetEditCurrentArgument()
void MeasureGUI_GetNonBlocksDlg::LineEditReturnPressed()
{
QLineEdit* send = (QLineEdit*)sender();
if (send == myGrp->LineEdit1) {
myEditCurrentArgument = myGrp->LineEdit1;
if (send == myObjectName) {
myEditCurrentArgument = myObjectName;
GEOMBase_Skeleton::LineEditReturnPressed();
}
}
@ -211,10 +261,11 @@ void MeasureGUI_GetNonBlocksDlg::ActivateThisDialog()
void MeasureGUI_GetNonBlocksDlg::processObject()
{
if (myObj->_is_nil()) {
myObjectName->setText("");
erasePreview();
}
else {
myGrp->LineEdit1->setText(GEOMBase::GetName(myObj));
myObjectName->setText(GEOMBase::GetName(myObj));
processPreview();
}
@ -243,9 +294,9 @@ GEOM::GEOM_IOperations_ptr MeasureGUI_GetNonBlocksDlg::createOperation()
// function : isValid
// purpose :
//=================================================================================
bool MeasureGUI_GetNonBlocksDlg::isValid (QString&)
bool MeasureGUI_GetNonBlocksDlg::isValid (QString &msg)
{
return !myObj->_is_nil();
return !myObj->_is_nil() && mySpinTol->isValid(msg, !IsPreview());
}
//=================================================================================
@ -256,7 +307,13 @@ bool MeasureGUI_GetNonBlocksDlg::execute (ObjectList& objects)
{
GEOM::GEOM_IBlocksOperations_var anOper = GEOM::GEOM_IBlocksOperations::_narrow(getOperation());
GEOM::GEOM_Object_var aNonQuads;
GEOM::GEOM_Object_var anObj = anOper->GetNonBlocks(myObj, aNonQuads);
double aC1Tol = -1.;
if (myUseC1Check->isChecked()) {
aC1Tol = mySpinTol->value();
}
GEOM::GEOM_Object_var anObj = anOper->GetNonBlocks(myObj, aC1Tol, aNonQuads);
//mainFrame()->ResultName->setText(tr("GEOM_NONBLOCKS"));
if (!anObj->_is_nil())

View File

@ -28,7 +28,11 @@
#include <GEOMBase_Skeleton.h>
class DlgRef_1Sel;
class QCheckBox;
class QLabel;
class QLineEdit;
class QPushButton;
class SalomeApp_DoubleSpinBox;
//=================================================================================
// class : MeasureGUI_GetNonBlocksDlg
@ -45,7 +49,7 @@ public:
protected:
// redefined from GEOMBase_Helper
virtual GEOM::GEOM_IOperations_ptr createOperation();
virtual bool isValid (QString&);
virtual bool isValid (QString &msg);
virtual bool execute (ObjectList&);
virtual GEOM::GEOM_Object_ptr getFather (GEOM::GEOM_Object_ptr);
@ -56,6 +60,7 @@ private slots:
void LineEditReturnPressed();
void SelectionIntoArgument();
void SetEditCurrentArgument();
void SetUseC1Tolerance();
private:
void Init();
@ -64,7 +69,11 @@ private:
private:
GEOM::GEOM_Object_var myObj;
DlgRef_1Sel* myGrp;
QLineEdit *myObjectName;
QPushButton *mySelButton;
QCheckBox *myUseC1Check;
QLabel *myTolLbl;
SalomeApp_DoubleSpinBox *mySpinTol;
};
#endif // MEASUREGUI_GETNONBLOCKSDLG_H