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

This commit is contained in:
skv 2015-01-22 12:14:55 +03:00 committed by vsr
parent 48e895f1fa
commit cbdcb3694d
20 changed files with 632 additions and 423 deletions

BIN
doc/salome/gui/GEOM/images/measures10.png Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 8.4 KiB

View File

@ -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.
- <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;
@ -26,7 +31,7 @@ In this dialog:
\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.

View File

@ -5,24 +5,45 @@
This operation retrieves all non-block solids and non-quadrangular faces from the selected shape.
A non-block solid is a solid that does not have 6 faces, or has 6 faces, but some of them are not quadrangular.
A block solid is a solid that has 6 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.
<em>geompy.GetNonBlocks(theShape, theIsUseC1 = False, theAngTolerance = 1.e-12).</em> \n
where \n
\em theShape is the shape to explore, \n
\em theIsUseC1 is the flag to check if there are 4 bounds on a face
taking into account C1 continuity, \n
\em theAngTolerance the angular tolerance to check if two neighbor edges are
codirectional in the common vertex with this tolerance. This parameter is
used only if \em theIsUseC1 is set to True.
The first object is a group of all non block solids; the second object is a group of all non
quadrangular faces.
This command returns a tuple of two GEOM_Objects.
The first object is a group of all non-block solids; the second object is a group
of all non-quadrangular faces.
See also a \ref tui_get_non_blocks_page "TUI example".

View File

@ -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.

View File

@ -1583,7 +1583,7 @@ bool AdvancedEngine_IOperations::MakePipeTShapePartition(Handle(GEOM_Object) the
// 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;
}

View File

@ -28,6 +28,11 @@
#include <BRep_Tool.hxx>
#include <Geom_Curve.hxx>
#include <gp_Pnt.hxx>
#include <gp_Vec.hxx>
#include <TopExp.hxx>
#include <TopExp_Explorer.hxx>
@ -36,8 +41,10 @@
#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>
@ -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 = "<<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);
}

View File

@ -30,6 +30,7 @@
#include <Standard_OStream.hxx>
class TopoDS_Shape;
class TopTools_ListOfShape;
#include <Standard.hxx>
#include <Standard_Macro.hxx>
@ -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;

View File

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

View File

