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.
-
-The first object is a group of all non block solids; the second object is a group of all non
-quadrangular faces.
+<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.
+
+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".
* \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.
<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>
#include <Bnd_Box.hxx>
#include <GProp_GProps.hxx>
+#include <Geom_Curve.hxx>
#include <Geom_Surface.hxx>
#include <ShapeAnalysis_Surface.hxx>
#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:
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) {
{
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;
TopExp_Explorer expF (theShape, TopAbs_FACE);
for (; expF.More(); expF.Next()) {
- if (mapFaces.Add(expF.Current())) {
- nbFaces++;
- //0021483//if (nbFaces > 6) break;
+ TopoDS_Face aF = TopoDS::Face(expF.Current());
- // 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;
- }
+ if (mapFaces.Add(aF)) {
+ nbFaces++;
- // 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
}
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
}
}
}
}
-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
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
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) {
*/
//=============================================================================
Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetNonBlocks
- (Handle(GEOM_Object) theShape,
+ (Handle(GEOM_Object) theShape,
+ const Standard_Real theToleranceC1,
Handle(GEOM_Object)& theNonQuads)
{
SetErrorCode(KO);
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");
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,
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
//=============================================================================
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;
//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();
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,
## # 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
## 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".
## 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.
# @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.
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
#include "MeasureGUI_GetNonBlocksDlg.h"
-#include <DlgRef.h>
#include <GEOMBase.h>
#include <GeometryGUI.h>
#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',
// 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")));
mainFrame()->RadioButton2->close();
mainFrame()->RadioButton3->setAttribute(Qt::WA_DeleteOnClose);
mainFrame()->RadioButton3->close();
-
- 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);
+
+ QGroupBox *aGrpParams =
+ new QGroupBox(tr("GEOM_GETNONBLOCKS"), centralWidget());
+ QGridLayout *aParamsLayout = new QGridLayout(aGrpParams);
+ QLabel *anObjLbl = new QLabel(tr("GEOM_OBJECT"), aGrpParams);
+
+ 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);
/***************************************************************/
showOnlyPreviewControl();
/* init variables */
- myEditCurrentArgument = myGrp->LineEdit1;
+ double SpecificStep = 0.0001;
+ double aDefaultTol = Precision::Angular();
- /* signals and slots connections */
- connect(buttonOk(), SIGNAL(clicked()), this, SLOT(ClickOnOk()));
- connect(buttonApply(), SIGNAL(clicked()), this, SLOT(ClickOnApply()));
+ initSpinBox(mySpinTol, aDefaultTol, MAX_NUMBER, SpecificStep, "ang_tol_precision");
+ mySpinTol->setValue(aDefaultTol);
+ myEditCurrentArgument = myObjectName;
- connect(myGrp->LineEdit1, SIGNAL(returnPressed()), this, SLOT(LineEditReturnPressed()));
- connect(myGrp->PushButton1, SIGNAL(clicked()), this, SLOT(SetEditCurrentArgument()));
+ /* signals and slots connections */
+ 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()));
//=================================================================================
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 :
void MeasureGUI_GetNonBlocksDlg::LineEditReturnPressed()
{
QLineEdit* send = (QLineEdit*)sender();
- if (send == myGrp->LineEdit1) {
- myEditCurrentArgument = myGrp->LineEdit1;
+ if (send == myObjectName) {
+ myEditCurrentArgument = myObjectName;
GEOMBase_Skeleton::LineEditReturnPressed();
}
}
void MeasureGUI_GetNonBlocksDlg::processObject()
{
if (myObj->_is_nil()) {
+ myObjectName->setText("");
erasePreview();
}
else {
- myGrp->LineEdit1->setText(GEOMBase::GetName(myObj));
+ myObjectName->setText(GEOMBase::GetName(myObj));
processPreview();
}
// 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());
}
//=================================================================================
{
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())
#include <GEOMBase_Skeleton.h>
-class DlgRef_1Sel;
+class QCheckBox;
+class QLabel;
+class QLineEdit;
+class QPushButton;
+class SalomeApp_DoubleSpinBox;
//=================================================================================
// class : MeasureGUI_GetNonBlocksDlg
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);
void LineEditReturnPressed();
void SelectionIntoArgument();
void SetEditCurrentArgument();
+ void SetUseC1Tolerance();
private:
void Init();
private:
GEOM::GEOM_Object_var myObj;
- DlgRef_1Sel* myGrp;
+ QLineEdit *myObjectName;
+ QPushButton *mySelButton;
+ QCheckBox *myUseC1Check;
+ QLabel *myTolLbl;
+ SalomeApp_DoubleSpinBox *mySpinTol;
};
#endif // MEASUREGUI_GETNONBLOCKSDLG_H