To be considered as a compound of blocks, the given shape must satisfy the
following conditions:
-- Each element of the compound should be a Block (6 faces and 12 edges);
+- Each element of the compound should be a Block (6 quadrangle faces);
+- Each quadrangle 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.
- Blocks can be connected only via an entire quadrangle face or an entire edge;
- The compound should be connected;
- Each couple of connecting quadrangle faces should be glued.
In this dialog:
-- \b Object - the checked object. \b Selection button allows picking it in the viewer or in the object browser.
-- \b Errors list informs of possible errors, for example:.
+- \b Object - the checked object. \b Selection button allows picking it in the viewer or in the object browser.
+- <b>Use C1 criterion</b> - option that shitches on/off the C1 continuity mode.
+- <b>Angular Tolerance</b> - angular tolerance to check C1 continuity between neighbor edges in a wire.
+- \b Errors list informs of possible errors, for example:
- Not a block;
- Not glued;
- Not connected;
\n <b>TUI Command:</b>
-<em>geompy.CheckCompoundOfBlocks(Compound).</em> Checks if the shape
+<em>geompy.CheckCompoundOfBlocks(Compound, theIsUseC1 = False, theAngTolerance = 1.e-12).</em> Checks if the shape
is a valid compound of blocks. If it is true, then the validity flag
is returned, and encountered errors are printed in the python console.
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 quadrangular faces.
+
+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".
* - The glue between two quadrangle faces should be applied.
* \note Single block is also accepted as a valid compound of blocks.
* \param theCompound The compound to check.
+ * \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 theErrors Structure, containing discovered errors and incriminated sub-shapes.
* \return TRUE, if the given shape is a compound of blocks.
*/
boolean CheckCompoundOfBlocks (in GEOM_Object theCompound,
+ in double theToleranceC1,
out BCErrors theErrors);
/*!
* \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.
// Last verification: result should be a block
std::list<GEOMImpl_IBlocksOperations::BCError> errList;
- if (!myBlocksOperations->CheckCompoundOfBlocks(Te3,errList)) {
+ if (!myBlocksOperations->CheckCompoundOfBlocks(Te3, -1, errList)) {
SetErrorCode("TShape is not a compound of block");
return false;
}
#include <BRep_Tool.hxx>
+#include <Geom_Curve.hxx>
+
+#include <gp_Pnt.hxx>
+#include <gp_Vec.hxx>
+
#include <TopExp.hxx>
#include <TopExp_Explorer.hxx>
#include <TopoDS_Face.hxx>
#include <TopoDS_Solid.hxx>
#include <TopoDS_Shape.hxx>
+#include <TopoDS_Vertex.hxx>
#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
+#include <TopTools_IndexedMapOfShape.hxx>
#include <TopTools_MapOfShape.hxx>
#include <TopTools_ListOfShape.hxx>
#include <TopTools_ListIteratorOfListOfShape.hxx>
BlockFix_CheckTool::BlockFix_CheckTool( )
{
myHasCheck = Standard_False;
+ myAngTolerance = -1.;
myPossibleBlocks.Clear();
}
myPossibleBlocks.Clear();
}
+//=======================================================================
+//function : SetAngTolerance
+//purpose :
+//=======================================================================
+void BlockFix_CheckTool::SetAngTolerance(const Standard_Real theTolerance)
+{
+ myHasCheck = Standard_False;
+ myAngTolerance = theTolerance;
+ myPossibleBlocks.Clear();
+}
+
//=======================================================================
//function : Perform
//purpose :
if (nbe < 12)
IsBlock = Standard_False;
if (nbe > 12) {
- IsBlock = Standard_False;
// check edges unification
// creating map of edge faces
TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFaces;
Standard_Integer i = 1;
for (; i <= aMapFacesEdges.Extent(); i++) {
const TopTools_ListOfShape& ListEdges = aMapFacesEdges.FindFromIndex(i);
- if (ListEdges.Extent() > 1) break;
+ if (ListEdges.Extent() > 1) {
+ if (myAngTolerance < 0.) {
+ break;
+ }
+
+ // Check if edges have C1 continuity.
+ if (!isC1(ListEdges)) {
+ break;
+ }
+ }
}
if (i <= aMapFacesEdges.Extent()) {
+ IsBlock = Standard_False;
MayBeUE = Standard_True;
break;
}
S<<" number of impossible blocks = "<<nbtmp<<endl;
}
}
+
+//=======================================================================
+//function : isC1
+//purpose :
+//=======================================================================
+Standard_Boolean BlockFix_CheckTool::isC1
+ (const TopTools_ListOfShape &theEdges) const
+{
+ // Fill the map vertex - list of ancestor edges
+ TopTools_IndexedDataMapOfShapeListOfShape aMapVE;
+ TopTools_ListIteratorOfListOfShape anIter(theEdges);
+ TopTools_MapOfShape aMapFence;
+ Standard_Integer i;
+ Standard_Integer aNbVtx;
+
+ for (; anIter.More(); anIter.Next()) {
+ TopTools_IndexedMapOfShape aMapVtx;
+ const TopoDS_Shape &anEdge = anIter.Value();
+
+ if (aMapFence.Add(anEdge)) {
+ TopExp::MapShapes(anEdge, TopAbs_VERTEX, aMapVtx);
+ aNbVtx = aMapVtx.Extent();
+
+ for (i = 1; i <= aNbVtx; ++i) {
+ const TopoDS_Shape &aVtx = aMapVtx.FindKey(i);
+
+ if (!aMapVE.Contains(aVtx)) {
+ aMapVE.Add(aVtx, TopTools_ListOfShape());
+ }
+
+ aMapVE.ChangeFromKey(aVtx).Append(anEdge);
+ }
+ }
+ }
+
+ // Check C1 continuity.
+ Standard_Integer aNbEnds = 0;
+
+ for (i = 1, aNbVtx = aMapVE.Extent(); i <= aNbVtx; ++i) {
+ const TopTools_ListOfShape &anEdges = aMapVE.FindFromIndex(i);
+ Standard_Integer aNbEdges = anEdges.Extent();
+
+ if (aNbEdges == 1) {
+ ++aNbEnds;
+ } else if (aNbEdges == 2) {
+ TopoDS_Vertex aCommonVtx = TopoDS::Vertex(aMapVE.FindKey(i));
+ TopoDS_Edge anEdge1 = TopoDS::Edge(anEdges.First());
+ TopoDS_Edge anEdge2 = TopoDS::Edge(anEdges.Last());
+ Standard_Real aParam1 = BRep_Tool::Parameter(aCommonVtx, anEdge1);
+ Standard_Real aParam2 = BRep_Tool::Parameter(aCommonVtx, anEdge2);
+ Standard_Real aPar[2];
+ Handle(Geom_Curve) aCurve1 =
+ BRep_Tool::Curve(anEdge1, aPar[0], aPar[1]);
+ Handle(Geom_Curve) aCurve2 =
+ BRep_Tool::Curve(anEdge2, aPar[0], aPar[1]);
+ gp_Pnt aPnt;
+ gp_Vec aVec1;
+ gp_Vec aVec2;
+
+ aCurve1->D1(aParam1, aPnt, aVec1);
+ aCurve2->D1(aParam2, aPnt, aVec2);
+
+ if (anEdge1.Orientation() != anEdge2.Orientation()) {
+ // Orientations are different. One vector should be reversed.
+ aVec1.Reverse();
+ }
+
+ const Standard_Real anAngle = aVec1.Angle(aVec2);
+
+ if (anAngle > myAngTolerance) {
+ // There is no C1 continuity.
+ break;
+ }
+ } else {
+ // Non-manifold case.
+ break;
+ }
+ }
+
+ return (i > aNbVtx && aNbEnds == 2);
+}
#include <Standard_OStream.hxx>
class TopoDS_Shape;
+class TopTools_ListOfShape;
#include <Standard.hxx>
#include <Standard_Macro.hxx>
public:
Standard_EXPORT BlockFix_CheckTool();
- Standard_EXPORT void SetShape(const TopoDS_Shape& aShape) ;
+ Standard_EXPORT void SetShape(const TopoDS_Shape& aShape);
+ Standard_EXPORT void SetAngTolerance(const Standard_Real theTolerance);
Standard_EXPORT void Perform() ;
Standard_EXPORT Standard_Integer NbPossibleBlocks() const;
Standard_EXPORT TopoDS_Shape PossibleBlock(const Standard_Integer num) const;
Standard_EXPORT void DumpCheckResult(Standard_OStream& S) const;
private:
- TopoDS_Shape myShape;
+
+ Standard_Boolean isC1(const TopTools_ListOfShape &theEdges) const;
+
+private:
+ TopoDS_Shape myShape;
+ Standard_Real myAngTolerance;
Standard_Boolean myHasCheck;
Standard_Integer myNbSolids;
Standard_Integer myNbBlocks;
<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;
// Check, if there are seam or degenerated edges
BlockFix_CheckTool aTool;
aTool.SetShape(theShape);
+ aTool.SetAngTolerance(theToleranceC1);
aTool.Perform();
if (aTool.NbPossibleBlocks() > 0) {
EXT.Append(theShape);
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
//=============================================================================
Standard_Boolean GEOMImpl_IBlocksOperations::CheckCompoundOfBlocks
(Handle(GEOM_Object) theCompound,
+ const Standard_Real theToleranceC1,
std::list<BCError>& theErrors)
{
SetErrorCode(KO);
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, theToleranceC1);
// 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,
+ const Standard_Real theToleranceC1,
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
//=============================================================================
CORBA::Boolean GEOM_IBlocksOperations_i::CheckCompoundOfBlocks
(GEOM::GEOM_Object_ptr theCompound,
+ const CORBA::Double theToleranceC1,
GEOM::GEOM_IBlocksOperations::BCErrors_out theErrors)
{
CORBA::Boolean isComp = false;
//Check
std::list<GEOMImpl_IBlocksOperations::BCError> errList;
- isComp = GetOperations()->CheckCompoundOfBlocks(aCompound, errList);
+ isComp = GetOperations()->CheckCompoundOfBlocks
+ (aCompound, theToleranceC1, errList);
if (!GetOperations()->IsDone())
return isComp;
//=============================================================================
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();
CORBA::Long& theNbBlocks);
CORBA::Boolean CheckCompoundOfBlocks (GEOM::GEOM_Object_ptr theCompound,
+ const CORBA::Double theToleranceC1,
GEOM::GEOM_IBlocksOperations::BCErrors_out theErrors);
char* PrintBCErrors (GEOM::GEOM_Object_ptr theCompound,
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,
beginService( " GEOM_Superv_i::CheckCompoundOfBlocks" );
MESSAGE("GEOM_Superv_i::CheckCompoundOfBlocks");
getBlocksOp();
- CORBA::Boolean aRes = myBlocksOp->CheckCompoundOfBlocks(theCompound, theErrors);
+ CORBA::Boolean aRes = myBlocksOp->CheckCompoundOfBlocks(theCompound, -1., theErrors);
endService( " GEOM_Superv_i::CheckCompoundOfBlocks" );
return aRes;
}
## # 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".
## Check, if the compound of blocks is given.
# To be considered as a compound of blocks, the
# given shape must satisfy the following conditions:
- # - Each element of the compound should be a Block (6 faces and 12 edges).
+ # - Each element of the compound should be a Block (6 faces).
+ # - Each face should be a quadrangle, i.e. it should have only 1 wire
+ # with 4 edges. If <VAR>theIsUseC1</VAR> is set to True and
+ # there are more than 4 edges in the only wire of a face,
+ # this face is considered to be quadrangle if it has 4 bounds
+ # (1 or more edge) of C1 continuity.
# - A connection between two Blocks should be an entire quadrangle face or an entire edge.
# - The compound should be connexe.
# - The glue between two quadrangle faces should be applied.
# @param theCompound The compound to check.
+ # @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.
# @return TRUE, if the given shape is a compound of blocks.
# If theCompound is not valid, prints all discovered errors.
#
# @ref tui_measurement_tools_page "Example 1"
# \n @ref swig_CheckCompoundOfBlocks "Example 2"
@ManageTransactions("BlocksOp")
- def CheckCompoundOfBlocks(self,theCompound):
+ def CheckCompoundOfBlocks(self,theCompound, theIsUseC1 = False,
+ theAngTolerance = 1.e-12):
"""
Check, if the compound of blocks is given.
To be considered as a compound of blocks, the
given shape must satisfy the following conditions:
- - Each element of the compound should be a Block (6 faces and 12 edges).
+ - Each element of the compound should be a Block (6 faces).
+ - Each face should be a quadrangle, i.e. it should have only 1 wire
+ with 4 edges. If theIsUseC1 is set to True and
+ there are more than 4 edges in the only wire of a face,
+ this face is considered to be quadrangle if it has 4 bounds
+ (1 or more edge) of C1 continuity.
- A connection between two Blocks should be an entire quadrangle face or an entire edge.
- The compound should be connexe.
- The glue between two quadrangle faces should be applied.
Parameters:
theCompound The compound to check.
+ 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.
Returns:
TRUE, if the given shape is a compound of blocks.
If theCompound is not valid, prints all discovered errors.
"""
# Example: see GEOM_Spanner.py
- (IsValid, BCErrors) = self.BlocksOp.CheckCompoundOfBlocks(theCompound)
+ aTolerance = -1.0
+ if theIsUseC1:
+ aTolerance = theAngTolerance
+ (IsValid, BCErrors) = self.BlocksOp.CheckCompoundOfBlocks(theCompound, aTolerance)
RaiseIfFailed("CheckCompoundOfBlocks", self.BlocksOp)
if IsValid == 0:
Descr = self.BlocksOp.PrintBCErrors(theCompound, BCErrors)
## 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.h"
#include "MeasureGUI_CheckCompoundOfBlocksDlg.h"
-#include "MeasureGUI_Widgets.h"
#include <SUIT_Session.h>
#include <SUIT_ResourceMgr.h>
#include <GEOMBase.h>
#include <GEOMImpl_Types.hxx>
+#include <QListWidget>
+
#define TEXTEDIT_FONT_FAMILY "Courier"
#define TEXTEDIT_FONT_SIZE 11
// true to construct a modal dialog.
//=================================================================================
MeasureGUI_CheckCompoundOfBlocksDlg::MeasureGUI_CheckCompoundOfBlocksDlg( GeometryGUI* GUI, QWidget* parent )
- : GEOMBase_Skeleton( GUI, parent, false )
+ : GEOMBase_Skeleton(GUI, parent, false),
+ myObjectName (0),
+ mySelButton (0),
+ myUseC1Check (0),
+ myTolLbl (0),
+ mySpinTol (0),
+ myTextView (0),
+ myListBox1 (0),
+ myListBox2 (0)
{
SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr();
QPixmap image0( aResMgr->loadPixmap( "GEOM", tr( "ICON_DLG_CHECK_COMPOUND_OF_BLOCKS" ) ) );
mainFrame()->RadioButton3->setAttribute( Qt::WA_DeleteOnClose );
mainFrame()->RadioButton3->close();
- myGrp = new MeasureGUI_1Sel1TextView2ListBox( centralWidget() );
- myGrp->GroupBox1->setTitle( tr( "GEOM_CHECK_INFOS" ) );
- myGrp->TextLabel1->setText( tr( "GEOM_OBJECT" ) );
-
- myGrp->TextView1->setReadOnly( true );
- QFont aFont( TEXTEDIT_FONT_FAMILY, TEXTEDIT_FONT_SIZE );
- aFont.setStyleHint( QFont::TypeWriter, QFont::PreferAntialias );
- myGrp->TextView1->setFont( aFont );
-
- myGrp->PushButton1->setIcon( image1 );
- myGrp->LineEdit1->setReadOnly( true );
-
- myGrp->TextLabel2->setText( tr( "GEOM_CHECK_BLOCKS_COMPOUND_ERRORS" ) );
- myGrp->TextLabel3->setText( tr( "GEOM_CHECK_BLOCKS_COMPOUND_SUBSHAPES" ) );
-
- myGrp->ListBox2->setSelectionMode( QAbstractItemView::ExtendedSelection );
+ QGroupBox *aGrpParams =
+ new QGroupBox(tr("GEOM_CHECK_INFOS"), centralWidget());
+ QGridLayout *aParamsLayout = new QGridLayout(aGrpParams);
+ QLabel *anObjLbl = new QLabel(tr("GEOM_OBJECT"), aGrpParams);
+ QLabel *anErrorsLbl =
+ new QLabel(tr("GEOM_CHECK_BLOCKS_COMPOUND_ERRORS"), aGrpParams);
+ QLabel *aNonBlocksLbl =
+ new QLabel(tr("GEOM_CHECK_BLOCKS_COMPOUND_SUBSHAPES"), 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);
+ myTextView = new QTextBrowser(aGrpParams);
+ myListBox1 = new QListWidget(aGrpParams);
+ myListBox2 = new QListWidget(aGrpParams);
+
+ myObjectName->setReadOnly(true);
+ mySelButton->setIcon(image1);
+ mySelButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+ myUseC1Check->setText(tr("GEOM_USE_C1_CRITERION"));
+ myUseC1Check->setChecked(true);
+ myTextView->setReadOnly(true);
+ myListBox2->setSelectionMode(QAbstractItemView::ExtendedSelection);
+
+ // Set text view font.
+ QFont aFont(TEXTEDIT_FONT_FAMILY, TEXTEDIT_FONT_SIZE);
+
+ aFont.setStyleHint(QFont::TypeWriter, QFont::PreferAntialias);
+ myTextView->setFont(aFont);
+
+ 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);
+ aParamsLayout->addWidget(myTextView, 3, 0, 1, 3);
+ aParamsLayout->addWidget(anErrorsLbl, 4, 0);
+ aParamsLayout->addWidget(myListBox1, 5, 0, 1, 2);
+ aParamsLayout->addWidget(aNonBlocksLbl, 4, 2);
+ aParamsLayout->addWidget(myListBox2, 5, 2);
QVBoxLayout* layout = new QVBoxLayout( centralWidget() );
layout->setMargin( 0 ); layout->setSpacing( 6 );
- layout->addWidget( myGrp );
-
- connect( myGrp->ListBox1, SIGNAL( itemSelectionChanged() ), SLOT( onErrorsListSelectionChanged() ) );
- connect( myGrp->ListBox2, SIGNAL( itemSelectionChanged() ), SLOT( onSubShapesListSelectionChanged() ) );
+ layout->addWidget( aGrpParams );
/***************************************************************/
//=================================================================================
void MeasureGUI_CheckCompoundOfBlocksDlg::Init()
{
- myEditCurrentArgument = myGrp->LineEdit1;
+ /* init variables */
+ 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(myObjectName, SIGNAL(returnPressed()), this, SLOT(LineEditReturnPressed()));
+ connect(mySelButton, SIGNAL(clicked()), this, SLOT(SetEditCurrentArgument()));
+ connect(myListBox1, SIGNAL(itemSelectionChanged()), this, SLOT(onErrorsListSelectionChanged()));
+ connect(myListBox2, SIGNAL(itemSelectionChanged()), this, SLOT(onSubShapesListSelectionChanged()));
+ connect(myUseC1Check, SIGNAL(clicked()), this, SLOT(SetUseC1Tolerance()));
+ connect(mySpinTol, SIGNAL(valueChanged(double)), this, SLOT(processObject()));
connect( myGeomGUI->getApp()->selectionMgr(), SIGNAL( currentSelectionChanged() ),
this, SLOT( SelectionIntoArgument() ) );
aSelMgr->selectedObjects(aSelList);
if (aSelList.Extent() != 1) {
- myGrp->LineEdit1->setText( "" );
+ myObjectName->setText( "" );
processObject();
return;
}
GEOMBase::ConvertIOinGEOMObject( aSelList.First() );
if ( aSelectedObject->_is_nil() ) {
- myGrp->LineEdit1->setText( "" );
+ myObjectName->setText( "" );
processObject();
return;
}
myObj = aSelectedObject;
- myGrp->LineEdit1->setText( GEOMBase::GetName( myObj ) );
+ myObjectName->setText( GEOMBase::GetName( myObj ) );
processObject();
DISPLAY_PREVIEW_MACRO;
}
//=================================================================================
void MeasureGUI_CheckCompoundOfBlocksDlg::SetEditCurrentArgument()
{
- myGrp->LineEdit1->setFocus();
- myEditCurrentArgument = myGrp->LineEdit1;
+ myObjectName->setFocus();
+ myEditCurrentArgument = myObjectName;
SelectionIntoArgument();
}
+//=================================================================================
+// function : SetUseC1Tolerance()
+// purpose :
+//=================================================================================
+void MeasureGUI_CheckCompoundOfBlocksDlg::SetUseC1Tolerance()
+{
+ myTolLbl->setEnabled(myUseC1Check->isChecked());
+ mySpinTol->setEnabled(myUseC1Check->isChecked());
+ processObject();
+}
+
//=================================================================================
// function : LineEditReturnPressed()
// purpose :
void MeasureGUI_CheckCompoundOfBlocksDlg::LineEditReturnPressed()
{
QLineEdit* send = (QLineEdit*)sender();
- if ( send == myGrp->LineEdit1 ) {
- myEditCurrentArgument = myGrp->LineEdit1;
+ if ( send == myObjectName ) {
+ myEditCurrentArgument = myObjectName;
GEOMBase_Skeleton::LineEditReturnPressed();
}
}
GEOM::GEOM_IBlocksOperations_var anOper = GEOM::GEOM_IBlocksOperations::_narrow( getOperation() );
try {
GEOM::GEOM_IBlocksOperations::BCErrors_var aErrs;
- theIsCompoundOfBlocks = anOper->CheckCompoundOfBlocks( myObj, aErrs );
+ double aC1Tol = -1.;
+
+ if (myUseC1Check->isChecked()) {
+ aC1Tol = mySpinTol->value();
+ }
+
+ theIsCompoundOfBlocks = anOper->CheckCompoundOfBlocks( myObj, aC1Tol, aErrs );
if (anOper->IsDone() && aErrs->length() > 0)
//if (anOper->IsDone() && !aErrs._is_nil())
theErrors = aErrs;
GEOM::GEOM_IBlocksOperations::BCErrors aErrs;
if ( !getBCErrors( isCompoundOfBlocks, aErrs ) ) {
aMsg += tr( "GEOM_CHECK_BLOCKS_COMPOUND_FAILED" );
- myGrp->TextView1->setText( aMsg );
- myGrp->ListBox1->clear();
- myGrp->ListBox2->clear();
+ myTextView->setText( aMsg );
+ myListBox1->clear();
+ myListBox2->clear();
erasePreview();
return;
}
buttonOk()->setEnabled( true );
buttonApply()->setEnabled( true );
}
- myGrp->TextView1->setText( aMsg );
+ myTextView->setText( aMsg );
QStringList aErrList;
QString aErrStr( "" );
aErrList.append( aErrStr );
}
- myGrp->ListBox1->clear();
- myGrp->ListBox2->clear();
- myGrp->ListBox1->addItems( aErrList );
+ myListBox1->clear();
+ myListBox2->clear();
+ myListBox1->addItems( aErrList );
}
//=================================================================================
void MeasureGUI_CheckCompoundOfBlocksDlg::onErrorsListSelectionChanged()
{
erasePreview();
- int aCurItem = myGrp->ListBox1->currentRow();
+ int aCurItem = myListBox1->currentRow();
if ( aCurItem < 0 )
return;
bool isCompoundOfBlocks;
GEOM::GEOM_IBlocksOperations::BCErrors aErrs;
if ( !getBCErrors( isCompoundOfBlocks, aErrs ) ) {
- myGrp->TextView1->setText( "" );
- myGrp->ListBox1->clear();
- myGrp->ListBox2->clear();
+ myTextView->setText( "" );
+ myListBox1->clear();
+ myListBox2->clear();
return;
}
- myGrp->ListBox2->clear();
+ myListBox2->clear();
if (aCurItem < aErrs.length()) {
GEOM::GEOM_IBlocksOperations::BCError aErr = aErrs[aCurItem];
aSubShapeList.append( QString( "%1_%2" ).arg( aType ).arg( aObjLst[i] ) );
}
}
- myGrp->ListBox2->addItems( aSubShapeList );
+ myListBox2->addItems( aSubShapeList );
}
}
void MeasureGUI_CheckCompoundOfBlocksDlg::onSubShapesListSelectionChanged()
{
erasePreview();
- int aErrCurItem = myGrp->ListBox1->currentRow();
+ int aErrCurItem = myListBox1->currentRow();
if ( aErrCurItem < 0 )
return;
QList<int> aIds;
- for ( int i = 0, n = myGrp->ListBox2->count(); i < n; i++ ) {
- if ( myGrp->ListBox2->item( i )->isSelected() )
+ for ( int i = 0, n = myListBox2->count(); i < n; i++ ) {
+ if ( myListBox2->item( i )->isSelected() )
aIds.append( i );
}
if ( aIds.count() < 1 )
bool isCompoundOfBlocks;
GEOM::GEOM_IBlocksOperations::BCErrors aErrs;
if ( !getBCErrors( isCompoundOfBlocks, aErrs ) ) {
- myGrp->TextView1->setText( "" );
- myGrp->ListBox1->clear();
- myGrp->ListBox2->clear();
+ myTextView->setText( "" );
+ myListBox1->clear();
+ myListBox2->clear();
return;
}
}
}
+//=================================================================================
+// function : onDisplayPreview
+// purpose :
+//=================================================================================
+void MeasureGUI_CheckCompoundOfBlocksDlg::onDisplayPreview()
+{
+ DISPLAY_PREVIEW_MACRO;
+}
+
//=================================================================================
// function : activateSelection
// purpose : activate selection of faces, shells, and solids
// function : isValid
// purpose :
//=================================================================================
-bool MeasureGUI_CheckCompoundOfBlocksDlg::isValid( QString& )
+bool MeasureGUI_CheckCompoundOfBlocksDlg::isValid( QString &msg)
{
- return !myObj->_is_nil();
+ return !myObj->_is_nil() && mySpinTol->isValid(msg, !IsPreview());
}
//=================================================================================
#include <GEOMBase_Skeleton.h>
-class MeasureGUI_1Sel1TextView2ListBox;
+class QCheckBox;
+class QLabel;
+class QLineEdit;
+class QListWidget;
+class QPushButton;
+class QTextBrowser;
+class SalomeApp_DoubleSpinBox;
//=================================================================================
// class : MeasureGUI_CheckCompoundOfBlocksDlg
protected:
// redefined from GEOMBase_Helper and GEOMBase_Skeleton
virtual GEOM::GEOM_IOperations_ptr createOperation();
- virtual bool isValid( QString& );
+ virtual bool isValid( QString &msg );
virtual bool execute( ObjectList& );
virtual void processObject();
void onErrorsListSelectionChanged();
void onSubShapesListSelectionChanged();
+ void SetUseC1Tolerance();
+ void onDisplayPreview();
private:
void Init();
private:
GEOM::GEOM_Object_var myObj;
- MeasureGUI_1Sel1TextView2ListBox* myGrp;
+ QLineEdit *myObjectName;
+ QPushButton *mySelButton;
+ QCheckBox *myUseC1Check;
+ QLabel *myTolLbl;
+ SalomeApp_DoubleSpinBox *mySpinTol;
+ QTextBrowser *myTextView;
+ QListWidget *myListBox1;
+ QListWidget *myListBox2;
};
#endif // MEASUREGUI_CHECKCOMPOUNDOFBLOCKSDLG_H
#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