@ -88,6 +88,7 @@
#include <Bnd_Box.hxx>
#include <GProp_GProps.hxx>
#include <Geom_Curve.hxx>
#include <Geom_Surface.hxx>
#include <ShapeAnalysis_Surface.hxx>
@ -103,6 +104,147 @@
#include <Standard_Failure.hxx>
#include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
/**
* This function returns Standard_True if the face is quadrangular. It means
* that it has only 1 wire with 4 edges. If there are more then 4 edges in
* the wire and theToleranceC1 is not negative the new implementation is used.
* According to it the face is quadrangular if it is quadrangular according to
* an old implementation or if it has a single wire with more then 4 edges
* that form exactly 4 bounds of C1 continuity with the given tolerance.
*
* \param theFace the face to be checked
* \param theToleranceC1 if negative, it is not used; otherwise it is used
* to check if two neighbor edges of face have C1 continuity.
* \return Standard_True if the face is quadrangular; Standard_False otherwise.
*/
static Standard_Boolean IsQuadrangle(const TopoDS_Face &theFace,
const Standard_Real theToleranceC1)
{
TopExp_Explorer aFExp (theFace, TopAbs_WIRE);
if (!aFExp.More()) {
// no wire in the face
return Standard_False;
}
TopoDS_Shape aWire = aFExp.Current();
aFExp.Next();
if (aFExp.More()) {
// multiple wires in the face
return Standard_False;
}
// Check number of edges in the face
Standard_Integer aNbEdges = 0;
TopTools_MapOfShape aMapEdges;
TopExp_Explorer aWExp(aWire, TopAbs_EDGE);
for (; aWExp.More(); aWExp.Next()) {
if (aMapEdges.Add(aWExp.Current())) {
aNbEdges++;
if (aNbEdges > 4) {
break;
}
}
}
if (aNbEdges < 4) {
return Standard_False;
}
if (aNbEdges > 4) {
if (theToleranceC1 < 0.) {
return Standard_False;
}
// Check if a wire has 4 bounds of C1 continuity.
BRepTools_WireExplorer aWireExp(TopoDS::Wire(aWire), theFace);
TopTools_ListOfShape anEdges;
for (aNbEdges = 0; aWireExp.More(); aWireExp.Next()) {
const TopoDS_Edge &anEdge = aWireExp.Current();
// Skip degenerated edges.
if (!BRep_Tool::Degenerated(anEdge)) {
anEdges.Append(anEdge);
++aNbEdges;
}
}
if (aNbEdges < 4) {
return Standard_False;
}
// Compute number of sharp corners.
anEdges.Append(anEdges.First()); // To make a loop.
TopTools_ListIteratorOfListOfShape anIter(anEdges);
Standard_Real aPar[2];
Standard_Integer aNbCorners = 0;
TopoDS_Edge anEdge1 = TopoDS::Edge(anEdges.First());
Handle(Geom_Curve) aCurve1 = BRep_Tool::Curve(anEdge1, aPar[0], aPar[1]);
Handle(Geom_Curve) aCurve2;
TopoDS_Edge anEdge2;
TopoDS_Vertex aCommonVtx;
gp_Pnt aPnt;
gp_Vec aVec1;
gp_Vec aVec2;
Standard_Boolean isReversed1 = (anEdge1.Orientation() == TopAbs_REVERSED);
Standard_Boolean isReversed2;
for (anIter.Next(); anIter.More(); anIter.Next()) {
TopoDS_Edge anEdge2 = TopoDS::Edge(anIter.Value());
if (!TopExp::CommonVertex(anEdge1, anEdge2, aCommonVtx)) {
// NEVERREACHED
return Standard_False;
}
// Check the angle between tangent vectors of 2 curves at this point.
Standard_Real aParam1 = BRep_Tool::Parameter(aCommonVtx, anEdge1);
Standard_Real aParam2 = BRep_Tool::Parameter(aCommonVtx, anEdge2);
aCurve2 = BRep_Tool::Curve(anEdge2, aPar[0], aPar[1]);
isReversed2 = (anEdge2.Orientation() == TopAbs_REVERSED);
aCurve1->D1(aParam1, aPnt, aVec1);
aCurve2->D1(aParam2, aPnt, aVec2);
if (isReversed1) {
aVec1.Reverse();
}
if (isReversed2) {
aVec2.Reverse();
}
const Standard_Real anAngle = aVec1.Angle(aVec2);
if (anAngle > theToleranceC1) {
++aNbCorners;
if (aNbCorners > 4) {
break;
}
}
// Go to the next couple of edges.
anEdge1 = anEdge2;
aCurve1 = aCurve2;
isReversed1 = isReversed2;
}
// Check the total number of corners.
if (aNbCorners != 4) {
return Standard_False;
}
}
return Standard_True;
}
//=============================================================================
/*!
* constructor:
@ -1647,7 +1789,8 @@ void GEOMImpl_IBlocksOperations::AddBlocksFrom (const TopoDS_Shape& theShape,
TopTools_ListOfShape& BLO,
TopTools_ListOfShape& NOT,
TopTools_ListOfShape& EXT,
TopTools_ListOfShape& NOQ)
TopTools_ListOfShape& NOQ,
const Standard_Real theToleranceC1)
{
TopAbs_ShapeEnum aType = theShape.ShapeType();
switch (aType) {
@ -1656,7 +1799,7 @@ void GEOMImpl_IBlocksOperations::AddBlocksFrom (const TopoDS_Shape& theShape,
{
TopoDS_Iterator It (theShape);
for (; It.More(); It.Next()) {
AddBlocksFrom(It.Value(), BLO, NOT, EXT, NOQ);
AddBlocksFrom(It.Value(), BLO, NOT, EXT, NOQ, theToleranceC1);
}
}
break;
@ -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())) {
TopoDS_Face aF = TopoDS::Face(expF.Current());
if (mapFaces.Add(aF)) {
nbFaces++;
//0021483//if (nbFaces > 6) break;
// get wire
TopoDS_Shape aF = expF.Current();
TopExp_Explorer wires (aF, TopAbs_WIRE);
if (!wires.More()) {
// no wire in the face
hasNonQuadr = Standard_True;
NOQ.Append(aF);//0021483
//0021483//break;
continue;
}
TopoDS_Shape aWire = wires.Current();
wires.Next();
if (wires.More()) {
// multiple wires in the face
hasNonQuadr = Standard_True;
NOQ.Append(aF);//0021483
//0021483//break;
continue;
}
// Check number of edges in the face
Standard_Integer nbEdges = 0;
TopTools_MapOfShape mapEdges;
TopExp_Explorer expW (aWire, TopAbs_EDGE);
for (; expW.More(); expW.Next()) {
if (mapEdges.Add(expW.Current())) {
nbEdges++;
if (nbEdges > 4) break;
}
}
if (nbEdges != 4) {
if (!IsQuadrangle(aF, theToleranceC1)) {
hasNonQuadr = Standard_True;
NOQ.Append(aF);//0021483
}
@ -1732,34 +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<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
@ -2294,6 +2140,7 @@ TCollection_AsciiString GEOMImpl_IBlocksOperations::PrintBCErrors
//=============================================================================
Standard_Boolean GEOMImpl_IBlocksOperations::CheckCompoundOfBlocks
(Handle(GEOM_Object) theCompound,
const Standard_Real theToleranceC1,
std::list<BCError>& 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");

View File

@ -125,16 +125,15 @@ class GEOMImpl_IBlocksOperations : public GEOM_IOperations {
std::list<int> incriminated;
};
Standard_EXPORT Standard_Boolean CheckCompoundOfBlocksOld (Handle(GEOM_Object) theCompound,
std::list<BCError>& theErrors);
Standard_EXPORT Standard_Boolean CheckCompoundOfBlocks (Handle(GEOM_Object) theCompound,
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,
@ -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

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

@ -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<GEOMImpl_IBlocksOperations::BCError> 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();

View File

@ -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,

View File

@ -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;
}

View File

@ -80,7 +80,7 @@
## # create and publish cylinder
## cyl = geompy.MakeCylinderRH(100, 100, "cylinder")
## # get non blocks from cylinder
## g1, g2 = geompy.GetNonBlocks(cyl, "nonblock")
## g1, g2 = geompy.GetNonBlocks(cyl, theName="nonblock")
## @endcode
##
## Above example will publish both result compounds (first with non-hexa solids and
@ -88,7 +88,7 @@
## However, if second command is invoked as
##
## @code
## g1, g2 = geompy.GetNonBlocks(cyl, ("nonhexa", "nonquad"))
## g1, g2 = geompy.GetNonBlocks(cyl, theName=("nonhexa", "nonquad"))
## @endcode
##
## ... the first compound will be published with "nonhexa" name, and second will be named "nonquad".
@ -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 <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)
@ -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
# <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.
@ -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 <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.
@ -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 <VAR>theIsUseC1</VAR> is set to True, faces
with 1 wire with not 4 edges that do not form 4 bounds of
C1 continuity).
Usage:
(res_sols, res_faces) = geompy.GetNonBlocks(myShape1)
"""
# Example: see GEOM_Spanner.py
aTuple = self.BlocksOp.GetNonBlocks(theShape)
aTolerance = -1.0
if theIsUseC1:
aTolerance = theAngTolerance
aTuple = self.BlocksOp.GetNonBlocks(theShape, aTolerance)
RaiseIfFailed("GetNonBlocks", self.BlocksOp)
self._autoPublish(aTuple, theName, ("groupNonHexas", "groupNonQuads"))
return aTuple

View File

@ -26,7 +26,6 @@
//
#include "MeasureGUI.h"
#include "MeasureGUI_CheckCompoundOfBlocksDlg.h"
#include "MeasureGUI_Widgets.h"
#include <SUIT_Session.h>
#include <SUIT_ResourceMgr.h>
@ -43,6 +42,8 @@
#include <GEOMBase.h>
#include <GEOMImpl_Types.hxx>
#include <QListWidget>
#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" ) );
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);
myGrp->TextView1->setReadOnly( true );
QFont aFont( TEXTEDIT_FONT_FAMILY, TEXTEDIT_FONT_SIZE );
aFont.setStyleHint( QFont::TypeWriter, QFont::PreferAntialias );
myGrp->TextView1->setFont( aFont );
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);
myGrp->PushButton1->setIcon( image1 );
myGrp->LineEdit1->setReadOnly( true );
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);
myGrp->TextLabel2->setText( tr( "GEOM_CHECK_BLOCKS_COMPOUND_ERRORS" ) );
myGrp->TextLabel3->setText( tr( "GEOM_CHECK_BLOCKS_COMPOUND_SUBSHAPES" ) );
// Set text view font.
QFont aFont(TEXTEDIT_FONT_FAMILY, TEXTEDIT_FONT_SIZE);
myGrp->ListBox2->setSelectionMode( QAbstractItemView::ExtendedSelection );
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<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 )
@ -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());
}
//=================================================================================

View File

@ -29,7 +29,13 @@
#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
@ -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

View File

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

View File

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