From: skv Date: Thu, 22 Jan 2015 09:14:55 +0000 (+0300) Subject: 0022775: [CEA 1091] Add an option on GetNonBlocks to retrieve quadrangular faces... X-Git-Tag: V7_6_0a1~63 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=cbdcb3694dfacde362169e99cc3d242a3a7d40cd;p=modules%2Fgeom.git 0022775: [CEA 1091] Add an option on GetNonBlocks to retrieve quadrangular faces defined on C1 edges --- diff --git a/doc/salome/gui/GEOM/images/measures10.png b/doc/salome/gui/GEOM/images/measures10.png old mode 100755 new mode 100644 index 091b2c0aa..7a05b55bb Binary files a/doc/salome/gui/GEOM/images/measures10.png and b/doc/salome/gui/GEOM/images/measures10.png differ diff --git a/doc/salome/gui/GEOM/images/measures2.png b/doc/salome/gui/GEOM/images/measures2.png index 21e5218a4..a9e064b5e 100644 Binary files a/doc/salome/gui/GEOM/images/measures2.png and b/doc/salome/gui/GEOM/images/measures2.png differ diff --git a/doc/salome/gui/GEOM/images/measures2a.png b/doc/salome/gui/GEOM/images/measures2a.png index 3068f49b1..718c60f90 100644 Binary files a/doc/salome/gui/GEOM/images/measures2a.png and b/doc/salome/gui/GEOM/images/measures2a.png differ diff --git a/doc/salome/gui/GEOM/input/check_compound_of_blocks.doc b/doc/salome/gui/GEOM/input/check_compound_of_blocks.doc index e9893b8e5..7151dcff7 100644 --- a/doc/salome/gui/GEOM/input/check_compound_of_blocks.doc +++ b/doc/salome/gui/GEOM/input/check_compound_of_blocks.doc @@ -8,7 +8,10 @@ This operation checks whether a shape is a compound of glued blocks. 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. @@ -16,8 +19,10 @@ following conditions: 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. +- Use C1 criterion - option that shitches on/off the C1 continuity mode. +- Angular Tolerance - 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; @@ -26,7 +31,7 @@ In this dialog: \n TUI Command: -geompy.CheckCompoundOfBlocks(Compound). Checks if the shape +geompy.CheckCompoundOfBlocks(Compound, theIsUseC1 = False, theAngTolerance = 1.e-12). 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. diff --git a/doc/salome/gui/GEOM/input/get_non_blocks.doc b/doc/salome/gui/GEOM/input/get_non_blocks.doc index 79f6ba021..e2b566dd3 100644 --- a/doc/salome/gui/GEOM/input/get_non_blocks.doc +++ b/doc/salome/gui/GEOM/input/get_non_blocks.doc @@ -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 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 +Use C1 criterion option and to set the Angular Tolerance +to check C1 continuity between neighbor edges in a wire. -Press \b Apply or Apply and Close 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 Apply and Close 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 TUI Command: -geompy.GetNonBlocks(Compound). 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. +geompy.GetNonBlocks(theShape, theIsUseC1 = False, theAngTolerance = 1.e-12). \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". diff --git a/idl/GEOM_Gen.idl b/idl/GEOM_Gen.idl index a85830009..2917f62cf 100644 --- a/idl/GEOM_Gen.idl +++ b/idl/GEOM_Gen.idl @@ -2770,10 +2770,14 @@ module GEOM * - 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); /*! @@ -2790,12 +2794,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. diff --git a/src/AdvancedEngine/AdvancedEngine_IOperations.cxx b/src/AdvancedEngine/AdvancedEngine_IOperations.cxx index 5d1b96999..ad7650b00 100644 --- a/src/AdvancedEngine/AdvancedEngine_IOperations.cxx +++ b/src/AdvancedEngine/AdvancedEngine_IOperations.cxx @@ -1583,7 +1583,7 @@ bool AdvancedEngine_IOperations::MakePipeTShapePartition(Handle(GEOM_Object) the // Last verification: result should be a block std::list errList; - if (!myBlocksOperations->CheckCompoundOfBlocks(Te3,errList)) { + if (!myBlocksOperations->CheckCompoundOfBlocks(Te3, -1, errList)) { SetErrorCode("TShape is not a compound of block"); return false; } diff --git a/src/BlockFix/BlockFix_CheckTool.cxx b/src/BlockFix/BlockFix_CheckTool.cxx index 32c0714be..36e527550 100644 --- a/src/BlockFix/BlockFix_CheckTool.cxx +++ b/src/BlockFix/BlockFix_CheckTool.cxx @@ -28,6 +28,11 @@ #include +#include + +#include +#include + #include #include @@ -36,8 +41,10 @@ #include #include #include +#include #include +#include #include #include #include @@ -49,6 +56,7 @@ BlockFix_CheckTool::BlockFix_CheckTool( ) { myHasCheck = Standard_False; + myAngTolerance = -1.; myPossibleBlocks.Clear(); } @@ -63,6 +71,17 @@ void BlockFix_CheckTool::SetShape(const TopoDS_Shape& aShape) myPossibleBlocks.Clear(); } +//======================================================================= +//function : SetAngTolerance +//purpose : +//======================================================================= +void BlockFix_CheckTool::SetAngTolerance(const Standard_Real theTolerance) +{ + myHasCheck = Standard_False; + myAngTolerance = theTolerance; + myPossibleBlocks.Clear(); +} + //======================================================================= //function : Perform //purpose : @@ -159,7 +178,6 @@ void BlockFix_CheckTool::Perform() if (nbe < 12) IsBlock = Standard_False; if (nbe > 12) { - IsBlock = Standard_False; // check edges unification // creating map of edge faces TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFaces; @@ -194,9 +212,19 @@ void BlockFix_CheckTool::Perform() 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; } @@ -265,3 +293,84 @@ void BlockFix_CheckTool::DumpCheckResult(Standard_OStream& S) const S<<" number of impossible blocks = "<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); +} diff --git a/src/BlockFix/BlockFix_CheckTool.hxx b/src/BlockFix/BlockFix_CheckTool.hxx index 83bd5b3c1..66711433c 100644 --- a/src/BlockFix/BlockFix_CheckTool.hxx +++ b/src/BlockFix/BlockFix_CheckTool.hxx @@ -30,6 +30,7 @@ #include class TopoDS_Shape; +class TopTools_ListOfShape; #include #include @@ -38,14 +39,20 @@ class BlockFix_CheckTool { 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; diff --git a/src/GEOMGUI/GEOM_msg_en.ts b/src/GEOMGUI/GEOM_msg_en.ts index 06cb15a74..22961d63e 100644 --- a/src/GEOMGUI/GEOM_msg_en.ts +++ b/src/GEOMGUI/GEOM_msg_en.ts @@ -407,6 +407,10 @@ Please, select face, shell or solid and try again GEOM_NONBLOCKS NonBlocksGroup + + GEOM_USE_C1_CRITERION + Use C1 criterion + GEOM_CHECK_INFOS Object And Its Topological Information diff --git a/src/GEOMImpl/GEOMImpl_IBlocksOperations.cxx b/src/GEOMImpl/GEOMImpl_IBlocksOperations.cxx index cca9f381f..2a733c51e 100644 --- a/src/GEOMImpl/GEOMImpl_IBlocksOperations.cxx +++ b/src/GEOMImpl/GEOMImpl_IBlocksOperations.cxx @@ -88,6 +88,7 @@ #include #include +#include #include #include @@ -103,6 +104,147 @@ #include #include // 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; @@ -1665,6 +1808,7 @@ void GEOMImpl_IBlocksOperations::AddBlocksFrom (const TopoDS_Shape& theShape, // 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); @@ -1676,41 +1820,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())) { - 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 } @@ -1732,34 +1847,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 +1862,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 +2084,6 @@ Standard_Boolean HasAnyConnection (const Standard_Integer theBlockIndex, return Standard_False; } -//============================================================================= -/*! - * CheckCompoundOfBlocksOld - */ -//============================================================================= -Standard_Boolean GEOMImpl_IBlocksOperations::CheckCompoundOfBlocksOld - (Handle(GEOM_Object) theCompound, - std::list& 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 - 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 @@ -2294,6 +2140,7 @@ TCollection_AsciiString GEOMImpl_IBlocksOperations::PrintBCErrors //============================================================================= Standard_Boolean GEOMImpl_IBlocksOperations::CheckCompoundOfBlocks (Handle(GEOM_Object) theCompound, + const Standard_Real theToleranceC1, std::list& theErrors) { SetErrorCode(KO); @@ -2312,7 +2159,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, theToleranceC1); // Report non-blocks if (NOT.Extent() > 0) { @@ -2478,7 +2325,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 +2339,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"); diff --git a/src/GEOMImpl/GEOMImpl_IBlocksOperations.hxx b/src/GEOMImpl/GEOMImpl_IBlocksOperations.hxx index 8a03b6e23..568872a08 100644 --- a/src/GEOMImpl/GEOMImpl_IBlocksOperations.hxx +++ b/src/GEOMImpl/GEOMImpl_IBlocksOperations.hxx @@ -125,16 +125,15 @@ class GEOMImpl_IBlocksOperations : public GEOM_IOperations { std::list incriminated; }; - Standard_EXPORT Standard_Boolean CheckCompoundOfBlocksOld (Handle(GEOM_Object) theCompound, - std::list& theErrors); - Standard_EXPORT Standard_Boolean CheckCompoundOfBlocks (Handle(GEOM_Object) theCompound, + const Standard_Real theToleranceC1, std::list& theErrors); Standard_EXPORT TCollection_AsciiString PrintBCErrors (Handle(GEOM_Object) theCompound, const std::list& 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 +147,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 diff --git a/src/GEOM_I/GEOM_IBlocksOperations_i.cc b/src/GEOM_I/GEOM_IBlocksOperations_i.cc old mode 100755 new mode 100644 index 55a9c3c70..513ffa752 --- a/src/GEOM_I/GEOM_IBlocksOperations_i.cc +++ b/src/GEOM_I/GEOM_IBlocksOperations_i.cc @@ -614,6 +614,7 @@ CORBA::Boolean GEOM_IBlocksOperations_i::IsCompoundOfBlocks //============================================================================= 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; @@ -627,7 +628,8 @@ CORBA::Boolean GEOM_IBlocksOperations_i::CheckCompoundOfBlocks //Check std::list errList; - isComp = GetOperations()->CheckCompoundOfBlocks(aCompound, errList); + isComp = GetOperations()->CheckCompoundOfBlocks + (aCompound, theToleranceC1, errList); if (!GetOperations()->IsDone()) return isComp; @@ -749,6 +751,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 +768,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(); diff --git a/src/GEOM_I/GEOM_IBlocksOperations_i.hh b/src/GEOM_I/GEOM_IBlocksOperations_i.hh index fa457b566..7755eeb64 100644 --- a/src/GEOM_I/GEOM_IBlocksOperations_i.hh +++ b/src/GEOM_I/GEOM_IBlocksOperations_i.hh @@ -116,12 +116,14 @@ class GEOM_I_EXPORT GEOM_IBlocksOperations_i : 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, diff --git a/src/GEOM_I_Superv/GEOM_Superv_i.cc b/src/GEOM_I_Superv/GEOM_Superv_i.cc index 867a5c6f7..0324e6e59 100644 --- a/src/GEOM_I_Superv/GEOM_Superv_i.cc +++ b/src/GEOM_I_Superv/GEOM_Superv_i.cc @@ -2713,7 +2713,7 @@ CORBA::Boolean GEOM_Superv_i::CheckCompoundOfBlocks 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; } diff --git a/src/GEOM_SWIG/geomBuilder.py b/src/GEOM_SWIG/geomBuilder.py index bb6519a93..be89ae1a3 100644 --- a/src/GEOM_SWIG/geomBuilder.py +++ b/src/GEOM_SWIG/geomBuilder.py @@ -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". @@ -11425,36 +11425,62 @@ class geomBuilder(object, GEOM._objref_GEOM_Gen): ## 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. # @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 + # theIsUseC1 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) @@ -11463,6 +11489,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 + # theIsUseC1 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. @@ -11470,17 +11502,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 theIsUseC1 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. @@ -11489,13 +11531,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 theIsUseC1 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 diff --git a/src/MeasureGUI/MeasureGUI_CheckCompoundOfBlocksDlg.cxx b/src/MeasureGUI/MeasureGUI_CheckCompoundOfBlocksDlg.cxx index 8d7961412..eee95b56b 100644 --- a/src/MeasureGUI/MeasureGUI_CheckCompoundOfBlocksDlg.cxx +++ b/src/MeasureGUI/MeasureGUI_CheckCompoundOfBlocksDlg.cxx @@ -26,7 +26,6 @@ // #include "MeasureGUI.h" #include "MeasureGUI_CheckCompoundOfBlocksDlg.h" -#include "MeasureGUI_Widgets.h" #include #include @@ -43,6 +42,8 @@ #include #include +#include + #define TEXTEDIT_FONT_FAMILY "Courier" #define TEXTEDIT_FONT_SIZE 11 @@ -54,7 +55,15 @@ // 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" ) ) ); @@ -70,29 +79,55 @@ MeasureGUI_CheckCompoundOfBlocksDlg::MeasureGUI_CheckCompoundOfBlocksDlg( Geomet 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 ); /***************************************************************/ @@ -116,14 +151,24 @@ MeasureGUI_CheckCompoundOfBlocksDlg::~MeasureGUI_CheckCompoundOfBlocksDlg() //================================================================================= 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() ) ); @@ -172,7 +217,7 @@ void MeasureGUI_CheckCompoundOfBlocksDlg::SelectionIntoArgument() aSelMgr->selectedObjects(aSelList); if (aSelList.Extent() != 1) { - myGrp->LineEdit1->setText( "" ); + myObjectName->setText( "" ); processObject(); return; } @@ -181,13 +226,13 @@ void MeasureGUI_CheckCompoundOfBlocksDlg::SelectionIntoArgument() 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; } @@ -198,11 +243,22 @@ void MeasureGUI_CheckCompoundOfBlocksDlg::SelectionIntoArgument() //================================================================================= 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 : @@ -210,8 +266,8 @@ void MeasureGUI_CheckCompoundOfBlocksDlg::SetEditCurrentArgument() void MeasureGUI_CheckCompoundOfBlocksDlg::LineEditReturnPressed() { QLineEdit* send = (QLineEdit*)sender(); - if ( send == myGrp->LineEdit1 ) { - myEditCurrentArgument = myGrp->LineEdit1; + if ( send == myObjectName ) { + myEditCurrentArgument = myObjectName; GEOMBase_Skeleton::LineEditReturnPressed(); } } @@ -245,7 +301,13 @@ bool MeasureGUI_CheckCompoundOfBlocksDlg::getBCErrors( bool& theIsCompoundOfBloc 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; @@ -270,9 +332,9 @@ void MeasureGUI_CheckCompoundOfBlocksDlg::processObject() 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; } @@ -287,7 +349,7 @@ void MeasureGUI_CheckCompoundOfBlocksDlg::processObject() buttonOk()->setEnabled( true ); buttonApply()->setEnabled( true ); } - myGrp->TextView1->setText( aMsg ); + myTextView->setText( aMsg ); QStringList aErrList; QString aErrStr( "" ); @@ -321,9 +383,9 @@ void MeasureGUI_CheckCompoundOfBlocksDlg::processObject() aErrList.append( aErrStr ); } - myGrp->ListBox1->clear(); - myGrp->ListBox2->clear(); - myGrp->ListBox1->addItems( aErrList ); + myListBox1->clear(); + myListBox2->clear(); + myListBox1->addItems( aErrList ); } //================================================================================= @@ -342,19 +404,19 @@ GEOM::GEOM_IOperations_ptr MeasureGUI_CheckCompoundOfBlocksDlg::createOperation( 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]; @@ -371,7 +433,7 @@ void MeasureGUI_CheckCompoundOfBlocksDlg::onErrorsListSelectionChanged() aSubShapeList.append( QString( "%1_%2" ).arg( aType ).arg( aObjLst[i] ) ); } } - myGrp->ListBox2->addItems( aSubShapeList ); + myListBox2->addItems( aSubShapeList ); } } @@ -382,12 +444,12 @@ void MeasureGUI_CheckCompoundOfBlocksDlg::onErrorsListSelectionChanged() void MeasureGUI_CheckCompoundOfBlocksDlg::onSubShapesListSelectionChanged() { erasePreview(); - int aErrCurItem = myGrp->ListBox1->currentRow(); + int aErrCurItem = myListBox1->currentRow(); if ( aErrCurItem < 0 ) return; QList 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 ) @@ -395,9 +457,9 @@ void MeasureGUI_CheckCompoundOfBlocksDlg::onSubShapesListSelectionChanged() 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; } @@ -433,6 +495,15 @@ void MeasureGUI_CheckCompoundOfBlocksDlg::onSubShapesListSelectionChanged() } } +//================================================================================= +// function : onDisplayPreview +// purpose : +//================================================================================= +void MeasureGUI_CheckCompoundOfBlocksDlg::onDisplayPreview() +{ + DISPLAY_PREVIEW_MACRO; +} + //================================================================================= // function : activateSelection // purpose : activate selection of faces, shells, and solids @@ -459,9 +530,9 @@ void MeasureGUI_CheckCompoundOfBlocksDlg::enterEvent( QEvent* ) // 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()); } //================================================================================= diff --git a/src/MeasureGUI/MeasureGUI_CheckCompoundOfBlocksDlg.h b/src/MeasureGUI/MeasureGUI_CheckCompoundOfBlocksDlg.h index e6a93c4f0..b2d43ca1f 100644 --- a/src/MeasureGUI/MeasureGUI_CheckCompoundOfBlocksDlg.h +++ b/src/MeasureGUI/MeasureGUI_CheckCompoundOfBlocksDlg.h @@ -29,7 +29,13 @@ #include -class MeasureGUI_1Sel1TextView2ListBox; +class QCheckBox; +class QLabel; +class QLineEdit; +class QListWidget; +class QPushButton; +class QTextBrowser; +class SalomeApp_DoubleSpinBox; //================================================================================= // class : MeasureGUI_CheckCompoundOfBlocksDlg @@ -47,7 +53,7 @@ public: 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(); @@ -61,6 +67,8 @@ private slots: void onErrorsListSelectionChanged(); void onSubShapesListSelectionChanged(); + void SetUseC1Tolerance(); + void onDisplayPreview(); private: void Init(); @@ -71,7 +79,14 @@ private: 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 diff --git a/src/MeasureGUI/MeasureGUI_GetNonBlocksDlg.cxx b/src/MeasureGUI/MeasureGUI_GetNonBlocksDlg.cxx index 5c04f273a..6ef248017 100644 --- a/src/MeasureGUI/MeasureGUI_GetNonBlocksDlg.cxx +++ b/src/MeasureGUI/MeasureGUI_GetNonBlocksDlg.cxx @@ -25,7 +25,6 @@ #include "MeasureGUI_GetNonBlocksDlg.h" -#include #include #include @@ -33,9 +32,18 @@ #include #include #include +#include #include #include +#include +#include +#include +#include +#include +#include +#include + //================================================================================= // 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(); - - 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); /***************************************************************/ @@ -94,14 +127,20 @@ void MeasureGUI_GetNonBlocksDlg::Init() 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())); @@ -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()) diff --git a/src/MeasureGUI/MeasureGUI_GetNonBlocksDlg.h b/src/MeasureGUI/MeasureGUI_GetNonBlocksDlg.h index 5282c8cd6..f6f59b680 100644 --- a/src/MeasureGUI/MeasureGUI_GetNonBlocksDlg.h +++ b/src/MeasureGUI/MeasureGUI_GetNonBlocksDlg.h @@ -28,7 +28,11 @@ #include -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